11049293ab484a734078cc60a246688d42264b2e
[Sone.git] / src / main / java / net / pterodactylus / sone / data / Album.java
1 /*
2  * Sone - Album.java - Copyright © 2011–2016 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.sone.data;
19
20 import static java.util.Arrays.asList;
21 import static java.util.Collections.emptyList;
22
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.List;
26 import javax.annotation.Nonnull;
27
28 import com.google.common.base.Function;
29 import com.google.common.base.Predicate;
30 import com.google.common.collect.FluentIterable;
31 import com.google.common.collect.ImmutableList;
32
33 /**
34  * Container for images that can also contain nested {@link Album}s.
35  */
36 public interface Album extends Identified, Fingerprintable {
37
38         /** Function that flattens the given album and all albums beneath it. */
39         Function<Album, List<Album>> FLATTENER = new Function<Album, List<Album>>() {
40
41                 @Override
42                 @Nonnull
43                 public List<Album> apply(Album album) {
44                         if (album == null) {
45                                 return emptyList();
46                         }
47                         List<Album> albums = new ArrayList<>();
48                         albums.add(album);
49                         for (Album subAlbum : album.getAlbums()) {
50                                 albums.addAll(FluentIterable.from(ImmutableList.of(subAlbum)).transformAndConcat(FLATTENER).toList());
51                         }
52                         return albums;
53                 }
54         };
55
56         /** Function that transforms an album into the images it contains. */
57         Function<Album, List<Image>> IMAGES = new Function<Album, List<Image>>() {
58
59                 @Override
60                 @Nonnull
61                 public List<Image> apply(Album album) {
62                         return (album != null) ? album.getImages() : Collections.<Image>emptyList();
63                 }
64         };
65
66         /**
67          * Filter that removes all albums that do not have any images in any album
68          * below it.
69          */
70         Predicate<Album> NOT_EMPTY = new Predicate<Album>() {
71
72                 @Override
73                 public boolean apply(Album album) {
74                         /* so, we flatten all albums below the given one and check whether at least one album… */
75                         return FluentIterable.from(asList(album)).transformAndConcat(FLATTENER).anyMatch(new Predicate<Album>() {
76
77                                 @Override
78                                 public boolean apply(Album album) {
79                                         /* …contains any inserted images. */
80                                         return !album.getImages().isEmpty() && FluentIterable.from(album.getImages()).allMatch(new Predicate<Image>() {
81
82                                                 @Override
83                                                 public boolean apply(Image input) {
84                                                         return input.isInserted();
85                                                 }
86                                         });
87                                 }
88                         });
89                 }
90         };
91
92         /**
93          * Returns the ID of this album.
94          *
95          * @return The ID of this album
96          */
97         String getId();
98
99         /**
100          * Returns the Sone this album belongs to.
101          *
102          * @return The Sone this album belongs to
103          */
104         Sone getSone();
105
106         /**
107          * Returns the nested albums.
108          *
109          * @return The nested albums
110          */
111         List<Album> getAlbums();
112
113         /**
114          * Adds an album to this album.
115          *
116          * @param album
117          *              The album to add
118          */
119         void addAlbum(Album album);
120
121         /**
122          * Removes an album from this album.
123          *
124          * @param album
125          *              The album to remove
126          */
127         void removeAlbum(Album album);
128
129         /**
130          * Moves the given album up in this album’s albums. If the album is already the
131          * first album, nothing happens.
132          *
133          * @param album
134          *              The album to move up
135          * @return The album that the given album swapped the place with, or
136          *         <code>null</code> if the album did not change its place
137          */
138         Album moveAlbumUp(Album album);
139
140         /**
141          * Moves the given album down in this album’s albums. If the album is already
142          * the last album, nothing happens.
143          *
144          * @param album
145          *              The album to move down
146          * @return The album that the given album swapped the place with, or
147          *         <code>null</code> if the album did not change its place
148          */
149         Album moveAlbumDown(Album album);
150
151         /**
152          * Returns the images in this album.
153          *
154          * @return The images in this album
155          */
156         List<Image> getImages();
157
158         /**
159          * Adds the given image to this album.
160          *
161          * @param image
162          *              The image to add
163          */
164         void addImage(Image image);
165
166         /**
167          * Removes the given image from this album.
168          *
169          * @param image
170          *              The image to remove
171          */
172         void removeImage(Image image);
173
174         /**
175          * Moves the given image up in this album’s images. If the image is already the
176          * first image, nothing happens.
177          *
178          * @param image
179          *              The image to move up
180          * @return The image that the given image swapped the place with, or
181          *         <code>null</code> if the image did not change its place
182          */
183         Image moveImageUp(Image image);
184
185         /**
186          * Moves the given image down in this album’s images. If the image is already
187          * the last image, nothing happens.
188          *
189          * @param image
190          *              The image to move down
191          * @return The image that the given image swapped the place with, or
192          *         <code>null</code> if the image did not change its place
193          */
194         Image moveImageDown(Image image);
195
196         /**
197          * Returns whether this album contains any other albums or images.
198          *
199          * @return {@code true} if this album is empty, {@code false} otherwise
200          */
201         boolean isEmpty();
202
203         /**
204          * Returns whether this album is an identitiy’s root album.
205          *
206          * @return {@code true} if this album is an identity’s root album, {@code
207          *         false} otherwise
208          */
209         boolean isRoot();
210
211         /**
212          * Returns the parent album of this album.
213          *
214          * @return The parent album of this album, or {@code null} if this album does
215          *         not have a parent
216          */
217         Album getParent();
218
219         /**
220          * Sets the parent album of this album.
221          *
222          * @param parent
223          *              The new parent album of this album
224          * @return This album
225          */
226         Album setParent(Album parent);
227
228         /**
229          * Removes the parent album of this album.
230          *
231          * @return This album
232          */
233         Album removeParent();
234
235         /**
236          * Returns the title of this album.
237          *
238          * @return The title of this album
239          */
240         String getTitle();
241
242         /**
243          * Returns the description of this album.
244          *
245          * @return The description of this album
246          */
247         String getDescription();
248
249         /**
250          * Returns a modifier for this album.
251          *
252          * @return A modifier for this album
253          * @throws IllegalStateException
254          *              if this album can not be modified
255          */
256         Modifier modify() throws IllegalStateException;
257
258         /**
259          * Allows modifying an album. Modifications are only performed once {@link
260          * #update()} has succesfully returned a new album with the modifications
261          * made.
262          */
263         interface Modifier {
264
265                 Modifier setTitle(String title);
266
267                 Modifier setDescription(String description);
268
269                 Album update() throws IllegalStateException;
270
271                 class AlbumTitleMustNotBeEmpty extends IllegalStateException { }
272
273         }
274
275 }