X-Git-Url: https://git.pterodactylus.net/?p=Sone.git;a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Fsone%2Fcore%2FCore.java;h=9beeac4df5deb5b667b72eb5e4e4eb95be217a94;hp=e08acd136f1ec212732c879bd98d7407a9e470e6;hb=1c0a2b5e67dda41e75d2315fd0f6f1cfecf26fa6;hpb=ffb2ea1773cf7e3d1b7fc41ab0e9c3c1eed514e0 diff --git a/src/main/java/net/pterodactylus/sone/core/Core.java b/src/main/java/net/pterodactylus/sone/core/Core.java index e08acd1..9beeac4 100644 --- a/src/main/java/net/pterodactylus/sone/core/Core.java +++ b/src/main/java/net/pterodactylus/sone/core/Core.java @@ -17,11 +17,15 @@ 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; @@ -40,10 +44,13 @@ 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; @@ -73,6 +80,7 @@ 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; @@ -338,9 +346,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, */ @Override public Collection getSones() { - synchronized (sones) { - return ImmutableSet.copyOf(sones.values()); - } + return database.getSones(); } /** @@ -354,9 +360,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, */ @Override public Optional getSone(String id) { - synchronized (sones) { - return Optional.fromNullable(sones.get(id)); - } + return database.getSone(id); } /** @@ -364,9 +368,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, */ @Override public Collection getLocalSones() { - synchronized (sones) { - return FluentIterable.from(sones.values()).filter(LOCAL_SONE_FILTER).toSet(); - } + return database.getLocalSones(); } /** @@ -399,9 +401,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, */ @Override public Collection getRemoteSones() { - synchronized (sones) { - return FluentIterable.from(sones.values()).filter(not(LOCAL_SONE_FILTER)).toSet(); - } + return database.getRemoteSones(); } /** @@ -605,6 +605,10 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, return database.getAlbum(albumId).orNull(); } + public ImageBuilder imageBuilder() { + return database.newImageBuilder(); + } + /** * Returns the image with the given ID, creating it if necessary. * @@ -716,7 +720,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, sone.setKnown(true); /* TODO - load posts ’n stuff */ sones.put(ownIdentity.getId(), sone); - final SoneInserter soneInserter = new SoneInserter(this, eventBus, freenetInterface, sone); + SoneInserter soneInserter = new SoneInserter(this, eventBus, freenetInterface, ownIdentity.getId()); soneInserters.put(sone, soneInserter); sone.setStatus(SoneStatus.idle); loadSone(sone); @@ -756,6 +760,8 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, 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()) { @@ -764,7 +770,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, 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()); @@ -934,7 +940,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, * {@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 storedSone = getSone(sone.getId()); if (storedSone.isPresent()) { if (!soneRescueMode && !(sone.getTime() > storedSone.get().getTime())) { @@ -942,78 +948,46 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, return; } /* find removed posts. */ - Collection removedPosts = new ArrayList(); - Collection newPosts = new ArrayList(); - Collection 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 newPostReplies = new ArrayList(); - Collection removedPostReplies = new ArrayList(); - 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 storedReplies = storedSone.get().getReplies(); - for (PostReply reply : sone.getReplies()) { - if (storedReplies.contains(reply)) { - continue; - } - if (reply.getTime() < getSoneFollowingTime(sone)) { - reply.setKnown(true); - } else if (!reply.isKnown()) { - newPostReplies.add(reply); + }); + soneChangeDetector.onRemovedPosts(new PostProcessor() { + @Override + public void processPost(Post post) { + eventBus.post(new PostRemovedEvent(post)); } - } - database.storePostReplies(sone, sone.getReplies()); - for (Album album : storedSone.get().getRootAlbum().getAlbums()) { - database.removeAlbum(album); - for (Image image : album.getImages()) { - database.removeImage(image); + }); + 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)); + } } - } - 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.onRemovedPostReplies(new PostReplyProcessor() { + @Override + public void processPostReply(PostReply postReply) { + eventBus.post(new PostReplyRemovedEvent(postReply)); } - } + }); + soneChangeDetector.detectChanges(sone); + database.storeSone(sone); synchronized (sones) { sone.setOptions(storedSone.get().getOptions()); sone.setKnown(storedSone.get().isKnown()); sone.setStatus((sone.getTime() == 0) ? SoneStatus.unknown : SoneStatus.idle); if (sone.isLocal()) { - soneInserters.get(storedSone.get()).setSone(sone); touchConfiguration(); } sones.put(sone.getId(), sone); @@ -1141,37 +1115,24 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, } /* 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. */ String avatarId = configuration.getStringValue(sonePrefix + "/Profile/Avatar").getValue(null); if (avatarId != null) { - profile.setAvatar(getImage(avatarId, false)); + final Map images = + configurationSoneParser.getImages(); + profile.setAvatar(images.get(avatarId)); } /* load options. */ @@ -1200,6 +1161,12 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, 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) { @@ -1947,19 +1914,14 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, OwnIdentity ownIdentity = identityRemovedEvent.ownIdentity(); Identity identity = identityRemovedEvent.identity(); trustedIdentities.remove(ownIdentity, identity); - boolean foundIdentity = false; for (Entry> 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 = getSone(identity.getId()); if (!sone.isPresent()) { /* TODO - we don’t have the Sone anymore. should this happen? */