package net.pterodactylus.sone.core;
+import static com.google.common.base.Optional.fromNullable;
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 com.google.common.primitives.Longs.tryParse;
+import static java.lang.String.format;
+import static java.util.logging.Level.WARNING;
import static net.pterodactylus.sone.data.Sone.LOCAL_SONE_FILTER;
+import static net.pterodactylus.sone.data.Sone.toAllAlbums;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.logging.Level;
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;
import net.pterodactylus.sone.core.Options.DefaultOption;
+import net.pterodactylus.sone.core.SoneChangeDetector.PostProcessor;
+import net.pterodactylus.sone.core.SoneChangeDetector.PostReplyProcessor;
import net.pterodactylus.sone.core.SoneInserter.SetInsertionDelay;
import net.pterodactylus.sone.core.event.ImageInsertFinishedEvent;
import net.pterodactylus.sone.core.event.MarkPostKnownEvent;
import net.pterodactylus.sone.data.Sone.SoneStatus;
import net.pterodactylus.sone.data.SoneImpl;
import net.pterodactylus.sone.data.TemporaryImage;
+import net.pterodactylus.sone.database.AlbumBuilder;
import net.pterodactylus.sone.database.Database;
import net.pterodactylus.sone.database.DatabaseException;
+import net.pterodactylus.sone.database.ImageBuilder;
import net.pterodactylus.sone.database.PostBuilder;
import net.pterodactylus.sone.database.PostProvider;
import net.pterodactylus.sone.database.PostReplyBuilder;
*/
@Override
public Collection<Sone> getSones() {
- synchronized (sones) {
- return ImmutableSet.copyOf(sones.values());
- }
+ return database.getSones();
}
/**
*/
@Override
public Optional<Sone> getSone(String id) {
- synchronized (sones) {
- return Optional.fromNullable(sones.get(id));
- }
+ return database.getSone(id);
}
/**
*/
@Override
public Collection<Sone> getLocalSones() {
- synchronized (sones) {
- return FluentIterable.from(sones.values()).filter(LOCAL_SONE_FILTER).toSet();
- }
+ return database.getLocalSones();
}
/**
*/
@Override
public Collection<Sone> getRemoteSones() {
- synchronized (sones) {
- return FluentIterable.from(sones.values()).filter(not(LOCAL_SONE_FILTER)).toSet();
- }
+ return database.getRemoteSones();
}
/**
return posts;
}
- /**
- * Returns the album with the given ID, creating a new album if no album
- * with the given ID can be found.
- *
- * @param albumId
- * The ID of the album
- * @return The album with the given ID
- */
- public Album getOrCreateAlbum(String albumId) {
- return getAlbum(albumId, true);
+ public AlbumBuilder albumBuilder() {
+ return database.newAlbumBuilder();
}
/**
*
* @param albumId
* The ID of the album
- * @param create
- * {@code true} to create a new album if none exists for the
- * given ID
* @return The album with the given ID, or {@code null} if no album with the
- * given ID exists and {@code create} is {@code false}
+ * given ID exists
*/
- public Album getAlbum(String albumId, boolean create) {
- Optional<Album> album = database.getAlbum(albumId);
- if (album.isPresent()) {
- return album.get();
- }
- if (!create) {
- return null;
- }
- Album newAlbum = database.newAlbumBuilder().withId(albumId).build();
- database.storeAlbum(newAlbum);
- return newAlbum;
+ public Album getAlbum(String albumId) {
+ return database.getAlbum(albumId).orNull();
+ }
+
+ public ImageBuilder imageBuilder() {
+ return database.newImageBuilder();
}
/**
logger.log(Level.WARNING, "Given Identity is null!");
return null;
}
+ final Long latestEdition = tryParse(fromNullable(
+ identity.getProperty("Sone.LatestEdition")).or("0"));
synchronized (sones) {
final Sone sone = getRemoteSone(identity.getId(), true);
if (sone.isLocal()) {
sone.setIdentity(identity);
boolean newSone = sone.getRequestUri() == null;
sone.setRequestUri(SoneUri.create(identity.getRequestUri()));
- sone.setLatestEdition(Numbers.safeParseLong(identity.getProperty("Sone.LatestEdition"), (long) 0));
+ sone.setLatestEdition(latestEdition);
if (newSone) {
synchronized (knownSones) {
newSone = !knownSones.contains(sone.getId());
* {@code true} if the stored Sone should be updated regardless
* of the age of the given Sone
*/
- public void updateSone(Sone sone, boolean soneRescueMode) {
+ public void updateSone(final Sone sone, boolean soneRescueMode) {
Optional<Sone> storedSone = getSone(sone.getId());
if (storedSone.isPresent()) {
if (!soneRescueMode && !(sone.getTime() > storedSone.get().getTime())) {
return;
}
/* find removed posts. */
- Collection<Post> removedPosts = new ArrayList<Post>();
- Collection<Post> newPosts = new ArrayList<Post>();
- Collection<Post> existingPosts = database.getPosts(sone.getId());
- for (Post oldPost : existingPosts) {
- if (!sone.getPosts().contains(oldPost)) {
- removedPosts.add(oldPost);
- }
- }
- /* find new posts. */
- for (Post newPost : sone.getPosts()) {
- if (existingPosts.contains(newPost)) {
- continue;
- }
- if (newPost.getTime() < getSoneFollowingTime(sone)) {
- newPost.setKnown(true);
- } else if (!newPost.isKnown()) {
- newPosts.add(newPost);
- }
- }
- /* store posts. */
- database.storePosts(sone, sone.getPosts());
- Collection<PostReply> newPostReplies = new ArrayList<PostReply>();
- Collection<PostReply> removedPostReplies = new ArrayList<PostReply>();
- if (!soneRescueMode) {
- for (PostReply reply : storedSone.get().getReplies()) {
- if (!sone.getReplies().contains(reply)) {
- removedPostReplies.add(reply);
+ SoneChangeDetector soneChangeDetector = new SoneChangeDetector(storedSone.get());
+ soneChangeDetector.onNewPosts(new PostProcessor() {
+ @Override
+ public void processPost(Post post) {
+ if (post.getTime() < getSoneFollowingTime(sone)) {
+ post.setKnown(true);
+ } else if (!post.isKnown()) {
+ eventBus.post(new NewPostFoundEvent(post));
}
}
- }
- Set<PostReply> storedReplies = storedSone.get().getReplies();
- for (PostReply reply : sone.getReplies()) {
- if (storedReplies.contains(reply)) {
- continue;
+ });
+ soneChangeDetector.onRemovedPosts(new PostProcessor() {
+ @Override
+ public void processPost(Post post) {
+ eventBus.post(new PostRemovedEvent(post));
}
- if (reply.getTime() < getSoneFollowingTime(sone)) {
- reply.setKnown(true);
- } else if (!reply.isKnown()) {
- newPostReplies.add(reply);
+ });
+ soneChangeDetector.onNewPostReplies(new PostReplyProcessor() {
+ @Override
+ public void processPostReply(PostReply postReply) {
+ if (postReply.getTime() < getSoneFollowingTime(sone)) {
+ postReply.setKnown(true);
+ } else if (!postReply.isKnown()) {
+ eventBus.post(new NewPostReplyFoundEvent(postReply));
+ }
}
- }
- database.storePostReplies(sone, sone.getReplies());
- for (Album album : storedSone.get().getRootAlbum().getAlbums()) {
- database.removeAlbum(album);
- for (Image image : album.getImages()) {
- database.removeImage(image);
+ });
+ soneChangeDetector.onRemovedPostReplies(new PostReplyProcessor() {
+ @Override
+ public void processPostReply(PostReply postReply) {
+ eventBus.post(new PostReplyRemovedEvent(postReply));
}
- }
- for (Post removedPost : removedPosts) {
- eventBus.post(new PostRemovedEvent(removedPost));
- }
- for (Post newPost : newPosts) {
- eventBus.post(new NewPostFoundEvent(newPost));
- }
- for (PostReply removedPostReply : removedPostReplies) {
- eventBus.post(new PostReplyRemovedEvent(removedPostReply));
- }
- for (PostReply newPostReply : newPostReplies) {
- eventBus.post(new NewPostReplyFoundEvent(newPostReply));
- }
- for (Album album : sone.getRootAlbum().getAlbums()) {
- database.storeAlbum(album);
- for (Image image : album.getImages()) {
- database.storeImage(image);
- }
- }
+ });
+ soneChangeDetector.detectChanges(sone);
+ database.storeSone(sone);
synchronized (sones) {
sone.setOptions(storedSone.get().getOptions());
sone.setKnown(storedSone.get().isKnown());
}
/* load post likes. */
- Set<String> likedPostIds = new HashSet<String>();
- while (true) {
- String likedPostId = configuration.getStringValue(sonePrefix + "/Likes/Post/" + likedPostIds.size() + "/ID").getValue(null);
- if (likedPostId == null) {
- break;
- }
- likedPostIds.add(likedPostId);
- }
+ Set<String> likedPostIds =
+ configurationSoneParser.parseLikedPostIds();
/* load reply likes. */
- Set<String> likedReplyIds = new HashSet<String>();
- while (true) {
- String likedReplyId = configuration.getStringValue(sonePrefix + "/Likes/Reply/" + likedReplyIds.size() + "/ID").getValue(null);
- if (likedReplyId == null) {
- break;
- }
- likedReplyIds.add(likedReplyId);
- }
+ Set<String> likedReplyIds =
+ configurationSoneParser.parseLikedPostReplyIds();
/* load friends. */
- Set<String> friends = new HashSet<String>();
- while (true) {
- String friendId = configuration.getStringValue(sonePrefix + "/Friends/" + friends.size() + "/ID").getValue(null);
- if (friendId == null) {
- break;
- }
- friends.add(friendId);
- }
+ 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 = getOrCreateAlbum(albumId).setSone(sone).modify().setTitle(albumTitle).setDescription(albumDescription).setAlbumImage(albumImageId).update();
- if (albumParentId != null) {
- Album parentAlbum = getAlbum(albumParentId, false);
- 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. */
- 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, false);
- 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. */
String avatarId = configuration.getStringValue(sonePrefix + "/Profile/Avatar").getValue(null);
if (avatarId != null) {
- profile.setAvatar(getImage(avatarId, false));
+ final Map<String, Image> images =
+ configurationSoneParser.getImages();
+ profile.setAvatar(images.get(avatarId));
}
/* load options. */
sone.getRootAlbum().addAlbum(album);
}
soneInserters.get(sone).setLastInsertFingerprint(lastInsertFingerprint);
+ for (Album album : toAllAlbums.apply(sone)) {
+ database.storeAlbum(album);
+ for (Image image : album.getImages()) {
+ database.storeImage(image);
+ }
+ }
}
synchronized (knownSones) {
for (String friend : friends) {
* @return The new album
*/
public Album createAlbum(Sone sone, Album parent) {
- Album album = database.newAlbumBuilder().randomId().build();
+ Album album = database.newAlbumBuilder().randomId().by(sone).build();
database.storeAlbum(album);
- album.setSone(sone);
parent.addAlbum(album);
return album;
}
OwnIdentity ownIdentity = identityRemovedEvent.ownIdentity();
Identity identity = identityRemovedEvent.identity();
trustedIdentities.remove(ownIdentity, identity);
- boolean foundIdentity = false;
for (Entry<OwnIdentity, Collection<Identity>> trustedIdentity : trustedIdentities.asMap().entrySet()) {
if (trustedIdentity.getKey().equals(ownIdentity)) {
continue;
}
if (trustedIdentity.getValue().contains(identity)) {
- foundIdentity = true;
+ return;
}
}
- if (foundIdentity) {
- /* some local identity still trusts this identity, don’t remove. */
- return;
- }
Optional<Sone> sone = getSone(identity.getId());
if (!sone.isPresent()) {
/* TODO - we don’t have the Sone anymore. should this happen? */