7908f5c4b4e3ca052ec654a313efbe6b9893e77d
[jFCPlib.git] / src / main / java / net / pterodactylus / fcp / quelaton / ClientGetCommandImpl.java
1 package net.pterodactylus.fcp.quelaton;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.util.Optional;
6 import java.util.concurrent.ExecutionException;
7 import java.util.concurrent.ExecutorService;
8 import java.util.function.Supplier;
9
10 import net.pterodactylus.fcp.AllData;
11 import net.pterodactylus.fcp.ClientGet;
12 import net.pterodactylus.fcp.FcpUtils.TempInputStream;
13 import net.pterodactylus.fcp.GetFailed;
14 import net.pterodactylus.fcp.Priority;
15 import net.pterodactylus.fcp.ReturnType;
16
17 import com.google.common.util.concurrent.ListeningExecutorService;
18 import com.google.common.util.concurrent.MoreExecutors;
19
20 /**
21  * Implementation of the {@link ClientGetCommand}.
22  *
23  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
24  */
25 class ClientGetCommandImpl implements ClientGetCommand {
26
27         private final ListeningExecutorService threadPool;
28         private final ConnectionSupplier connectionSupplier;
29         private final Supplier<String> identifierGenerator;
30
31         private boolean ignoreDataStore;
32         private boolean dataStoreOnly;
33         private Long maxSize;
34         private Priority priority;
35         private boolean realTime;
36         private boolean global;
37
38         public ClientGetCommandImpl(ExecutorService threadPool, ConnectionSupplier connectionSupplier, Supplier<String> identifierGenerator) {
39                 this.threadPool = MoreExecutors.listeningDecorator(threadPool);
40                 this.connectionSupplier = connectionSupplier;
41                 this.identifierGenerator = identifierGenerator;
42         }
43
44         @Override
45         public ClientGetCommand ignoreDataStore() {
46                 ignoreDataStore = true;
47                 return this;
48         }
49
50         @Override
51         public ClientGetCommand dataStoreOnly() {
52                 dataStoreOnly = true;
53                 return this;
54         }
55
56         @Override
57         public ClientGetCommand maxSize(long maxSize) {
58                 this.maxSize = maxSize;
59                 return this;
60         }
61
62         @Override
63         public ClientGetCommand priority(Priority priority) {
64                 this.priority = priority;
65                 return this;
66         }
67
68         @Override
69         public ClientGetCommand realTime() {
70                 realTime = true;
71                 return this;
72         }
73
74         @Override
75         public ClientGetCommand global() {
76                 global = true;
77                 return this;
78         }
79
80         @Override
81         public Executable<Optional<Data>> uri(String uri) {
82                 return () -> threadPool.submit(() -> execute(uri));
83         }
84
85         private Optional<Data> execute(String uri) throws InterruptedException, ExecutionException, IOException {
86                 ClientGet clientGet = createClientGetCommand(uri);
87                 try (ClientGetDialog clientGetDialog = new ClientGetDialog()) {
88                         return clientGetDialog.send(clientGet).get();
89                 }
90         }
91
92         private ClientGet createClientGetCommand(String uri) {
93                 String identifier = identifierGenerator.get();
94                 ClientGet clientGet = new ClientGet(uri, identifier, ReturnType.direct);
95                 if (ignoreDataStore) {
96                         clientGet.setIgnoreDataStore(true);
97                 }
98                 if (dataStoreOnly) {
99                         clientGet.setDataStoreOnly(true);
100                 }
101                 if (maxSize != null) {
102                         clientGet.setMaxSize(maxSize);
103                 }
104                 if (priority != null) {
105                         clientGet.setPriority(priority);
106                 }
107                 if (realTime) {
108                         clientGet.setRealTimeFlag(true);
109                 }
110                 if (global) {
111                         clientGet.setGlobal(true);
112                 }
113                 return clientGet;
114         }
115
116         private class ClientGetDialog extends FcpDialog<Optional<Data>> {
117
118                 public ClientGetDialog() throws IOException {
119                         super(ClientGetCommandImpl.this.threadPool, ClientGetCommandImpl.this.connectionSupplier.get(), Optional.<Data>empty());
120                 }
121
122                 @Override
123                 protected void consumeAllData(AllData allData) {
124                         synchronized (this) {
125                                 String contentType = allData.getContentType();
126                                 long dataLength = allData.getDataLength();
127                                 try {
128                                         InputStream payload = new TempInputStream(allData.getPayloadInputStream(), dataLength);
129                                         setResult(Optional.of(createData(contentType, dataLength, payload)));
130                                 } catch (IOException e) {
131                                         // TODO – logging
132                                         finish();
133                                 }
134                         }
135                 }
136
137                 private Data createData(String contentType, long dataLength, InputStream payload) {
138                         return new Data() {
139                                 @Override
140                                 public String getMimeType() {
141                                         return contentType;
142                                 }
143
144                                 @Override
145                                 public long size() {
146                                         return dataLength;
147                                 }
148
149                                 @Override
150                                 public InputStream getInputStream() {
151                                         return payload;
152                                 }
153                         };
154                 }
155
156                 @Override
157                 protected void consumeGetFailed(GetFailed getFailed) {
158                         finish();
159                 }
160
161         }
162
163 }