X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;ds=inline;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Fsone%2Fcore%2FCore.java;h=343fe69b5f8a9f6b5ae143a339f07f67f139115d;hb=a6ed1f08b0331a283674795a09f3f6c7377322c7;hp=06a1467b1364c8a353932927388c1f3cfa22e2c2;hpb=7dfc9c778882083632f916b178a241f06c2a08fe;p=Sone.git
diff --git a/src/main/java/net/pterodactylus/sone/core/Core.java b/src/main/java/net/pterodactylus/sone/core/Core.java
index 06a1467..343fe69 100644
--- a/src/main/java/net/pterodactylus/sone/core/Core.java
+++ b/src/main/java/net/pterodactylus/sone/core/Core.java
@@ -39,6 +39,7 @@ import net.pterodactylus.sone.data.Profile;
import net.pterodactylus.sone.data.Profile.Field;
import net.pterodactylus.sone.data.Reply;
import net.pterodactylus.sone.data.Sone;
+import net.pterodactylus.sone.data.TemporaryImage;
import net.pterodactylus.sone.freenet.wot.Identity;
import net.pterodactylus.sone.freenet.wot.IdentityListener;
import net.pterodactylus.sone.freenet.wot.IdentityManager;
@@ -59,7 +60,7 @@ import freenet.keys.FreenetURI;
*
* @author David âBombeâ Roden
*/
-public class Core implements IdentityListener, UpdateListener {
+public class Core implements IdentityListener, UpdateListener, ImageInsertListener {
/**
* Enumeration for the possible states of a {@link Sone}.
@@ -108,6 +109,9 @@ public class Core implements IdentityListener, UpdateListener {
/** The Sone downloader. */
private final SoneDownloader soneDownloader;
+ /** The image inserter. */
+ private final ImageInserter imageInserter;
+
/** The update checker. */
private final UpdateChecker updateChecker;
@@ -173,6 +177,9 @@ public class Core implements IdentityListener, UpdateListener {
/** All known images. */
private Map images = new HashMap();
+ /** All temporary images. */
+ private Map temporaryImages = new HashMap();
+
/**
* Creates a new core.
*
@@ -188,6 +195,7 @@ public class Core implements IdentityListener, UpdateListener {
this.freenetInterface = freenetInterface;
this.identityManager = identityManager;
this.soneDownloader = new SoneDownloader(this, freenetInterface);
+ this.imageInserter = new ImageInserter(this, freenetInterface);
this.updateChecker = new UpdateChecker(freenetInterface);
}
@@ -533,7 +541,8 @@ public class Core implements IdentityListener, UpdateListener {
* @return {@code true} if the target Sone is trusted by the origin Sone
*/
public boolean isSoneTrusted(Sone origin, Sone target) {
- return trustedIdentities.containsKey(origin) && trustedIdentities.get(origin.getIdentity()).contains(target);
+ Validation.begin().isNotNull("Origin", origin).isNotNull("Target", target).check().isInstanceOf("Originâs OwnIdentity", origin.getIdentity(), OwnIdentity.class).check();
+ return trustedIdentities.containsKey(origin.getIdentity()) && trustedIdentities.get(origin.getIdentity()).contains(target.getIdentity());
}
/**
@@ -541,7 +550,7 @@ public class Core implements IdentityListener, UpdateListener {
*
* @param postId
* The ID of the post to get
- * @return The post, or {@code null} if there is no such post
+ * @return The post with the given ID, or a new post with the given ID
*/
public Post getPost(String postId) {
return getPost(postId, true);
@@ -583,6 +592,27 @@ public class Core implements IdentityListener, UpdateListener {
}
/**
+ * Returns all posts that have the given Sone as recipient.
+ *
+ * @see Post#getRecipient()
+ * @param recipient
+ * The recipient of the posts
+ * @return All posts that have the given Sone as recipient
+ */
+ public Set getDirectedPosts(Sone recipient) {
+ Validation.begin().isNotNull("Recipient", recipient).check();
+ Set directedPosts = new HashSet();
+ synchronized (posts) {
+ for (Post post : posts.values()) {
+ if (recipient.equals(post.getRecipient())) {
+ directedPosts.add(post);
+ }
+ }
+ }
+ return directedPosts;
+ }
+
+ /**
* Returns the reply with the given ID. If there is no reply with the given
* ID yet, a new one is created.
*
@@ -799,6 +829,20 @@ public class Core implements IdentityListener, UpdateListener {
}
}
+ /**
+ * Returns the temporary image with the given ID.
+ *
+ * @param imageId
+ * The ID of the temporary image
+ * @return The temporary image, or {@code null} if there is no temporary
+ * image with the given ID
+ */
+ public TemporaryImage getTemporaryImage(String imageId) {
+ synchronized (temporaryImages) {
+ return temporaryImages.get(imageId);
+ }
+ }
+
//
// ACTIONS
//
@@ -894,7 +938,6 @@ public class Core implements IdentityListener, UpdateListener {
@SuppressWarnings("synthetic-access")
public void run() {
if (!preferences.isSoneRescueMode()) {
- soneDownloader.fetchSone(sone);
return;
}
logger.log(Level.INFO, "Trying to restore Sone from Freenetâ¦");
@@ -932,6 +975,8 @@ public class Core implements IdentityListener, UpdateListener {
return null;
}
Sone sone = addLocalSone(ownIdentity);
+ sone.getOptions().addBooleanOption("AutoFollow", new DefaultOption(false));
+ saveSone(sone);
return sone;
}
@@ -961,6 +1006,11 @@ public class Core implements IdentityListener, UpdateListener {
}
if (newSone) {
coreListenerManager.fireNewSoneFound(sone);
+ for (Sone localSone : getLocalSones()) {
+ if (localSone.getOptions().getBooleanOption("AutoFollow").get()) {
+ localSone.addFriend(sone.getId());
+ }
+ }
}
}
remoteSones.put(identity.getId(), sone);
@@ -1150,6 +1200,7 @@ public class Core implements IdentityListener, UpdateListener {
storedSone.setReplies(sone.getReplies());
storedSone.setLikePostIds(sone.getLikedPostIds());
storedSone.setLikeReplyIds(sone.getLikedReplyIds());
+ storedSone.setAlbums(sone.getAlbums());
}
storedSone.setLatestEdition(sone.getLatestEdition());
}
@@ -1321,8 +1372,9 @@ public class Core implements IdentityListener, UpdateListener {
/* load albums. */
List topLevelAlbums = new ArrayList();
+ int albumCounter = 0;
while (true) {
- String albumPrefix = sonePrefix + "/Albums/" + albums.size();
+ String albumPrefix = sonePrefix + "/Albums/" + albumCounter++;
String albumId = configuration.getStringValue(albumPrefix + "/ID").getValue(null);
if (albumId == null) {
break;
@@ -1347,6 +1399,35 @@ public class Core implements IdentityListener, UpdateListener {
}
}
+ /* 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).setSone(sone).setCreationTime(creationTime).setKey(key);
+ image.setTitle(title).setDescription(description).setWidth(width).setHeight(height);
+ album.addImage(image);
+ }
+
/* load options. */
sone.getOptions().addBooleanOption("AutoFollow", new DefaultOption(false));
sone.getOptions().getBooleanOption("AutoFollow").set(configuration.getBooleanValue(sonePrefix + "/Options/AutoFollow").getValue(null));
@@ -1468,16 +1549,7 @@ public class Core implements IdentityListener, UpdateListener {
configuration.getStringValue(sonePrefix + "/Friends/" + friendCounter + "/ID").setValue(null);
/* save albums. first, collect in a flat structure, top-level first. */
- List albums = new ArrayList();
- albums.addAll(sone.getAlbums());
- int lastAlbumIndex = 0;
- while (lastAlbumIndex < albums.size()) {
- int previousAlbumCount = albums.size();
- for (Album album : new ArrayList(albums.subList(lastAlbumIndex, albums.size()))) {
- albums.addAll(album.getAlbums());
- }
- lastAlbumIndex = previousAlbumCount;
- }
+ List albums = Sone.flattenAlbums(sone.getAlbums());
int albumCounter = 0;
for (Album album : albums) {
@@ -1489,6 +1561,26 @@ public class Core implements IdentityListener, UpdateListener {
}
configuration.getStringValue(sonePrefix + "/Albums/" + albumCounter + "/ID").setValue(null);
+ /* save images. */
+ int imageCounter = 0;
+ for (Album album : albums) {
+ for (Image image : album.getImages()) {
+ if (!image.isInserted()) {
+ continue;
+ }
+ String imagePrefix = sonePrefix + "/Images/" + imageCounter++;
+ configuration.getStringValue(imagePrefix + "/ID").setValue(image.getId());
+ configuration.getStringValue(imagePrefix + "/Album").setValue(album.getId());
+ configuration.getStringValue(imagePrefix + "/Key").setValue(image.getKey());
+ configuration.getStringValue(imagePrefix + "/Title").setValue(image.getTitle());
+ configuration.getStringValue(imagePrefix + "/Description").setValue(image.getDescription());
+ configuration.getLongValue(imagePrefix + "/CreationTime").setValue(image.getCreationTime());
+ configuration.getIntValue(imagePrefix + "/Width").setValue(image.getWidth());
+ configuration.getIntValue(imagePrefix + "/Height").setValue(image.getHeight());
+ }
+ }
+ configuration.getStringValue(sonePrefix + "/Images/" + imageCounter + "/ID").setValue(null);
+
/* save options. */
configuration.getBooleanValue(sonePrefix + "/Options/AutoFollow").setValue(sone.getOptions().getBooleanOption("AutoFollow").getReal());
@@ -1572,7 +1664,8 @@ public class Core implements IdentityListener, UpdateListener {
posts.put(post.getId(), post);
}
synchronized (newPosts) {
- knownPosts.add(post.getId());
+ newPosts.add(post.getId());
+ coreListenerManager.fireNewPostFound(post);
}
sone.addPost(post);
saveSone(sone);
@@ -1594,6 +1687,10 @@ public class Core implements IdentityListener, UpdateListener {
synchronized (posts) {
posts.remove(post.getId());
}
+ synchronized (newPosts) {
+ markPostKnown(post);
+ knownPosts.remove(post.getId());
+ }
saveSone(post.getSone());
}
@@ -1696,7 +1793,8 @@ public class Core implements IdentityListener, UpdateListener {
replies.put(reply.getId(), reply);
}
synchronized (newReplies) {
- knownReplies.add(reply.getId());
+ newReplies.add(reply.getId());
+ coreListenerManager.fireNewReplyFound(reply);
}
sone.addReply(reply);
saveSone(sone);
@@ -1718,6 +1816,10 @@ public class Core implements IdentityListener, UpdateListener {
synchronized (replies) {
replies.remove(reply.getId());
}
+ synchronized (newReplies) {
+ markReplyKnown(reply);
+ knownReplies.remove(reply.getId());
+ }
sone.removeReply(reply);
saveSone(sone);
}
@@ -1775,6 +1877,115 @@ public class Core implements IdentityListener, UpdateListener {
}
/**
+ * Deletes the given album. The owner of the album has to be a local Sone,
+ * and the album has to be {@link Album#isEmpty() empty} to be deleted.
+ *
+ * @param album
+ * The album to remove
+ */
+ public void deleteAlbum(Album album) {
+ Validation.begin().isNotNull("Album", album).check().is("Local Sone", isLocalSone(album.getSone())).check();
+ if (!album.isEmpty()) {
+ return;
+ }
+ if (album.getParent() == null) {
+ album.getSone().removeAlbum(album);
+ } else {
+ album.getParent().removeAlbum(album);
+ }
+ synchronized (albums) {
+ albums.remove(album.getId());
+ }
+ saveSone(album.getSone());
+ }
+
+ /**
+ * Creates a new image.
+ *
+ * @param sone
+ * The Sone creating the image
+ * @param album
+ * The album the image will be inserted into
+ * @param temporaryImage
+ * The temporary image to create the image from
+ * @return The newly created image
+ */
+ public Image createImage(Sone sone, Album album, TemporaryImage temporaryImage) {
+ Validation.begin().isNotNull("Sone", sone).isNotNull("Album", album).isNotNull("Temporary Image", temporaryImage).check().is("Local Sone", isLocalSone(sone)).check().isEqual("Owner and Album Owner", sone, album.getSone()).check();
+ Image image = new Image(temporaryImage.getId()).setSone(sone).setCreationTime(System.currentTimeMillis());
+ album.addImage(image);
+ synchronized (images) {
+ images.put(image.getId(), image);
+ }
+ imageInserter.insertImage(temporaryImage, image);
+ return image;
+ }
+
+ /**
+ * Deletes the given image. This method will also delete a matching
+ * temporary image.
+ *
+ * @see #deleteTemporaryImage(TemporaryImage)
+ * @param image
+ * The image to delete
+ */
+ public void deleteImage(Image image) {
+ Validation.begin().isNotNull("Image", image).check().is("Local Sone", isLocalSone(image.getSone())).check();
+ deleteTemporaryImage(image.getId());
+ image.getAlbum().removeImage(image);
+ synchronized (images) {
+ images.remove(image.getId());
+ }
+ saveSone(image.getSone());
+ }
+
+ /**
+ * Creates a new temporary image.
+ *
+ * @param mimeType
+ * The MIME type of the temporary image
+ * @param imageData
+ * The encoded data of the image
+ * @return The temporary image
+ */
+ public TemporaryImage createTemporaryImage(String mimeType, byte[] imageData) {
+ TemporaryImage temporaryImage = new TemporaryImage();
+ temporaryImage.setMimeType(mimeType).setImageData(imageData);
+ synchronized (temporaryImages) {
+ temporaryImages.put(temporaryImage.getId(), temporaryImage);
+ }
+ return temporaryImage;
+ }
+
+ /**
+ * Deletes the given temporary image.
+ *
+ * @param temporaryImage
+ * The temporary image to delete
+ */
+ public void deleteTemporaryImage(TemporaryImage temporaryImage) {
+ Validation.begin().isNotNull("Temporary Image", temporaryImage).check();
+ deleteTemporaryImage(temporaryImage.getId());
+ }
+
+ /**
+ * Deletes the temporary image with the given ID.
+ *
+ * @param imageId
+ * The ID of the temporary image to delete
+ */
+ public void deleteTemporaryImage(String imageId) {
+ Validation.begin().isNotNull("Temporary Image ID", imageId).check();
+ synchronized (temporaryImages) {
+ temporaryImages.remove(imageId);
+ }
+ Image image = getImage(imageId, false);
+ if (image != null) {
+ imageInserter.cancelImageInsert(image);
+ }
+ }
+
+ /**
* Starts the core.
*/
public void start() {
@@ -1815,6 +2026,7 @@ public class Core implements IdentityListener, UpdateListener {
try {
configuration.getIntValue("Option/ConfigurationVersion").setValue(0);
configuration.getIntValue("Option/InsertionDelay").setValue(options.getIntegerOption("InsertionDelay").getReal());
+ configuration.getIntValue("Option/PostsPerPage").setValue(options.getIntegerOption("PostsPerPage").getReal());
configuration.getIntValue("Option/PositiveTrust").setValue(options.getIntegerOption("PositiveTrust").getReal());
configuration.getIntValue("Option/NegativeTrust").setValue(options.getIntegerOption("NegativeTrust").getReal());
configuration.getStringValue("Option/TrustComment").setValue(options.getStringOption("TrustComment").getReal());
@@ -1888,8 +2100,9 @@ public class Core implements IdentityListener, UpdateListener {
}
}));
+ options.addIntegerOption("PostsPerPage", new DefaultOption(10));
options.addIntegerOption("PositiveTrust", new DefaultOption(75));
- options.addIntegerOption("NegativeTrust", new DefaultOption(-100));
+ options.addIntegerOption("NegativeTrust", new DefaultOption(-25));
options.addStringOption("TrustComment", new DefaultOption("Set from Sone Web Interface"));
options.addBooleanOption("SoneRescueMode", new DefaultOption(false));
options.addBooleanOption("ClearOnNextRestart", new DefaultOption(false));
@@ -1907,6 +2120,7 @@ public class Core implements IdentityListener, UpdateListener {
}
options.getIntegerOption("InsertionDelay").set(configuration.getIntValue("Option/InsertionDelay").getValue(null));
+ options.getIntegerOption("PostsPerPage").set(configuration.getIntValue("Option/PostsPerPage").getValue(null));
options.getIntegerOption("PositiveTrust").set(configuration.getIntValue("Option/PositiveTrust").getValue(null));
options.getIntegerOption("NegativeTrust").set(configuration.getIntValue("Option/NegativeTrust").getValue(null));
options.getStringOption("TrustComment").set(configuration.getStringValue("Option/TrustComment").getValue(null));
@@ -2052,6 +2266,49 @@ public class Core implements IdentityListener, UpdateListener {
coreListenerManager.fireUpdateFound(version, releaseTime, latestEdition);
}
+ //
+ // INTERFACE ImageInsertListener
+ //
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void imageInsertStarted(Image image) {
+ logger.log(Level.WARNING, "Image insert started for " + image);
+ coreListenerManager.fireImageInsertStarted(image);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void imageInsertAborted(Image image) {
+ logger.log(Level.WARNING, "Image insert aborted for " + image);
+ coreListenerManager.fireImageInsertAborted(image);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void imageInsertFinished(Image image, FreenetURI key) {
+ logger.log(Level.WARNING, "Image insert finished for " + image + ": " + key);
+ image.setKey(key.toString());
+ deleteTemporaryImage(image.getId());
+ saveSone(image.getSone());
+ coreListenerManager.fireImageInsertFinished(image);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void imageInsertFailed(Image image, Throwable cause) {
+ logger.log(Level.WARNING, "Image insert failed for " + image, cause);
+ coreListenerManager.fireImageInsertFailed(image, cause);
+ }
+
/**
* Convenience interface for external classes that want to access the coreâs
* configuration.
@@ -2096,6 +2353,27 @@ public class Core implements IdentityListener, UpdateListener {
}
/**
+ * Returns the number of posts to show per page.
+ *
+ * @return The number of posts to show per page
+ */
+ public int getPostsPerPage() {
+ return options.getIntegerOption("PostsPerPage").get();
+ }
+
+ /**
+ * Sets the number of posts to show per page.
+ *
+ * @param postsPerPage
+ * The number of posts to show per page
+ * @return This preferences object
+ */
+ public Preferences setPostsPerPage(Integer postsPerPage) {
+ options.getIntegerOption("PostsPerPage").set(postsPerPage);
+ return this;
+ }
+
+ /**
* Returns the positive trust.
*
* @return The positive trust