Create links to posts using an excerpt from the parsed post, not the raw text.
[Sone.git] / src / main / java / net / pterodactylus / sone / core / TrustUpdater.java
1 /*
2  * Sone - TrustUpdater.java - Copyright © 2012 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.sone.core;
19
20 import java.util.concurrent.BlockingQueue;
21 import java.util.concurrent.LinkedBlockingQueue;
22 import java.util.logging.Level;
23 import java.util.logging.Logger;
24
25 import net.pterodactylus.sone.freenet.plugin.PluginException;
26 import net.pterodactylus.sone.freenet.wot.DefaultIdentity;
27 import net.pterodactylus.sone.freenet.wot.Identity;
28 import net.pterodactylus.sone.freenet.wot.OwnIdentity;
29 import net.pterodactylus.sone.freenet.wot.Trust;
30 import net.pterodactylus.sone.freenet.wot.WebOfTrustConnector;
31 import net.pterodactylus.sone.freenet.wot.WebOfTrustException;
32 import net.pterodactylus.util.logging.Logging;
33 import net.pterodactylus.util.service.AbstractService;
34
35 /**
36  * Updates identity’s trust in a background thread because getting updates from
37  * the WebOfTrust plugin can potentially last quite long.
38  *
39  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
40  */
41 public class TrustUpdater extends AbstractService {
42
43         /** The logger. */
44         private static final Logger logger = Logging.getLogger(TrustUpdater.class);
45
46         /** Stop job. */
47         private static final TrustUpdateJob stopJob = new TrustUpdateJob(null, null);
48
49         /** The web of trust connector. */
50         private final WebOfTrustConnector webOfTrustConnector;
51
52         /** The queue for jobs. */
53         private final BlockingQueue<TrustUpdateJob> updateJobs = new LinkedBlockingQueue<TrustUpdateJob>();
54
55         /**
56          * Creates a new trust updater.
57          *
58          * @param webOfTrustConnector
59          *            The web of trust connector
60          */
61         public TrustUpdater(WebOfTrustConnector webOfTrustConnector) {
62                 super("Trust Updater");
63                 this.webOfTrustConnector = webOfTrustConnector;
64         }
65
66         //
67         // ACTIONS
68         //
69
70         /**
71          * Retrieves the trust relation between the truster and the trustee. This
72          * method will return immediately and perform a trust update in the
73          * background.
74          *
75          * @param truster
76          *            The identity giving the trust
77          * @param trustee
78          *            The identity receiving the trust
79          */
80         public void getTrust(OwnIdentity truster, Identity trustee) {
81                 GetTrustJob getTrustJob = new GetTrustJob(truster, trustee);
82                 if (!updateJobs.contains(getTrustJob)) {
83                         logger.log(Level.FINER, "Adding Trust Update Job: " + getTrustJob);
84                         try {
85                                 updateJobs.put(getTrustJob);
86                         } catch (InterruptedException ie1) {
87                                 /* the queue is unbounded so it should never block. */
88                         }
89                 }
90         }
91
92         /**
93          * Updates the trust relation between the truster and the trustee. This
94          * method will return immediately and perform a trust update in the
95          * background.
96          *
97          * @param truster
98          *            The identity giving the trust
99          * @param trustee
100          *            The identity receiving the trust
101          * @param score
102          *            The new level of trust (from -100 to 100, may be {@code null}
103          *            to remove the trust completely)
104          * @param comment
105          *            The comment of the trust relation
106          */
107         public void setTrust(OwnIdentity truster, Identity trustee, Integer score, String comment) {
108                 SetTrustJob setTrustJob = new SetTrustJob(truster, trustee, score, comment);
109                 if (updateJobs.contains(setTrustJob)) {
110                         updateJobs.remove(setTrustJob);
111                 }
112                 logger.log(Level.FINER, "Adding Trust Update Job: " + setTrustJob);
113                 try {
114                         updateJobs.put(setTrustJob);
115                 } catch (InterruptedException e) {
116                         /* the queue is unbounded so it should never block. */
117                 }
118         }
119
120         //
121         // SERVICE METHODS
122         //
123
124         /**
125          * {@inheritDoc}
126          */
127         @Override
128         protected void serviceRun() {
129                 while (!shouldStop()) {
130                         try {
131                                 TrustUpdateJob updateJob = updateJobs.take();
132                                 if (shouldStop() || (updateJob == stopJob)) {
133                                         break;
134                                 }
135                                 logger.log(Level.FINE, "Running Trust Update Job: " + updateJob);
136                                 long startTime = System.currentTimeMillis();
137                                 updateJob.run();
138                                 long endTime = System.currentTimeMillis();
139                                 logger.log(Level.FINE, "Trust Update Job finished, took " + (endTime - startTime) + " ms.");
140                         } catch (InterruptedException ie1) {
141                                 /* happens, ignore, loop. */
142                         }
143                 }
144         }
145
146         /**
147          * {@inheritDoc}
148          */
149         @Override
150         protected void serviceStop() {
151                 try {
152                         updateJobs.put(stopJob);
153                 } catch (InterruptedException ie1) {
154                         /* the queue is unbounded so it should never block. */
155                 }
156         }
157
158         /**
159          * Base class for trust update jobs.
160          *
161          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
162          */
163         private static class TrustUpdateJob {
164
165                 /** The identity giving the trust. */
166                 protected final OwnIdentity truster;
167
168                 /** The identity receiving the trust. */
169                 protected final Identity trustee;
170
171                 /**
172                  * Creates a new trust update job.
173                  *
174                  * @param truster
175                  *            The identity giving the trust
176                  * @param trustee
177                  *            The identity receiving the trust
178                  */
179                 public TrustUpdateJob(OwnIdentity truster, Identity trustee) {
180                         this.truster = truster;
181                         this.trustee = trustee;
182                 }
183
184                 //
185                 // ACCESSORS
186                 //
187
188                 /**
189                  * Performs the actual update operation.
190                  * <p>
191                  * The implementation of this class does nothing.
192                  */
193                 public void run() {
194                         /* does nothing. */
195                 }
196
197                 //
198                 // OBJECT METHODS
199                 //
200
201                 /**
202                  * {@inheritDoc}
203                  */
204                 @Override
205                 public boolean equals(Object object) {
206                         if ((object == null) || !object.getClass().equals(getClass())) {
207                                 return false;
208                         }
209                         TrustUpdateJob updateJob = (TrustUpdateJob) object;
210                         return ((truster == null) ? (updateJob.truster == null) : updateJob.truster.equals(truster)) && ((trustee == null) ? (updateJob.trustee == null) : updateJob.trustee.equals(trustee));
211                 }
212
213                 /**
214                  * {@inheritDoc}
215                  */
216                 @Override
217                 public int hashCode() {
218                         return getClass().hashCode() ^ ((truster == null) ? 0 : truster.hashCode()) ^ ((trustee == null) ? 0 : trustee.hashCode());
219                 }
220
221                 /**
222                  * {@inheritDoc}
223                  */
224                 @Override
225                 public String toString() {
226                         return String.format("%s[truster=%s,trustee=%s]", getClass().getSimpleName(), (truster == null) ? null : truster.getId(), (trustee == null) ? null : trustee.getId());
227                 }
228
229         }
230
231         /**
232          * Update job that sets the trust relation between two identities.
233          *
234          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
235          */
236         private class SetTrustJob extends TrustUpdateJob {
237
238                 /** The score of the relation. */
239                 private final Integer score;
240
241                 /** The comment of the relation. */
242                 private final String comment;
243
244                 /**
245                  * Creates a new set trust job.
246                  *
247                  * @param truster
248                  *            The identity giving the trust
249                  * @param trustee
250                  *            The identity receiving the trust
251                  * @param score
252                  *            The score of the trust (from -100 to 100, may be
253                  *            {@code null} to remote the trust relation completely)
254                  * @param comment
255                  *            The comment of the trust relation
256                  */
257                 public SetTrustJob(OwnIdentity truster, Identity trustee, Integer score, String comment) {
258                         super(truster, trustee);
259                         this.score = score;
260                         this.comment = comment;
261                 }
262
263                 /**
264                  * {@inheritDoc}
265                  */
266                 @Override
267                 @SuppressWarnings("synthetic-access")
268                 public void run() {
269                         try {
270                                 if (score != null) {
271                                         if (trustee instanceof DefaultIdentity) {
272                                                 ((DefaultIdentity) trustee).setTrust(truster, new Trust(score, null, 0));
273                                         }
274                                         webOfTrustConnector.setTrust(truster, trustee, score, comment);
275                                 } else {
276                                         if (trustee instanceof DefaultIdentity) {
277                                                 ((DefaultIdentity) trustee).setTrust(truster, null);
278                                         }
279                                         webOfTrustConnector.removeTrust(truster, trustee);
280                                 }
281                         } catch (WebOfTrustException wote1) {
282                                 logger.log(Level.WARNING, "Could not set Trust value for " + truster + " -> " + trustee + " to " + score + " (" + comment + ")!", wote1);
283                         }
284                 }
285
286         }
287
288         /**
289          * Update job that retrieves the trust relation between two identities.
290          *
291          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
292          */
293         private class GetTrustJob extends TrustUpdateJob {
294
295                 /**
296                  * Creates a new trust update job.
297                  *
298                  * @param truster
299                  *            The identity giving the trust
300                  * @param trustee
301                  *            The identity receiving the trust
302                  */
303                 public GetTrustJob(OwnIdentity truster, Identity trustee) {
304                         super(truster, trustee);
305                 }
306
307                 /**
308                  * {@inheritDoc}
309                  */
310                 @Override
311                 @SuppressWarnings("synthetic-access")
312                 public void run() {
313                         try {
314                                 Trust trust = webOfTrustConnector.getTrust(truster, trustee);
315                                 if (trustee instanceof DefaultIdentity) {
316                                         ((DefaultIdentity) trustee).setTrust(truster, trust);
317                                 }
318                         } catch (PluginException pe1) {
319                                 logger.log(Level.WARNING, "Could not get Trust value for " + truster + " -> " + trustee + "!", pe1);
320                         }
321                 }
322         }
323
324 }