Commit 07ffed20 authored by Matija Obreza's avatar Matija Obreza
Browse files

See genesys-server#169

- Image gallery will be automagically removed when it contains 0 images
parent cbf59930
......@@ -41,12 +41,12 @@ public interface ImageGalleryService {
ImageGallery loadImageGallery(String path);
/**
* Create a gallery at the specified path. Path of the gallery must be unique in the repository.
* Create a gallery at the specified path if it does not exist. Path of the gallery must be unique in the repository.
*
* @param path Image gallery path in the repository.
* @param title Image gallery title in English.
* @param description Image gallery description in English.
* @return the new ImageGallery.
* @return the new ImageGallery or existing gallery at the specified path.
*/
ImageGallery createImageGallery(String path, String title, String description);
......@@ -54,7 +54,7 @@ public interface ImageGalleryService {
* Delete the image gallery, but don't remove the images at that path.
*
* @param imageGallery the image gallery
* @throws InvalidRepositoryPathException
* @throws InvalidRepositoryPathException
*/
void removeGallery(ImageGallery imageGallery) throws InvalidRepositoryPathException;
......@@ -77,8 +77,8 @@ public interface ImageGalleryService {
ImageGallery saveImageOrder(ImageGallery imageGallery);
/**
* Ensure that thumbnails of images in the gallery exist in the repository at the {@link ImageGallery#path}/_thumb/ <code>width</code>x <code>height</code>_<code>uuid</code>.
* <code>ext</code>.
* Ensure that thumbnails of images in the gallery exist in the repository at the {@link ImageGallery#path}/_thumb/ <code>width</code>x
* <code>height</code>_<code>uuid</code>. <code>ext</code>.
*
* @param imageGallery The ImageGallery.
* @param width Maximum width of thumbnail image. Can be null.
......
package org.genesys.filerepository.service.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.genesys.filerepository.model.RepositoryImage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Aspect
public abstract class AbstractImageGalleryAspects {
/** The Constant LOG. */
protected Logger LOG = LoggerFactory.getLogger(getClass());
@AfterReturning(value = "execution(* org.genesys.filerepository.persistence.RepositoryImagePersistence.save(*))", returning = "repositoryImages")
public Object afterRepositoryImageSaveIterable(final JoinPoint joinPoint, final Iterable<RepositoryImage> repositoryImages) throws Throwable {
LOG.debug("Many images were saved: {}", repositoryImages);
if (repositoryImages != null) {
repositoryImages.forEach(ri -> addImageToGallery(ri));
}
return repositoryImages;
}
protected abstract void addImageToGallery(RepositoryImage repositoryImage);
@AfterReturning(value = "execution(* org.genesys.filerepository.persistence.RepositoryImagePersistence.save(*))", returning = "repositoryImage")
public Object afterRepositoryImageSave(final JoinPoint joinPoint, final RepositoryImage repositoryImage) throws Throwable {
if (LOG.isTraceEnabled()) {
LOG.trace("1 image was saved: {}", repositoryImage);
}
if (repositoryImage != null) {
addImageToGallery(repositoryImage);
}
return repositoryImage;
}
@Around(value = "execution(* org.genesys.filerepository.persistence.RepositoryImagePersistence.delete(*)) && args(repositoryImage)")
public Object aroundRepositoryImageDelete(final ProceedingJoinPoint joinPoint, final RepositoryImage repositoryImage) throws Throwable {
if (repositoryImage != null) {
LOG.trace("1 image is being deleted path={} originalFilename={}", repositoryImage.getPath(), repositoryImage.getOriginalFilename());
}
removeImageFromGallery(repositoryImage);
try {
joinPoint.proceed();
} catch (final Throwable e) {
// FIXME is this necessary? Exception should cancel transaction!
LOG.info("Putting image back to gallery.");
addImageToGallery(repositoryImage);
throw e;
}
return repositoryImage;
}
protected abstract void removeImageFromGallery(RepositoryImage repositoryImage);
}
\ No newline at end of file
/*
* Copyright 2016 Global Crop Diversity Trust, www.croptrust.org
* Copyright 2017 Global Crop Diversity Trust, www.croptrust.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -19,17 +19,13 @@ package org.genesys.filerepository.service.aspect;
import java.util.ArrayList;
import java.util.List;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.genesys.filerepository.InvalidRepositoryPathException;
import org.genesys.filerepository.model.ImageGallery;
import org.genesys.filerepository.model.RepositoryImage;
import org.genesys.filerepository.persistence.RepositoryImagePersistence;
import org.genesys.filerepository.service.ImageGalleryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
......@@ -40,84 +36,25 @@ import org.springframework.stereotype.Component;
*/
@Aspect
@Component
public class ImageGalleryAspects {
/** The Constant LOG. */
private final static Logger LOG = LoggerFactory.getLogger(ImageGalleryAspects.class);
public class ImageGalleryAspectsImpl extends AbstractImageGalleryAspects implements InitializingBean {
/** The image gallery service. */
@Autowired
private ImageGalleryService imageGalleryService;
/**
* Add images to the galleries when images are saved to the repository.
*
* @param joinPoint the join point
* @param repositoryImages the repository images
* @return the object
* @throws Throwable the throwable
*/
@AfterReturning(value = "execution(* org.genesys.filerepository.persistence.RepositoryImagePersistence.save(*))", returning = "repositoryImages")
public Object afterRepositoryImageSaveIterable(final JoinPoint joinPoint, final Iterable<RepositoryImage> repositoryImages) throws Throwable {
LOG.debug("Many images were saved: {}", repositoryImages);
if (repositoryImages != null) {
repositoryImages.forEach(ri -> addImageToGallery(ri));
}
return repositoryImages;
public void setImageGalleryService(ImageGalleryService imageGalleryService) {
this.imageGalleryService = imageGalleryService;
}
/**
* Add image to the gallery when one image is saved to the repository.
*
* @param joinPoint the join point
* @param repositoryImage the repository image
* @return the object
* @throws Throwable the throwable
*/
@AfterReturning(value = "execution(* org.genesys.filerepository.persistence.RepositoryImagePersistence.save(*))", returning = "repositoryImage")
public Object afterRepositoryImageSave(final JoinPoint joinPoint, final RepositoryImage repositoryImage) throws Throwable {
if (LOG.isTraceEnabled()) {
LOG.trace("1 image was saved: {}", repositoryImage);
}
if (repositoryImage != null) {
addImageToGallery(repositoryImage);
}
@Override
public void afterPropertiesSet() throws Exception {
LOG.warn("Instantiating bean {}", getClass().getName());
return repositoryImage;
}
/**
* Add image to the gallery when one image is saved to the repository.
*
* @param joinPoint the join point
* @param repositoryImage the repository image
* @return the object
* @throws Throwable the throwable
*/
@Around(value = "execution(* org.genesys.filerepository.persistence.RepositoryImagePersistence.delete(*)) && args(repositoryImage)")
public Object aroundRepositoryImageDelete(final ProceedingJoinPoint joinPoint, final RepositoryImage repositoryImage) throws Throwable {
if (repositoryImage != null) {
LOG.trace("1 image is being deleted path={} originalFilename={}", repositoryImage.getPath(), repositoryImage.getOriginalFilename());
}
removeImageFromGallery(repositoryImage);
try {
joinPoint.proceed();
} catch (final Throwable e) {
LOG.info("Putting image back to gallery.");
addImageToGallery(repositoryImage);
throw e;
}
return repositoryImage;
public ImageGalleryAspectsImpl() {
// log it
LOG.warn("Instantiating {}", getClass().getName());
}
/**
......@@ -125,7 +62,8 @@ public class ImageGalleryAspects {
*
* @param repositoryImage the repository image
*/
private void addImageToGallery(final RepositoryImage repositoryImage) {
@Override
public void addImageToGallery(final RepositoryImage repositoryImage) {
if (repositoryImage == null) {
return;
}
......@@ -141,7 +79,7 @@ public class ImageGalleryAspects {
List<RepositoryImage> imagesList = imageGallery.getImages();
if (imagesList == null) {
imagesList = new ArrayList<RepositoryImage>(1);
imagesList = new ArrayList<>(1);
}
if (!imagesList.contains(repositoryImage)) {
......@@ -159,7 +97,7 @@ public class ImageGalleryAspects {
*
* @param repositoryImage the repository image
*/
private void removeImageFromGallery(final RepositoryImage repositoryImage) {
public void removeImageFromGallery(final RepositoryImage repositoryImage) {
if (repositoryImage == null) {
return;
}
......@@ -189,7 +127,15 @@ public class ImageGalleryAspects {
LOG.trace("New images size=" + imagesList.size());
}
imageGalleryService.saveImageOrder(imageGallery);
if (imagesList.size() == 0) {
try {
imageGalleryService.removeGallery(imageGallery);
} catch (final InvalidRepositoryPathException e) {
LOG.error("Failed to remove empty image gallery", e);
}
} else {
imageGalleryService.saveImageOrder(imageGallery);
}
}
}
/*
* Copyright 2016 Global Crop Diversity Trust, www.croptrust.org
* Copyright 2017 Global Crop Diversity Trust, www.croptrust.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -38,7 +38,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
// TODO: Auto-generated Javadoc
/**
* The Class ImageGalleryServiceImpl.
*/
......@@ -96,11 +95,15 @@ public class ImageGalleryServiceImpl implements ImageGalleryService {
@Override
@Transactional
public ImageGallery createImageGallery(final String path, final String title, final String description) {
if (LOG.isDebugEnabled()) {
LOG.debug("Creating ImageGallery at path=" + path);
}
LOG.debug("Creating ImageGallery at path={}", path);
final ImageGallery imageGallery = new ImageGallery();
ImageGallery imageGallery = imageGalleryPersistence.findByPath(path);
if (imageGallery != null) {
return imageGallery;
} else {
LOG.info("Creating new image gallery at path={}", path);
imageGallery = new ImageGallery();
}
imageGallery.setPath(path);
imageGallery.setTitle(title);
......@@ -212,6 +215,7 @@ public class ImageGalleryServiceImpl implements ImageGalleryService {
/**
* Ensure thumbnail.
*
* @param width the width
* @param height the height
* @param repositoryImage the repository image
......@@ -219,8 +223,7 @@ public class ImageGalleryServiceImpl implements ImageGalleryService {
* @throws IOException Signals that an I/O exception has occurred.
* @throws InvalidRepositoryPathException if path is messed up
*/
private void ensureThumbnail(final Integer width, final Integer height, final RepositoryImage repositoryImage) throws IOException,
InvalidRepositoryPathException {
private void ensureThumbnail(final Integer width, final Integer height, final RepositoryImage repositoryImage) throws IOException, InvalidRepositoryPathException {
final String filename = getThumbnailFilename(width, height, repositoryImage.getUuid());
if (!bytesStorageService.exists(getFullThumbnailsPath(repositoryImage), filename)) {
......
......@@ -22,7 +22,8 @@ import org.genesys.filerepository.service.BytesStorageService;
import org.genesys.filerepository.service.ImageGalleryService;
import org.genesys.filerepository.service.RepositoryService;
import org.genesys.filerepository.service.ThumbnailGenerator;
import org.genesys.filerepository.service.aspect.ImageGalleryAspects;
import org.genesys.filerepository.service.aspect.AbstractImageGalleryAspects;
import org.genesys.filerepository.service.aspect.ImageGalleryAspectsImpl;
import org.genesys.filerepository.service.impl.FilesystemStorageServiceImpl;
import org.genesys.filerepository.service.impl.ImageGalleryServiceImpl;
import org.genesys.filerepository.service.impl.RepositoryServiceImpl;
......@@ -122,8 +123,8 @@ public class ServiceBeanConfig {
* @return the image gallery aspects
*/
@Bean
public ImageGalleryAspects imageGalleryAspects() {
return new ImageGalleryAspects();
public AbstractImageGalleryAspects imageGalleryAspects() {
return new ImageGalleryAspectsImpl();
}
/**
......
......@@ -237,7 +237,7 @@ public class ImageGalleryTest {
fileRepoService.removeFile(repoImage1);
// Expect the image to be gone from the list!
assertThat("Image list must be null", imageGalleryService.loadImageGallery(imageGallery.getPath()).getImages(), hasSize(0));
assertThat("Image gallery must be deleted", imageGalleryService.loadImageGallery(imageGallery.getPath()), is(nullValue()));
}
/**
......@@ -290,7 +290,7 @@ public class ImageGalleryTest {
fileRepoService.removeFile(images.remove(idx));
if (images.size() == 0) {
assertThat("Image gallery must have 0 images", imageGalleryService.loadImageGallery(imageGallery.getPath()).getImages(), hasSize(0));
assertThat("Image gallery must be deleted", imageGalleryService.loadImageGallery(imageGallery.getPath()), is(nullValue()));
} else {
// Test order
assertThat("Images must be reordered!", imageGalleryService.loadImageGallery(imageGallery.getPath()).getImages(), contains(images.toArray(EMPTY_REPOSITORYIMAGE_ARRAY)));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment