b08ff4e6846bcc8cd8af8c0ec1141bc1e69a5814
[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 = new ClientGet(uri, identifier, ReturnType.direct);
85                 if (ignoreDataStore) {
86                         clientGet.setIgnoreDataStore(true);
87                 }
88                 if (dataStoreOnly) {
89                         clientGet.setDataStoreOnly(true);
90                 }
91                 if (maxSize != null) {
92                         clientGet.setMaxSize(maxSize);
93                 }
94                 if (priority != null) {
95                         clientGet.setPriority(priority);
96                 }
97                 if (realTime) {
98                         clientGet.setRealTimeFlag(true);
99                 }
100                 if (global) {
101                         clientGet.setGlobal(true);
102                 }
103                 return threadPool.submit(() -> {
104                         FcpReplySequence<Optional<Data>> replySequence =
105                                 new ClientGetReplySequence();
106                         return replySequence.send(clientGet).get();
107                 });
108         }
109
110         private class ClientGetReplySequence extends FcpReplySequence<Optional<Data>> {
111
112                 private final AtomicBoolean finished = new AtomicBoolean();
113                 private final AtomicBoolean failed = new AtomicBoolean();
114
115                 private final String identifier = ClientGetCommandImpl.this.identifier;
116
117                 private String contentType;
118                 private long dataLength;
119                 private InputStream payload;
120
121                 public ClientGetReplySequence() throws IOException {
122                         super(ClientGetCommandImpl.this.threadPool, ClientGetCommandImpl.this.connectionSupplier.get());
123                 }
124
125                 @Override
126                 protected boolean isFinished() {
127                         return finished.get() || failed.get();
128                 }
129
130                 @Override
131                 protected Optional<Data> getResult() {
132                         return failed.get() ? Optional.empty() : Optional.of(new Data() {
133                                 @Override
134                                 public String getMimeType() {
135                                         return contentType;
136                                 }
137
138                                 @Override
139                                 public long size() {
140                                         return dataLength;
141                                 }
142
143                                 @Override
144                                 public InputStream getInputStream() {
145                                         return payload;
146                                 }
147                         });
148                 }
149
150                 @Override
151                 protected void consumeAllData(AllData allData) {
152                         if (allData.getIdentifier().equals(identifier)) {
153                                 synchronized (this) {
154                                         contentType = allData.getContentType();
155                                         dataLength = allData.getDataLength();
156                                         try {
157                                                 payload = new TempInputStream(allData.getPayloadInputStream(), dataLength);
158                                                 finished.set(true);
159                                         } catch (IOException e) {
160                                                 // TODO – logging
161                                                 failed.set(true);
162                                         }
163                                 }
164                         }
165                 }
166
167                 @Override
168                 protected void consumeGetFailed(GetFailed getFailed) {
169                         if (getFailed.getIdentifier().equals(identifier)) {
170                                 failed.set(true);
171                         }
172                 }
173
174                 @Override
175                 protected void consumeConnectionClosed(Throwable throwable) {
176                         failed.set(true);
177                 }
178
179         }
180
181 }