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