Move album parsing to new configuration parser.
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Tue, 9 Sep 2014 17:09:33 +0000 (19:09 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Tue, 9 Sep 2014 17:09:33 +0000 (19:09 +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 39dcd12..7b7be9f 100644 (file)
@@ -1,14 +1,20 @@
 package net.pterodactylus.sone.core;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import javax.annotation.Nullable;
 
+import net.pterodactylus.sone.data.Album;
 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.AlbumBuilderFactory;
 import net.pterodactylus.sone.database.PostBuilder;
 import net.pterodactylus.sone.database.PostBuilderFactory;
 import net.pterodactylus.sone.database.PostReplyBuilder;
@@ -175,8 +181,67 @@ public class ConfigurationSoneParser {
                return friends;
        }
 
+       public List<Album> parseTopLevelAlbums(
+                       AlbumBuilderFactory albumBuilderFactory) {
+               Map<String, Album> albums = new HashMap<String, Album>();
+               List<Album> topLevelAlbums = new ArrayList<Album>();
+               int albumCounter = 0;
+               while (true) {
+                       String albumPrefix = "/Albums/" + albumCounter++;
+                       String albumId = getString(albumPrefix + "/ID", null);
+                       if (albumId == null) {
+                               break;
+                       }
+                       String albumTitle = getString(albumPrefix + "/Title", null);
+                       String albumDescription =
+                                       getString(albumPrefix + "/Description", null);
+                       String albumParentId = getString(albumPrefix + "/Parent", null);
+                       String albumImageId =
+                                       getString(albumPrefix + "/AlbumImage", null);
+                       if ((albumTitle == null) || (albumDescription == null)) {
+                               throw new InvalidAlbumFound();
+                       }
+                       Album album = albumBuilderFactory.newAlbumBuilder()
+                                       .withId(albumId)
+                                       .by(sone)
+                                       .build()
+                                       .modify()
+                                       .setTitle(albumTitle)
+                                       .setDescription(albumDescription)
+                                       .setAlbumImage(albumImageId)
+                                       .update();
+                       if (albumParentId != null) {
+                               Album parentAlbum = albums.get(albumParentId);
+                               if (parentAlbum == null) {
+                                       throw new InvalidParentAlbumFound(albumParentId);
+                               }
+                               parentAlbum.addAlbum(album);
+                       } else {
+                               topLevelAlbums.add(album);
+                       }
+                       albums.put(albumId, album);
+               }
+               return topLevelAlbums;
+       }
+
        public static class InvalidPostFound extends RuntimeException { }
 
        public static class InvalidPostReplyFound extends RuntimeException { }
 
+       public static class InvalidAlbumFound extends RuntimeException { }
+
+       public static class InvalidParentAlbumFound extends RuntimeException {
+
+               private final String albumParentId;
+
+               public InvalidParentAlbumFound(String albumParentId) {
+                       this.albumParentId = albumParentId;
+               }
+
+               public String getAlbumParentId() {
+                       return albumParentId;
+               }
+
+       }
+
 }
index a6b4c96..e08acd1 100644 (file)
@@ -20,6 +20,7 @@ package net.pterodactylus.sone.core;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Predicates.not;
+import static java.lang.String.format;
 import static net.pterodactylus.sone.data.Sone.LOCAL_SONE_FILTER;
 
 import java.net.MalformedURLException;
@@ -38,6 +39,8 @@ import java.util.concurrent.TimeUnit;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidAlbumFound;
+import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidParentAlbumFound;
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostFound;
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostReplyFound;
 import net.pterodactylus.sone.core.Options.DefaultOption;
@@ -1124,43 +1127,17 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                Set<String> friends = configurationSoneParser.parseFriends();
 
                /* load albums. */
-               List<Album> topLevelAlbums = new ArrayList<Album>();
-               int albumCounter = 0;
-               while (true) {
-                       String albumPrefix = sonePrefix + "/Albums/" + albumCounter++;
-                       String albumId = configuration.getStringValue(albumPrefix + "/ID").getValue(null);
-                       if (albumId == null) {
-                               break;
-                       }
-                       String albumTitle = configuration.getStringValue(albumPrefix + "/Title").getValue(null);
-                       String albumDescription = configuration.getStringValue(albumPrefix + "/Description").getValue(null);
-                       String albumParentId = configuration.getStringValue(albumPrefix + "/Parent").getValue(null);
-                       String albumImageId = configuration.getStringValue(albumPrefix + "/AlbumImage").getValue(null);
-                       if ((albumTitle == null) || (albumDescription == null)) {
-                               logger.log(Level.WARNING, "Invalid album found, aborting load!");
-                               return;
-                       }
-                       Album album = database.newAlbumBuilder()
-                                       .withId(albumId)
-                                       .by(sone)
-                                       .build()
-                                       .modify()
-                                       .setTitle(albumTitle)
-                                       .setDescription(albumDescription)
-                                       .setAlbumImage(albumImageId)
-                                       .update();
-                       if (albumParentId != null) {
-                               Album parentAlbum = getAlbum(albumParentId);
-                               if (parentAlbum == null) {
-                                       logger.log(Level.WARNING, String.format("Invalid parent album ID: %s", albumParentId));
-                                       return;
-                               }
-                               parentAlbum.addAlbum(album);
-                       } else {
-                               if (!topLevelAlbums.contains(album)) {
-                                       topLevelAlbums.add(album);
-                               }
-                       }
+               List<Album> topLevelAlbums;
+               try {
+                       topLevelAlbums =
+                                       configurationSoneParser.parseTopLevelAlbums(database);
+               } catch (InvalidAlbumFound iaf) {
+                       logger.log(Level.WARNING, "Invalid album found, aborting load!");
+                       return;
+               } catch (InvalidParentAlbumFound ipaf) {
+                       logger.log(Level.WARNING, format("Invalid parent album ID: %s",
+                                       ipaf.getAlbumParentId()));
+                       return;
                }
 
                /* load images. */
index 41eb0dd..c73866e 100644 (file)
@@ -22,6 +22,7 @@ import static java.util.regex.Pattern.compile;
 import java.io.IOException;
 import java.io.InputStream;
 
+import net.pterodactylus.sone.data.Album;
 import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.data.PostReply;
 
@@ -101,6 +102,86 @@ public class Matchers {
                return new PostReplyMatcher(postReplyId, postId, time, text);
        }
 
+       public static Matcher<Album> isAlbum(final String albumId,
+                       final String parentAlbumId,
+                       final String title, final String albumDescription,
+                       final String imageId) {
+               return new TypeSafeDiagnosingMatcher<Album>() {
+                       @Override
+                       protected boolean matchesSafely(Album album,
+                                       Description mismatchDescription) {
+                               if (!album.getId().equals(albumId)) {
+                                       mismatchDescription.appendText("ID is ")
+                                                       .appendValue(album.getId());
+                                       return false;
+                               }
+                               if (parentAlbumId == null) {
+                                       if (album.getParent() != null) {
+                                               mismatchDescription.appendText("has parent album");
+                                               return false;
+                                       }
+                               } else {
+                                       if (album.getParent() == null) {
+                                               mismatchDescription.appendText("has no parent album");
+                                               return false;
+                                       }
+                                       if (!album.getParent().getId().equals(parentAlbumId)) {
+                                               mismatchDescription.appendText("parent album is ")
+                                                               .appendValue(album.getParent().getId());
+                                               return false;
+                                       }
+                               }
+                               if (!title.equals(album.getTitle())) {
+                                       mismatchDescription.appendText("has title ")
+                                                       .appendValue(album.getTitle());
+                                       return false;
+                               }
+                               if (!albumDescription.equals(album.getDescription())) {
+                                       mismatchDescription.appendText("has description ")
+                                                       .appendValue(album.getDescription());
+                                       return false;
+                               }
+                               if (imageId == null) {
+                                       if (album.getAlbumImage() != null) {
+                                               mismatchDescription.appendText("has album image");
+                                               return false;
+                                       }
+                               } else {
+                                       if (album.getAlbumImage() == null) {
+                                               mismatchDescription.appendText("has no album image");
+                                               return false;
+                                       }
+                                       if (!album.getAlbumImage().getId().equals(imageId)) {
+                                               mismatchDescription.appendText("has album image ")
+                                                               .appendValue(album.getAlbumImage().getId());
+                                               return false;
+                                       }
+                               }
+                               return true;
+                       }
+
+                       @Override
+                       public void describeTo(Description description) {
+                               description.appendText("is album ").appendValue(albumId);
+                               if (parentAlbumId == null) {
+                                       description.appendText(", has no parent");
+                               } else {
+                                       description.appendText(", has parent ")
+                                                       .appendValue(parentAlbumId);
+                               }
+                               description.appendText(", has title ").appendValue(title);
+                               description.appendText(", has description ")
+                                               .appendValue(albumDescription);
+                               if (imageId == null) {
+                                       description.appendText(", has no album image");
+                               } else {
+                                       description.appendText(", has album image ")
+                                                       .appendValue(imageId);
+                               }
+                       }
+               };
+       }
+
        private static class PostMatcher extends TypeSafeDiagnosingMatcher<Post> {
 
                private final String postId;
index 4aa291b..b5e57f7 100644 (file)
@@ -4,6 +4,7 @@ import static com.google.common.base.Optional.fromNullable;
 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.isAlbum;
 import static net.pterodactylus.sone.Matchers.isPost;
 import static net.pterodactylus.sone.Matchers.isPostReply;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -14,23 +15,33 @@ import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.notNullValue;
 import static org.hamcrest.Matchers.nullValue;
+import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
 
+import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidAlbumFound;
+import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidParentAlbumFound;
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostFound;
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostReplyFound;
+import net.pterodactylus.sone.data.Album;
+import net.pterodactylus.sone.data.Album.Modifier;
+import net.pterodactylus.sone.data.Image;
 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.AlbumBuilder;
+import net.pterodactylus.sone.database.AlbumBuilderFactory;
 import net.pterodactylus.sone.database.PostBuilder;
 import net.pterodactylus.sone.database.PostBuilderFactory;
 import net.pterodactylus.sone.database.PostReplyBuilder;
@@ -314,6 +325,80 @@ public class ConfigurationSoneParserTest {
                setupString("Sone/1/Friends/3/ID", null);
        }
 
+       @Test
+       public void topLevelAlbumsAreParsedCorrectly() {
+               setupTopLevelAlbums();
+               AlbumBuilderFactory albumBuilderFactory = createAlbumBuilderFactory();
+               List<Album> topLevelAlbums =
+                               configurationSoneParser.parseTopLevelAlbums(
+                                               albumBuilderFactory);
+               assertThat(topLevelAlbums, hasSize(2));
+               Album firstAlbum = topLevelAlbums.get(0);
+               assertThat(firstAlbum, isAlbum("A1", null, "T1", "D1", "I1"));
+               assertThat(firstAlbum.getAlbums(), emptyIterable());
+               assertThat(firstAlbum.getImages(), emptyIterable());
+               Album secondAlbum = topLevelAlbums.get(1);
+               assertThat(secondAlbum, isAlbum("A2", null, "T2", "D2", null));
+               assertThat(secondAlbum.getAlbums(), hasSize(1));
+               assertThat(secondAlbum.getImages(), emptyIterable());
+               Album thirdAlbum = secondAlbum.getAlbums().get(0);
+               assertThat(thirdAlbum, isAlbum("A3", "A2", "T3", "D3", "I3"));
+               assertThat(thirdAlbum.getAlbums(), emptyIterable());
+               assertThat(thirdAlbum.getImages(), emptyIterable());
+       }
+
+       private void setupTopLevelAlbums() {
+               setupAlbum(0, "A1", null, "T1", "D1", "I1");
+               setupAlbum(1, "A2", null, "T2", "D2", null);
+               setupAlbum(2, "A3", "A2", "T3", "D3", "I3");
+               setupAlbum(3, null, null, null, null, null);
+       }
+
+       private void setupAlbum(int albumNumber, String albumId,
+                       String parentAlbumId,
+                       String title, String description, String imageId) {
+               final String albumPrefix = "Sone/1/Albums/" + albumNumber;
+               setupString(albumPrefix + "/ID", albumId);
+               setupString(albumPrefix + "/Title", title);
+               setupString(albumPrefix + "/Description", description);
+               setupString(albumPrefix + "/Parent", parentAlbumId);
+               setupString(albumPrefix + "/AlbumImage", imageId);
+       }
+
+       private AlbumBuilderFactory createAlbumBuilderFactory() {
+               AlbumBuilderFactory albumBuilderFactory =
+                               mock(AlbumBuilderFactory.class);
+               when(albumBuilderFactory.newAlbumBuilder()).thenAnswer(
+                               new Answer<AlbumBuilder>() {
+                                       @Override
+                                       public AlbumBuilder answer(InvocationOnMock invocation) {
+                                               return new TestAlbumBuilder();
+                                       }
+                               });
+               return albumBuilderFactory;
+       }
+
+       @Test(expected = InvalidAlbumFound.class)
+       public void albumWithInvalidTitleIsRecognized() {
+               setupAlbum(0, "A1", null, null, "D1", "I1");
+               configurationSoneParser.parseTopLevelAlbums(
+                               createAlbumBuilderFactory());
+       }
+
+       @Test(expected = InvalidAlbumFound.class)
+       public void albumWithInvalidDescriptionIsRecognized() {
+               setupAlbum(0, "A1", null, "T1", null, "I1");
+               configurationSoneParser.parseTopLevelAlbums(
+                               createAlbumBuilderFactory());
+       }
+
+       @Test(expected = InvalidParentAlbumFound.class)
+       public void albumWithInvalidParentIsRecognized() {
+               setupAlbum(0, "A1", "A0", "T1", "D1", "I1");
+               configurationSoneParser.parseTopLevelAlbums(
+                               createAlbumBuilderFactory());
+       }
+
        private static class TestValue<T> implements Value<T> {
 
                private final AtomicReference<T> value = new AtomicReference<T>();
@@ -457,4 +542,119 @@ public class ConfigurationSoneParserTest {
 
        }
 
+       private static class TestAlbumBuilder implements AlbumBuilder {
+
+               private final Album album = mock(Album.class);
+               private final List<Album> albums = new ArrayList<Album>();
+               private final List<Image> images = new ArrayList<Image>();
+               private Album parentAlbum;
+               private String title;
+               private String description;
+               private String imageId;
+
+               public TestAlbumBuilder() {
+                       when(album.getTitle()).thenAnswer(new Answer<String>() {
+                               @Override
+                               public String answer(InvocationOnMock invocation) {
+                                       return title;
+                               }
+                       });
+                       when(album.getDescription()).thenAnswer(new Answer<String>() {
+                               @Override
+                               public String answer(InvocationOnMock invocation) {
+                                       return description;
+                               }
+                       });
+                       when(album.getAlbumImage()).thenAnswer(new Answer<Image>() {
+                               @Override
+                               public Image answer(InvocationOnMock invocation) {
+                                       if (imageId == null) {
+                                               return null;
+                                       }
+                                       Image image = mock(Image.class);
+                                       when(image.getId()).thenReturn(imageId);
+                                       return image;
+                               }
+                       });
+                       when(album.getAlbums()).thenReturn(albums);
+                       when(album.getImages()).thenReturn(images);
+                       doAnswer(new Answer<Void>() {
+                               @Override
+                               public Void answer(InvocationOnMock invocation) {
+                                       albums.add((Album) invocation.getArguments()[0]);
+                                       ((Album) invocation.getArguments()[0]).setParent(album);
+                                       return null;
+                               }
+                       }).when(album).addAlbum(any(Album.class));
+                       doAnswer(new Answer<Void>() {
+                               @Override
+                               public Void answer(InvocationOnMock invocation) {
+                                       images.add((Image) invocation.getArguments()[0]);
+                                       return null;
+                               }
+                       }).when(album).addImage(any(Image.class));
+                       doAnswer(new Answer<Void>() {
+                               @Override
+                               public Void answer(InvocationOnMock invocation) {
+                                       parentAlbum = (Album) invocation.getArguments()[0];
+                                       return null;
+                               }
+                       }).when(album).setParent(any(Album.class));
+                       when(album.getParent()).thenAnswer(new Answer<Album>() {
+                               @Override
+                               public Album answer(InvocationOnMock invocation) {
+                                       return parentAlbum;
+                               }
+                       });
+                       when(album.modify()).thenReturn(new Modifier() {
+                               @Override
+                               public Modifier setTitle(String title) {
+                                       TestAlbumBuilder.this.title = title;
+                                       return this;
+                               }
+
+                               @Override
+                               public Modifier setDescription(String description) {
+                                       TestAlbumBuilder.this.description = description;
+                                       return this;
+                               }
+
+                               @Override
+                               public Modifier setAlbumImage(String imageId) {
+                                       TestAlbumBuilder.this.imageId = imageId;
+                                       return this;
+                               }
+
+                               @Override
+                               public Album update() throws IllegalStateException {
+                                       return album;
+                               }
+                       });
+               }
+
+               @Override
+               public AlbumBuilder randomId() {
+                       when(album.getId()).thenReturn(randomUUID().toString());
+                       return this;
+               }
+
+               @Override
+               public AlbumBuilder withId(String id) {
+                       when(album.getId()).thenReturn(id);
+                       return this;
+               }
+
+               @Override
+               public AlbumBuilder by(Sone sone) {
+                       when(album.getSone()).thenReturn(sone);
+                       return this;
+               }
+
+               @Override
+               public Album build() throws IllegalStateException {
+                       return album;
+               }
+
+       }
+
 }