Use database methods where possible.
[Sone.git] / src / main / java / net / pterodactylus / sone / core / Core.java
index 9a5d983..d60bbda 100644 (file)
@@ -25,6 +25,7 @@ import static com.google.common.primitives.Longs.tryParse;
 import static java.lang.String.format;
 import static java.util.logging.Level.WARNING;
 import static net.pterodactylus.sone.data.Sone.LOCAL_SONE_FILTER;
+import static net.pterodactylus.sone.data.Sone.toAllAlbums;
 
 import java.net.MalformedURLException;
 import java.util.ArrayList;
@@ -48,6 +49,8 @@ import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidParentAlbumFou
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostFound;
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostReplyFound;
 import net.pterodactylus.sone.core.Options.DefaultOption;
+import net.pterodactylus.sone.core.SoneChangeDetector.PostProcessor;
+import net.pterodactylus.sone.core.SoneChangeDetector.PostReplyProcessor;
 import net.pterodactylus.sone.core.SoneInserter.SetInsertionDelay;
 import net.pterodactylus.sone.core.event.ImageInsertFinishedEvent;
 import net.pterodactylus.sone.core.event.MarkPostKnownEvent;
@@ -77,6 +80,7 @@ import net.pterodactylus.sone.data.TemporaryImage;
 import net.pterodactylus.sone.database.AlbumBuilder;
 import net.pterodactylus.sone.database.Database;
 import net.pterodactylus.sone.database.DatabaseException;
+import net.pterodactylus.sone.database.ImageBuilder;
 import net.pterodactylus.sone.database.PostBuilder;
 import net.pterodactylus.sone.database.PostProvider;
 import net.pterodactylus.sone.database.PostReplyBuilder;
@@ -342,9 +346,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         */
        @Override
        public Collection<Sone> getSones() {
-               synchronized (sones) {
-                       return ImmutableSet.copyOf(sones.values());
-               }
+               return database.getSones();
        }
 
        /**
@@ -358,9 +360,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         */
        @Override
        public Optional<Sone> getSone(String id) {
-               synchronized (sones) {
-                       return Optional.fromNullable(sones.get(id));
-               }
+               return database.getSone(id);
        }
 
        /**
@@ -368,9 +368,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         */
        @Override
        public Collection<Sone> getLocalSones() {
-               synchronized (sones) {
-                       return FluentIterable.from(sones.values()).filter(LOCAL_SONE_FILTER).toSet();
-               }
+               return database.getLocalSones();
        }
 
        /**
@@ -403,9 +401,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         */
        @Override
        public Collection<Sone> getRemoteSones() {
-               synchronized (sones) {
-                       return FluentIterable.from(sones.values()).filter(not(LOCAL_SONE_FILTER)).toSet();
-               }
+               return database.getRemoteSones();
        }
 
        /**
@@ -609,6 +605,10 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                return database.getAlbum(albumId).orNull();
        }
 
+       public ImageBuilder imageBuilder() {
+               return database.newImageBuilder();
+       }
+
        /**
         * Returns the image with the given ID, creating it if necessary.
         *
@@ -760,8 +760,8 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                        logger.log(Level.WARNING, "Given Identity is null!");
                        return null;
                }
-               final Long latestEdition = fromNullable(tryParse(
-                               identity.getProperty("Sone.LatestEdition"))).or(0L);
+               final Long latestEdition = tryParse(fromNullable(
+                               identity.getProperty("Sone.LatestEdition")).or("0"));
                synchronized (sones) {
                        final Sone sone = getRemoteSone(identity.getId(), true);
                        if (sone.isLocal()) {
@@ -940,7 +940,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         *            {@code true} if the stored Sone should be updated regardless
         *            of the age of the given Sone
         */
-       public void updateSone(Sone sone, boolean soneRescueMode) {
+       public void updateSone(final Sone sone, boolean soneRescueMode) {
                Optional<Sone> storedSone = getSone(sone.getId());
                if (storedSone.isPresent()) {
                        if (!soneRescueMode && !(sone.getTime() > storedSone.get().getTime())) {
@@ -948,72 +948,41 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                                return;
                        }
                        /* find removed posts. */
-                       Collection<Post> removedPosts = new ArrayList<Post>();
-                       Collection<Post> newPosts = new ArrayList<Post>();
-                       Collection<Post> existingPosts = database.getPosts(sone.getId());
-                       for (Post oldPost : existingPosts) {
-                               if (!sone.getPosts().contains(oldPost)) {
-                                       removedPosts.add(oldPost);
-                               }
-                       }
-                       /* find new posts. */
-                       for (Post newPost : sone.getPosts()) {
-                               if (existingPosts.contains(newPost)) {
-                                       continue;
-                               }
-                               if (newPost.getTime() < getSoneFollowingTime(sone)) {
-                                       newPost.setKnown(true);
-                               } else if (!newPost.isKnown()) {
-                                       newPosts.add(newPost);
-                               }
-                       }
-                       /* store posts. */
-                       database.storePosts(sone, sone.getPosts());
-                       Collection<PostReply> newPostReplies = new ArrayList<PostReply>();
-                       Collection<PostReply> removedPostReplies = new ArrayList<PostReply>();
-                       if (!soneRescueMode) {
-                               for (PostReply reply : storedSone.get().getReplies()) {
-                                       if (!sone.getReplies().contains(reply)) {
-                                               removedPostReplies.add(reply);
+                       SoneChangeDetector soneChangeDetector = new SoneChangeDetector(storedSone.get());
+                       soneChangeDetector.onNewPosts(new PostProcessor() {
+                               @Override
+                               public void processPost(Post post) {
+                                       if (post.getTime() < getSoneFollowingTime(sone)) {
+                                               post.setKnown(true);
+                                       } else if (!post.isKnown()) {
+                                               eventBus.post(new NewPostFoundEvent(post));
                                        }
                                }
-                       }
-                       Set<PostReply> storedReplies = storedSone.get().getReplies();
-                       for (PostReply reply : sone.getReplies()) {
-                               if (storedReplies.contains(reply)) {
-                                       continue;
-                               }
-                               if (reply.getTime() < getSoneFollowingTime(sone)) {
-                                       reply.setKnown(true);
-                               } else if (!reply.isKnown()) {
-                                       newPostReplies.add(reply);
+                       });
+                       soneChangeDetector.onRemovedPosts(new PostProcessor() {
+                               @Override
+                               public void processPost(Post post) {
+                                       eventBus.post(new PostRemovedEvent(post));
                                }
-                       }
-                       database.storePostReplies(sone, sone.getReplies());
-                       for (Album album : storedSone.get().getRootAlbum().getAlbums()) {
-                               database.removeAlbum(album);
-                               for (Image image : album.getImages()) {
-                                       database.removeImage(image);
+                       });
+                       soneChangeDetector.onNewPostReplies(new PostReplyProcessor() {
+                               @Override
+                               public void processPostReply(PostReply postReply) {
+                                       if (postReply.getTime() < getSoneFollowingTime(sone)) {
+                                               postReply.setKnown(true);
+                                       } else if (!postReply.isKnown()) {
+                                               eventBus.post(new NewPostReplyFoundEvent(postReply));
+                                       }
                                }
-                       }
-                       for (Post removedPost : removedPosts) {
-                               eventBus.post(new PostRemovedEvent(removedPost));
-                       }
-                       for (Post newPost : newPosts) {
-                               eventBus.post(new NewPostFoundEvent(newPost));
-                       }
-                       for (PostReply removedPostReply : removedPostReplies) {
-                               eventBus.post(new PostReplyRemovedEvent(removedPostReply));
-                       }
-                       for (PostReply newPostReply : newPostReplies) {
-                               eventBus.post(new NewPostReplyFoundEvent(newPostReply));
-                       }
-                       for (Album album : sone.getRootAlbum().getAlbums()) {
-                               database.storeAlbum(album);
-                               for (Image image : album.getImages()) {
-                                       database.storeImage(image);
+                       });
+                       soneChangeDetector.onRemovedPostReplies(new PostReplyProcessor() {
+                               @Override
+                               public void processPostReply(PostReply postReply) {
+                                       eventBus.post(new PostReplyRemovedEvent(postReply));
                                }
-                       }
+                       });
+                       soneChangeDetector.detectChanges(sone);
+                       database.storeSone(sone);
                        synchronized (sones) {
                                sone.setOptions(storedSone.get().getOptions());
                                sone.setKnown(storedSone.get().isKnown());
@@ -1162,7 +1131,9 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                /* load avatar. */
                String avatarId = configuration.getStringValue(sonePrefix + "/Profile/Avatar").getValue(null);
                if (avatarId != null) {
-                       profile.setAvatar(getImage(avatarId, false));
+                       final Map<String, Image> images =
+                                       configurationSoneParser.getImages();
+                       profile.setAvatar(images.get(avatarId));
                }
 
                /* load options. */
@@ -1191,6 +1162,12 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                                sone.getRootAlbum().addAlbum(album);
                        }
                        soneInserters.get(sone).setLastInsertFingerprint(lastInsertFingerprint);
+                       for (Album album : toAllAlbums.apply(sone)) {
+                               database.storeAlbum(album);
+                               for (Image image : album.getImages()) {
+                                       database.storeImage(image);
+                               }
+                       }
                }
                synchronized (knownSones) {
                        for (String friend : friends) {
@@ -1938,19 +1915,14 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                OwnIdentity ownIdentity = identityRemovedEvent.ownIdentity();
                Identity identity = identityRemovedEvent.identity();
                trustedIdentities.remove(ownIdentity, identity);
-               boolean foundIdentity = false;
                for (Entry<OwnIdentity, Collection<Identity>> trustedIdentity : trustedIdentities.asMap().entrySet()) {
                        if (trustedIdentity.getKey().equals(ownIdentity)) {
                                continue;
                        }
                        if (trustedIdentity.getValue().contains(identity)) {
-                               foundIdentity = true;
+                               return;
                        }
                }
-               if (foundIdentity) {
-                       /* some local identity still trusts this identity, don’t remove. */
-                       return;
-               }
                Optional<Sone> sone = getSone(identity.getId());
                if (!sone.isPresent()) {
                        /* TODO - we don’t have the Sone anymore. should this happen? */