/** Trusted identities, sorted by own identities. */
private final Multimap<OwnIdentity, Identity> trustedIdentities = Multimaps.synchronizedSetMultimap(HashMultimap.<OwnIdentity, Identity>create());
- /** All known images. */
- private final Map<String, Image> images = new HashMap<String, Image>();
-
/** All temporary images. */
private final Map<String, TemporaryImage> temporaryImages = new HashMap<String, TemporaryImage>();
* none was created
*/
public Image getImage(String imageId, boolean create) {
- synchronized (images) {
- Image image = images.get(imageId);
- if (create && (image == null)) {
- image = new Image(imageId);
- images.put(imageId, image);
- }
- return image;
+ Optional<Image> image = database.getImage(imageId);
+ if (image.isPresent()) {
+ return image.get();
}
+ if (!create) {
+ return null;
+ }
+ Image newImage = database.newImageBuilder().withId(imageId).build();
+ database.storeImage(newImage);
+ return newImage;
}
/**
}
}
database.storePostReplies(sone, sone.getReplies());
- synchronized (images) {
- for (Album album : storedSone.get().getRootAlbum().getAlbums()) {
- database.removeAlbum(album);
- for (Image image : album.getImages()) {
- images.remove(image.getId());
- }
+ for (Album album : storedSone.get().getRootAlbum().getAlbums()) {
+ database.removeAlbum(album);
+ for (Image image : album.getImages()) {
+ database.removeImage(image);
}
- for (Album album : sone.getRootAlbum().getAlbums()) {
- database.storeAlbum(album);
- for (Image image : album.getImages()) {
- images.put(image.getId(), image);
- }
+ }
+ for (Album album : sone.getRootAlbum().getAlbums()) {
+ database.storeAlbum(album);
+ for (Image image : album.getImages()) {
+ database.storeImage(image);
}
}
synchronized (sones) {
logger.log(Level.WARNING, "Invalid album image encountered, aborting load!");
return;
}
- Image image = getImage(imageId).setSone(sone).setCreationTime(creationTime).setKey(key);
- image.setTitle(title).setDescription(description).setWidth(width).setHeight(height);
+ Image image = getImage(imageId).modify().setSone(sone).setCreationTime(creationTime).setKey(key).setTitle(title).setDescription(description).setWidth(width).setHeight(height).update();
album.addImage(image);
}
checkNotNull(temporaryImage, "temporaryImage must not be null");
checkArgument(sone.isLocal(), "sone must be a local Sone");
checkArgument(sone.equals(album.getSone()), "album must belong to the given Sone");
- Image image = new Image(temporaryImage.getId()).setSone(sone).setCreationTime(System.currentTimeMillis());
+ Image image = database.newImageBuilder().withId(temporaryImage.getId()).build().modify().setSone(sone).setCreationTime(System.currentTimeMillis()).update();
album.addImage(image);
- synchronized (images) {
- images.put(image.getId(), image);
- }
+ database.storeImage(image);
imageInserter.insertImage(temporaryImage, image);
return image;
}
checkArgument(image.getSone().isLocal(), "image must belong to a local Sone");
deleteTemporaryImage(image.getId());
image.getAlbum().removeImage(image);
- synchronized (images) {
- images.remove(image.getId());
- }
+ database.removeImage(image);
touchConfiguration();
}
@Subscribe
public void imageInsertFinished(ImageInsertFinishedEvent imageInsertFinishedEvent) {
logger.log(Level.WARNING, String.format("Image insert finished for %s: %s", imageInsertFinishedEvent.image(), imageInsertFinishedEvent.resultingUri()));
- imageInsertFinishedEvent.image().setKey(imageInsertFinishedEvent.resultingUri().toString());
+ imageInsertFinishedEvent.image().modify().setKey(imageInsertFinishedEvent.resultingUri().toString()).update();
deleteTemporaryImage(imageInsertFinishedEvent.image().getId());
touchConfiguration();
}
logger.log(Level.WARNING, String.format("Downloaded Sone %s contains image %s with invalid dimensions (%s, %s)!", sone, imageId, imageWidthString, imageHeightString));
return null;
}
- Image image = core.getImage(imageId).setSone(sone).setKey(imageKey).setCreationTime(creationTime);
- image.setTitle(imageTitle).setDescription(imageDescription);
- image.setWidth(imageWidth).setHeight(imageHeight);
+ Image image = core.getImage(imageId).modify().setSone(sone).setKey(imageKey).setCreationTime(creationTime).update();
+ image = image.modify().setTitle(imageTitle).setDescription(imageDescription).update();
+ image = image.modify().setWidth(imageWidth).setHeight(imageHeight).update();
album.addImage(image);
}
}
package net.pterodactylus.sone.data;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-
-import java.util.UUID;
-
-import com.google.common.hash.Hasher;
-import com.google.common.hash.Hashing;
-
/**
* Container for image metadata.
*
- * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ * @author <a href="mailto:d.roden@xplosion.de">David Roden</a>
*/
-public class Image implements Identified, Fingerprintable {
-
- /** The ID of the image. */
- private final String id;
-
- /** The Sone the image belongs to. */
- private Sone sone;
-
- /** The album this image belongs to. */
- private Album album;
-
- /** The request key of the image. */
- private String key;
-
- /** The creation time of the image. */
- private long creationTime;
-
- /** The width of the image. */
- private int width;
-
- /** The height of the image. */
- private int height;
-
- /** The title of the image. */
- private String title;
-
- /** The description of the image. */
- private String description;
-
- /**
- * Creates a new image with a random ID.
- */
- public Image() {
- this(UUID.randomUUID().toString());
- setCreationTime(System.currentTimeMillis());
- }
-
- /**
- * Creates a new image.
- *
- * @param id
- * The ID of the image
- */
- public Image(String id) {
- this.id = checkNotNull(id, "id must not be null");
- }
-
- //
- // ACCESSORS
- //
+public interface Image extends Identified, Fingerprintable {
/**
* Returns the ID of this image.
*
* @return The ID of this image
*/
- public String getId() {
- return id;
- }
+ String getId();
/**
* Returns the Sone this image belongs to.
*
* @return The Sone this image belongs to
*/
- public Sone getSone() {
- return sone;
- }
-
- /**
- * Sets the owner of this image. The owner can only be set if no owner has
- * yet been set.
- *
- * @param sone
- * The new owner of this image
- * @return This image
- */
- public Image setSone(Sone sone) {
- checkNotNull(sone, "sone must not be null");
- checkArgument((this.sone == null) || this.sone.equals(sone), "sone must not already be set to another sone");
- this.sone = sone;
- return this;
- }
+ Sone getSone();
/**
* Returns the album this image belongs to.
*
* @return The album this image belongs to
*/
- public Album getAlbum() {
- return album;
- }
+ Album getAlbum();
/**
* Sets the album this image belongs to. The album of an image can only be
* The album this image belongs to
* @return This image
*/
- public Image setAlbum(Album album) {
- checkNotNull(album, "album must not be null");
- checkNotNull(album.getSone().equals(getSone()), "album must belong to the same Sone as this image");
- this.album = album;
- return this;
- }
+ Image setAlbum(Album album);
/**
* Returns the request key of this image.
*
* @return The request key of this image
*/
- public String getKey() {
- return key;
- }
-
- /**
- * Sets the request key of this image. The request key can only be set as
- * long as no request key has yet been set.
- *
- * @param key
- * The new request key of this image
- * @return This image
- */
- public Image setKey(String key) {
- checkNotNull(key, "key must not be null");
- checkState((this.key == null) || this.key.equals(key), "key must not be already set to another key");
- this.key = key;
- return this;
- }
+ String getKey();
/**
* Returns whether the image has already been inserted. An image is
* @return {@code true} if there is a key for this image, {@code false}
* otherwise
*/
- public boolean isInserted() {
- return key != null;
- }
+ boolean isInserted();
/**
* Returns the creation time of this image.
* @return The creation time of this image (in milliseconds since 1970, Jan
* 1, UTC)
*/
- public long getCreationTime() {
- return creationTime;
- }
-
- /**
- * Sets the new creation time of this image. The creation time can only be
- * set as long as no creation time has been set yet.
- *
- * @param creationTime
- * The new creation time of this image
- * @return This image
- */
- public Image setCreationTime(long creationTime) {
- checkArgument(creationTime > 0, "creationTime must be > 0");
- checkState((this.creationTime == 0) || (this.creationTime == creationTime), "creationTime must not already be set");
- this.creationTime = creationTime;
- return this;
- }
+ long getCreationTime();
/**
* Returns the width of this image.
*
* @return The width of this image (in pixels)
*/
- public int getWidth() {
- return width;
- }
-
- /**
- * Sets the width of this image. The width can only be set as long as no
- * width has been set yet.
- *
- * @param width
- * The new width of this image
- * @return This image
- */
- public Image setWidth(int width) {
- checkArgument(width > 0, "width must be > 0");
- checkState((this.width == 0) || (this.width == width), "width must not already be set to another width");
- this.width = width;
- return this;
- }
+ int getWidth();
/**
* Returns the height of this image.
*
* @return The height of this image (in pixels)
*/
- public int getHeight() {
- return height;
- }
-
- /**
- * Sets the new height of this image. The height can only be set as long as
- * no height has yet been set.
- *
- * @param height
- * The new height of this image
- * @return This image
- */
- public Image setHeight(int height) {
- checkArgument(height > 0, "height must be > 0");
- checkState((this.height == 0) || (this.height == height), "height must not already be set to another height");
- this.height = height;
- return this;
- }
+ int getHeight();
/**
* Returns the title of this image.
*
* @return The title of this image
*/
- public String getTitle() {
- return title;
- }
-
- /**
- * Sets the title of this image.
- *
- * @param title
- * The title of this image
- * @return This image
- */
- public Image setTitle(String title) {
- this.title = checkNotNull(title, "title must not be null");
- return this;
- }
+ String getTitle();
/**
* Returns the description of this image.
*
* @return The description of this image
*/
- public String getDescription() {
- return description;
- }
-
- /**
- * Sets the description of this image.
- *
- * @param description
- * The description of this image
- * @return This image
- */
- public Image setDescription(String description) {
- this.description = checkNotNull(description, "description must not be null");
- return this;
- }
-
- //
- // FINGERPRINTABLE METHODS
- //
+ String getDescription();
/**
* {@inheritDoc}
*/
@Override
- public String getFingerprint() {
- Hasher hash = Hashing.sha256().newHasher();
- hash.putString("Image(");
- hash.putString("ID(").putString(id).putString(")");
- hash.putString("Title(").putString(title).putString(")");
- hash.putString("Description(").putString(description).putString(")");
- hash.putString(")");
- return hash.hash().toString();
- }
+ String getFingerprint();
- //
- // OBJECT METHODS
- //
+ Modifier modify() throws IllegalStateException;
- /**
- * {@inheritDoc}
- */
- @Override
- public int hashCode() {
- return id.hashCode();
- }
+ interface Modifier {
+
+ Modifier setSone(Sone sone);
+
+ Modifier setCreationTime(long creationTime);
+
+ Modifier setKey(String key);
+
+ Modifier setTitle(String title);
+
+ Modifier setDescription(String description);
+
+ Modifier setWidth(int width);
+
+ Modifier setHeight(int height);
+
+ Image update() throws IllegalStateException;
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean equals(Object object) {
- if (!(object instanceof Image)) {
- return false;
- }
- return ((Image) object).id.equals(id);
}
}
--- /dev/null
+/*
+ * Sone - ImageImpl.java - Copyright © 2011–2013 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 <http://www.gnu.org/licenses/>.
+ */
+package net.pterodactylus.sone.data;
+
+import static com.google.common.base.Optional.absent;
+import static com.google.common.base.Optional.fromNullable;
+import static com.google.common.base.Optional.of;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.UUID;
+
+import com.google.common.base.Optional;
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
+
+/**
+ * Container for image metadata.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class ImageImpl implements Image {
+
+ /** The ID of the image. */
+ private final String id;
+
+ /** The Sone the image belongs to. */
+ private Sone sone;
+
+ /** The album this image belongs to. */
+ private Album album;
+
+ /** The request key of the image. */
+ private String key;
+
+ /** The creation time of the image. */
+ private long creationTime;
+
+ /** The width of the image. */
+ private int width;
+
+ /** The height of the image. */
+ private int height;
+
+ /** The title of the image. */
+ private String title;
+
+ /** The description of the image. */
+ private String description;
+
+ /** Creates a new image with a random ID. */
+ public ImageImpl() {
+ this(UUID.randomUUID().toString());
+ this.creationTime = System.currentTimeMillis();
+ }
+
+ /**
+ * Creates a new image.
+ *
+ * @param id
+ * The ID of the image
+ */
+ public ImageImpl(String id) {
+ this.id = checkNotNull(id, "id must not be null");
+ }
+
+ //
+ // ACCESSORS
+ //
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public Sone getSone() {
+ return sone;
+ }
+
+ @Override
+ public Album getAlbum() {
+ return album;
+ }
+
+ @Override
+ public Image setAlbum(Album album) {
+ checkNotNull(album, "album must not be null");
+ checkNotNull(album.getSone().equals(getSone()), "album must belong to the same Sone as this image");
+ this.album = album;
+ return this;
+ }
+
+ @Override
+ public String getKey() {
+ return key;
+ }
+
+ @Override
+ public boolean isInserted() {
+ return key != null;
+ }
+
+ @Override
+ public long getCreationTime() {
+ return creationTime;
+ }
+
+ @Override
+ public int getWidth() {
+ return width;
+ }
+
+ @Override
+ public int getHeight() {
+ return height;
+ }
+
+ @Override
+ public String getTitle() {
+ return title;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ public Modifier modify() throws IllegalStateException {
+ checkState((sone == null) || sone.isLocal(), "only local images may be modified");
+ return new Modifier() {
+ private Optional<Sone> sone = absent();
+
+ private Optional<Long> creationTime = absent();
+
+ private Optional<String> key = absent();
+
+ private Optional<String> title = absent();
+
+ private Optional<String> description = absent();
+
+ private Optional<Integer> width = absent();
+
+ private Optional<Integer> height = absent();
+
+ @Override
+ public Modifier setSone(Sone sone) {
+ this.sone = fromNullable(sone);
+ return this;
+ }
+
+ @Override
+ public Modifier setCreationTime(long creationTime) {
+ this.creationTime = of(creationTime);
+ return this;
+ }
+
+ @Override
+ public Modifier setKey(String key) {
+ this.key = fromNullable(key);
+ return this;
+ }
+
+ @Override
+ public Modifier setTitle(String title) {
+ this.title = fromNullable(title);
+ return this;
+ }
+
+ @Override
+ public Modifier setDescription(String description) {
+ this.description = fromNullable(description);
+ return this;
+ }
+
+ @Override
+ public Modifier setWidth(int width) {
+ this.width = of(width);
+ return this;
+ }
+
+ @Override
+ public Modifier setHeight(int height) {
+ this.height = of(height);
+ return this;
+ }
+
+ @Override
+ public Image update() throws IllegalStateException {
+ checkState(!sone.isPresent() || sone.get().equals(ImageImpl.this.sone), "can not change Sone once set");
+ checkState(!creationTime.isPresent() || (ImageImpl.this.creationTime == 0), "can not change creation time once set");
+ checkState(!key.isPresent() || key.get().equals(ImageImpl.this.key), "can not change key once set");
+ checkState(!width.isPresent() || width.get().equals(ImageImpl.this.width), "can not change width once set");
+ checkState(!height.isPresent() || height.get().equals(ImageImpl.this.height), "can not change height once set");
+
+ ImageImpl.this.sone = sone.or(ImageImpl.this.sone);
+ ImageImpl.this.creationTime = creationTime.or(ImageImpl.this.creationTime);
+ ImageImpl.this.key = key.or(ImageImpl.this.key);
+ ImageImpl.this.title = title.or(ImageImpl.this.title);
+ ImageImpl.this.description = description.or(ImageImpl.this.description);
+ ImageImpl.this.width = width.or(ImageImpl.this.width);
+ ImageImpl.this.height = height.or(ImageImpl.this.height);
+
+ return ImageImpl.this;
+ }
+ };
+ }
+
+ //
+ // FINGERPRINTABLE METHODS
+ //
+
+ @Override
+ public String getFingerprint() {
+ Hasher hash = Hashing.sha256().newHasher();
+ hash.putString("Image(");
+ hash.putString("ID(").putString(id).putString(")");
+ hash.putString("Title(").putString(title).putString(")");
+ hash.putString("Description(").putString(description).putString(")");
+ hash.putString(")");
+ return hash.hash().toString();
+ }
+
+ //
+ // OBJECT METHODS
+ //
+
+ /** {@inheritDoc} */
+ @Override
+ public int hashCode() {
+ return id.hashCode();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean equals(Object object) {
+ if (!(object instanceof ImageImpl)) {
+ return false;
+ }
+ return ((ImageImpl) object).id.equals(id);
+ }
+
+}
--- /dev/null
+/*
+ * Sone - AbstractImageBuilder.java - Copyright © 2013 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 <http://www.gnu.org/licenses/>.
+ */
+package net.pterodactylus.sone.data.impl;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import net.pterodactylus.sone.database.ImageBuilder;
+
+/**
+ * Abstract {@link ImageBuilder} implementation. It stores the state of the new
+ * album and performs validation, you only need to implement {@link #build()}.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public abstract class AbstractImageBuilder implements ImageBuilder {
+
+ /** Whether to create an album with a random ID. */
+ protected boolean randomId;
+
+ /** The ID of the album to create. */
+ protected String id;
+
+ @Override
+ public ImageBuilder randomId() {
+ randomId = true;
+ return this;
+ }
+
+ @Override
+ public ImageBuilder withId(String id) {
+ this.id = id;
+ return this;
+ }
+
+ //
+ // PROTECTED METHODS
+ //
+
+ /**
+ * Validates the state of this image builder.
+ *
+ * @throws IllegalStateException
+ * if the state is not valid for building a new image
+ */
+ protected void validate() throws IllegalStateException {
+ checkState((randomId && (id == null)) || (!randomId && (id != null)), "exactly one of random ID or custom ID must be set");
+ }
+
+}
--- /dev/null
+/*
+ * Sone - ImageBuilderImpl.java - Copyright © 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.data.impl;
+
+import net.pterodactylus.sone.data.Image;
+import net.pterodactylus.sone.data.ImageImpl;
+import net.pterodactylus.sone.database.ImageBuilder;
+
+/**
+ * {@link ImageBuilder} implementation that creates {@link ImageImpl} objects.
+ *
+ * @author <a href="mailto:d.roden@xplosion.de">David Roden</a>
+ */
+public class ImageBuilderImpl extends AbstractImageBuilder {
+
+ @Override
+ public Image build() throws IllegalStateException {
+ validate();
+ return randomId ? new ImageImpl() : new ImageImpl(id);
+ }
+
+}
*
* @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
*/
-public interface Database extends Service, PostDatabase, PostReplyDatabase, AlbumDatabase {
+public interface Database extends Service, PostDatabase, PostReplyDatabase, AlbumDatabase, ImageDatabase {
/**
* Saves the database.
--- /dev/null
+/*
+ * Sone - ImageBuilder.java - Copyright © 2013 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 <http://www.gnu.org/licenses/>.
+ */
+package net.pterodactylus.sone.database;
+
+import net.pterodactylus.sone.data.Image;
+
+/**
+ * Builder for {@link Image} objects.
+ *
+ * @author <a href="mailto:d.roden@xplosion.de">David Roden</a>
+ */
+public interface ImageBuilder {
+
+ ImageBuilder randomId();
+
+ ImageBuilder withId(String id);
+
+ Image build() throws IllegalStateException;
+
+}
--- /dev/null
+/*
+ * Sone - ImageBuilderFactory.java - Copyright © 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.database;
+
+/**
+ * Factory for {@link ImageBuilder}s.
+ *
+ * @author <a href="mailto:d.roden@xplosion.de">David Roden</a>
+ */
+public interface ImageBuilderFactory {
+
+ ImageBuilder newImageBuilder();
+
+}
--- /dev/null
+/*
+ * Sone - ImageDatabase.java - Copyright © 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.database;
+
+/**
+ * Combines an {@link ImageProvider}, an {@link ImageBuilderFactory}, and an
+ * {@link ImageStore} into an image database.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public interface ImageDatabase extends ImageProvider, ImageBuilderFactory, ImageStore {
+
+ /* nothing here. */
+
+}
--- /dev/null
+/*
+ * Sone - ImageProvider.java - Copyright © 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.database;
+
+import net.pterodactylus.sone.data.Image;
+
+import com.google.common.base.Optional;
+
+/**
+ * Provides {@link Image}.
+ *
+ * @author <a href="mailto:d.roden@xplosion.de">David Roden</a>
+ */
+public interface ImageProvider {
+
+ Optional<Image> getImage(String imageId);
+
+}
--- /dev/null
+/*
+ * Sone - ImageStore.java - Copyright © 2013 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 <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.database;
+
+import net.pterodactylus.sone.data.Image;
+
+/**
+ * Manages {@link Image} storage.
+ *
+ * @author <a href="mailto:d.roden@xplosion.de">David Roden</a>
+ */
+public interface ImageStore {
+
+ void storeImage(Image image);
+
+ void removeImage(Image image);
+
+}
import java.util.concurrent.locks.ReentrantReadWriteLock;
import net.pterodactylus.sone.data.Album;
+import net.pterodactylus.sone.data.Image;
import net.pterodactylus.sone.data.Post;
import net.pterodactylus.sone.data.PostReply;
import net.pterodactylus.sone.data.Reply;
import net.pterodactylus.sone.data.Sone;
import net.pterodactylus.sone.data.impl.AlbumBuilderImpl;
+import net.pterodactylus.sone.data.impl.ImageBuilderImpl;
import net.pterodactylus.sone.database.AlbumBuilder;
import net.pterodactylus.sone.database.Database;
import net.pterodactylus.sone.database.DatabaseException;
+import net.pterodactylus.sone.database.ImageBuilder;
import net.pterodactylus.sone.database.PostBuilder;
import net.pterodactylus.sone.database.PostDatabase;
import net.pterodactylus.sone.database.PostReplyBuilder;
private final Map<String, Album> allAlbums = new HashMap<String, Album>();
+ private final Map<String, Image> allImages = new HashMap<String, Image>();
+
/**
* Creates a new memory database.
*
}
//
+ // IMAGEPROVIDER METHODS
+ //
+
+ @Override
+ public Optional<Image> getImage(String imageId) {
+ lock.readLock().lock();
+ try {
+ return fromNullable(allImages.get(imageId));
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ //
+ // IMAGEBUILDERFACTORY METHODS
+ //
+
+ @Override
+ public ImageBuilder newImageBuilder() {
+ return new ImageBuilderImpl();
+ }
+
+ //
+ // IMAGESTORE METHODS
+ //
+
+ @Override
+ public void storeImage(Image image) {
+ lock.writeLock().lock();
+ try {
+ allImages.put(image.getId(), image);
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ @Override
+ public void removeImage(Image image) {
+ lock.writeLock().lock();
+ try {
+ allImages.remove(image.getId());
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ //
// PACKAGE-PRIVATE METHODS
//
if (title.length() == 0) {
templateContext.set("titleMissing", true);
}
- image.setTitle(title);
- image.setDescription(TextFilter.filter(request.getHttpRequest().getHeader("host"), description));
+ image.modify().setTitle(title).setDescription(TextFilter.filter(request.getHttpRequest().getHeader("host"), description)).update();
}
webInterface.getCore().touchConfiguration();
throw new RedirectException(returnPage);
String mimeType = getMimeType(imageData);
TemporaryImage temporaryImage = webInterface.getCore().createTemporaryImage(mimeType, imageData);
image = webInterface.getCore().createImage(currentSone, parent, temporaryImage);
- image.setTitle(name).setDescription(TextFilter.filter(request.getHttpRequest().getHeader("host"), description)).setWidth(uploadedImage.getWidth(null)).setHeight(uploadedImage.getHeight(null));
+ image.modify().setTitle(name).setDescription(TextFilter.filter(request.getHttpRequest().getHeader("host"), description)).setWidth(uploadedImage.getWidth(null)).setHeight(uploadedImage.getHeight(null)).update();
} catch (IOException ioe1) {
logger.log(Level.WARNING, "Could not read uploaded image!", ioe1);
return;
}
String title = request.getHttpRequest().getParam("title").trim();
String description = request.getHttpRequest().getParam("description").trim();
- image.setTitle(title).setDescription(TextFilter.filter(request.getHttpRequest().getHeader("host"), description));
+ image.modify().setTitle(title).setDescription(TextFilter.filter(request.getHttpRequest().getHeader("host"), description)).update();
webInterface.getCore().touchConfiguration();
return createSuccessJsonObject().put("imageId", image.getId()).put("title", image.getTitle()).put("description", image.getDescription()).put("parsedDescription", (String) parserFilter.format(new TemplateContext(), image.getDescription(), ImmutableMap.<String, Object>builder().put("sone", image.getSone()).build()));
}