b4e391ad7c6f9ed8830f9db6b7de93752f890c93
[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.ExecutorService;
7 import java.util.concurrent.Future;
8 import java.util.concurrent.atomic.AtomicBoolean;
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 /**
18  * Implementation of the {@link ClientGetCommand}.
19  *
20  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
21  */
22 class ClientGetCommandImpl implements ClientGetCommand {
23
24         private final ExecutorService threadPool;
25         private final ConnectionSupplier connectionSupplier;
26
27         private String identifier;
28         private boolean ignoreDataStore;
29         private boolean dataStoreOnly;
30         private Long maxSize;
31         private Priority priority;
32         private boolean realTime;
33         private boolean global;
34
35         public ClientGetCommandImpl(ExecutorService threadPool, ConnectionSupplier connectionSupplier) {
36                 this.threadPool = threadPool;
37                 this.connectionSupplier = connectionSupplier;
38         }
39
40         @Override
41         public ClientGetCommand identifier(String identifier) {
42                 this.identifier = identifier;
43                 return this;
44         }
45
46         @Override
47         public ClientGetCommand ignoreDataStore() {
48                 ignoreDataStore = true;
49                 return this;
50         }
51
52         @Override
53         public ClientGetCommand dataStoreOnly() {
54                 dataStoreOnly = true;
55                 return this;
56         }
57
58         @Override
59         public ClientGetCommand maxSize(long maxSize) {
60                 this.maxSize = maxSize;
61                 return this;
62         }
63
64         @Override
65         public ClientGetCommand priority(Priority priority) {
66                 this.priority = priority;
67                 return this;
68         }
69
70         @Override
71         public ClientGetCommand realTime() {
72                 realTime = true;
73                 return this;
74         }
75
76         @Override
77         public ClientGetCommand global() {
78                 global = true;
79                 return this;
80         }
81
82         @Override
83         public Future<Optional<Data>> uri(String uri) {
84                 ClientGet clientGet = createClientGetCommand(uri);
85                 return threadPool.submit(() -> new ClientGetReplySequence().send(clientGet).get());
86         }
87
88         private ClientGet createClientGetCommand(String uri) {
89                 ClientGet clientGet = new ClientGet(uri, identifier, ReturnType.direct);
90                 if (ignoreDataStore) {
91                         clientGet.setIgnoreDataStore(true);
92                 }
93                 if (dataStoreOnly) {
94                         clientGet.setDataStoreOnly(true);
95                 }
96                 if (maxSize != null) {
97                         clientGet.setMaxSize(maxSize);
98                 }
99                 if (priority != null) {
100                         clientGet.setPriority(priority);
101                 }
102                 if (realTime) {
103                         clientGet.setRealTimeFlag(true);
104                 }
105                 if (global) {
106                         clientGet.setGlobal(true);
107                 }
108                 return clientGet;
109         }
110
111         private class ClientGetReplySequence extends FcpReplySequence<Optional<Data>> {
112
113                 private final AtomicBoolean finished = new AtomicBoolean();
114                 private final AtomicBoolean failed = new AtomicBoolean();
115
116                 private final String identifier = ClientGetCommandImpl.this.identifier;
117
118                 private String contentType;
119                 private long dataLength;
120                 private InputStream payload;
121
122                 public ClientGetReplySequence() throws IOException {
123                         super(ClientGetCommandImpl.this.threadPool, ClientGetCommandImpl.this.connectionSupplier.get());
124                 }
125
126                 @Override
127                 protected boolean isFinished() {
128                         return finished.get() || failed.get();
129                 }
130
131                 @Override
132                 protected Optional<Data> getResult() {
133                         return failed.get() ? Optional.empty() : Optional.of(new Data() {
134                                 @Override
135                                 public String getMimeType() {
136                                         return contentType;
137                                 }
138
139                                 @Override
140                                 public long size() {
141                                         return dataLength;
142                                 }
143
144                                 @Override
145                                 public InputStream getInputStream() {
146                                         return payload;
147                                 }
148                         });
149                 }
150
151                 @Override
152                 protected void consumeAllData(AllData allData) {
153                         if (allData.getIdentifier().equals(identifier)) {
154                                 synchronized (this) {
155                                         contentType = allData.getContentType();
156                                         dataLength = allData.getDataLength();
157                                         try {
158                                                 payload = new TempInputStream(allData.getPayloadInputStream(), dataLength);
159                                                 finished.set(true);
160                                         } catch (IOException e) {
161                                                 // TODO – logging
162                                                 failed.set(true);
163                                         }
164                                 }
165                         }
166                 }
167
168                 @Override
169                 protected void consumeGetFailed(GetFailed getFailed) {
170                         if (getFailed.getIdentifier().equals(identifier)) {
171                                 failed.set(true);
172                         }
173                 }
174
175                 @Override
176                 protected void consumeConnectionClosed(Throwable throwable) {
177                         failed.set(true);
178                 }
179
180         }
181
182 }