Merge branch 'next' into image-management
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Mon, 10 Jan 2011 19:16:25 +0000 (20:16 +0100)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Mon, 10 Jan 2011 19:16:25 +0000 (20:16 +0100)
src/main/java/net/pterodactylus/sone/data/Album.java [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/data/Fingerprintable.java [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/data/Image.java [new file with mode: 0644]
src/main/java/net/pterodactylus/sone/data/Sone.java
src/main/resources/templates/insert/include/album.xml [new file with mode: 0644]
src/main/resources/templates/insert/sone.xml

diff --git a/src/main/java/net/pterodactylus/sone/data/Album.java b/src/main/java/net/pterodactylus/sone/data/Album.java
new file mode 100644 (file)
index 0000000..76015c8
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * Sone - Album.java - Copyright © 2011 David Roden
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import net.pterodactylus.util.validation.Validation;
+
+/**
+ * Container for images that can also contain nested {@link Album}s.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class Album implements Fingerprintable {
+
+       /** The ID of this album. */
+       private final String id;
+
+       /** The Sone this album belongs to. */
+       private final Sone sone;
+
+       /** Nested albums. */
+       private final List<Album> albums = new ArrayList<Album>();
+
+       /** The images in this album. */
+       private final List<Image> images = new ArrayList<Image>();
+
+       /** The parent album. */
+       private Album parent;
+
+       /** The name of this album. */
+       private String name;
+
+       /** The description of this album. */
+       private String description;
+
+       /**
+        * Creates a new album with a random ID.
+        *
+        * @param sone
+        *            The Sone this album belongs to
+        */
+       public Album(Sone sone) {
+               this(UUID.randomUUID().toString(), sone);
+       }
+
+       /**
+        * Creates a new album with the given ID.
+        *
+        * @param id
+        *            The ID of the album
+        * @param sone
+        *            The Sone this album belongs to
+        */
+       public Album(String id, Sone sone) {
+               Validation.begin().isNotNull("Album ID", id).isNotNull("Album Owner", sone).check();
+               this.id = id;
+               this.sone = sone;
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the ID of this album.
+        *
+        * @return The ID of this album
+        */
+       public String getId() {
+               return id;
+       }
+
+       /**
+        * Returns the Sone this album belongs to.
+        *
+        * @return The Sone this album belongs to
+        */
+       public Sone getSone() {
+               return sone;
+       }
+
+       /**
+        * Returns the nested albums.
+        *
+        * @return The nested albums
+        */
+       public List<Album> getNestedAlbums() {
+               return new ArrayList<Album>(albums);
+       }
+
+       /**
+        * Adds an album to this album.
+        *
+        * @param album
+        *            The album to add
+        */
+       public void addAlbum(Album album) {
+               Validation.begin().isNotNull("Album", album).check().isEqual("Album Owner", album.sone, sone).isNull("Album Parent", album.parent).check();
+               albums.add(album);
+               album.setParent(this);
+       }
+
+       /**
+        * Removes an album from this album.
+        *
+        * @param album
+        *            The album to remove
+        */
+       public void removeAlbum(Album album) {
+               Validation.begin().isNotNull("Album", album).check().isEqual("Album Owner", album.sone, sone).isEqual("Album Parent", album.parent, this).check();
+               albums.remove(album);
+               album.removeParent();
+       }
+
+       /**
+        * Returns the images in this album.
+        *
+        * @return The images in this album
+        */
+       public List<Image> getImages() {
+               return new ArrayList<Image>(images);
+       }
+
+       /**
+        * Adds the given image to this album.
+        *
+        * @param image
+        *            The image to add
+        */
+       public void addImage(Image image) {
+               Validation.begin().isNotNull("Image", image).check().isEqual("Image Owner", image.getSone(), sone).check();
+               images.add(image);
+       }
+
+       /**
+        * Removes the given image from this album.
+        *
+        * @param image
+        *            The image to remove
+        */
+       public void removeImage(Image image) {
+               Validation.begin().isNotNull("Image", image).check().isEqual("Image Owner", image.getSone(), sone).check();
+               images.remove(image);
+       }
+
+       /**
+        * Returns the parent album of this album.
+        *
+        * @return The parent album of this album, or {@code null} if this album
+        *         does not have a parent
+        */
+       public Album getParent() {
+               return parent;
+       }
+
+       /**
+        * Sets the parent album of this album.
+        *
+        * @param parent
+        *            The new parent album of this album
+        * @return This album
+        */
+       protected Album setParent(Album parent) {
+               Validation.begin().isNotNull("Album Parent", parent).check();
+               this.parent = parent;
+               return this;
+       }
+
+       /**
+        * Removes the parent album of this album.
+        *
+        * @return This album
+        */
+       protected Album removeParent() {
+               Validation.begin().isNotNull("Album Parent", parent).check();
+               this.parent = null;
+               return this;
+       }
+
+       /**
+        * Returns the name of this album.
+        *
+        * @return The name of this album
+        */
+       public String getName() {
+               return name;
+       }
+
+       /**
+        * Sets the name of this album.
+        *
+        * @param name
+        *            The name of this album
+        * @return This album
+        */
+       public Album setName(String name) {
+               Validation.begin().isNotNull("Album Name", name).check();
+               this.name = name;
+               return this;
+       }
+
+       /**
+        * Returns the description of this album.
+        *
+        * @return The description of this album
+        */
+       public String getDescription() {
+               return description;
+       }
+
+       /**
+        * Sets the description of this album.
+        *
+        * @param description
+        *            The description of this album
+        * @return This album
+        */
+       public Album setDescription(String description) {
+               Validation.begin().isNotNull("Album Description", description).check();
+               this.description = description;
+               return this;
+       }
+
+       //
+       // FINGERPRINTABLE METHODS
+       //
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       public String getFingerprint() {
+               StringBuilder fingerprint = new StringBuilder();
+               fingerprint.append("Album(");
+               fingerprint.append("ID(").append(id).append(')');
+               fingerprint.append("Name(").append(name).append(')');
+               fingerprint.append("Description(").append(description).append(')');
+
+               /* add nested albums. */
+               fingerprint.append("Albums(");
+               for (Album album : albums) {
+                       fingerprint.append(album.getFingerprint());
+               }
+               fingerprint.append(')');
+
+               /* add images. */
+               fingerprint.append("Images(");
+               for (Image image : images) {
+                       fingerprint.append(image.getFingerprint());
+               }
+               fingerprint.append(')');
+
+               fingerprint.append(')');
+               return fingerprint.toString();
+       }
+
+       //
+       // OBJECT METHODS
+       //
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       public boolean equals(Object object) {
+               if (!(object instanceof Album)) {
+                       return false;
+               }
+               Album album = (Album) object;
+               return sone.equals(album.sone) && id.equals(album.id);
+       }
+
+}
diff --git a/src/main/java/net/pterodactylus/sone/data/Fingerprintable.java b/src/main/java/net/pterodactylus/sone/data/Fingerprintable.java
new file mode 100644 (file)
index 0000000..013e0b3
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Sone - Fingerprintable.java - Copyright © 2011 David Roden
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data;
+
+/**
+ * Interface for objects that can create a fingerprint of themselves, e.g. to
+ * detect modifications. The fingerprint should only contain original
+ * information; derived information should not be included.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public interface Fingerprintable {
+
+       /**
+        * Returns the fingerprint of this object.
+        *
+        * @return The fingerprint of this object
+        */
+       public String getFingerprint();
+
+}
diff --git a/src/main/java/net/pterodactylus/sone/data/Image.java b/src/main/java/net/pterodactylus/sone/data/Image.java
new file mode 100644 (file)
index 0000000..6b7b1dd
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Sone - Image.java - Copyright © 2011 David Roden
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data;
+
+import java.util.UUID;
+
+import net.pterodactylus.util.validation.Validation;
+
+/**
+ * Container for image metadata.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class Image implements Fingerprintable {
+
+       /** The ID of the image. */
+       private final String id;
+
+       /** The Sone the image belongs to. */
+       private final Sone sone;
+
+       /** The key of the image. */
+       private final String key;
+
+       /** The creation time of the image. */
+       private final long creationTime;
+
+       /** The width of the image. */
+       private final int width;
+
+       /** The height of the image. */
+       private final int height;
+
+       /** The title of the image. */
+       private String title;
+
+       /** The description of the image. */
+       private String description;
+
+       /**
+        * Creates a new image.
+        *
+        * @param sone
+        *            The Sone the image belongs to
+        * @param key
+        *            The key of the image
+        * @param creationTime
+        *            The creation time of the image
+        * @param width
+        *            The width of the image
+        * @param height
+        *            The height of the image
+        */
+       public Image(Sone sone, String key, long creationTime, int width, int height) {
+               this(UUID.randomUUID().toString(), sone, key, creationTime, width, height);
+       }
+
+       /**
+        * Creates a new image.
+        *
+        * @param id
+        *            The ID of the image
+        * @param sone
+        *            The Sone the image belongs to
+        * @param key
+        *            The key of the image
+        * @param creationTime
+        *            The creation time of the image
+        * @param width
+        *            The width of the image
+        * @param height
+        *            The height of the image
+        */
+       public Image(String id, Sone sone, String key, long creationTime, int width, int height) {
+               Validation.begin().isNotNull("Image ID", id).isNotNull("Image Owner", sone).isNotNull("Image Key", key).isGreater("Image Creation Time", creationTime, 0).isGreater("Image Width", width, 0).isGreater("Image Height", height, 0).check();
+               this.id = id;
+               this.sone = sone;
+               this.key = key;
+               this.creationTime = creationTime;
+               this.width = width;
+               this.height = height;
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the ID of this image.
+        *
+        * @return The ID of this image
+        */
+       public String getId() {
+               return id;
+       }
+
+       /**
+        * Returns the Sone this image belongs to.
+        *
+        * @return The Sone this image belongs to
+        */
+       public Sone getSone() {
+               return sone;
+       }
+
+       /**
+        * Returns the key of this image.
+        *
+        * @return The key of this image
+        */
+       public String getKey() {
+               return key;
+       }
+
+       /**
+        * Returns the creation time of this image.
+        *
+        * @return The creation time of this image (in milliseconds since 1970, Jan
+        *         1, UTC)
+        */
+       public long getCreationTime() {
+               return creationTime;
+       }
+
+       /**
+        * Returns the width of this image.
+        *
+        * @return The width of this image (in pixels)
+        */
+       public int getWidth() {
+               return width;
+       }
+
+       /**
+        * Returns the height of this image.
+        *
+        * @return The height of this image (in pixels)
+        */
+       public int getHeight() {
+               return height;
+       }
+
+       /**
+        * Returns the title of this image.
+        *
+        * @return The title of this image
+        */
+       public String getTitle() {
+               return title;
+       }
+
+       /**
+        * Sets the title of this image.
+        *
+        * @param title
+        *            The title of this image
+        * @return This image
+        */
+       public Image setTitle(String title) {
+               Validation.begin().isNotNull("Image Title", title).check();
+               this.title = title;
+               return this;
+       }
+
+       /**
+        * Returns the description of this image.
+        *
+        * @return The description of this image
+        */
+       public String getDescription() {
+               return description;
+       }
+
+       /**
+        * Sets the description of this image.
+        *
+        * @param description
+        *            The description of this image
+        * @return This image
+        */
+       public Image setDescription(String description) {
+               Validation.begin().isNotNull("Image Description", description).check();
+               this.description = description;
+               return this;
+       }
+
+       //
+       // FINGERPRINTABLE METHODS
+       //
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       public String getFingerprint() {
+               StringBuilder fingerprint = new StringBuilder();
+               fingerprint.append("Image(");
+               fingerprint.append("ID(").append(id).append(')');
+               fingerprint.append("Title(").append(title).append(')');
+               fingerprint.append("Description(").append(description).append(')');
+               fingerprint.append(')');
+               return fingerprint.toString();
+       }
+
+}
index 7d4f7ef..91b1c10 100644 (file)
@@ -30,6 +30,7 @@ import java.util.logging.Logger;
 import net.pterodactylus.sone.freenet.wot.Identity;
 import net.pterodactylus.sone.template.SoneAccessor;
 import net.pterodactylus.util.logging.Logging;
+import net.pterodactylus.util.validation.Validation;
 import freenet.keys.FreenetURI;
 
 /**
@@ -40,7 +41,7 @@ import freenet.keys.FreenetURI;
  *
  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
  */
-public class Sone {
+public class Sone implements Fingerprintable {
 
        /** comparator that sorts Sones by their nice name. */
        public static final Comparator<Sone> NICE_NAME_COMPARATOR = new Comparator<Sone>() {
@@ -99,6 +100,9 @@ public class Sone {
        /** The IDs of all liked replies. */
        private final Set<String> likedReplyIds = Collections.synchronizedSet(new HashSet<String>());
 
+       /** The albums of this Sone. */
+       private final List<Album> albums = Collections.synchronizedList(new ArrayList<Album>());
+
        /**
         * Creates a new Sone.
         *
@@ -581,13 +585,44 @@ public class Sone {
        }
 
        /**
-        * Returns a fingerprint of this Sone. The fingerprint only depends on data
-        * that is actually stored when a Sone is inserted. The fingerprint can be
-        * used to detect changes in Sone data and can also be used to detect if
-        * previous changes are reverted.
+        * Returns the albums of this Sone.
+        *
+        * @return The albums of this Sone
+        */
+       public List<Album> getAlbums() {
+               return Collections.unmodifiableList(albums);
+       }
+
+       /**
+        * Adds an album to this Sone.
         *
-        * @return The fingerprint of this Sone
+        * @param album
+        *            The album to add
         */
+       public synchronized void addAlbum(Album album) {
+               Validation.begin().isNotNull("Album", album).check().isEqual("Album Owner", album.getSone(), this).check();
+               albums.add(album);
+       }
+
+       /**
+        * Removes an album from this Sone.
+        *
+        * @param album
+        *            The album to remove
+        */
+       public synchronized void removeAlbum(Album album) {
+               Validation.begin().isNotNull("Album", album).check().isEqual("Album Owner", album.getSone(), this).check();
+               albums.remove(album);
+       }
+
+       //
+       // FINGERPRINTABLE METHODS
+       //
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
        public synchronized String getFingerprint() {
                StringBuilder fingerprint = new StringBuilder();
                fingerprint.append("Profile(");
@@ -641,6 +676,12 @@ public class Sone {
                }
                fingerprint.append(')');
 
+               fingerprint.append("Albums(");
+               for (Album album : albums) {
+                       fingerprint.append(album.getFingerprint());
+               }
+               fingerprint.append(')');
+
                return fingerprint.toString();
        }
 
diff --git a/src/main/resources/templates/insert/include/album.xml b/src/main/resources/templates/insert/include/album.xml
new file mode 100644 (file)
index 0000000..cd845da
--- /dev/null
@@ -0,0 +1,23 @@
+<album>
+       <id><% album.id|xml></id>
+       <name><% album.name|xml></name>
+       <description><% album.description|xml></description>
+       <albums>
+               <%foreach album.albums album>
+               <%include insert/include/album.xml>
+               <%/foreach>
+       </albums>
+       <images>
+               <%foreach album.images image>
+               <image>
+                       <id><% image.id|xml></id>
+                       <creation-time><% image.creationTime|xml></creation-time>
+                       <key><% image.key|xml></key>
+                       <width><% image.width|xml></width>
+                       <height><% image.height|xml></height>
+                       <title><% image.title|xml></title>
+                       <description><% image.description|xml></description>
+               </image>
+               <%/foreach>
+       </images>
+</album>
index 7d3c8aa..1f12d90 100644 (file)
                <%/foreach>
        </reply-likes>
 
+       <albums>
+               <%foreach currentSone.albums album>
+               <%include insert/include/album.xml>
+               <%/foreach>
+       </albums>
+
 </sone>