Implement ImageInsertListener interface in Core.
[Sone.git] / src / main / java / net / pterodactylus / sone / core / Core.java
index 9c2cedc..2b619b6 100644 (file)
@@ -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 <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
  */
-public class Core implements IdentityListener, UpdateListener {
+public class Core implements IdentityListener, UpdateListener, ImageInsertListener {
 
        /**
         * Enumeration for the possible states of a {@link Sone}.
@@ -173,6 +174,9 @@ public class Core implements IdentityListener, UpdateListener {
        /** All known images. */
        private Map<String, Image> images = new HashMap<String, Image>();
 
+       /** All temporary images. */
+       private Map<String, TemporaryImage> temporaryImages = new HashMap<String, TemporaryImage>();
+
        /**
         * Creates a new core.
         *
@@ -799,6 +803,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
        //
@@ -1319,6 +1337,67 @@ public class Core implements IdentityListener, UpdateListener {
                        friends.add(friendId);
                }
 
+               /* load albums. */
+               List<Album> topLevelAlbums = new ArrayList<Album>();
+               while (true) {
+                       String albumPrefix = sonePrefix + "/Albums/" + albums.size();
+                       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);
+                       if ((albumTitle == null) || (albumDescription == null)) {
+                               logger.log(Level.WARNING, "Invalid album found, aborting load!");
+                               return;
+                       }
+                       Album album = getAlbum(albumId).setSone(sone).setTitle(albumTitle).setDescription(albumDescription);
+                       if (albumParentId != null) {
+                               Album parentAlbum = getAlbum(albumParentId, false);
+                               if (parentAlbum == null) {
+                                       logger.log(Level.WARNING, "Invalid parent album ID: " + albumParentId);
+                                       return;
+                               }
+                               parentAlbum.addAlbum(album);
+                       } else {
+                               topLevelAlbums.add(album);
+                       }
+               }
+
+               /* 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<Boolean>(false));
+               sone.getOptions().getBooleanOption("AutoFollow").set(configuration.getBooleanValue(sonePrefix + "/Options/AutoFollow").getValue(null));
+
                /* if we’re still here, Sone was loaded successfully. */
                synchronized (sone) {
                        sone.setTime(soneTime);
@@ -1328,6 +1407,7 @@ public class Core implements IdentityListener, UpdateListener {
                        sone.setLikePostIds(likedPostIds);
                        sone.setLikeReplyIds(likedReplyIds);
                        sone.setFriends(friends);
+                       sone.setAlbums(topLevelAlbums);
                        soneInserters.get(sone).setLastInsertFingerprint(lastInsertFingerprint);
                }
                synchronized (newSones) {
@@ -1434,6 +1514,51 @@ 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<Album> albums = new ArrayList<Album>();
+                       albums.addAll(sone.getAlbums());
+                       int lastAlbumIndex = 0;
+                       while (lastAlbumIndex < albums.size()) {
+                               int previousAlbumCount = albums.size();
+                               for (Album album : new ArrayList<Album>(albums.subList(lastAlbumIndex, albums.size()))) {
+                                       albums.addAll(album.getAlbums());
+                               }
+                               lastAlbumIndex = previousAlbumCount;
+                       }
+
+                       int albumCounter = 0;
+                       for (Album album : albums) {
+                               String albumPrefix = sonePrefix + "/Albums/" + albumCounter++;
+                               configuration.getStringValue(albumPrefix + "/ID").setValue(album.getId());
+                               configuration.getStringValue(albumPrefix + "/Title").setValue(album.getTitle());
+                               configuration.getStringValue(albumPrefix + "/Description").setValue(album.getDescription());
+                               configuration.getStringValue(albumPrefix + "/Parent").setValue(album.getParent() == null ? null : album.getParent().getId());
+                       }
+                       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());
+
                        configuration.save();
                        logger.log(Level.INFO, "Sone %s saved.", sone);
                } catch (ConfigurationException ce1) {
@@ -1717,6 +1842,69 @@ public class Core implements IdentityListener, UpdateListener {
        }
 
        /**
+        * 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);
+               }
+               return image;
+       }
+
+       /**
+        * 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 deteleTemporaryImage(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);
+               }
+       }
+
+       /**
         * Starts the core.
         */
        public void start() {
@@ -1994,6 +2182,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.