Remove @author tags
[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.Comparator;
26 import java.util.List;
27 import javax.annotation.Nonnull;
28
29 import com.google.common.base.Function;
30 import com.google.common.base.Predicate;
31 import com.google.common.collect.FluentIterable;
32 import com.google.common.collect.ImmutableList;
33
34 /**
35  * Container for images that can also contain nested {@link Album}s.
36  */
37 public interface Album extends Identified, Fingerprintable {
38
39         /** Compares two {@link Album}s by {@link #getTitle()}. */
40         Comparator<Album> TITLE_COMPARATOR = new Comparator<Album>() {
41
42                 @Override
43                 public int compare(Album leftAlbum, Album rightAlbum) {
44                         return leftAlbum.getTitle().compareToIgnoreCase(rightAlbum.getTitle());
45                 }
46         };
47
48         /** Function that flattens the given album and all albums beneath it. */
49         Function<Album, List<Album>> FLATTENER = new Function<Album, List<Album>>() {
50
51                 @Override
52                 @Nonnull
53                 public List<Album> apply(Album album) {
54                         if (album == null) {
55                                 return emptyList();
56                         }
57                         List<Album> albums = new ArrayList<Album>();
58                         albums.add(album);
59                         for (Album subAlbum : album.getAlbums()) {
60                                 albums.addAll(FluentIterable.from(ImmutableList.of(subAlbum)).transformAndConcat(FLATTENER).toList());
61                         }
62                         return albums;
63                 }
64         };
65
66         /** Function that transforms an album into the images it contains. */
67         Function<Album, List<Image>> IMAGES = new Function<Album, List<Image>>() {
68
69                 @Override
70                 @Nonnull
71                 public List<Image> apply(Album album) {
72                         return (album != null) ? album.getImages() : Collections.<Image>emptyList();
73                 }
74         };
75
76         /**
77          * Filter that removes all albums that do not have any images in any album
78          * below it.
79          */
80         Predicate<Album> NOT_EMPTY = new Predicate<Album>() {
81
82                 @Override
83                 public boolean apply(Album album) {
84                         /* so, we flatten all albums below the given one and check whether at least one album… */
85                         return FluentIterable.from(asList(album)).transformAndConcat(FLATTENER).anyMatch(new Predicate<Album>() {
86
87                                 @Override
88                                 public boolean apply(Album album) {
89                                         /* …contains any inserted images. */
90                                         return !album.getImages().isEmpty() && FluentIterable.from(album.getImages()).allMatch(new Predicate<Image>() {
91
92                                                 @Override
93                                                 public boolean apply(Image input) {
94                                                         return input.isInserted();
95                                                 }
96                                         });
97                                 }
98                         });
99                 }
100         };
101
102         /**
103          * Returns the ID of this album.
104          *
105          * @return The ID of this album
106          */
107         String getId();
108
109         /**
110          * Returns the Sone this album belongs to.
111          *
112          * @return The Sone this album belongs to
113          */
114         Sone getSone();
115
116         /**
117          * Returns the nested albums.
118          *
119          * @return The nested albums
120          */
121         List<Album> getAlbums();
122
123         /**
124          * Adds an album to this album.
125          *
126          * @param album
127          *              The album to add
128          */
129         void addAlbum(Album album);
130
131         /**
132          * Removes an album from this album.
133          *
134          * @param album
135          *              The album to remove
136          */
137         void removeAlbum(Album album);
138
139         /**
140          * Moves the given album up in this album’s albums. If the album is already the
141          * first album, nothing happens.
142          *
143          * @param album
144          *              The album to move up
145          * @return The album that the given album swapped the place with, or
146          *         <code>null</code> if the album did not change its place
147          */
148         Album moveAlbumUp(Album album);
149
150         /**
151          * Moves the given album down in this album’s albums. If the album is already
152          * the last album, nothing happens.
153          *
154          * @param album
155          *              The album to move down
156          * @return The album that the given album swapped the place with, or
157          *         <code>null</code> if the album did not change its place
158          */
159         Album moveAlbumDown(Album album);
160
161         /**
162          * Returns the images in this album.
163          *
164          * @return The images in this album
165          */
166         List<Image> getImages();
167
168         /**
169          * Adds the given image to this album.
170          *
171          * @param image
172          *              The image to add
173          */
174         void addImage(Image image);
175
176         /**
177          * Removes the given image from this album.
178          *
179          * @param image
180          *              The image to remove
181          */
182         void removeImage(Image image);
183
184         /**
185          * Moves the given image up in this album’s images. If the image is already the
186          * first image, nothing happens.
187          *
188          * @param image
189          *              The image to move up
190          * @return The image that the given image swapped the place with, or
191          *         <code>null</code> if the image did not change its place
192          */
193         Image moveImageUp(Image image);
194
195         /**
196          * Moves the given image down in this album’s images. If the image is already
197          * the last image, nothing happens.
198          *
199          * @param image
200          *              The image to move down
201          * @return The image that the given image swapped the place with, or
202          *         <code>null</code> if the image did not change its place
203          */
204         Image moveImageDown(Image image);
205
206         /**
207          * Returns whether this album contains any other albums or images.
208          *
209          * @return {@code true} if this album is empty, {@code false} otherwise
210          */
211         boolean isEmpty();
212
213         /**
214          * Returns whether this album is an identitiy’s root album.
215          *
216          * @return {@code true} if this album is an identity’s root album, {@code
217          *         false} otherwise
218          */
219         boolean isRoot();
220
221         /**
222          * Returns the parent album of this album.
223          *
224          * @return The parent album of this album, or {@code null} if this album does
225          *         not have a parent
226          */
227         Album getParent();
228
229         /**
230          * Sets the parent album of this album.
231          *
232          * @param parent
233          *              The new parent album of this album
234          * @return This album
235          */
236         Album setParent(Album parent);
237
238         /**
239          * Removes the parent album of this album.
240          *
241          * @return This album
242          */
243         Album removeParent();
244
245         /**
246          * Returns the title of this album.
247          *
248          * @return The title of this album
249          */
250         String getTitle();
251
252         /**
253          * Returns the description of this album.
254          *
255          * @return The description of this album
256          */
257         String getDescription();
258
259         /**
260          * Returns a modifier for this album.
261          *
262          * @return A modifier for this album
263          * @throws IllegalStateException
264          *              if this album can not be modified
265          */
266         Modifier modify() throws IllegalStateException;
267
268         /**
269          * Allows modifying an album. Modifications are only performed once {@link
270          * #update()} has succesfully returned a new album with the modifications
271          * made.
272          */
273         interface Modifier {
274
275                 Modifier setTitle(String title);
276
277                 Modifier setDescription(String description);
278
279                 Album update() throws IllegalStateException;
280
281                 class AlbumTitleMustNotBeEmpty extends IllegalStateException { }
282
283         }
284
285 }