package net.pterodactylus.sone.core;
+import static java.util.Collections.unmodifiableMap;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import javax.annotation.Nullable;
import net.pterodactylus.sone.data.Album;
+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.Sone;
import net.pterodactylus.sone.database.AlbumBuilderFactory;
+import net.pterodactylus.sone.database.ImageBuilderFactory;
import net.pterodactylus.sone.database.PostBuilder;
import net.pterodactylus.sone.database.PostBuilderFactory;
import net.pterodactylus.sone.database.PostReplyBuilder;
private final Configuration configuration;
private final Sone sone;
private final String sonePrefix;
+ private final Map<String, Album> albums = new HashMap<String, Album>();
+ private final List<Album> topLevelAlbums = new ArrayList<Album>();
public ConfigurationSoneParser(Configuration configuration, Sone sone) {
this.configuration = configuration;
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++;
return topLevelAlbums;
}
+ public Map<String, Album> getAlbums() {
+ return unmodifiableMap(albums);
+ }
+
+ public void parseImages(ImageBuilderFactory imageBuilderFactory) {
+ int imageCounter = 0;
+ while (true) {
+ String imagePrefix = "/Images/" + imageCounter++;
+ String imageId = getString(imagePrefix + "/ID", null);
+ if (imageId == null) {
+ break;
+ }
+ String albumId = getString(imagePrefix + "/Album", null);
+ String key = getString(imagePrefix + "/Key", null);
+ String title = getString(imagePrefix + "/Title", null);
+ String description =
+ getString(imagePrefix + "/Description", null);
+ Long creationTime = getLong(imagePrefix + "/CreationTime", null);
+ Integer width = getInt(imagePrefix + "/Width", null);
+ Integer height = getInt(imagePrefix + "/Height", null);
+ if (albumAttributesAreInvalid(albumId, key, title, description,
+ creationTime,
+ width, height)) {
+ throw new InvalidImageFound();
+ }
+ Album album = albums.get(albumId);
+ if (album == null) {
+ throw new InvalidParentAlbumFound(albumId);
+ }
+ Image image = imageBuilderFactory.newImageBuilder()
+ .withId(imageId)
+ .build()
+ .modify()
+ .setSone(sone)
+ .setCreationTime(creationTime)
+ .setKey(key)
+ .setTitle(title)
+ .setDescription(description)
+ .setWidth(width)
+ .setHeight(height)
+ .update();
+ album.addImage(image);
+ }
+ }
+
+ private boolean albumAttributesAreInvalid(String albumId, String key,
+ String title, String description, Long creationTime,
+ Integer width, Integer height) {
+ return (albumId == null) || (key == null) || (title == null) || (
+ description == null) || (creationTime == null) || (width
+ == null) || (height == null);
+ }
+
public static class InvalidPostFound extends RuntimeException { }
public static class InvalidPostReplyFound extends RuntimeException { }
}
+ public static class InvalidImageFound extends RuntimeException { }
+
}
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.not;
import static java.lang.String.format;
+import static java.util.logging.Level.WARNING;
import static net.pterodactylus.sone.data.Sone.LOCAL_SONE_FILTER;
import java.net.MalformedURLException;
import java.util.logging.Logger;
import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidAlbumFound;
+import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidImageFound;
import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidParentAlbumFound;
import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostFound;
import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostReplyFound;
}
/* load images. */
- int imageCounter = 0;
- while (true) {
- String imagePrefix = sonePrefix + "/Images/" + imageCounter++;
- String imageId = configuration.getStringValue(imagePrefix + "/ID").getValue(null);
- if (imageId == null) {
- break;
- }
- String albumId = configuration.getStringValue(imagePrefix + "/Album").getValue(null);
- String key = configuration.getStringValue(imagePrefix + "/Key").getValue(null);
- String title = configuration.getStringValue(imagePrefix + "/Title").getValue(null);
- String description = configuration.getStringValue(imagePrefix + "/Description").getValue(null);
- Long creationTime = configuration.getLongValue(imagePrefix + "/CreationTime").getValue(null);
- Integer width = configuration.getIntValue(imagePrefix + "/Width").getValue(null);
- Integer height = configuration.getIntValue(imagePrefix + "/Height").getValue(null);
- if ((albumId == null) || (key == null) || (title == null) || (description == null) || (creationTime == null) || (width == null) || (height == null)) {
- logger.log(Level.WARNING, "Invalid image found, aborting load!");
- return;
- }
- Album album = getAlbum(albumId);
- if (album == null) {
- logger.log(Level.WARNING, "Invalid album image encountered, aborting load!");
- return;
- }
- Image image = getImage(imageId).modify().setSone(sone).setCreationTime(creationTime).setKey(key).setTitle(title).setDescription(description).setWidth(width).setHeight(height).update();
- album.addImage(image);
+ try {
+ configurationSoneParser.parseImages(database);
+ } catch (InvalidImageFound iif) {
+ logger.log(WARNING, "Invalid image found, aborting load!");
+ return;
+ } catch (InvalidParentAlbumFound ipaf) {
+ logger.log(Level.WARNING,
+ format("Invalid album image (%s) encountered, aborting load!",
+ ipaf.getAlbumParentId()));
+ return;
}
/* load avatar. */
import java.io.InputStream;
import net.pterodactylus.sone.data.Album;
+import net.pterodactylus.sone.data.Image;
import net.pterodactylus.sone.data.Post;
import net.pterodactylus.sone.data.PostReply;
};
}
+ public static Matcher<Image> isImage(final String id,
+ final long creationTime,
+ final String key, final String title,
+ final String imageDescription,
+ final int width, final int height) {
+ return new TypeSafeDiagnosingMatcher<Image>() {
+ @Override
+ protected boolean matchesSafely(Image image,
+ Description mismatchDescription) {
+ if (!image.getId().equals(id)) {
+ mismatchDescription.appendText("ID is ")
+ .appendValue(image.getId());
+ return false;
+ }
+ if (image.getCreationTime() != creationTime) {
+ mismatchDescription.appendText("created at @")
+ .appendValue(image.getCreationTime());
+ return false;
+ }
+ if (!image.getKey().equals(key)) {
+ mismatchDescription.appendText("key is ")
+ .appendValue(image.getKey());
+ return false;
+ }
+ if (!image.getTitle().equals(title)) {
+ mismatchDescription.appendText("title is ")
+ .appendValue(image.getTitle());
+ return false;
+ }
+ if (!image.getDescription().equals(imageDescription)) {
+ mismatchDescription.appendText("description is ")
+ .appendValue(image.getDescription());
+ return false;
+ }
+ if (image.getWidth() != width) {
+ mismatchDescription.appendText("width is ")
+ .appendValue(image.getWidth());
+ return false;
+ }
+ if (image.getHeight() != height) {
+ mismatchDescription.appendText("height is ")
+ .appendValue(image.getHeight());
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("image with ID ").appendValue(id);
+ description.appendText(", created at @")
+ .appendValue(creationTime);
+ description.appendText(", has key ").appendValue(key);
+ description.appendText(", has title ").appendValue(title);
+ description.appendText(", has description ")
+ .appendValue(imageDescription);
+ description.appendText(", has width ").appendValue(width);
+ description.appendText(", has height ").appendValue(height);
+ }
+ };
+ }
+
private static class PostMatcher extends TypeSafeDiagnosingMatcher<Post> {
private final String postId;
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.isImage;
import static net.pterodactylus.sone.Matchers.isPost;
import static net.pterodactylus.sone.Matchers.isPostReply;
import static org.hamcrest.MatcherAssert.assertThat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidAlbumFound;
+import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidImageFound;
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.Sone;
import net.pterodactylus.sone.database.AlbumBuilder;
import net.pterodactylus.sone.database.AlbumBuilderFactory;
+import net.pterodactylus.sone.database.ImageBuilder;
+import net.pterodactylus.sone.database.ImageBuilderFactory;
import net.pterodactylus.sone.database.PostBuilder;
import net.pterodactylus.sone.database.PostBuilderFactory;
import net.pterodactylus.sone.database.PostReplyBuilder;
createAlbumBuilderFactory());
}
+ @Test
+ public void imagesAreParsedCorrectly() {
+ setupTopLevelAlbums();
+ configurationSoneParser.parseTopLevelAlbums(
+ createAlbumBuilderFactory());
+ setupImages();
+ configurationSoneParser.parseImages(createImageBuilderFactory());
+ Map<String, Album> albums = configurationSoneParser.getAlbums();
+ assertThat(albums.get("A1").getImages(),
+ contains(isImage("I1", 1000L, "K1", "T1", "D1", 16, 9)));
+ assertThat(albums.get("A2").getImages(), contains(
+ isImage("I2", 2000L, "K2", "T2", "D2", 16 * 2, 9 * 2)));
+ assertThat(albums.get("A3").getImages(), contains(
+ isImage("I3", 3000L, "K3", "T3", "D3", 16 * 3, 9 * 3)));
+ }
+
+ private void setupImages() {
+ setupImage(0, "I1", "A1", 1000L, "K1", "T1", "D1", 16, 9);
+ setupImage(1, "I2", "A2", 2000L, "K2", "T2", "D2", 16 * 2, 9 * 2);
+ setupImage(2, "I3", "A3", 3000L, "K3", "T3", "D3", 16 * 3, 9 * 3);
+ setupImage(3, null, null, 0L, null, null, null, 0, 0);
+ }
+
+ private void setupImage(int imageNumber, String id,
+ String parentAlbumId, Long creationTime, String key, String title,
+ String description, Integer width, Integer height) {
+ final String imagePrefix = "Sone/1/Images/" + imageNumber;
+ setupString(imagePrefix + "/ID", id);
+ setupString(imagePrefix + "/Album", parentAlbumId);
+ setupLong(imagePrefix + "/CreationTime", creationTime);
+ setupString(imagePrefix + "/Key", key);
+ setupString(imagePrefix + "/Title", title);
+ setupString(imagePrefix + "/Description", description);
+ setupInteger(imagePrefix + "/Width", width);
+ setupInteger(imagePrefix + "/Height", height);
+ }
+
+ private ImageBuilderFactory createImageBuilderFactory() {
+ ImageBuilderFactory imageBuilderFactory =
+ mock(ImageBuilderFactory.class);
+ when(imageBuilderFactory.newImageBuilder()).thenAnswer(
+ new Answer<ImageBuilder>() {
+ @Override
+ public ImageBuilder answer(InvocationOnMock invocation)
+ throws Throwable {
+ return new TestImageBuilder();
+ }
+ });
+ return imageBuilderFactory;
+ }
+
+ @Test(expected = InvalidImageFound.class)
+ public void missingAlbumIdIsRecognized() {
+ setupTopLevelAlbums();
+ configurationSoneParser.parseTopLevelAlbums(
+ createAlbumBuilderFactory());
+ setupImage(0, "I1", null, 1000L, "K1", "T1", "D1", 16, 9);
+ configurationSoneParser.parseImages(createImageBuilderFactory());
+ }
+
+ @Test(expected = InvalidParentAlbumFound.class)
+ public void invalidAlbumIdIsRecognized() {
+ setupTopLevelAlbums();
+ configurationSoneParser.parseTopLevelAlbums(
+ createAlbumBuilderFactory());
+ setupImage(0, "I1", "A4", 1000L, "K1", "T1", "D1", 16, 9);
+ configurationSoneParser.parseImages(createImageBuilderFactory());
+ }
+
+ @Test(expected = InvalidImageFound.class)
+ public void missingCreationTimeIsRecognized() {
+ setupTopLevelAlbums();
+ configurationSoneParser.parseTopLevelAlbums(
+ createAlbumBuilderFactory());
+ setupImage(0, "I1", "A1", null, "K1", "T1", "D1", 16, 9);
+ configurationSoneParser.parseImages(createImageBuilderFactory());
+ }
+
+ @Test(expected = InvalidImageFound.class)
+ public void missingKeyIsRecognized() {
+ setupTopLevelAlbums();
+ configurationSoneParser.parseTopLevelAlbums(
+ createAlbumBuilderFactory());
+ setupImage(0, "I1", "A1", 1000L, null, "T1", "D1", 16, 9);
+ configurationSoneParser.parseImages(createImageBuilderFactory());
+ }
+
+ @Test(expected = InvalidImageFound.class)
+ public void missingTitleIsRecognized() {
+ setupTopLevelAlbums();
+ configurationSoneParser.parseTopLevelAlbums(
+ createAlbumBuilderFactory());
+ setupImage(0, "I1", "A1", 1000L, "K1", null, "D1", 16, 9);
+ configurationSoneParser.parseImages(createImageBuilderFactory());
+ }
+
+ @Test(expected = InvalidImageFound.class)
+ public void missingDescriptionIsRecognized() {
+ setupTopLevelAlbums();
+ configurationSoneParser.parseTopLevelAlbums(
+ createAlbumBuilderFactory());
+ setupImage(0, "I1", "A1", 1000L, "K1", "T1", null, 16, 9);
+ configurationSoneParser.parseImages(createImageBuilderFactory());
+ }
+
+ @Test(expected = InvalidImageFound.class)
+ public void missingWidthIsRecognized() {
+ setupTopLevelAlbums();
+ configurationSoneParser.parseTopLevelAlbums(
+ createAlbumBuilderFactory());
+ setupImage(0, "I1", "A1", 1000L, "K1", "T1", "D1", null, 9);
+ configurationSoneParser.parseImages(createImageBuilderFactory());
+ }
+
+ @Test(expected = InvalidImageFound.class)
+ public void missingHeightIsRecognized() {
+ setupTopLevelAlbums();
+ configurationSoneParser.parseTopLevelAlbums(
+ createAlbumBuilderFactory());
+ setupImage(0, "I1", "A1", 1000L, "K1", "T1", "D1", 16, null);
+ configurationSoneParser.parseImages(createImageBuilderFactory());
+ }
+
private static class TestValue<T> implements Value<T> {
private final AtomicReference<T> value = new AtomicReference<T>();
}
+ private static class TestImageBuilder implements ImageBuilder {
+
+ private final Image image;
+
+ private TestImageBuilder() {
+ image = mock(Image.class);
+ Image.Modifier imageModifier = new Image.Modifier() {
+ private Sone sone = image.getSone();
+ private long creationTime = image.getCreationTime();
+ private String key = image.getKey();
+ private String title = image.getTitle();
+ private String description = image.getDescription();
+ private int width = image.getWidth();
+ private int height = image.getHeight();
+
+ @Override
+ public Image.Modifier setSone(Sone sone) {
+ this.sone = sone;
+ return this;
+ }
+
+ @Override
+ public Image.Modifier setCreationTime(long creationTime) {
+ this.creationTime = creationTime;
+ return this;
+ }
+
+ @Override
+ public Image.Modifier setKey(String key) {
+ this.key = key;
+ return this;
+ }
+
+ @Override
+ public Image.Modifier setTitle(String title) {
+ this.title = title;
+ return this;
+ }
+
+ @Override
+ public Image.Modifier setDescription(String description) {
+ this.description = description;
+ return this;
+ }
+
+ @Override
+ public Image.Modifier setWidth(int width) {
+ this.width = width;
+ return this;
+ }
+
+ @Override
+ public Image.Modifier setHeight(int height) {
+ this.height = height;
+ return this;
+ }
+
+ @Override
+ public Image update() throws IllegalStateException {
+ when(image.getSone()).thenReturn(sone);
+ when(image.getCreationTime()).thenReturn(creationTime);
+ when(image.getKey()).thenReturn(key);
+ when(image.getTitle()).thenReturn(title);
+ when(image.getDescription()).thenReturn(description);
+ when(image.getWidth()).thenReturn(width);
+ when(image.getHeight()).thenReturn(height);
+ return image;
+ }
+ };
+ when(image.modify()).thenReturn(imageModifier);
+ }
+
+ @Override
+ public ImageBuilder randomId() {
+ when(image.getId()).thenReturn(randomUUID().toString());
+ return this;
+ }
+
+ @Override
+ public ImageBuilder withId(String id) {
+ when(image.getId()).thenReturn(id);
+ return this;
+ }
+
+ @Override
+ public Image build() throws IllegalStateException {
+ return image;
+ }
+
+ }
+
}