Add ListPeer command
[jFCPlib.git] / src / main / java / net / pterodactylus / fcp / quelaton / ListPeerCommandImpl.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.atomic.AtomicBoolean;
7 import java.util.concurrent.atomic.AtomicReference;
8
9 import net.pterodactylus.fcp.ListPeer;
10 import net.pterodactylus.fcp.Peer;
11 import net.pterodactylus.fcp.UnknownNodeIdentifier;
12
13 import com.google.common.util.concurrent.ListenableFuture;
14 import com.google.common.util.concurrent.ListeningExecutorService;
15
16 /**
17  * Default {@link ListPeerCommand} implementation based on {@link FcpReplySequence}.
18  *
19  * @author <a href="mailto:bombe@freenetproject.org">David ‘Bombe’ Roden</a>
20  */
21 public class ListPeerCommandImpl implements ListPeerCommand {
22
23         private final ListeningExecutorService threadPool;
24         private final ConnectionSupplier connectionSupplier;
25         private final AtomicReference<String> nodeIdentifier = new AtomicReference<>();
26
27         public ListPeerCommandImpl(ListeningExecutorService threadPool, ConnectionSupplier connectionSupplier) {
28                 this.threadPool = threadPool;
29                 this.connectionSupplier = connectionSupplier;
30         }
31
32         @Override
33         public Executable<Optional<Peer>> byName(String name) {
34                 nodeIdentifier.set(name);
35                 return this::execute;
36         }
37
38         @Override
39         public Executable<Optional<Peer>> byIdentity(String identity) {
40                 nodeIdentifier.set(identity);
41                 return this::execute;
42         }
43
44         @Override
45         public Executable<Optional<Peer>> byHostAndPort(String host, int port) {
46                 nodeIdentifier.set(String.format("%s:%d", host, port));
47                 return this::execute;
48         }
49
50         private ListenableFuture<Optional<Peer>> execute() {
51                 return threadPool.submit(this::executeSequence);
52         }
53
54         private Optional<Peer> executeSequence() throws IOException, ExecutionException, InterruptedException {
55                 ListPeer listPeer = new ListPeer(new RandomIdentifierGenerator().generate(), nodeIdentifier.get());
56                 try (ListPeerSequence listPeerSequence = new ListPeerSequence()) {
57                         return Optional.ofNullable(listPeerSequence.send(listPeer).get());
58                 }
59         }
60
61         private class ListPeerSequence extends FcpReplySequence<Peer> {
62
63                 private final AtomicBoolean finished = new AtomicBoolean();
64                 private final AtomicReference<Peer> peer = new AtomicReference<>();
65
66                 public ListPeerSequence() throws IOException {
67                         super(threadPool, connectionSupplier.get());
68                 }
69
70                 @Override
71                 protected boolean isFinished() {
72                         return finished.get();
73                 }
74
75                 @Override
76                 protected Peer getResult() {
77                         return peer.get();
78                 }
79
80                 @Override
81                 protected void consumePeer(Peer peer) {
82                         this.peer.set(peer);
83                         finished.set(true);
84                 }
85
86                 @Override
87                 protected void consumeUnknownNodeIdentifier(UnknownNodeIdentifier unknownNodeIdentifier) {
88                         finished.set(true);
89                 }
90
91         }
92
93 }