/*
* Sone - Album.java - Copyright © 2011 David Roden
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package net.pterodactylus.sone.data;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import net.pterodactylus.util.collection.Mapper;
import net.pterodactylus.util.collection.Mappers;
import net.pterodactylus.util.validation.Validation;
/**
* Container for images that can also contain nested {@link Album}s.
*
* @author David ‘Bombe’ Roden
*/
public class Album implements Fingerprintable {
/** The ID of this album. */
private final String id;
/** The Sone this album belongs to. */
private Sone sone;
/** Nested albums. */
private final List albums = new ArrayList();
/** The image IDs in order. */
private final List imageIds = new ArrayList();
/** The images in this album. */
private final Map images = new HashMap();
/** The parent album. */
private Album parent;
/** The title of this album. */
private String title;
/** The description of this album. */
private String description;
/** The ID of the album picture. */
private String albumImage;
/**
* Creates a new album with a random ID.
*/
public Album() {
this(UUID.randomUUID().toString());
}
/**
* Creates a new album with the given ID.
*
* @param id
* The ID of the album
*/
public Album(String id) {
Validation.begin().isNotNull("Album ID", id).check();
this.id = id;
}
//
// ACCESSORS
//
/**
* Returns the ID of this album.
*
* @return The ID of this album
*/
public String getId() {
return id;
}
/**
* Returns the Sone this album belongs to.
*
* @return The Sone this album belongs to
*/
public Sone getSone() {
return sone;
}
/**
* Sets the owner of the album. The owner can only be set as long as the
* current owner is {@code null}.
*
* @param sone
* The album owner
* @return This album
*/
public Album setSone(Sone sone) {
Validation.begin().isNotNull("New Album Owner", sone).isEither("Old Album Owner", this.sone, null, sone).check();
this.sone = sone;
return this;
}
/**
* Returns the nested albums.
*
* @return The nested albums
*/
public List getAlbums() {
return new ArrayList(albums);
}
/**
* Adds an album to this album.
*
* @param album
* The album to add
*/
public void addAlbum(Album album) {
Validation.begin().isNotNull("Album", album).check().isEqual("Album Owner", album.sone, sone).isEither("Old Album Parent", this.parent, null, album.parent).check();
album.setParent(this);
if (!albums.contains(album)) {
albums.add(album);
}
}
/**
* Removes an album from this album.
*
* @param album
* The album to remove
*/
public void removeAlbum(Album album) {
Validation.begin().isNotNull("Album", album).check().isEqual("Album Owner", album.sone, sone).isEqual("Album Parent", album.parent, this).check();
albums.remove(album);
album.removeParent();
}
/**
* Returns the images in this album.
*
* @return The images in this album
*/
public List getImages() {
return Mappers.mappedList(imageIds, new Mapper() {
@Override
@SuppressWarnings("synthetic-access")
public Image map(String imageId) {
return images.get(imageId);
}
});
}
/**
* Adds the given image to this album.
*
* @param image
* The image to add
*/
public void addImage(Image image) {
Validation.begin().isNotNull("Image", image).check().isNotNull("Image Owner", image.getSone()).check().isEqual("Image Owner", image.getSone(), sone).check();
if (image.getAlbum() != null) {
image.getAlbum().removeImage(image);
}
image.setAlbum(this);
if (imageIds.isEmpty()) {
albumImage = image.getId();
}
if (!imageIds.contains(image.getId())) {
imageIds.add(image.getId());
images.put(image.getId(), image);
}
}
/**
* Removes the given image from this album.
*
* @param image
* The image to remove
*/
public void removeImage(Image image) {
Validation.begin().isNotNull("Image", image).check().isEqual("Image Owner", image.getSone(), sone).check();
imageIds.remove(image.getId());
images.remove(image.getId());
if (image.getId().equals(albumImage)) {
if (images.isEmpty()) {
albumImage = null;
} else {
albumImage = images.values().iterator().next().getId();
}
}
}
/**
* Moves the given image up in this album’s images. If the image is already
* the first image, nothing happens.
*
* @param image
* The image to move up
*/
public void moveImageUp(Image image) {
Validation.begin().isNotNull("Image", image).check().isEqual("Image Album", image.getAlbum(), this).isEqual("Album Owner", image.getAlbum().getSone(), sone).check();
int oldIndex = imageIds.indexOf(image.getId());
if (oldIndex <= 0) {
return;
}
imageIds.remove(image.getId());
imageIds.add(oldIndex - 1, image.getId());
}
/**
* Move the given image down in this album’s images. If the image is already
* the last image, nothing happens.
*
* @param image
* The image to move down
*/
public void moveImageDown(Image image) {
Validation.begin().isNotNull("Image", image).check().isEqual("Image Album", image.getAlbum(), this).isEqual("Album Owner", image.getAlbum().getSone(), sone).check();
int oldIndex = imageIds.indexOf(image.getId());
if ((oldIndex == -1) || (oldIndex >= (imageIds.size() - 1))) {
return;
}
imageIds.remove(image.getId());
imageIds.add(oldIndex + 1, image.getId());
}
/**
* Returns the album image of this album, or {@code null} if no album image
* has been set.
*
* @return The image to show when this album is listed
*/
public Image getAlbumImage() {
if (albumImage == null) {
return null;
}
return images.get(albumImage);
}
/**
* Sets the ID of the album image.
*
* @param id
* The ID of the album image
* @return This album
*/
public Album setAlbumImage(String id) {
this.albumImage = id;
return this;
}
/**
* Returns whether this album contains any other albums or images.
*
* @return {@code true} if this album is empty, {@code false} otherwise
*/
public boolean isEmpty() {
return albums.isEmpty() && images.isEmpty();
}
/**
* Returns the parent album of this album.
*
* @return The parent album of this album, or {@code null} if this album
* does not have a parent
*/
public Album getParent() {
return parent;
}
/**
* Sets the parent album of this album.
*
* @param parent
* The new parent album of this album
* @return This album
*/
protected Album setParent(Album parent) {
Validation.begin().isNotNull("Album Parent", parent).check();
this.parent = parent;
return this;
}
/**
* Removes the parent album of this album.
*
* @return This album
*/
protected Album removeParent() {
this.parent = null;
return this;
}
/**
* Returns the title of this album.
*
* @return The title of this album
*/
public String getTitle() {
return title;
}
/**
* Sets the title of this album.
*
* @param title
* The title of this album
* @return This album
*/
public Album setTitle(String title) {
Validation.begin().isNotNull("Album Title", title).check();
this.title = title;
return this;
}
/**
* Returns the description of this album.
*
* @return The description of this album
*/
public String getDescription() {
return description;
}
/**
* Sets the description of this album.
*
* @param description
* The description of this album
* @return This album
*/
public Album setDescription(String description) {
Validation.begin().isNotNull("Album Description", description).check();
this.description = description;
return this;
}
//
// FINGERPRINTABLE METHODS
//
/**
* {@inheritDoc}
*/
@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(')');
/* add nested albums. */
fingerprint.append("Albums(");
for (Album album : albums) {
fingerprint.append(album.getFingerprint());
}
fingerprint.append(')');
/* add images. */
fingerprint.append("Images(");
for (Image image : images.values()) {
if (image.isInserted()) {
fingerprint.append(image.getFingerprint());
}
}
fingerprint.append(')');
fingerprint.append(')');
return fingerprint.toString();
}
//
// OBJECT METHODS
//
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return id.hashCode();
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object object) {
if (!(object instanceof Album)) {
return false;
}
Album album = (Album) object;
return id.equals(album.id);
}
}