Extract album baseclass that only stores the primitives.
[Sone.git] / src / main / java / net / pterodactylus / sone / data / impl / DefaultAlbum.java
1 /*
2  * Sone - Album.java - Copyright © 2011–2013 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.impl;
19
20 import static com.google.common.base.Preconditions.checkArgument;
21 import static com.google.common.base.Preconditions.checkNotNull;
22 import static com.google.common.base.Preconditions.checkState;
23
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.UUID;
29
30 import net.pterodactylus.sone.data.Album;
31 import net.pterodactylus.sone.data.Image;
32 import net.pterodactylus.sone.data.Sone;
33 import net.pterodactylus.sone.database.ImageBuilder;
34
35 import com.google.common.base.Function;
36 import com.google.common.base.Optional;
37 import com.google.common.base.Predicates;
38 import com.google.common.collect.Collections2;
39
40 /**
41  * Dumb, store-everything-in-memory implementation of an {@link Album}.
42  *
43  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
44  */
45 public class DefaultAlbum extends AbstractAlbum {
46
47         /** The Sone this album belongs to. */
48         private Sone sone;
49
50         /** Nested albums. */
51         private final List<Album> albums = new ArrayList<Album>();
52
53         /** The image IDs in order. */
54         private final List<String> imageIds = new ArrayList<String>();
55
56         /** The images in this album. */
57         private final Map<String, Image> images = new HashMap<String, Image>();
58
59         /** The parent album. */
60         private Album parent;
61
62         /** Creates a new album with a random ID. */
63         public DefaultAlbum() {
64                 this(UUID.randomUUID().toString());
65         }
66
67         /**
68          * Creates a new album with the given ID.
69          *
70          * @param id
71          *              The ID of the album
72          */
73         public DefaultAlbum(String id) {
74                 super(id);
75         }
76
77         //
78         // ACCESSORS
79         //
80
81         @Override
82         public Sone getSone() {
83                 return sone;
84         }
85
86         @Override
87         public Album setSone(Sone sone) {
88                 checkNotNull(sone, "sone must not be null");
89                 checkState((this.sone == null) || (this.sone.equals(sone)), "album owner must not already be set to some other Sone");
90                 this.sone = sone;
91                 return this;
92         }
93
94         @Override
95         public List<Album> getAlbums() {
96                 return new ArrayList<Album>(albums);
97         }
98
99         @Override
100         public void addAlbum(Album album) {
101                 checkNotNull(album, "album must not be null");
102                 checkArgument(album.getSone().equals(sone), "album must belong to the same Sone as this album");
103                 album.setParent(this);
104                 if (!albums.contains(album)) {
105                         albums.add(album);
106                 }
107         }
108
109         @Override
110         public void removeAlbum(Album album) {
111                 checkNotNull(album, "album must not be null");
112                 checkArgument(album.getSone().equals(sone), "album must belong this album’s Sone");
113                 checkArgument(equals(album.getParent()), "album must belong to this album");
114                 albums.remove(album);
115                 album.removeParent();
116         }
117
118         @Override
119         public Album moveAlbumUp(Album album) {
120                 checkNotNull(album, "album must not be null");
121                 checkArgument(album.getSone().equals(sone), "album must belong to the same Sone as this album");
122                 checkArgument(equals(album.getParent()), "album must belong to this album");
123                 int oldIndex = albums.indexOf(album);
124                 if (oldIndex <= 0) {
125                         return null;
126                 }
127                 albums.remove(oldIndex);
128                 albums.add(oldIndex - 1, album);
129                 return albums.get(oldIndex);
130         }
131
132         @Override
133         public Album moveAlbumDown(Album album) {
134                 checkNotNull(album, "album must not be null");
135                 checkArgument(album.getSone().equals(sone), "album must belong to the same Sone as this album");
136                 checkArgument(equals(album.getParent()), "album must belong to this album");
137                 int oldIndex = albums.indexOf(album);
138                 if ((oldIndex < 0) || (oldIndex >= (albums.size() - 1))) {
139                         return null;
140                 }
141                 albums.remove(oldIndex);
142                 albums.add(oldIndex + 1, album);
143                 return albums.get(oldIndex);
144         }
145
146         @Override
147         public List<Image> getImages() {
148                 return new ArrayList<Image>(Collections2.filter(Collections2.transform(imageIds, new Function<String, Image>() {
149
150                         @Override
151                         @SuppressWarnings("synthetic-access")
152                         public Image apply(String imageId) {
153                                 return images.get(imageId);
154                         }
155                 }), Predicates.notNull()));
156         }
157
158         @Override
159         public void removeImage(Image image) {
160                 checkNotNull(image, "image must not be null");
161                 checkNotNull(image.getSone(), "image must have an owner");
162                 checkArgument(image.getSone().equals(sone), "image must belong to the same Sone as this album");
163                 imageIds.remove(image.getId());
164                 images.remove(image.getId());
165                 if (image.getId().equals(albumImage)) {
166                         if (images.isEmpty()) {
167                                 albumImage = null;
168                         } else {
169                                 albumImage = images.values().iterator().next().getId();
170                         }
171                 }
172         }
173
174         @Override
175         public Image moveImageUp(Image image) {
176                 checkNotNull(image, "image must not be null");
177                 checkNotNull(image.getSone(), "image must have an owner");
178                 checkArgument(image.getSone().equals(sone), "image must belong to the same Sone as this album");
179                 checkArgument(image.getAlbum().equals(this), "image must belong to this album");
180                 int oldIndex = imageIds.indexOf(image.getId());
181                 if (oldIndex <= 0) {
182                         return null;
183                 }
184                 imageIds.remove(image.getId());
185                 imageIds.add(oldIndex - 1, image.getId());
186                 return images.get(imageIds.get(oldIndex));
187         }
188
189         @Override
190         public Image moveImageDown(Image image) {
191                 checkNotNull(image, "image must not be null");
192                 checkNotNull(image.getSone(), "image must have an owner");
193                 checkArgument(image.getSone().equals(sone), "image must belong to the same Sone as this album");
194                 checkArgument(image.getAlbum().equals(this), "image must belong to this album");
195                 int oldIndex = imageIds.indexOf(image.getId());
196                 if ((oldIndex == -1) || (oldIndex >= (imageIds.size() - 1))) {
197                         return null;
198                 }
199                 imageIds.remove(image.getId());
200                 imageIds.add(oldIndex + 1, image.getId());
201                 return images.get(imageIds.get(oldIndex));
202         }
203
204         @Override
205         public Image getAlbumImage() {
206                 if (albumImage == null) {
207                         return null;
208                 }
209                 return Optional.fromNullable(images.get(albumImage)).or(images.values().iterator().next());
210         }
211
212         @Override
213         public Album getParent() {
214                 return parent;
215         }
216
217         @Override
218         public Album setParent(Album parent) {
219                 this.parent = checkNotNull(parent, "parent must not be null");
220                 return this;
221         }
222
223         @Override
224         public Album removeParent() {
225                 this.parent = null;
226                 return this;
227         }
228
229         @Override
230         public ImageBuilder newImageBuilder() throws IllegalStateException {
231                 return new DefaultImageBuilder(sone, this) {
232                         @Override
233                         public Image build() throws IllegalStateException {
234                                 Image image = super.build();
235                                 if (images.isEmpty() && (albumImage == null)) {
236                                         albumImage = image.getId();
237                                 }
238                                 images.put(image.getId(), image);
239                                 imageIds.add(image.getId());
240                                 return image;
241                         }
242                 };
243         }
244
245 }