Add builder for post replies.
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Fri, 18 Jan 2013 13:36:37 +0000 (14:36 +0100)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Fri, 18 Jan 2013 13:36:37 +0000 (14:36 +0100)
src/main/java/net/pterodactylus/sone/core/Core.java
src/main/java/net/pterodactylus/sone/core/SoneDownloader.java
src/main/java/net/pterodactylus/sone/data/PostReplyBuilder.java [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/data/PostReplyBuilderFactory.java [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/data/ReplyBuilder.java [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/data/impl/AbstractReplyBuilder.java [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/data/impl/DefaultPostReplyBuilderFactory.java [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/data/impl/PostReplyBuilderImpl.java [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/main/SonePlugin.java

index 5ce01fe..fe7f6ac 100644 (file)
@@ -59,6 +59,8 @@ import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.data.PostBuilder;
 import net.pterodactylus.sone.data.PostBuilderFactory;
 import net.pterodactylus.sone.data.PostReply;
+import net.pterodactylus.sone.data.PostReplyBuilder;
+import net.pterodactylus.sone.data.PostReplyBuilderFactory;
 import net.pterodactylus.sone.data.Profile;
 import net.pterodactylus.sone.data.Profile.Field;
 import net.pterodactylus.sone.data.Reply;
@@ -66,7 +68,6 @@ import net.pterodactylus.sone.data.Sone;
 import net.pterodactylus.sone.data.Sone.ShowCustomAvatars;
 import net.pterodactylus.sone.data.Sone.SoneStatus;
 import net.pterodactylus.sone.data.TemporaryImage;
-import net.pterodactylus.sone.data.impl.PostReplyImpl;
 import net.pterodactylus.sone.fcp.FcpInterface;
 import net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired;
 import net.pterodactylus.sone.freenet.wot.Identity;
@@ -178,6 +179,9 @@ public class Core extends AbstractService implements SoneProvider, PostProvider
        /** All known posts. */
        private final Set<String> knownPosts = new HashSet<String>();
 
+       /** The post reply builder factory. */
+       private final PostReplyBuilderFactory postReplyBuilderFactory;
+
        /** All replies. */
        private final Map<String, PostReply> replies = new HashMap<String, PostReply>();
 
@@ -221,9 +225,11 @@ public class Core extends AbstractService implements SoneProvider, PostProvider
         *            The event bus
         * @param postBuilderFactory
         *            The post builder
+        * @param postReplyBuilderFactory
+        *            The post reply builder factory
         */
        @Inject
-       public Core(Configuration configuration, FreenetInterface freenetInterface, IdentityManager identityManager, WebOfTrustUpdater webOfTrustUpdater, EventBus eventBus, PostBuilderFactory postBuilderFactory) {
+       public Core(Configuration configuration, FreenetInterface freenetInterface, IdentityManager identityManager, WebOfTrustUpdater webOfTrustUpdater, EventBus eventBus, PostBuilderFactory postBuilderFactory, PostReplyBuilderFactory postReplyBuilderFactory) {
                super("Sone Core");
                this.configuration = configuration;
                this.freenetInterface = freenetInterface;
@@ -234,6 +240,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider
                this.webOfTrustUpdater = webOfTrustUpdater;
                this.eventBus = eventBus;
                this.postBuilderFactory = postBuilderFactory;
+               this.postReplyBuilderFactory = postReplyBuilderFactory;
        }
 
        //
@@ -558,6 +565,15 @@ public class Core extends AbstractService implements SoneProvider, PostProvider
        }
 
        /**
+        * Returns a post reply builder.
+        *
+        * @return A new post reply builder
+        */
+       public PostReplyBuilder postReplyBuilder() {
+               return postReplyBuilderFactory.newPostReplyBuilder();
+       }
+
+       /**
         * Returns the reply with the given ID.
         *
         * @param replyId
@@ -1319,7 +1335,9 @@ public class Core extends AbstractService implements SoneProvider, PostProvider
                                logger.log(Level.WARNING, "Invalid reply found, aborting load!");
                                return;
                        }
-                       replies.add(getPostReply(replyId, true).setSone(sone).setPost(getPost(postId)).setTime(replyTime).setText(replyText));
+                       PostReplyBuilder postReplyBuilder = postReplyBuilderFactory.newPostReplyBuilder();
+                       postReplyBuilder.withId(replyId).from(sone).to(getPost(postId)).withTime(replyTime).withText(replyText);
+                       replies.add(postReplyBuilder.build());
                }
 
                /* load post likes. */
@@ -1644,30 +1662,15 @@ public class Core extends AbstractService implements SoneProvider, PostProvider
         * @return The created reply
         */
        public PostReply createReply(Sone sone, Post post, String text) {
-               return createReply(sone, post, System.currentTimeMillis(), text);
-       }
-
-       /**
-        * Creates a new reply.
-        *
-        * @param sone
-        *            The Sone that creates the reply
-        * @param post
-        *            The post that this reply refers to
-        * @param time
-        *            The time of the reply
-        * @param text
-        *            The text of the reply
-        * @return The created reply
-        */
-       public PostReply createReply(Sone sone, Post post, long time, String text) {
                checkNotNull(text, "text must not be null");
                checkArgument(text.trim().length() > 0, "text must not be empty");
                if (!sone.isLocal()) {
                        logger.log(Level.FINE, String.format("Tried to create reply for non-local Sone: %s", sone));
                        return null;
                }
-               final PostReply reply = new PostReplyImpl(sone, post, System.currentTimeMillis(), text.trim());
+               PostReplyBuilder postReplyBuilder = postReplyBuilderFactory.newPostReplyBuilder();
+               postReplyBuilder.randomId().from(sone).to(post).currentTime().withText(text.trim());
+               final PostReply reply = postReplyBuilder.build();
                synchronized (replies) {
                        replies.put(reply.getId(), reply);
                }
index 36b672c..51bc6fd 100644 (file)
@@ -33,6 +33,7 @@ import net.pterodactylus.sone.data.Image;
 import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.data.PostBuilder;
 import net.pterodactylus.sone.data.PostReply;
+import net.pterodactylus.sone.data.PostReplyBuilder;
 import net.pterodactylus.sone.data.Profile;
 import net.pterodactylus.sone.data.Sone;
 import net.pterodactylus.sone.data.Sone.SoneStatus;
@@ -406,7 +407,10 @@ public class SoneDownloader extends AbstractService {
                                        return null;
                                }
                                try {
-                                       replies.add(core.getPostReply(replyId, true).setSone(sone).setPost(core.getPost(replyPostId)).setTime(Long.parseLong(replyTime)).setText(replyText));
+                                       PostReplyBuilder postReplyBuilder = core.postReplyBuilder();
+                                       /* TODO - parse time correctly. */
+                                       postReplyBuilder.withId(replyId).from(sone).to(core.getPost(replyPostId)).withTime(Long.parseLong(replyTime)).withText(replyText);
+                                       replies.add(postReplyBuilder.build());
                                } catch (NumberFormatException nfe1) {
                                        /* TODO - mark Sone as bad. */
                                        logger.log(Level.WARNING, String.format("Downloaded reply for Sone %s with invalid time: %s", sone, replyTime));
diff --git a/src/main/java/net/pterodactylus/sone/data/PostReplyBuilder.java b/src/main/java/net/pterodactylus/sone/data/PostReplyBuilder.java
new file mode 100644 (file)
index 0000000..6c3e236
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Sone - PostReplyBuilder.java - Copyright © 2013 David Roden
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data;
+
+/**
+ * Builder for a {@link PostReply} object.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public interface PostReplyBuilder extends ReplyBuilder<PostReplyBuilder> {
+
+       /**
+        * Configures this builder to set the given post as post the created reply
+        * refers to.
+        *
+        * @param post
+        *            The post the reply refers to
+        * @return This builder
+        */
+       public PostReplyBuilder to(Post post);
+
+       /**
+        * Verifies the configuration of this builder and creates a new post reply.
+        * <p>
+        * The following conditions must be met in order for the configuration to be
+        * considered valid:
+        * <ul>
+        * <li>Exactly one of {@link #randomId()} or {@link #withId(String)} must
+        * have been called.</li>
+        * <li>The {@link #from(Sone) sender} must not be {@code null}.</li>
+        * <li>Exactly one of {@link #currentTime()} or {@link #withTime(long)} must
+        * have been called.</li>
+        * <li>The {@link #withText(String) text} must not be {@code null} and must
+        * contain something other than whitespace.</li>
+        * <li>The {@link #to(Post) post} have been set.</li>
+        * </ul>
+        *
+        * @return The created post reply
+        * @throws IllegalStateException
+        *             if this builder’s configuration is not valid
+        */
+       public PostReply build() throws IllegalStateException;
+
+}
diff --git a/src/main/java/net/pterodactylus/sone/data/PostReplyBuilderFactory.java b/src/main/java/net/pterodactylus/sone/data/PostReplyBuilderFactory.java
new file mode 100644 (file)
index 0000000..17a92f3
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Sone - PostReplyBuilderFactory.java - Copyright © 2013 David Roden
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data;
+
+/**
+ * Factory for {@link PostReplyBuilder}s.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public interface PostReplyBuilderFactory {
+
+       /**
+        * Creates a new post reply builder.
+        *
+        * @return A new post reply builder
+        */
+       public PostReplyBuilder newPostReplyBuilder();
+
+}
diff --git a/src/main/java/net/pterodactylus/sone/data/ReplyBuilder.java b/src/main/java/net/pterodactylus/sone/data/ReplyBuilder.java
new file mode 100644 (file)
index 0000000..53f3153
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Sone - ReplyBuilder.java - Copyright © 2013 David Roden
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data;
+
+/**
+ * Methods that all reply builders need to implement in order to be able to
+ * create any kind of {@link Reply}.
+ *
+ * @param <B>
+ *            The type of the builder
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public interface ReplyBuilder<B extends ReplyBuilder<B>> {
+
+       /**
+        * Configures this builder to use a random ID when creating the reply. If
+        * this method is used, {@link #withId(String)} must not be used.
+        *
+        * @return This builder
+        */
+       public B randomId();
+
+       /**
+        * Configures this builder to use the given ID when creating the reply. If
+        * this method is used, {@link #randomId()} must not be used.
+        *
+        * @param id
+        *            The ID of the reply
+        * @return This builder
+        */
+       public B withId(String id);
+
+       /**
+        * Configures this builder to use the given {@link Sone} as sender of the
+        * reply.
+        *
+        * @param sender
+        *            The sender of the reply
+        * @return This builder
+        */
+       public B from(Sone sender);
+
+       /**
+        * Configures this builder to use the current time when creating the reply.
+        * If this method is used, {@link #withTime(long)} must not be used.
+        *
+        * @return This builder
+        */
+       public B currentTime();
+
+       /**
+        * Configures this builder to use the given time when creating the reply. If
+        * this method is used, {@link #currentTime()} must not be used.
+        *
+        * @param time
+        *            The time of the reply
+        * @return This builder
+        */
+       public B withTime(long time);
+
+       /**
+        * Configures this builder to use the given text when creating the reply.
+        *
+        * @param text
+        *            The text of the reply
+        * @return This builder
+        */
+       public B withText(String text);
+
+}
diff --git a/src/main/java/net/pterodactylus/sone/data/impl/AbstractReplyBuilder.java b/src/main/java/net/pterodactylus/sone/data/impl/AbstractReplyBuilder.java
new file mode 100644 (file)
index 0000000..77e484a
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Sone - ReplyBuilder.java - Copyright © 2013 David Roden
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data.impl;
+
+import net.pterodactylus.sone.data.ReplyBuilder;
+import net.pterodactylus.sone.data.Sone;
+
+/**
+ * Abstract implementation of a {@link ReplyBuilder}.
+ *
+ * @param <C>
+ *            The concrete implementation of the builder
+ * @param <B>
+ *            The interface implemented and exposed by the builder
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class AbstractReplyBuilder<C extends AbstractReplyBuilder<C, B>, B extends ReplyBuilder<B>> implements ReplyBuilder<B> {
+
+       /** Whether to use a random ID for the reply. */
+       protected boolean randomId;
+
+       /** The ID of the reply. */
+       protected String id;
+
+       /** The sender of the reply. */
+       protected Sone sender;
+
+       /** Whether to use the current time when creating the reply. */
+       protected boolean currentTime;
+
+       /** The time of the reply. */
+       protected long time;
+
+       /** The text of the reply. */
+       protected String text;
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       @SuppressWarnings("unchecked")
+       public B randomId() {
+               this.randomId = true;
+               return (B) this;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       @SuppressWarnings("unchecked")
+       public B withId(String id) {
+               this.id = id;
+               return (B) this;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       @SuppressWarnings("unchecked")
+       public B from(Sone sender) {
+               this.sender = sender;
+               return (B) this;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       @SuppressWarnings("unchecked")
+       public B currentTime() {
+               this.currentTime = true;
+               return (B) this;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       @SuppressWarnings("unchecked")
+       public B withTime(long time) {
+               this.time = time;
+               return (B) this;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       @SuppressWarnings("unchecked")
+       public B withText(String text) {
+               this.text = text;
+               return (B) this;
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/sone/data/impl/DefaultPostReplyBuilderFactory.java b/src/main/java/net/pterodactylus/sone/data/impl/DefaultPostReplyBuilderFactory.java
new file mode 100644 (file)
index 0000000..efe3c30
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Sone - DefaultPostReplyBuilderFactory.java - Copyright © 2013 David Roden
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data.impl;
+
+import net.pterodactylus.sone.data.PostReplyBuilder;
+import net.pterodactylus.sone.data.PostReplyBuilderFactory;
+
+/**
+ * {@link PostReplyBuilderFactory} that creates {@link PostReplyBuilderImpl}s.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class DefaultPostReplyBuilderFactory implements PostReplyBuilderFactory {
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       public PostReplyBuilder newPostReplyBuilder() {
+               return new PostReplyBuilderImpl();
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/sone/data/impl/PostReplyBuilderImpl.java b/src/main/java/net/pterodactylus/sone/data/impl/PostReplyBuilderImpl.java
new file mode 100644 (file)
index 0000000..756f28e
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Sone - PostReplyBuilderImpl.java - Copyright © 2013 David Roden
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data.impl;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.UUID;
+
+import net.pterodactylus.sone.data.Post;
+import net.pterodactylus.sone.data.PostReply;
+import net.pterodactylus.sone.data.PostReplyBuilder;
+
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * {@link PostReplyBuilder} implementation that creates {@link PostReplyImpl}
+ * objects.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class PostReplyBuilderImpl extends AbstractReplyBuilder<PostReplyBuilderImpl, PostReplyBuilder> implements PostReplyBuilder {
+
+       /** The post the created reply refers to. */
+       private Post post;
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       public PostReplyBuilder to(Post post) {
+               this.post = post;
+               return this;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       public PostReply build() {
+               checkState((randomId && (id == null)) || (!randomId && (id != null)), "either random ID nor custom ID must be set");
+               checkState(sender != null, "sender must not be null");
+               checkState((currentTime && (time == 0)) || (!currentTime && (time >= 0)), "either current time or custom time must be set");
+               checkState(!StringUtils.isBlank(text), "text must not be empty");
+               checkState(post != null, "post must not be null");
+
+               /* create new post reply. */
+               PostReplyImpl postReplyImpl = new PostReplyImpl(randomId ? UUID.randomUUID().toString() : id);
+               postReplyImpl.setSone(sender);
+               postReplyImpl.setPost(post);
+               postReplyImpl.setTime(currentTime ? System.currentTimeMillis() : time);
+               postReplyImpl.setText(text);
+               return postReplyImpl;
+       }
+}
index 1080818..152a70f 100644 (file)
@@ -26,7 +26,9 @@ import net.pterodactylus.sone.core.Core;
 import net.pterodactylus.sone.core.FreenetInterface;
 import net.pterodactylus.sone.core.WebOfTrustUpdater;
 import net.pterodactylus.sone.data.PostBuilderFactory;
+import net.pterodactylus.sone.data.PostReplyBuilderFactory;
 import net.pterodactylus.sone.data.impl.DefaultPostBuilderFactory;
+import net.pterodactylus.sone.data.impl.DefaultPostReplyBuilderFactory;
 import net.pterodactylus.sone.fcp.FcpInterface;
 import net.pterodactylus.sone.freenet.PluginStoreConfigurationBackend;
 import net.pterodactylus.sone.freenet.plugin.PluginConnector;
@@ -220,6 +222,7 @@ public class SonePlugin implements FredPlugin, FredPluginFCP, FredPluginL10n, Fr
                                bind(SonePlugin.class).toInstance(SonePlugin.this);
                                bind(FcpInterface.class).in(Singleton.class);
                                bind(PostBuilderFactory.class).to(DefaultPostBuilderFactory.class).in(Singleton.class);
+                               bind(PostReplyBuilderFactory.class).to(DefaultPostReplyBuilderFactory.class).in(Singleton.class);
                                bindListener(Matchers.any(), new TypeListener() {
 
                                        @Override