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