Avoid retaining multiple copies of elements.
[Sone.git] / src / main / java / net / pterodactylus / sone / core / Core.java
index 5e98c47..d7b998e 100644 (file)
@@ -87,9 +87,13 @@ import net.pterodactylus.util.number.Numbers;
 import net.pterodactylus.util.service.AbstractService;
 import net.pterodactylus.util.thread.NamedThreadFactory;
 
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.Collections2;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Ordering;
 import com.google.common.eventbus.EventBus;
 import com.google.common.eventbus.Subscribe;
 import com.google.inject.Inject;
@@ -537,9 +541,9 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         * {@inheritDoc}
         */
        @Override
-       public Post getPost(String postId) {
+       public Optional<Post> getPost(String postId) {
                synchronized (posts) {
-                       return posts.get(postId);
+                       return Optional.fromNullable(posts.get(postId));
                }
        }
 
@@ -577,9 +581,9 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         * {@inheritDoc}
         */
        @Override
-       public PostReply getPostReply(String replyId) {
+       public Optional<PostReply> getPostReply(String replyId) {
                synchronized (replies) {
-                       return replies.get(replyId);
+                       return Optional.fromNullable(replies.get(replyId));
                }
        }
 
@@ -587,18 +591,20 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         * {@inheritDoc}
         */
        @Override
-       public List<PostReply> getReplies(Post post) {
-               Set<Sone> sones = getSones();
-               List<PostReply> replies = new ArrayList<PostReply>();
-               for (Sone sone : sones) {
-                       for (PostReply reply : sone.getReplies()) {
-                               if (reply.getPost().equals(post)) {
-                                       replies.add(reply);
-                               }
+       public List<PostReply> getReplies(final Post post) {
+               return Ordering.from(Reply.TIME_COMPARATOR).sortedCopy(FluentIterable.from(getSones()).transformAndConcat(new Function<Sone, Iterable<PostReply>>() {
+
+                       @Override
+                       public Iterable<PostReply> apply(Sone sone) {
+                               return sone.getReplies();
                        }
-               }
-               Collections.sort(replies, Reply.TIME_COMPARATOR);
-               return replies;
+               }).filter(new Predicate<PostReply>() {
+
+                       @Override
+                       public boolean apply(PostReply reply) {
+                               return post.getId().equals(reply.getPostId());
+                       }
+               }));
        }
 
        /**
@@ -670,9 +676,9 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                Set<Post> posts = new HashSet<Post>();
                synchronized (bookmarkedPosts) {
                        for (String bookmarkedPostId : bookmarkedPosts) {
-                               Post post = getPost(bookmarkedPostId);
-                               if (post != null) {
-                                       posts.add(post);
+                               Optional<Post> post = getPost(bookmarkedPostId);
+                               if (!post.isPresent()) {
+                                       posts.add(post.get());
                                }
                        }
                }
@@ -1103,18 +1109,16 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                                List<Post> storedPosts = storedSone.getPosts();
                                synchronized (knownPosts) {
                                        for (Post post : sone.getPosts()) {
-                                               PostBuilder postBuilder = postBuilderFactory.newPostBuilder();
-                                               postBuilder.copyPost(post).from(storedSone);
-                                               Post newPost = postBuilder.build().setKnown(knownPosts.contains(post.getId()));
-                                               if (!storedPosts.contains(newPost)) {
-                                                       if (newPost.getTime() < getSoneFollowingTime(sone)) {
-                                                               knownPosts.add(newPost.getId());
-                                                               newPost.setKnown(true);
-                                                       } else if (!knownPosts.contains(newPost.getId())) {
-                                                               eventBus.post(new NewPostFoundEvent(newPost));
+                                               post.setKnown(knownPosts.contains(post.getId()));
+                                               if (!storedPosts.contains(post)) {
+                                                       if (post.getTime() < getSoneFollowingTime(sone)) {
+                                                               knownPosts.add(post.getId());
+                                                               post.setKnown(true);
+                                                       } else if (!knownPosts.contains(post.getId())) {
+                                                               eventBus.post(new NewPostFoundEvent(post));
                                                        }
                                                }
-                                               posts.put(newPost.getId(), newPost);
+                                               posts.put(post.getId(), post);
                                        }
                                }
                        }
@@ -1130,7 +1134,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                                Set<PostReply> storedReplies = storedSone.getReplies();
                                synchronized (knownReplies) {
                                        for (PostReply reply : sone.getReplies()) {
-                                               reply.setSone(storedSone).setKnown(knownReplies.contains(reply.getId()));
+                                               reply.setKnown(knownReplies.contains(reply.getId()));
                                                if (!storedReplies.contains(reply)) {
                                                        if (reply.getTime() < getSoneFollowingTime(sone)) {
                                                                knownReplies.add(reply.getId());
@@ -1159,36 +1163,8 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                                        }
                                }
                        }
-                       synchronized (storedSone) {
-                               if (!soneRescueMode || (sone.getTime() > storedSone.getTime())) {
-                                       storedSone.setTime(sone.getTime());
-                               }
-                               storedSone.setClient(sone.getClient());
-                               storedSone.setProfile(sone.getProfile());
-                               if (soneRescueMode) {
-                                       for (Post post : sone.getPosts()) {
-                                               storedSone.addPost(post);
-                                       }
-                                       for (PostReply reply : sone.getReplies()) {
-                                               storedSone.addReply(reply);
-                                       }
-                                       for (String likedPostId : sone.getLikedPostIds()) {
-                                               storedSone.addLikedPostId(likedPostId);
-                                       }
-                                       for (String likedReplyId : sone.getLikedReplyIds()) {
-                                               storedSone.addLikedReplyId(likedReplyId);
-                                       }
-                                       for (Album album : sone.getAlbums()) {
-                                               storedSone.addAlbum(album);
-                                       }
-                               } else {
-                                       storedSone.setPosts(sone.getPosts());
-                                       storedSone.setReplies(sone.getReplies());
-                                       storedSone.setLikePostIds(sone.getLikedPostIds());
-                                       storedSone.setLikeReplyIds(sone.getLikedReplyIds());
-                                       storedSone.setAlbums(sone.getAlbums());
-                               }
-                               storedSone.setLatestEdition(sone.getLatestEdition());
+                       synchronized (sones) {
+                               sones.put(sone.getId(), sone);
                        }
                }
        }
@@ -1307,9 +1283,9 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                                logger.log(Level.WARNING, "Invalid post found, aborting load!");
                                return;
                        }
-                       PostBuilder postBuilder = postBuilderFactory.newPostBuilder().withId(postId).from(sone).withTime(postTime).withText(postText);
+                       PostBuilder postBuilder = postBuilder().withId(postId).from(sone.getId()).withTime(postTime).withText(postText);
                        if ((postRecipientId != null) && (postRecipientId.length() == 43)) {
-                               postBuilder.to(getSone(postRecipientId));
+                               postBuilder.to(postRecipientId);
                        }
                        posts.add(postBuilder.build());
                }
@@ -1330,7 +1306,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                                return;
                        }
                        PostReplyBuilder postReplyBuilder = postReplyBuilderFactory.newPostReplyBuilder();
-                       postReplyBuilder.withId(replyId).from(sone).to(getPost(postId)).withTime(replyTime).withText(replyText);
+                       postReplyBuilder.withId(replyId).from(sone.getId()).to(postId).withTime(replyTime).withText(replyText);
                        replies.add(postReplyBuilder.build());
                }
 
@@ -1536,9 +1512,9 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                        return null;
                }
                PostBuilder postBuilder = postBuilderFactory.newPostBuilder();
-               postBuilder.from(sone).randomId().withTime(time).withText(text.trim());
+               postBuilder.from(sone.getId()).randomId().withTime(time).withText(text.trim());
                if (recipient != null) {
-                       postBuilder.to(recipient);
+                       postBuilder.to(recipient.getId());
                }
                final Post post = postBuilder.build();
                synchronized (posts) {
@@ -1663,7 +1639,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                        return null;
                }
                PostReplyBuilder postReplyBuilder = postReplyBuilderFactory.newPostReplyBuilder();
-               postReplyBuilder.randomId().from(sone).to(post).currentTime().withText(text.trim());
+               postReplyBuilder.randomId().from(sone.getId()).to(post.getId()).currentTime().withText(text.trim());
                final PostReply reply = postReplyBuilder.build();
                synchronized (replies) {
                        replies.put(reply.getId(), reply);
@@ -1936,6 +1912,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                webOfTrustUpdater.stop();
                updateChecker.stop();
                soneDownloader.stop();
+               soneDownloaders.shutdown();
                identityManager.stop();
        }
 
@@ -2002,7 +1979,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                        for (PostReply reply : sone.getReplies()) {
                                String replyPrefix = sonePrefix + "/Replies/" + replyCounter++;
                                configuration.getStringValue(replyPrefix + "/ID").setValue(reply.getId());
-                               configuration.getStringValue(replyPrefix + "/Post/ID").setValue(reply.getPost().getId());
+                               configuration.getStringValue(replyPrefix + "/Post/ID").setValue(reply.getPostId());
                                configuration.getLongValue(replyPrefix + "/Time").setValue(reply.getTime());
                                configuration.getStringValue(replyPrefix + "/Text").setValue(reply.getText());
                        }
@@ -2304,23 +2281,6 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
        }
 
        /**
-        * Generate a Sone URI from the given URI and latest edition.
-        *
-        * @param uriString
-        *            The URI to derive the Sone URI from
-        * @return The derived URI
-        */
-       private static FreenetURI getSoneUri(String uriString) {
-               try {
-                       FreenetURI uri = new FreenetURI(uriString).setDocName("Sone").setMetaString(new String[0]);
-                       return uri;
-               } catch (MalformedURLException mue1) {
-                       logger.log(Level.WARNING, String.format("Could not create Sone URI from URI: %s", uriString), mue1);
-                       return null;
-               }
-       }
-
-       /**
         * Notifies the core that a new {@link OwnIdentity} was added.
         *
         * @param ownIdentityAddedEvent