a675280c6009a05124db4d83930033fcbff1289b
[jFCPlib.git] / src / main / java / net / pterodactylus / fcp / quelaton / ModifyPeerCommandImpl.java
1 package net.pterodactylus.fcp.quelaton;
2
3 import java.io.IOException;
4 import java.util.Optional;
5 import java.util.concurrent.ExecutionException;
6 import java.util.concurrent.ExecutorService;
7 import java.util.concurrent.atomic.AtomicBoolean;
8 import java.util.concurrent.atomic.AtomicReference;
9
10 import net.pterodactylus.fcp.ModifyPeer;
11 import net.pterodactylus.fcp.Peer;
12 import net.pterodactylus.fcp.UnknownNodeIdentifier;
13
14 import com.google.common.util.concurrent.ListenableFuture;
15 import com.google.common.util.concurrent.ListeningExecutorService;
16 import com.google.common.util.concurrent.MoreExecutors;
17
18 /**
19  * Default {@link ModifyPeerCommand} implementation based on {@link FcpDialog}.
20  *
21  * @author <a href="mailto:bombe@freenetproject.org">David ‘Bombe’ Roden</a>
22  */
23 public class ModifyPeerCommandImpl implements ModifyPeerCommand {
24
25         private final ListeningExecutorService threadPool;
26         private final ConnectionSupplier connectionSupplier;
27         private final AtomicReference<String> nodeIdentifier = new AtomicReference<>();
28         private final AtomicReference<Boolean> enabled = new AtomicReference<>();
29         private final AtomicReference<Boolean> allowLocalAddresses = new AtomicReference<>();
30         private final AtomicReference<Boolean> burstOnly = new AtomicReference<>();
31         private final AtomicReference<Boolean> listenOnly = new AtomicReference<>();
32         private final AtomicReference<Boolean> ignoreSource = new AtomicReference<>();
33
34         public ModifyPeerCommandImpl(ExecutorService threadPool, ConnectionSupplier connectionSupplier) {
35                 this.threadPool = MoreExecutors.listeningDecorator(threadPool);
36                 this.connectionSupplier = connectionSupplier;
37         }
38
39         @Override
40         public ModifyPeerCommand enable() {
41                 enabled.set(true);
42                 return this;
43         }
44
45         @Override
46         public ModifyPeerCommand disable() {
47                 enabled.set(false);
48                 return this;
49         }
50
51         @Override
52         public ModifyPeerCommand allowLocalAddresses() {
53                 allowLocalAddresses.set(true);
54                 return this;
55         }
56
57         @Override
58         public ModifyPeerCommand disallowLocalAddresses() {
59                 allowLocalAddresses.set(false);
60                 return this;
61         }
62
63         @Override
64         public ModifyPeerCommand setBurstOnly() {
65                 burstOnly.set(true);
66                 return this;
67         }
68
69         @Override
70         public ModifyPeerCommand clearBurstOnly() {
71                 burstOnly.set(false);
72                 return this;
73         }
74
75         @Override
76         public ModifyPeerCommand setListenOnly() {
77                 listenOnly.set(true);
78                 return this;
79         }
80
81         @Override
82         public ModifyPeerCommand clearListenOnly() {
83                 listenOnly.set(false);
84                 return this;
85         }
86
87         @Override
88         public ModifyPeerCommand ignoreSource() {
89                 ignoreSource.set(true);
90                 return this;
91         }
92
93         @Override
94         public ModifyPeerCommand useSource() {
95                 ignoreSource.set(false);
96                 return this;
97         }
98
99         @Override
100         public Executable<Optional<Peer>> byName(String name) {
101                 nodeIdentifier.set(name);
102                 return this::execute;
103         }
104
105         @Override
106         public Executable<Optional<Peer>> byIdentity(String nodeIdentity) {
107                 nodeIdentifier.set(nodeIdentity);
108                 return this::execute;
109         }
110
111         @Override
112         public Executable<Optional<Peer>> byHostAndPort(String host, int port) {
113                 nodeIdentifier.set(String.format("%s:%d", host, port));
114                 return this::execute;
115         }
116
117         private ListenableFuture<Optional<Peer>> execute() {
118                 return threadPool.submit(this::executeDialog);
119         }
120
121         private Optional<Peer> executeDialog() throws IOException, ExecutionException, InterruptedException {
122                 ModifyPeer modifyPeer = new ModifyPeer(new RandomIdentifierGenerator().generate(), nodeIdentifier.get());
123                 Optional.ofNullable(enabled.get()).ifPresent(enabled -> modifyPeer.setEnabled(enabled));
124                 Optional.ofNullable(allowLocalAddresses.get()).ifPresent(allowed -> modifyPeer.setAllowLocalAddresses(allowed));
125                 Optional.ofNullable(burstOnly.get()).ifPresent(burstOnly -> modifyPeer.setBurstOnly(burstOnly));
126                 Optional.ofNullable(listenOnly.get()).ifPresent(listenOnly -> modifyPeer.setListenOnly(listenOnly));
127                 Optional.ofNullable(ignoreSource.get()).ifPresent(ignoreSource -> modifyPeer.setIgnoreSource(ignoreSource));
128                 try (ModifyPeerDialog modifyPeerDialog = new ModifyPeerDialog()) {
129                         return modifyPeerDialog.send(modifyPeer).get();
130                 }
131         }
132
133         private class ModifyPeerDialog extends FcpDialog<Optional<Peer>> {
134
135                 private final AtomicBoolean finished = new AtomicBoolean();
136                 private final AtomicReference<Peer> peer = new AtomicReference<>();
137
138                 public ModifyPeerDialog() throws IOException {
139                         super(threadPool, connectionSupplier.get());
140                 }
141
142                 @Override
143                 protected boolean isFinished() {
144                         return finished.get();
145                 }
146
147                 @Override
148                 protected Optional<Peer> getResult() {
149                         return Optional.ofNullable(peer.get());
150                 }
151
152                 @Override
153                 protected void consumePeer(Peer peer) {
154                         this.peer.set(peer);
155                         finished.set(true);
156                 }
157
158                 @Override
159                 protected void consumeUnknownNodeIdentifier(UnknownNodeIdentifier unknownNodeIdentifier) {
160                         finished.set(true);
161                 }
162
163         }
164
165 }