package net.pterodactylus.sone.core;
import static java.util.Collections.unmodifiableMap;
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.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;
import net.pterodactylus.sone.database.PostReplyBuilderFactory;
import net.pterodactylus.util.config.Configuration;
/**
* Parses a {@link Sone}’s data from a {@link Configuration}.
*
* @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
*/
public class ConfigurationSoneParser {
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>();
private final Map<String, Image> images = new HashMap<String, Image>();
public ConfigurationSoneParser(Configuration configuration, Sone sone) {
this.configuration = configuration;
this.sone = sone;
sonePrefix = "Sone/" + sone.getId();
}
public Profile parseProfile() {
Profile profile = new Profile(sone);
profile.setFirstName(getString("/Profile/FirstName", null));
profile.setMiddleName(getString("/Profile/MiddleName", null));
profile.setLastName(getString("/Profile/LastName", null));
profile.setBirthDay(getInt("/Profile/BirthDay", null));
profile.setBirthMonth(getInt("/Profile/BirthMonth", null));
profile.setBirthYear(getInt("/Profile/BirthYear", null));
/* load profile fields. */
int fieldCount = 0;
while (true) {
String fieldPrefix = "/Profile/Fields/" + fieldCount++;
String fieldName = getString(fieldPrefix + "/Name", null);
if (fieldName == null) {
break;
}
String fieldValue = getString(fieldPrefix + "/Value", "");
profile.addField(fieldName).setValue(fieldValue);
}
return profile;
}
private String getString(String nodeName, @Nullable String defaultValue) {
return configuration.getStringValue(sonePrefix + nodeName)
.getValue(defaultValue);
}
private Integer getInt(String nodeName, @Nullable Integer defaultValue) {
return configuration.getIntValue(sonePrefix + nodeName)
.getValue(defaultValue);
}
private Long getLong(String nodeName, @Nullable Long defaultValue) {
return configuration.getLongValue(sonePrefix + nodeName)
.getValue(defaultValue);
}
public Set<Post> parsePosts(PostBuilderFactory postBuilderFactory)
throws InvalidPostFound {
Set<Post> posts = new HashSet<Post>();
while (true) {
String postPrefix = "/Posts/" + posts.size();
String postId = getString(postPrefix + "/ID", null);
if (postId == null) {
break;
}
long postTime = getLong(postPrefix + "/Time", 0L);
String postText = getString(postPrefix + "/Text", null);
if (postAttributesAreInvalid(postTime, postText)) {
throw new InvalidPostFound();
}
PostBuilder postBuilder = postBuilderFactory.newPostBuilder()
.withId(postId)
.from(sone.getId())
.withTime(postTime)
.withText(postText);
String postRecipientId =
getString(postPrefix + "/Recipient", null);
if (postRecipientIsValid(postRecipientId)) {
postBuilder.to(postRecipientId);
}
posts.add(postBuilder.build());
}
return posts;
}
private boolean postAttributesAreInvalid(long postTime, String postText) {
return (postTime == 0) || (postText == null);
}
private boolean postRecipientIsValid(String postRecipientId) {
return (postRecipientId != null) && (postRecipientId.length() == 43);
}
public Set<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 Set<String> parseLikedPostIds() {
Set<String> likedPostIds = new HashSet<String>();
while (true) {
String likedPostId =
getString("/Likes/Post/" + likedPostIds.size() + "/ID",
null);
if (likedPostId == null) {
break;
}
likedPostIds.add(likedPostId);
}
return likedPostIds;
}
public Set<String> parseLikedPostReplyIds() {
Set<String> likedPostReplyIds = new HashSet<String>();
while (true) {
String likedReplyId = getString(
"/Likes/Reply/" + likedPostReplyIds.size() + "/ID", null);
if (likedReplyId == null) {
break;
}
likedPostReplyIds.add(likedReplyId);
}
return likedPostReplyIds;
}
public Set<String> parseFriends() {
Set<String> friends = new HashSet<String>();
while (true) {
String friendId =
getString("/Friends/" + friends.size() + "/ID", null);
if (friendId == null) {
break;
}
friends.add(friendId);
}
return friends;
}
public List<Album> parseTopLevelAlbums(
AlbumBuilderFactory albumBuilderFactory) {
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);
if ((albumTitle == null) || (albumDescription == null)) {
throw new InvalidAlbumFound();
}
Album album = albumBuilderFactory.newAlbumBuilder()
.withId(albumId)
.by(sone)
.build()
.modify()
.setTitle(albumTitle)
.setDescription(albumDescription)
.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 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);
images.put(image.getId(), image);
}
}
public Map<String, Image> getImages() {
return images;
}
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 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;
}
}
public static class InvalidImageFound extends RuntimeException { }
}