Add isRoot() method to Album, only dump album ID in sone.xml if the parent is not...
[Sone.git] / src / main / java / net / pterodactylus / sone / data / Album.java
index c1ae267..8238b3f 100644 (file)
@@ -20,6 +20,7 @@ package net.pterodactylus.sone.data;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
+import static java.util.Arrays.asList;
 
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -30,15 +31,20 @@ import java.util.UUID;
 
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.Collections2;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
 
 /**
  * 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 {
+public class Album implements Identified, Fingerprintable {
 
        /** Compares two {@link Album}s by {@link #getTitle()}. */
        public static final Comparator<Album> TITLE_COMPARATOR = new Comparator<Album>() {
@@ -49,6 +55,55 @@ public class Album implements Fingerprintable {
                }
        };
 
+       /** Function that flattens the given album and all albums beneath it. */
+       public static final Function<Album, List<Album>> FLATTENER = new Function<Album, List<Album>>() {
+
+               @Override
+               public List<Album> apply(Album album) {
+                       List<Album> albums = new ArrayList<Album>();
+                       albums.add(album);
+                       for (Album subAlbum : album.getAlbums()) {
+                               albums.addAll(FluentIterable.from(ImmutableList.of(subAlbum)).transformAndConcat(FLATTENER).toList());
+                       }
+                       return albums;
+               }
+       };
+
+       /** Function that transforms an album into the images it contains. */
+       public static final Function<Album, List<Image>> IMAGES = new Function<Album, List<Image>>() {
+
+               @Override
+               public List<Image> apply(Album album) {
+                       return album.getImages();
+               }
+       };
+
+       /**
+        * Filter that removes all albums that do not have any images in any album
+        * below it.
+        */
+       public static final Predicate<Album> NOT_EMPTY = new Predicate<Album>() {
+
+               @Override
+               public boolean apply(Album album) {
+                       /* so, we flatten all albums below the given one and check whether at least one album… */
+                       return FluentIterable.from(asList(album)).transformAndConcat(FLATTENER).anyMatch(new Predicate<Album>() {
+
+                               @Override
+                               public boolean apply(Album album) {
+                                       /* …contains any inserted images. */
+                                       return !album.getImages().isEmpty() && FluentIterable.from(album.getImages()).allMatch(new Predicate<Image>() {
+
+                                               @Override
+                                               public boolean apply(Image input) {
+                                                       return input.isInserted();
+                                               }
+                                       });
+                               }
+                       });
+               }
+       };
+
        /** The ID of this album. */
        private final String id;
 
@@ -148,7 +203,6 @@ public class Album implements Fingerprintable {
        public void addAlbum(Album album) {
                checkNotNull(album, "album must not be null");
                checkArgument(album.getSone().equals(sone), "album must belong to the same Sone as this album");
-               checkState((this.parent == null) || (this.parent.equals(album.parent)), "album must not already be set to some other Sone");
                album.setParent(this);
                if (!albums.contains(album)) {
                        albums.add(album);
@@ -354,6 +408,16 @@ public class Album implements Fingerprintable {
        }
 
        /**
+        * Returns whether this album is an identitiy’s root album.
+        *
+        * @return {@code true} if this album is an identity’s root album, {@code
+        *         false} otherwise
+        */
+       public boolean isRoot() {
+               return parent == null;
+       }
+
+       /**
         * Returns the parent album of this album.
         *
         * @return The parent album of this album, or {@code null} if this album
@@ -436,33 +500,33 @@ public class Album implements Fingerprintable {
         */
        @Override
        public String getFingerprint() {
-               StringBuilder fingerprint = new StringBuilder();
-               fingerprint.append("Album(");
-               fingerprint.append("ID(").append(id).append(')');
-               fingerprint.append("Title(").append(title).append(')');
-               fingerprint.append("Description(").append(description).append(')');
+               Hasher hash = Hashing.sha256().newHasher();
+               hash.putString("Album(");
+               hash.putString("ID(").putString(id).putString(")");
+               hash.putString("Title(").putString(title).putString(")");
+               hash.putString("Description(").putString(description).putString(")");
                if (albumImage != null) {
-                       fingerprint.append("AlbumImage(").append(albumImage).append(')');
+                       hash.putString("AlbumImage(").putString(albumImage).putString(")");
                }
 
                /* add nested albums. */
-               fingerprint.append("Albums(");
+               hash.putString("Albums(");
                for (Album album : albums) {
-                       fingerprint.append(album.getFingerprint());
+                       hash.putString(album.getFingerprint());
                }
-               fingerprint.append(')');
+               hash.putString(")");
 
                /* add images. */
-               fingerprint.append("Images(");
+               hash.putString("Images(");
                for (Image image : getImages()) {
                        if (image.isInserted()) {
-                               fingerprint.append(image.getFingerprint());
+                               hash.putString(image.getFingerprint());
                        }
                }
-               fingerprint.append(')');
+               hash.putString(")");
 
-               fingerprint.append(')');
-               return fingerprint.toString();
+               hash.putString(")");
+               return hash.hash().toString();
        }
 
        //