Merge commit 'c30ad3a3fcfc66d0c1757a50afe413d9942d7793' into less-critical
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Fri, 25 Jan 2013 19:14:21 +0000 (20:14 +0100)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Fri, 25 Jan 2013 19:14:21 +0000 (20:14 +0100)
29 files changed:
src/main/java/net/pterodactylus/sone/core/Core.java
src/main/java/net/pterodactylus/sone/core/PostProvider.java
src/main/java/net/pterodactylus/sone/core/PostReplyProvider.java
src/main/java/net/pterodactylus/sone/data/PostReply.java
src/main/java/net/pterodactylus/sone/data/impl/DefaultPostBuilderFactory.java
src/main/java/net/pterodactylus/sone/data/impl/PostReplyImpl.java
src/main/java/net/pterodactylus/sone/fcp/AbstractSoneCommand.java
src/main/java/net/pterodactylus/sone/main/SonePlugin.java
src/main/java/net/pterodactylus/sone/notify/ListNotificationFilters.java
src/main/java/net/pterodactylus/sone/template/ReplyGroupFilter.java
src/main/java/net/pterodactylus/sone/text/SoneTextParser.java
src/main/java/net/pterodactylus/sone/web/CreateReplyPage.java
src/main/java/net/pterodactylus/sone/web/DeletePostPage.java
src/main/java/net/pterodactylus/sone/web/DeleteReplyPage.java
src/main/java/net/pterodactylus/sone/web/MarkAsKnownPage.java
src/main/java/net/pterodactylus/sone/web/NewPage.java
src/main/java/net/pterodactylus/sone/web/SearchPage.java
src/main/java/net/pterodactylus/sone/web/ViewPostPage.java
src/main/java/net/pterodactylus/sone/web/ViewSonePage.java
src/main/java/net/pterodactylus/sone/web/WebInterface.java
src/main/java/net/pterodactylus/sone/web/ajax/CreateReplyAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/DeletePostAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/DeleteReplyAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/GetLikesAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/GetPostAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/GetReplyAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/GetStatusAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/GetTimesAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/MarkAsKnownAjaxPage.java

index 862cc78..15ce975 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());
                                }
                        }
                }
@@ -1069,18 +1075,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.getId());
-                                               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);
                                        }
                                }
                        }
@@ -1125,36 +1129,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);
                        }
                }
        }
@@ -1273,7 +1249,7 @@ 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.getId()).withTime(postTime).withText(postText);
+                       PostBuilder postBuilder = postBuilder().withId(postId).from(sone.getId()).withTime(postTime).withText(postText);
                        if ((postRecipientId != null) && (postRecipientId.length() == 43)) {
                                postBuilder.to(postRecipientId);
                        }
@@ -1902,6 +1878,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                webOfTrustUpdater.stop();
                updateChecker.stop();
                soneDownloader.stop();
+               soneDownloaders.shutdown();
                identityManager.stop();
        }
 
@@ -1968,7 +1945,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());
                        }
index e7167cd..19a0e5d 100644 (file)
@@ -19,6 +19,8 @@ package net.pterodactylus.sone.core;
 
 import net.pterodactylus.sone.data.Post;
 
+import com.google.common.base.Optional;
+
 /**
  * Interface for objects that can provide {@link Post}s by their ID.
  *
@@ -33,6 +35,6 @@ public interface PostProvider {
         *            The ID of the post to return
         * @return The post with the given ID, or {@code null}
         */
-       public Post getPost(String postId);
+       public Optional<Post> getPost(String postId);
 
 }
index 9854b6c..5decdc7 100644 (file)
@@ -22,6 +22,8 @@ import java.util.List;
 import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.data.PostReply;
 
+import com.google.common.base.Optional;
+
 /**
  * Interface for objects that can provide {@link PostReply}s.
  *
@@ -36,7 +38,7 @@ public interface PostReplyProvider {
         *            The ID of the reply to get
         * @return The reply, or {@code null} if there is no such reply
         */
-       public PostReply getPostReply(String id);
+       public Optional<PostReply> getPostReply(String id);
 
        /**
         * Returns all replies for the given post, order ascending by time.
index 3dd0a14..1e870b9 100644 (file)
@@ -17,6 +17,9 @@
 
 package net.pterodactylus.sone.data;
 
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+
 /**
  * A reply is like a {@link Post} but can never be posted on its own, it always
  * refers to another {@link Post}.
@@ -26,10 +29,29 @@ package net.pterodactylus.sone.data;
 public interface PostReply extends Reply<PostReply> {
 
        /**
+        * Filter that selects {@link PostReply}s that have a
+        * {@link Optional#isPresent() present} {@link #getPost() post}.
+        */
+       public static final Predicate<PostReply> HAS_POST_FILTER = new Predicate<PostReply>() {
+
+               @Override
+               public boolean apply(PostReply postReply) {
+                       return postReply.getPost().isPresent();
+               }
+       };
+
+       /**
+        * Returns the ID of the post this reply refers to.
+        *
+        * @return The ID of the post this reply refers to
+        */
+       public String getPostId();
+
+       /**
         * Returns the post this reply refers to.
         *
         * @return The post this reply refers to
         */
-       public Post getPost();
+       public Optional<Post> getPost();
 
 }
index 25f6a86..cf32640 100644 (file)
@@ -17,6 +17,8 @@
 
 package net.pterodactylus.sone.data.impl;
 
+import com.google.inject.Inject;
+
 import net.pterodactylus.sone.core.SoneProvider;
 import net.pterodactylus.sone.data.PostBuilder;
 import net.pterodactylus.sone.data.PostBuilderFactory;
@@ -38,6 +40,7 @@ public class DefaultPostBuilderFactory implements PostBuilderFactory {
         * @param soneProvider
         *            The Sone provider
         */
+       @Inject
        public DefaultPostBuilderFactory(SoneProvider soneProvider) {
                this.soneProvider = soneProvider;
        }
index 97c84e4..065ce2f 100644 (file)
@@ -22,6 +22,8 @@ import net.pterodactylus.sone.core.SoneProvider;
 import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.data.PostReply;
 
+import com.google.common.base.Optional;
+
 /**
  * Simple {@link PostReply} implementation.
  *
@@ -64,10 +66,18 @@ public class PostReplyImpl extends ReplyImpl<PostReply> implements PostReply {
        //
 
        /**
+        * {@inheritDocs}
+        */
+       @Override
+       public String getPostId() {
+               return postId;
+       }
+
+       /**
         * {@inheritDoc}
         */
        @Override
-       public Post getPost() {
+       public Optional<Post> getPost() {
                return postProvider.getPost(postId);
        }
 
index 80802ad..368f49a 100644 (file)
@@ -33,6 +33,7 @@ import net.pterodactylus.sone.freenet.fcp.Command;
 import net.pterodactylus.sone.freenet.fcp.FcpException;
 import net.pterodactylus.sone.template.SoneAccessor;
 
+import com.google.common.base.Optional;
 import com.google.common.collect.Collections2;
 
 import freenet.node.FSParseException;
@@ -185,11 +186,11 @@ public abstract class AbstractSoneCommand extends AbstractCommand {
        protected Post getPost(SimpleFieldSet simpleFieldSet, String parameterName) throws FcpException {
                try {
                        String postId = simpleFieldSet.getString(parameterName);
-                       Post post = core.getPost(postId);
-                       if (post == null) {
+                       Optional<Post> post = core.getPost(postId);
+                       if (!post.isPresent()) {
                                throw new FcpException("Could not load post from “" + postId + "”.");
                        }
-                       return post;
+                       return post.get();
                } catch (FSParseException fspe1) {
                        throw new FcpException("Could not post ID from “" + parameterName + "”.", fspe1);
                }
@@ -211,11 +212,11 @@ public abstract class AbstractSoneCommand extends AbstractCommand {
        protected PostReply getReply(SimpleFieldSet simpleFieldSet, String parameterName) throws FcpException {
                try {
                        String replyId = simpleFieldSet.getString(parameterName);
-                       PostReply reply = core.getPostReply(replyId);
-                       if (reply == null) {
+                       Optional<PostReply> reply = core.getPostReply(replyId);
+                       if (!reply.isPresent()) {
                                throw new FcpException("Could not load reply from “" + replyId + "”.");
                        }
-                       return reply;
+                       return reply.get();
                } catch (FSParseException fspe1) {
                        throw new FcpException("Could not reply ID from “" + parameterName + "”.", fspe1);
                }
index 04b0de4..4b0f3eb 100644 (file)
@@ -213,6 +213,7 @@ public class SonePlugin implements FredPlugin, FredPluginFCP, FredPluginL10n, Fr
 
                        @Override
                        protected void configure() {
+                               bind(Core.class).in(Singleton.class);
                                bind(EventBus.class).toInstance(eventBus);
                                bind(Configuration.class).toInstance(startConfiguration);
                                bind(FreenetInterface.class).in(Singleton.class);
index 1881a1b..dbf09a3 100644 (file)
@@ -31,6 +31,8 @@ import net.pterodactylus.sone.freenet.wot.OwnIdentity;
 import net.pterodactylus.sone.freenet.wot.Trust;
 import net.pterodactylus.util.notify.Notification;
 
+import com.google.common.base.Optional;
+
 /**
  * Filter for {@link ListNotification}s.
  *
@@ -282,11 +284,11 @@ public class ListNotificationFilters {
         */
        public static boolean isReplyVisible(Sone sone, PostReply reply) {
                checkNotNull(reply, "reply must not be null");
-               Post post = reply.getPost();
-               if (post == null) {
+               Optional<Post> post = reply.getPost();
+               if (!post.isPresent()) {
                        return false;
                }
-               if (!isPostVisible(sone, post)) {
+               if (!isPostVisible(sone, post.get())) {
                        return false;
                }
                if (reply.getTime() > System.currentTimeMillis()) {
index 4806cee..bcf73d8 100644 (file)
@@ -29,6 +29,8 @@ import net.pterodactylus.sone.data.Sone;
 import net.pterodactylus.util.template.Filter;
 import net.pterodactylus.util.template.TemplateContext;
 
+import com.google.common.base.Optional;
+
 /**
  * {@link Filter} implementation that groups replies by the post the are in
  * reply to, returning a map with the post as key and the list of replies as
@@ -48,17 +50,21 @@ public class ReplyGroupFilter implements Filter {
                Map<Post, Set<Sone>> postSones = new HashMap<Post, Set<Sone>>();
                Map<Post, Set<PostReply>> postReplies = new HashMap<Post, Set<PostReply>>();
                for (PostReply reply : allReplies) {
-                       Post post = reply.getPost();
-                       Set<Sone> sones = postSones.get(post);
+                       /*
+                        * All replies from a new-reply notification have posts,
+                        * ListNotificationFilters takes care of that.
+                        */
+                       Optional<Post> post = reply.getPost();
+                       Set<Sone> sones = postSones.get(post.get());
                        if (sones == null) {
                                sones = new HashSet<Sone>();
-                               postSones.put(post, sones);
+                               postSones.put(post.get(), sones);
                        }
                        sones.add(reply.getSone());
-                       Set<PostReply> replies = postReplies.get(post);
+                       Set<PostReply> replies = postReplies.get(post.get());
                        if (replies == null) {
                                replies = new HashSet<PostReply>();
-                               postReplies.put(post, replies);
+                               postReplies.put(post.get(), replies);
                        }
                        replies.add(reply);
                }
index a093e46..6e84c70 100644 (file)
@@ -26,6 +26,8 @@ import java.util.logging.Logger;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import com.google.common.base.Optional;
+
 import net.pterodactylus.sone.core.PostProvider;
 import net.pterodactylus.sone.core.SoneProvider;
 import net.pterodactylus.sone.data.Post;
@@ -258,9 +260,9 @@ public class SoneTextParser implements Parser<SoneTextParserContext> {
                                        if (linkType == LinkType.POST) {
                                                if (line.length() >= (7 + 36)) {
                                                        String postId = line.substring(7, 43);
-                                                       Post post = postProvider.getPost(postId);
-                                                       if ((post != null) && (post.getSone() != null)) {
-                                                               parts.add(new PostPart(post));
+                                                       Optional<Post> post = postProvider.getPost(postId);
+                                                       if (post.isPresent()) {
+                                                               parts.add(new PostPart(post.get()));
                                                        } else {
                                                                parts.add(new PlainTextPart(line.substring(0, 43)));
                                                        }
index e6a5735..c8979c1 100644 (file)
@@ -17,6 +17,8 @@
 
 package net.pterodactylus.sone.web;
 
+import com.google.common.base.Optional;
+
 import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.data.Sone;
 import net.pterodactylus.sone.text.TextFilter;
@@ -58,7 +60,10 @@ public class CreateReplyPage extends SoneTemplatePage {
                String text = request.getHttpRequest().getPartAsStringFailsafe("text", 65536).trim();
                String returnPage = request.getHttpRequest().getPartAsStringFailsafe("returnPage", 256);
                if (request.getMethod() == Method.POST) {
-                       Post post = webInterface.getCore().getPost(postId);
+                       Optional<Post> post = webInterface.getCore().getPost(postId);
+                       if (!post.isPresent()) {
+                               throw new RedirectException("noPermission.html");
+                       }
                        if (text.length() > 0) {
                                String senderId = request.getHttpRequest().getPartAsStringFailsafe("sender", 43);
                                Sone sender = webInterface.getCore().getLocalSone(senderId, false);
@@ -66,7 +71,7 @@ public class CreateReplyPage extends SoneTemplatePage {
                                        sender = getCurrentSone(request.getToadletContext());
                                }
                                text = TextFilter.filter(request.getHttpRequest().getHeader("host"), text);
-                               webInterface.getCore().createReply(sender, post, text);
+                               webInterface.getCore().createReply(sender, post.get(), text);
                                throw new RedirectException(returnPage);
                        }
                        templateContext.set("errorTextEmpty", true);
index 1363ac9..6ef86f0 100644 (file)
@@ -17,6 +17,8 @@
 
 package net.pterodactylus.sone.web;
 
+import com.google.common.base.Optional;
+
 import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.web.page.FreenetRequest;
 import net.pterodactylus.util.template.Template;
@@ -55,19 +57,22 @@ public class DeletePostPage extends SoneTemplatePage {
                if (request.getMethod() == Method.GET) {
                        String postId = request.getHttpRequest().getParam("post");
                        String returnPage = request.getHttpRequest().getParam("returnPage");
-                       Post post = webInterface.getCore().getPost(postId);
-                       templateContext.set("post", post);
+                       Optional<Post> post = webInterface.getCore().getPost(postId);
+                       if (!post.isPresent()) {
+                               throw new RedirectException("noPermission.html");
+                       }
+                       templateContext.set("post", post.get());
                        templateContext.set("returnPage", returnPage);
                        return;
                } else if (request.getMethod() == Method.POST) {
                        String postId = request.getHttpRequest().getPartAsStringFailsafe("post", 36);
                        String returnPage = request.getHttpRequest().getPartAsStringFailsafe("returnPage", 256);
-                       Post post = webInterface.getCore().getPost(postId);
-                       if (!post.getSone().isLocal()) {
+                       Optional<Post> post = webInterface.getCore().getPost(postId);
+                       if (!post.isPresent() || !post.get().getSone().isLocal()) {
                                throw new RedirectException("noPermission.html");
                        }
                        if (request.getHttpRequest().isPartSet("confirmDelete")) {
-                               webInterface.getCore().deletePost(post);
+                               webInterface.getCore().deletePost(post.get());
                                throw new RedirectException(returnPage);
                        } else if (request.getHttpRequest().isPartSet("abortDelete")) {
                                throw new RedirectException(returnPage);
index 25a9e0b..f7ca132 100644 (file)
@@ -23,6 +23,8 @@ import net.pterodactylus.util.template.Template;
 import net.pterodactylus.util.template.TemplateContext;
 import net.pterodactylus.util.web.Method;
 
+import com.google.common.base.Optional;
+
 /**
  * This page lets the user delete a reply.
  *
@@ -53,14 +55,14 @@ public class DeleteReplyPage extends SoneTemplatePage {
        protected void processTemplate(FreenetRequest request, TemplateContext templateContext) throws RedirectException {
                super.processTemplate(request, templateContext);
                String replyId = request.getHttpRequest().getPartAsStringFailsafe("reply", 36);
-               PostReply reply = webInterface.getCore().getPostReply(replyId);
+               Optional<PostReply> reply = webInterface.getCore().getPostReply(replyId);
                String returnPage = request.getHttpRequest().getPartAsStringFailsafe("returnPage", 256);
                if (request.getMethod() == Method.POST) {
-                       if (!reply.getSone().isLocal()) {
+                       if (!reply.get().getSone().isLocal()) {
                                throw new RedirectException("noPermission.html");
                        }
                        if (request.getHttpRequest().isPartSet("confirmDelete")) {
-                               webInterface.getCore().deleteReply(reply);
+                               webInterface.getCore().deleteReply(reply.get());
                                throw new RedirectException(returnPage);
                        } else if (request.getHttpRequest().isPartSet("abortDelete")) {
                                throw new RedirectException(returnPage);
index 0bf5285..f183ff4 100644 (file)
@@ -27,6 +27,8 @@ import net.pterodactylus.sone.web.page.FreenetRequest;
 import net.pterodactylus.util.template.Template;
 import net.pterodactylus.util.template.TemplateContext;
 
+import com.google.common.base.Optional;
+
 /**
  * Page that lets the user mark a number of {@link Sone}s, {@link Post}s, or
  * {@link Reply Replie}s as known.
@@ -65,17 +67,17 @@ public class MarkAsKnownPage extends SoneTemplatePage {
                for (StringTokenizer idTokenizer = new StringTokenizer(ids); idTokenizer.hasMoreTokens();) {
                        String id = idTokenizer.nextToken();
                        if (type.equals("post")) {
-                               Post post = webInterface.getCore().getPost(id);
-                               if (post == null) {
+                               Optional<Post> post = webInterface.getCore().getPost(id);
+                               if (!post.isPresent()) {
                                        continue;
                                }
-                               webInterface.getCore().markPostKnown(post);
+                               webInterface.getCore().markPostKnown(post.get());
                        } else if (type.equals("reply")) {
-                               PostReply reply = webInterface.getCore().getPostReply(id);
-                               if (reply == null) {
+                               Optional<PostReply> reply = webInterface.getCore().getPostReply(id);
+                               if (!reply.isPresent()) {
                                        continue;
                                }
-                               webInterface.getCore().markReplyKnown(reply);
+                               webInterface.getCore().markReplyKnown(reply.get());
                        } else if (type.equals("sone")) {
                                Sone sone = webInterface.getCore().getSone(id, false);
                                if (sone == null) {
index 2d4ec55..71200d8 100644 (file)
@@ -23,6 +23,8 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
+import com.google.common.collect.Collections2;
+
 import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.data.PostReply;
 import net.pterodactylus.sone.notify.ListNotificationFilters;
@@ -66,8 +68,8 @@ public class NewPage extends SoneTemplatePage {
 
                /* collect new elements from notifications. */
                Set<Post> posts = new HashSet<Post>(webInterface.getNewPosts());
-               for (PostReply reply : webInterface.getNewReplies()) {
-                       posts.add(reply.getPost());
+               for (PostReply reply : Collections2.filter(webInterface.getNewReplies(), PostReply.HAS_POST_FILTER)) {
+                       posts.add(reply.getPost().get());
                }
 
                /* filter and sort them. */
index 337918d..6cb2c0c 100644 (file)
@@ -44,6 +44,7 @@ import net.pterodactylus.util.text.StringEscaper;
 import net.pterodactylus.util.text.TextException;
 
 import com.google.common.base.Function;
+import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
@@ -336,7 +337,11 @@ public class SearchPage extends SoneTemplatePage {
         */
        private String getReplyPostId(String phrase) {
                String replyId = phrase.startsWith("reply://") ? phrase.substring(8) : phrase;
-               return (webInterface.getCore().getPostReply(replyId) != null) ? webInterface.getCore().getPostReply(replyId).getPost().getId() : null;
+               Optional<PostReply> postReply = webInterface.getCore().getPostReply(replyId);
+               if (!postReply.isPresent()) {
+                       return null;
+               }
+               return postReply.get().getPostId();
        }
 
        /**
index ca78d99..50719ee 100644 (file)
@@ -19,6 +19,8 @@ package net.pterodactylus.sone.web;
 
 import java.net.URI;
 
+import com.google.common.base.Optional;
+
 import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.template.SoneAccessor;
 import net.pterodactylus.sone.web.page.FreenetRequest;
@@ -54,11 +56,11 @@ public class ViewPostPage extends SoneTemplatePage {
        @Override
        protected String getPageTitle(FreenetRequest request) {
                String postId = request.getHttpRequest().getParam("post");
-               Post post = webInterface.getCore().getPost(postId);
+               Optional<Post> post = webInterface.getCore().getPost(postId);
                String title = "";
-               if ((post != null) && (post.getSone() != null)) {
-                       title = post.getText().substring(0, Math.min(20, post.getText().length())) + "…";
-                       title += " - " + SoneAccessor.getNiceName(post.getSone()) + " - ";
+               if (post.isPresent()) {
+                       title = post.get().getText().substring(0, Math.min(20, post.get().getText().length())) + "…";
+                       title += " - " + SoneAccessor.getNiceName(post.get().getSone()) + " - ";
                }
                title += webInterface.getL10n().getString("Page.ViewPost.Title");
                return title;
@@ -72,8 +74,8 @@ public class ViewPostPage extends SoneTemplatePage {
                super.processTemplate(request, templateContext);
                String postId = request.getHttpRequest().getParam("post");
                boolean raw = request.getHttpRequest().getParam("raw").equals("true");
-               Post post = webInterface.getCore().getPost(postId);
-               templateContext.set("post", post);
+               Optional<Post> post = webInterface.getCore().getPost(postId);
+               templateContext.set("post", post.get());
                templateContext.set("raw", raw);
        }
 
index dec4fe2..5572bca 100644 (file)
@@ -36,6 +36,8 @@ import net.pterodactylus.util.number.Numbers;
 import net.pterodactylus.util.template.Template;
 import net.pterodactylus.util.template.TemplateContext;
 
+import com.google.common.base.Optional;
+
 /**
  * Lets the user browser another Sone.
  *
@@ -95,11 +97,11 @@ public class ViewSonePage extends SoneTemplatePage {
                Set<PostReply> replies = sone.getReplies();
                final Map<Post, List<PostReply>> repliedPosts = new HashMap<Post, List<PostReply>>();
                for (PostReply reply : replies) {
-                       Post post = reply.getPost();
-                       if (repliedPosts.containsKey(post) || sone.equals(post.getSone()) || (sone.equals(post.getRecipient()))) {
+                       Optional<Post> post = reply.getPost();
+                       if (!post.isPresent() || repliedPosts.containsKey(post.get()) || sone.equals(post.get().getSone()) || (sone.equals(post.get().getRecipient()))) {
                                continue;
                        }
-                       repliedPosts.put(post, webInterface.getCore().getReplies(post));
+                       repliedPosts.put(post.get(), webInterface.getCore().getReplies(post.get()));
                }
                List<Post> posts = new ArrayList<Post>(repliedPosts.keySet());
                Collections.sort(posts, new Comparator<Post>() {
index 60cda15..3bb11d5 100644 (file)
@@ -857,8 +857,8 @@ public class WebInterface {
                }
                if (!hasFirstStartNotification()) {
                        notificationManager.addNotification(isLocal ? localReplyNotification : newReplyNotification);
-                       if (!getMentionedSones(reply.getText()).isEmpty() && !isLocal && (reply.getPost().getSone() != null) && (reply.getTime() <= System.currentTimeMillis())) {
-                               mentionNotification.add(reply.getPost());
+                       if (!getMentionedSones(reply.getText()).isEmpty() && !isLocal && reply.getPost().isPresent() && (reply.getTime() <= System.currentTimeMillis())) {
+                               mentionNotification.add(reply.getPost().get());
                                notificationManager.addNotification(mentionNotification);
                        }
                } else {
@@ -900,7 +900,7 @@ public class WebInterface {
        public void markReplyKnown(MarkPostReplyKnownEvent markPostReplyKnownEvent) {
                newReplyNotification.remove(markPostReplyKnownEvent.postReply());
                localReplyNotification.remove(markPostReplyKnownEvent.postReply());
-               mentionNotification.remove(markPostReplyKnownEvent.postReply().getPost());
+               mentionNotification.remove(markPostReplyKnownEvent.postReply().getPost().get());
        }
 
        /**
@@ -940,11 +940,11 @@ public class WebInterface {
                localReplyNotification.remove(reply);
                if (!getMentionedSones(reply.getText()).isEmpty()) {
                        boolean isMentioned = false;
-                       for (PostReply existingReply : getCore().getReplies(reply.getPost())) {
+                       for (PostReply existingReply : getCore().getReplies(reply.getPost().get())) {
                                isMentioned |= !reply.isKnown() && !getMentionedSones(existingReply.getText()).isEmpty();
                        }
                        if (!isMentioned) {
-                               mentionNotification.remove(reply.getPost());
+                               mentionNotification.remove(reply.getPost().get());
                        }
                }
        }
@@ -964,7 +964,6 @@ public class WebInterface {
                        @SuppressWarnings("synthetic-access")
                        public void run() {
                                lockedSonesNotification.add(sone);
-                               lockedSonesTickerObjects.remove(sone);
                                notificationManager.addNotification(lockedSonesNotification);
                        }
                }, 5, TimeUnit.MINUTES);
index 164ec19..8a35185 100644 (file)
@@ -17,6 +17,8 @@
 
 package net.pterodactylus.sone.web.ajax;
 
+import com.google.common.base.Optional;
+
 import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.data.PostReply;
 import net.pterodactylus.sone.data.Sone;
@@ -58,12 +60,12 @@ public class CreateReplyAjaxPage extends JsonPage {
                if (sender == null) {
                        sender = getCurrentSone(request.getToadletContext());
                }
-               Post post = webInterface.getCore().getPost(postId);
-               if ((post == null) || (post.getSone() == null)) {
+               Optional<Post> post = webInterface.getCore().getPost(postId);
+               if (!post.isPresent()) {
                        return createErrorJsonObject("invalid-post-id");
                }
                text = TextFilter.filter(request.getHttpRequest().getHeader("host"), text);
-               PostReply reply = webInterface.getCore().createReply(sender, post, text);
+               PostReply reply = webInterface.getCore().createReply(sender, post.get(), text);
                return createSuccessJsonObject().put("reply", reply.getId()).put("sone", sender.getId());
        }
 
index 3beb85d..71b0016 100644 (file)
@@ -17,6 +17,8 @@
 
 package net.pterodactylus.sone.web.ajax;
 
+import com.google.common.base.Optional;
+
 import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.web.WebInterface;
 import net.pterodactylus.sone.web.page.FreenetRequest;
@@ -49,14 +51,14 @@ public class DeletePostAjaxPage extends JsonPage {
        @Override
        protected JsonObject createJsonObject(FreenetRequest request) {
                String postId = request.getHttpRequest().getParam("post");
-               Post post = webInterface.getCore().getPost(postId);
-               if ((post == null) || (post.getSone() == null)) {
+               Optional<Post> post = webInterface.getCore().getPost(postId);
+               if (!post.isPresent()) {
                        return createErrorJsonObject("invalid-post-id");
                }
-               if (!post.getSone().isLocal()) {
+               if (!post.get().getSone().isLocal()) {
                        return createErrorJsonObject("not-authorized");
                }
-               webInterface.getCore().deletePost(post);
+               webInterface.getCore().deletePost(post.get());
                return createSuccessJsonObject();
        }
 
index b1a3317..2aa217d 100644 (file)
@@ -17,6 +17,8 @@
 
 package net.pterodactylus.sone.web.ajax;
 
+import com.google.common.base.Optional;
+
 import net.pterodactylus.sone.data.PostReply;
 import net.pterodactylus.sone.web.WebInterface;
 import net.pterodactylus.sone.web.page.FreenetRequest;
@@ -49,14 +51,14 @@ public class DeleteReplyAjaxPage extends JsonPage {
        @Override
        protected JsonObject createJsonObject(FreenetRequest request) {
                String replyId = request.getHttpRequest().getParam("reply");
-               PostReply reply = webInterface.getCore().getPostReply(replyId);
-               if (reply == null) {
+               Optional<PostReply> reply = webInterface.getCore().getPostReply(replyId);
+               if (!reply.isPresent()) {
                        return createErrorJsonObject("invalid-reply-id");
                }
-               if (!reply.getSone().isLocal()) {
+               if (!reply.get().getSone().isLocal()) {
                        return createErrorJsonObject("not-authorized");
                }
-               webInterface.getCore().deleteReply(reply);
+               webInterface.getCore().deleteReply(reply.get());
                return createSuccessJsonObject();
        }
 
index 04191fa..1a5286f 100644 (file)
@@ -31,6 +31,8 @@ import net.pterodactylus.sone.web.page.FreenetRequest;
 import net.pterodactylus.util.json.JsonArray;
 import net.pterodactylus.util.json.JsonObject;
 
+import com.google.common.base.Optional;
+
 /**
  * AJAX page that retrieves the number of “likes” a {@link Post} has.
  *
@@ -63,12 +65,18 @@ public class GetLikesAjaxPage extends JsonPage {
                        return createErrorJsonObject("invalid-" + type + "-id");
                }
                if ("post".equals(type)) {
-                       Post post = webInterface.getCore().getPost(id);
-                       Set<Sone> sones = webInterface.getCore().getLikes(post);
+                       Optional<Post> post = webInterface.getCore().getPost(id);
+                       if (!post.isPresent()) {
+                               return createErrorJsonObject("invalid-post-id");
+                       }
+                       Set<Sone> sones = webInterface.getCore().getLikes(post.get());
                        return createSuccessJsonObject().put("likes", sones.size()).put("sones", getSones(sones));
                } else if ("reply".equals(type)) {
-                       PostReply reply = webInterface.getCore().getPostReply(id);
-                       Set<Sone> sones = webInterface.getCore().getLikes(reply);
+                       Optional<PostReply> reply = webInterface.getCore().getPostReply(id);
+                       if (!reply.isPresent()) {
+                               return createErrorJsonObject("invalid-reply-id");
+                       }
+                       Set<Sone> sones = webInterface.getCore().getLikes(reply.get());
                        return createSuccessJsonObject().put("likes", sones.size()).put("sones", getSones(sones));
                }
                return createErrorJsonObject("invalid-type");
index 0c2311e..e32573d 100644 (file)
@@ -19,6 +19,8 @@ package net.pterodactylus.sone.web.ajax;
 
 import java.io.StringWriter;
 
+import com.google.common.base.Optional;
+
 import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.data.Sone;
 import net.pterodactylus.sone.web.WebInterface;
@@ -59,11 +61,11 @@ public class GetPostAjaxPage extends JsonPage {
        @Override
        protected JsonObject createJsonObject(FreenetRequest request) {
                String postId = request.getHttpRequest().getParam("post");
-               Post post = webInterface.getCore().getPost(postId);
-               if (post == null) {
+               Optional<Post> post = webInterface.getCore().getPost(postId);
+               if (!post.isPresent()) {
                        return createErrorJsonObject("invalid-post-id");
                }
-               return createSuccessJsonObject().put("post", createJsonPost(request, post, getCurrentSone(request.getToadletContext())));
+               return createSuccessJsonObject().put("post", createJsonPost(request, post.get(), getCurrentSone(request.getToadletContext())));
        }
 
        /**
index 6139776..b617608 100644 (file)
@@ -19,6 +19,8 @@ package net.pterodactylus.sone.web.ajax;
 
 import java.io.StringWriter;
 
+import com.google.common.base.Optional;
+
 import net.pterodactylus.sone.data.PostReply;
 import net.pterodactylus.sone.data.Sone;
 import net.pterodactylus.sone.web.WebInterface;
@@ -62,11 +64,11 @@ public class GetReplyAjaxPage extends JsonPage {
        @Override
        protected JsonObject createJsonObject(FreenetRequest request) {
                String replyId = request.getHttpRequest().getParam("reply");
-               PostReply reply = webInterface.getCore().getPostReply(replyId);
-               if ((reply == null) || (reply.getSone() == null)) {
+               Optional<PostReply> reply = webInterface.getCore().getPostReply(replyId);
+               if (!reply.isPresent()) {
                        return createErrorJsonObject("invalid-reply-id");
                }
-               return createSuccessJsonObject().put("reply", createJsonReply(request, reply, getCurrentSone(request.getToadletContext())));
+               return createSuccessJsonObject().put("reply", createJsonReply(request, reply.get(), getCurrentSone(request.getToadletContext())));
        }
 
        /**
@@ -95,7 +97,7 @@ public class GetReplyAjaxPage extends JsonPage {
        private JsonObject createJsonReply(FreenetRequest request, PostReply reply, Sone currentSone) {
                JsonObject jsonReply = new JsonObject();
                jsonReply.put("id", reply.getId());
-               jsonReply.put("postId", reply.getPost().getId());
+               jsonReply.put("postId", reply.getPostId());
                jsonReply.put("soneId", reply.getSone().getId());
                jsonReply.put("time", reply.getTime());
                StringWriter stringWriter = new StringWriter();
index 8657a6a..6caa2fd 100644 (file)
@@ -122,20 +122,14 @@ public class GetStatusAjaxPage extends JsonPage {
                        });
                }
                /* remove replies to unknown posts. */
-               newReplies = Collections2.filter(newReplies, new Predicate<PostReply>() {
-
-                       @Override
-                       public boolean apply(PostReply reply) {
-                               return (reply.getPost() != null) && (reply.getPost().getSone() != null);
-                       }
-               });
+               newReplies = Collections2.filter(newReplies, PostReply.HAS_POST_FILTER);
                JsonArray jsonReplies = new JsonArray();
                for (PostReply reply : newReplies) {
                        JsonObject jsonReply = new JsonObject();
                        jsonReply.put("id", reply.getId());
                        jsonReply.put("sone", reply.getSone().getId());
-                       jsonReply.put("post", reply.getPost().getId());
-                       jsonReply.put("postSone", reply.getPost().getSone().getId());
+                       jsonReply.put("post", reply.getPostId());
+                       jsonReply.put("postSone", reply.getPost().get().getSone().getId());
                        jsonReplies.add(jsonReply);
                }
                return createSuccessJsonObject().put("loggedIn", currentSone != null).put("options", createJsonOptions(currentSone)).put("sones", jsonSones).put("notificationHash", notifications.hashCode()).put("newPosts", jsonPosts).put("newReplies", jsonReplies);
index 13cf424..4f54571 100644 (file)
@@ -28,6 +28,8 @@ import net.pterodactylus.sone.web.WebInterface;
 import net.pterodactylus.sone.web.page.FreenetRequest;
 import net.pterodactylus.util.json.JsonObject;
 
+import com.google.common.base.Optional;
+
 /**
  * Ajax page that returns a formatted, relative timestamp for replies or posts.
  *
@@ -58,16 +60,16 @@ public class GetTimesAjaxPage extends JsonPage {
                if (allIds.length() > 0) {
                        String[] ids = allIds.split(",");
                        for (String id : ids) {
-                               Post post = webInterface.getCore().getPost(id);
-                               if (post == null) {
+                               Optional<Post> post = webInterface.getCore().getPost(id);
+                               if (!post.isPresent()) {
                                        continue;
                                }
                                JsonObject postTime = new JsonObject();
-                               Time time = getTime(post.getTime());
+                               Time time = getTime(post.get().getTime());
                                postTime.put("timeText", time.getText());
                                postTime.put("refreshTime", TimeUnit.MILLISECONDS.toSeconds(time.getRefresh()));
                                synchronized (dateFormat) {
-                                       postTime.put("tooltip", dateFormat.format(new Date(post.getTime())));
+                                       postTime.put("tooltip", dateFormat.format(new Date(post.get().getTime())));
                                }
                                postTimes.put(id, postTime);
                        }
@@ -77,16 +79,16 @@ public class GetTimesAjaxPage extends JsonPage {
                if (allIds.length() > 0) {
                        String[] ids = allIds.split(",");
                        for (String id : ids) {
-                               PostReply reply = webInterface.getCore().getPostReply(id);
-                               if (reply == null) {
+                               Optional<PostReply> reply = webInterface.getCore().getPostReply(id);
+                               if (!reply.isPresent()) {
                                        continue;
                                }
                                JsonObject replyTime = new JsonObject();
-                               Time time = getTime(reply.getTime());
+                               Time time = getTime(reply.get().getTime());
                                replyTime.put("timeText", time.getText());
                                replyTime.put("refreshTime", TimeUnit.MILLISECONDS.toSeconds(time.getRefresh()));
                                synchronized (dateFormat) {
-                                       replyTime.put("tooltip", dateFormat.format(new Date(reply.getTime())));
+                                       replyTime.put("tooltip", dateFormat.format(new Date(reply.get().getTime())));
                                }
                                replyTimes.put(id, replyTime);
                        }
index e9c582a..997c9dc 100644 (file)
@@ -26,6 +26,8 @@ import net.pterodactylus.sone.web.WebInterface;
 import net.pterodactylus.sone.web.page.FreenetRequest;
 import net.pterodactylus.util.json.JsonObject;
 
+import com.google.common.base.Optional;
+
 /**
  * AJAX page that lets the user mark a number of {@link Sone}s, {@link Post}s,
  * or {@link Reply}s as known.
@@ -57,17 +59,17 @@ public class MarkAsKnownAjaxPage extends JsonPage {
                Core core = webInterface.getCore();
                for (String id : ids) {
                        if (type.equals("post")) {
-                               Post post = core.getPost(id);
-                               if (post == null) {
+                               Optional<Post> post = core.getPost(id);
+                               if (!post.isPresent()) {
                                        continue;
                                }
-                               core.markPostKnown(post);
+                               core.markPostKnown(post.get());
                        } else if (type.equals("reply")) {
-                               PostReply reply = core.getPostReply(id);
-                               if (reply == null) {
+                               Optional<PostReply> reply = core.getPostReply(id);
+                               if (!reply.isPresent()) {
                                        continue;
                                }
-                               core.markReplyKnown(reply);
+                               core.markReplyKnown(reply.get());
                        } else if (type.equals("sone")) {
                                Sone sone = core.getSone(id, false);
                                if (sone == null) {