Move post reply parsing to new configuration parser.
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sun, 7 Sep 2014 19:43:39 +0000 (21:43 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sun, 7 Sep 2014 19:43:39 +0000 (21:43 +0200)
src/main/java/net/pterodactylus/sone/core/ConfigurationSoneParser.java
src/main/java/net/pterodactylus/sone/core/Core.java
src/test/java/net/pterodactylus/sone/Matchers.java
src/test/java/net/pterodactylus/sone/core/ConfigurationSoneParserTest.java

index 8f09b3b..01d3221 100644 (file)
@@ -7,10 +7,13 @@ import java.util.Set;
 import javax.annotation.Nullable;
 
 import net.pterodactylus.sone.data.Post;
+import net.pterodactylus.sone.data.PostReply;
 import net.pterodactylus.sone.data.Profile;
 import net.pterodactylus.sone.data.Sone;
 import net.pterodactylus.sone.database.PostBuilder;
 import net.pterodactylus.sone.database.PostBuilderFactory;
+import net.pterodactylus.sone.database.PostReplyBuilder;
+import net.pterodactylus.sone.database.PostReplyBuilderFactory;
 import net.pterodactylus.util.config.Configuration;
 
 /**
@@ -106,6 +109,35 @@ public class ConfigurationSoneParser {
                return (postRecipientId != null) && (postRecipientId.length() == 43);
        }
 
+       public Collection<PostReply> parsePostReplies(
+                       PostReplyBuilderFactory postReplyBuilderFactory) {
+               Set<PostReply> replies = new HashSet<PostReply>();
+               while (true) {
+                       String replyPrefix = "/Replies/" + replies.size();
+                       String replyId = getString(replyPrefix + "/ID", null);
+                       if (replyId == null) {
+                               break;
+                       }
+                       String postId = getString(replyPrefix + "/Post/ID", null);
+                       long replyTime = getLong(replyPrefix + "/Time", 0L);
+                       String replyText = getString(replyPrefix + "/Text", null);
+                       if ((postId == null) || (replyTime == 0) || (replyText == null)) {
+                               throw new InvalidPostReplyFound();
+                       }
+                       PostReplyBuilder postReplyBuilder = postReplyBuilderFactory
+                                       .newPostReplyBuilder()
+                                       .withId(replyId)
+                                       .from(sone.getId())
+                                       .to(postId)
+                                       .withTime(replyTime)
+                                       .withText(replyText);
+                       replies.add(postReplyBuilder.build());
+               }
+               return replies;
+       }
+
        public static class InvalidPostFound extends RuntimeException { }
 
+       public static class InvalidPostReplyFound extends RuntimeException { }
+
 }
index 87add90..1541066 100644 (file)
@@ -39,6 +39,7 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostFound;
+import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostReplyFound;
 import net.pterodactylus.sone.core.Options.DefaultOption;
 import net.pterodactylus.sone.core.SoneInserter.SetInsertionDelay;
 import net.pterodactylus.sone.core.event.ImageInsertFinishedEvent;
@@ -1122,22 +1123,12 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                }
 
                /* load replies. */
-               Set<PostReply> replies = new HashSet<PostReply>();
-               while (true) {
-                       String replyPrefix = sonePrefix + "/Replies/" + replies.size();
-                       String replyId = configuration.getStringValue(replyPrefix + "/ID").getValue(null);
-                       if (replyId == null) {
-                               break;
-                       }
-                       String postId = configuration.getStringValue(replyPrefix + "/Post/ID").getValue(null);
-                       long replyTime = configuration.getLongValue(replyPrefix + "/Time").getValue((long) 0);
-                       String replyText = configuration.getStringValue(replyPrefix + "/Text").getValue(null);
-                       if ((postId == null) || (replyTime == 0) || (replyText == null)) {
-                               logger.log(Level.WARNING, "Invalid reply found, aborting load!");
-                               return;
-                       }
-                       PostReplyBuilder postReplyBuilder = postReplyBuilder().withId(replyId).from(sone.getId()).to(postId).withTime(replyTime).withText(replyText);
-                       replies.add(postReplyBuilder.build());
+               Collection<PostReply> replies;
+               try {
+                       replies = configurationSoneParser.parsePostReplies(database);
+               } catch (InvalidPostReplyFound iprf) {
+                       logger.log(Level.WARNING, "Invalid reply found, aborting load!");
+                       return;
                }
 
                /* load post likes. */
index 14a8a00..41eb0dd 100644 (file)
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.io.InputStream;
 
 import net.pterodactylus.sone.data.Post;
+import net.pterodactylus.sone.data.PostReply;
 
 import com.google.common.base.Optional;
 import org.hamcrest.Description;
@@ -95,6 +96,11 @@ public class Matchers {
                return new PostMatcher(postId, time, text, recipient);
        }
 
+       public static Matcher<PostReply> isPostReply(String postReplyId,
+                       String postId, long time, String text) {
+               return new PostReplyMatcher(postReplyId, postId, time, text);
+       }
+
        private static class PostMatcher extends TypeSafeDiagnosingMatcher<Post> {
 
                private final String postId;
@@ -162,4 +168,56 @@ public class Matchers {
 
        }
 
+       private static class PostReplyMatcher
+                       extends TypeSafeDiagnosingMatcher<PostReply> {
+
+               private final String postReplyId;
+               private final String postId;
+               private final long time;
+               private final String text;
+
+               private PostReplyMatcher(String postReplyId, String postId, long time,
+                               String text) {
+                       this.postReplyId = postReplyId;
+                       this.postId = postId;
+                       this.time = time;
+                       this.text = text;
+               }
+
+               @Override
+               protected boolean matchesSafely(PostReply postReply,
+                               Description mismatchDescription) {
+                       if (!postReply.getId().equals(postReplyId)) {
+                               mismatchDescription.appendText("is post reply ")
+                                               .appendValue(postReply.getId());
+                               return false;
+                       }
+                       if (!postReply.getPostId().equals(postId)) {
+                               mismatchDescription.appendText("is reply to ")
+                                               .appendValue(postReply.getPostId());
+                               return false;
+                       }
+                       if (postReply.getTime() != time) {
+                               mismatchDescription.appendText("is created at @").appendValue(
+                                               postReply.getTime());
+                               return false;
+                       }
+                       if (!postReply.getText().equals(text)) {
+                               mismatchDescription.appendText("says ")
+                                               .appendValue(postReply.getText());
+                               return false;
+                       }
+                       return true;
+               }
+
+               @Override
+               public void describeTo(Description description) {
+                       description.appendText("is post reply ").appendValue(postReplyId);
+                       description.appendText(", replies to post ").appendValue(postId);
+                       description.appendText(", is created at @").appendValue(time);
+                       description.appendText(", says ").appendValue(text);
+               }
+
+       }
+
 }
index daf2cf9..4e9e863 100644 (file)
@@ -5,8 +5,10 @@ import static com.google.common.base.Optional.of;
 import static java.lang.System.currentTimeMillis;
 import static java.util.UUID.randomUUID;
 import static net.pterodactylus.sone.Matchers.isPost;
+import static net.pterodactylus.sone.Matchers.isPostReply;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.emptyIterable;
 import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.is;
@@ -22,12 +24,16 @@ import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostFound;
+import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostReplyFound;
 import net.pterodactylus.sone.data.Post;
+import net.pterodactylus.sone.data.PostReply;
 import net.pterodactylus.sone.data.Profile;
 import net.pterodactylus.sone.data.Profile.Field;
 import net.pterodactylus.sone.data.Sone;
 import net.pterodactylus.sone.database.PostBuilder;
 import net.pterodactylus.sone.database.PostBuilderFactory;
+import net.pterodactylus.sone.database.PostReplyBuilder;
+import net.pterodactylus.sone.database.PostReplyBuilderFactory;
 import net.pterodactylus.util.config.Configuration;
 import net.pterodactylus.util.config.ConfigurationException;
 import net.pterodactylus.util.config.Value;
@@ -200,6 +206,68 @@ public class ConfigurationSoneParserTest {
                setupPost("1", null, 0L, null, null);
        }
 
+       @Test
+       public void postRepliesAreParsedCorrectly() {
+               setupPostReplies();
+               PostReplyBuilderFactory postReplyBuilderFactory =
+                               new PostReplyBuilderFactory() {
+                                       @Override
+                                       public PostReplyBuilder newPostReplyBuilder() {
+                                               return new TestPostReplyBuilder();
+                                       }
+                               };
+               Collection<PostReply> postReplies =
+                               configurationSoneParser.parsePostReplies(
+                                               postReplyBuilderFactory);
+               assertThat(postReplies, hasSize(2));
+               assertThat(postReplies,
+                               containsInAnyOrder(isPostReply("R0", "P0", 1000L, "T0"),
+                                               isPostReply("R1", "P1", 1001L, "T1")));
+       }
+
+       private void setupPostReplies() {
+               setupPostReply("0", "R0", "P0", 1000L, "T0");
+               setupPostReply("1", "R1", "P1", 1001L, "T1");
+               setupPostReply("2", null, null, 0L, null);
+       }
+
+       private void setupPostReply(String postReplyNumber, String postReplyId,
+                       String postId, long time, String text) {
+               setupString("Sone/1/Replies/" + postReplyNumber + "/ID", postReplyId);
+               setupString("Sone/1/Replies/" + postReplyNumber + "/Post/ID", postId);
+               setupLong("Sone/1/Replies/" + postReplyNumber + "/Time", time);
+               setupString("Sone/1/Replies/" + postReplyNumber + "/Text", text);
+       }
+
+       @Test(expected = InvalidPostReplyFound.class)
+       public void missingPostIdIsRecognized() {
+               setupPostReplyWithMissingPostId();
+               configurationSoneParser.parsePostReplies(null);
+       }
+
+       private void setupPostReplyWithMissingPostId() {
+               setupPostReply("0", "R0", null, 1000L, "T0");
+       }
+
+       @Test(expected = InvalidPostReplyFound.class)
+       public void missingPostReplyTimeIsRecognized() {
+               setupPostReplyWithMissingPostReplyTime();
+               configurationSoneParser.parsePostReplies(null);
+       }
+
+       private void setupPostReplyWithMissingPostReplyTime() {
+               setupPostReply("0", "R0", "P0", 0L, "T0");
+       }
+
+       @Test(expected = InvalidPostReplyFound.class)
+       public void missingPostReplyTextIsRecognized() {
+               setupPostReplyWithMissingPostReplyText();
+               configurationSoneParser.parsePostReplies(null);
+       }
+
+       private void setupPostReplyWithMissingPostReplyText() {
+               setupPostReply("0", "R0", "P0", 1000L, null);
+       }
 
        private static class TestValue<T> implements Value<T> {
 
@@ -289,4 +357,59 @@ public class ConfigurationSoneParserTest {
 
        }
 
+       private static class TestPostReplyBuilder implements PostReplyBuilder {
+
+               private final PostReply postReply = mock(PostReply.class);
+
+               @Override
+               public PostReplyBuilder to(String postId) {
+                       when(postReply.getPostId()).thenReturn(postId);
+                       return this;
+               }
+
+               @Override
+               public PostReply build() throws IllegalStateException {
+                       return postReply;
+               }
+
+               @Override
+               public PostReplyBuilder randomId() {
+                       when(postReply.getId()).thenReturn(randomUUID().toString());
+                       return this;
+               }
+
+               @Override
+               public PostReplyBuilder withId(String id) {
+                       when(postReply.getId()).thenReturn(id);
+                       return this;
+               }
+
+               @Override
+               public PostReplyBuilder from(String senderId) {
+                       Sone sone = mock(Sone.class);
+                       when(sone.getId()).thenReturn(senderId);
+                       when(postReply.getSone()).thenReturn(sone);
+                       return this;
+               }
+
+               @Override
+               public PostReplyBuilder currentTime() {
+                       when(postReply.getTime()).thenReturn(currentTimeMillis());
+                       return this;
+               }
+
+               @Override
+               public PostReplyBuilder withTime(long time) {
+                       when(postReply.getTime()).thenReturn(time);
+                       return this;
+               }
+
+               @Override
+               public PostReplyBuilder withText(String text) {
+                       when(postReply.getText()).thenReturn(text);
+                       return this;
+               }
+
+       }
+
 }