From fdc519da8a4d5c994c3b2233fc049e3be728bb76 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Sun, 7 Sep 2014 21:43:39 +0200 Subject: [PATCH] Move post reply parsing to new configuration parser. --- .../sone/core/ConfigurationSoneParser.java | 32 ++++++ .../java/net/pterodactylus/sone/core/Core.java | 23 ++-- src/test/java/net/pterodactylus/sone/Matchers.java | 58 ++++++++++ .../sone/core/ConfigurationSoneParserTest.java | 123 +++++++++++++++++++++ 4 files changed, 220 insertions(+), 16 deletions(-) diff --git a/src/main/java/net/pterodactylus/sone/core/ConfigurationSoneParser.java b/src/main/java/net/pterodactylus/sone/core/ConfigurationSoneParser.java index 8f09b3b..01d3221 100644 --- a/src/main/java/net/pterodactylus/sone/core/ConfigurationSoneParser.java +++ b/src/main/java/net/pterodactylus/sone/core/ConfigurationSoneParser.java @@ -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 parsePostReplies( + PostReplyBuilderFactory postReplyBuilderFactory) { + Set replies = new HashSet(); + 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 { } + } diff --git a/src/main/java/net/pterodactylus/sone/core/Core.java b/src/main/java/net/pterodactylus/sone/core/Core.java index 87add90..1541066 100644 --- a/src/main/java/net/pterodactylus/sone/core/Core.java +++ b/src/main/java/net/pterodactylus/sone/core/Core.java @@ -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 replies = new HashSet(); - 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 replies; + try { + replies = configurationSoneParser.parsePostReplies(database); + } catch (InvalidPostReplyFound iprf) { + logger.log(Level.WARNING, "Invalid reply found, aborting load!"); + return; } /* load post likes. */ diff --git a/src/test/java/net/pterodactylus/sone/Matchers.java b/src/test/java/net/pterodactylus/sone/Matchers.java index 14a8a00..41eb0dd 100644 --- a/src/test/java/net/pterodactylus/sone/Matchers.java +++ b/src/test/java/net/pterodactylus/sone/Matchers.java @@ -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 isPostReply(String postReplyId, + String postId, long time, String text) { + return new PostReplyMatcher(postReplyId, postId, time, text); + } + private static class PostMatcher extends TypeSafeDiagnosingMatcher { private final String postId; @@ -162,4 +168,56 @@ public class Matchers { } + private static class PostReplyMatcher + extends TypeSafeDiagnosingMatcher { + + 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); + } + + } + } diff --git a/src/test/java/net/pterodactylus/sone/core/ConfigurationSoneParserTest.java b/src/test/java/net/pterodactylus/sone/core/ConfigurationSoneParserTest.java index daf2cf9..4e9e863 100644 --- a/src/test/java/net/pterodactylus/sone/core/ConfigurationSoneParserTest.java +++ b/src/test/java/net/pterodactylus/sone/core/ConfigurationSoneParserTest.java @@ -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 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 implements Value { @@ -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; + } + + } + } -- 2.7.4