Remove exception from Identity interface, let null signal an error.
[Sone.git] / src / main / java / net / pterodactylus / sone / core / Core.java
index 9263063..053e042 100644 (file)
@@ -40,12 +40,14 @@ import net.pterodactylus.sone.freenet.wot.Identity;
 import net.pterodactylus.sone.freenet.wot.IdentityListener;
 import net.pterodactylus.sone.freenet.wot.IdentityManager;
 import net.pterodactylus.sone.freenet.wot.OwnIdentity;
+import net.pterodactylus.sone.freenet.wot.Trust;
 import net.pterodactylus.sone.freenet.wot.WebOfTrustException;
 import net.pterodactylus.sone.main.SonePlugin;
 import net.pterodactylus.util.config.Configuration;
 import net.pterodactylus.util.config.ConfigurationException;
 import net.pterodactylus.util.logging.Logging;
 import net.pterodactylus.util.number.Numbers;
+import net.pterodactylus.util.validation.Validation;
 import freenet.keys.FreenetURI;
 
 /**
@@ -87,6 +89,9 @@ public class Core implements IdentityListener {
        /** The configuration. */
        private Configuration configuration;
 
+       /** Whether we’re currently saving the configuration. */
+       private boolean storingConfiguration = false;
+
        /** The identity manager. */
        private final IdentityManager identityManager;
 
@@ -727,7 +732,9 @@ public class Core implements IdentityListener {
         */
        public void lockSone(Sone sone) {
                synchronized (lockedSones) {
-                       lockedSones.add(sone);
+                       if (lockedSones.add(sone)) {
+                               coreListenerManager.fireSoneLocked(sone);
+                       }
                }
        }
 
@@ -740,7 +747,9 @@ public class Core implements IdentityListener {
         */
        public void unlockSone(Sone sone) {
                synchronized (lockedSones) {
-                       lockedSones.remove(sone);
+                       if (lockedSones.remove(sone)) {
+                               coreListenerManager.fireSoneUnlocked(sone);
+                       }
                }
        }
 
@@ -890,6 +899,97 @@ public class Core implements IdentityListener {
        }
 
        /**
+        * Retrieves the trust relationship from the origin to the target. If the
+        * trust relationship can not be retrieved, {@code null} is returned.
+        *
+        * @see Identity#getTrust(OwnIdentity)
+        * @param origin
+        *            The origin of the trust tree
+        * @param target
+        *            The target of the trust
+        * @return The trust relationship
+        */
+       public Trust getTrust(Sone origin, Sone target) {
+               if (!isLocalSone(origin)) {
+                       logger.log(Level.WARNING, "Tried to get trust from remote Sone: %s", origin);
+                       return null;
+               }
+               return target.getIdentity().getTrust((OwnIdentity) origin.getIdentity());
+       }
+
+       /**
+        * Sets the trust value of the given origin Sone for the target Sone.
+        *
+        * @param origin
+        *            The origin Sone
+        * @param target
+        *            The target Sone
+        * @param trustValue
+        *            The trust value (from {@code -100} to {@code 100})
+        */
+       public void setTrust(Sone origin, Sone target, int trustValue) {
+               Validation.begin().isNotNull("Trust Origin", origin).check().isInstanceOf("Trust Origin", origin.getIdentity(), OwnIdentity.class).isNotNull("Trust Target", target).isLessOrEqual("Trust Value", trustValue, 100).isGreaterOrEqual("Trust Value", trustValue, -100).check();
+               try {
+                       ((OwnIdentity) origin.getIdentity()).setTrust(target.getIdentity(), trustValue, "Set from Sone Web Interface");
+               } catch (WebOfTrustException wote1) {
+                       logger.log(Level.WARNING, "Could not set trust for Sone: " + target, wote1);
+               }
+       }
+
+       /**
+        * Removes any trust assignment for the given target Sone.
+        *
+        * @param origin
+        *            The trust origin
+        * @param target
+        *            The trust target
+        */
+       public void removeTrust(Sone origin, Sone target) {
+               Validation.begin().isNotNull("Trust Origin", origin).isNotNull("Trust Target", target).check().isInstanceOf("Trust Origin Identity", origin.getIdentity(), OwnIdentity.class).check();
+               try {
+                       ((OwnIdentity) origin.getIdentity()).removeTrust(target.getIdentity());
+               } catch (WebOfTrustException wote1) {
+                       logger.log(Level.WARNING, "Could not remove trust for Sone: " + target, wote1);
+               }
+       }
+
+       /**
+        * Assigns the configured positive trust value for the given target.
+        *
+        * @param origin
+        *            The trust origin
+        * @param target
+        *            The trust target
+        */
+       public void trustSone(Sone origin, Sone target) {
+               setTrust(origin, target, options.getIntegerOption("PositiveTrust").get());
+       }
+
+       /**
+        * Assigns the configured negative trust value for the given target.
+        *
+        * @param origin
+        *            The trust origin
+        * @param target
+        *            The trust target
+        */
+       public void distrustSone(Sone origin, Sone target) {
+               setTrust(origin, target, options.getIntegerOption("NegativeTrust").get());
+       }
+
+       /**
+        * Removes the trust assignment for the given target.
+        *
+        * @param origin
+        *            The trust origin
+        * @param target
+        *            The trust target
+        */
+       public void untrustSone(Sone origin, Sone target) {
+               removeTrust(origin, target);
+       }
+
+       /**
         * Updates the stores Sone with the given Sone.
         *
         * @param sone
@@ -1143,7 +1243,7 @@ public class Core implements IdentityListener {
         * @param sone
         *            The Sone to save
         */
-       public void saveSone(Sone sone) {
+       public synchronized void saveSone(Sone sone) {
                if (!isLocalSone(sone)) {
                        logger.log(Level.FINE, "Tried to save non-local Sone: %s", sone);
                        return;
@@ -1214,6 +1314,7 @@ public class Core implements IdentityListener {
                        }
                        configuration.getStringValue(sonePrefix + "/Friends/" + friendCounter + "/ID").setValue(null);
 
+                       configuration.save();
                        logger.log(Level.INFO, "Sone %s saved.", sone);
                } catch (ConfigurationException ce1) {
                        logger.log(Level.WARNING, "Could not save Sone: " + sone, ce1);
@@ -1330,6 +1431,7 @@ public class Core implements IdentityListener {
                        if (newPosts.remove(post.getId())) {
                                knownPosts.add(post.getId());
                                coreListenerManager.fireMarkPostKnown(post);
+                               saveConfiguration();
                        }
                }
        }
@@ -1410,6 +1512,7 @@ public class Core implements IdentityListener {
                        if (newReplies.remove(reply.getId())) {
                                knownReplies.add(reply.getId());
                                coreListenerManager.fireMarkReplyKnown(reply);
+                               saveConfiguration();
                        }
                }
        }
@@ -1430,6 +1533,7 @@ public class Core implements IdentityListener {
                                soneInserter.stop();
                        }
                }
+               soneDownloader.stop();
                saveConfiguration();
                stopped = true;
        }
@@ -1438,9 +1542,19 @@ public class Core implements IdentityListener {
         * Saves the current options.
         */
        public void saveConfiguration() {
+               synchronized (configuration) {
+                       if (storingConfiguration) {
+                               logger.log(Level.FINE, "Already storing configuration…");
+                               return;
+                       }
+                       storingConfiguration = true;
+               }
+
                /* store the options first. */
                try {
                        configuration.getIntValue("Option/InsertionDelay").setValue(options.getIntegerOption("InsertionDelay").getReal());
+                       configuration.getIntValue("Option/PositiveTrust").setValue(options.getIntegerOption("PositiveTrust").getReal());
+                       configuration.getIntValue("Option/NegativeTrust").setValue(options.getIntegerOption("NegativeTrust").getReal());
                        configuration.getBooleanValue("Option/SoneRescueMode").setValue(options.getBooleanOption("SoneRescueMode").getReal());
                        configuration.getBooleanValue("Option/ClearOnNextRestart").setValue(options.getBooleanOption("ClearOnNextRestart").getReal());
                        configuration.getBooleanValue("Option/ReallyClearOnNextRestart").setValue(options.getBooleanOption("ReallyClearOnNextRestart").getReal());
@@ -1477,6 +1591,10 @@ public class Core implements IdentityListener {
 
                } catch (ConfigurationException ce1) {
                        logger.log(Level.SEVERE, "Could not store configuration!", ce1);
+               } finally {
+                       synchronized (configuration) {
+                               storingConfiguration = false;
+                       }
                }
        }
 
@@ -1498,6 +1616,8 @@ public class Core implements IdentityListener {
                        }
 
                }));
+               options.addIntegerOption("PositiveTrust", new DefaultOption<Integer>(75));
+               options.addIntegerOption("NegativeTrust", new DefaultOption<Integer>(-100));
                options.addBooleanOption("SoneRescueMode", new DefaultOption<Boolean>(false));
                options.addBooleanOption("ClearOnNextRestart", new DefaultOption<Boolean>(false));
                options.addBooleanOption("ReallyClearOnNextRestart", new DefaultOption<Boolean>(false));
@@ -1514,6 +1634,8 @@ public class Core implements IdentityListener {
                }
 
                options.getIntegerOption("InsertionDelay").set(configuration.getIntValue("Option/InsertionDelay").getValue(null));
+               options.getIntegerOption("PositiveTrust").set(configuration.getIntValue("Option/PositiveTrust").getValue(null));
+               options.getIntegerOption("NegativeTrust").set(configuration.getIntValue("Option/NegativeTrust").getValue(null));
                options.getBooleanOption("SoneRescueMode").set(configuration.getBooleanValue("Option/SoneRescueMode").getValue(null));
 
                /* load known Sones. */
@@ -1617,6 +1739,7 @@ public class Core implements IdentityListener {
                        @SuppressWarnings("synthetic-access")
                        public void run() {
                                Sone sone = getRemoteSone(identity.getId());
+                               sone.setIdentity(identity);
                                soneDownloader.fetchSone(sone);
                        }
                }).start();