diff --git a/ccm-cms/src/main/java/org/librecms/assets/Asset.java b/ccm-cms/src/main/java/org/librecms/assets/Asset.java index 0dd987458..8b47f6e5f 100644 --- a/ccm-cms/src/main/java/org/librecms/assets/Asset.java +++ b/ccm-cms/src/main/java/org/librecms/assets/Asset.java @@ -69,6 +69,70 @@ import static org.librecms.CmsConstants.*; query = "SELECT a FROM Asset a " + "WHERE a.uuid = :uuid " + "AND TYPE(a) = :type") + , + @NamedQuery( + name = "Asset.findByFolder", + query = "SELECT a FROM Asset a " + + "JOIN a.categories c " + + "WHERE c.category = :folder " + + "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER + "'") + , + @NamedQuery( + name = "Asset.countInFolder", + query = "SELECT COUNT(a) FROM Asset a " + + "JOIN a.categories c " + + "WHERE c.category = :folder " + + "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER + "'") + , + @NamedQuery( + name = "Asset.filterByFolderAndName", + query = "SELECT a FROM Asset a " + + "JOIN a.categories c " + + "WHERE c.category = :folder " + + "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER + "' " + + "AND LOWER(a.displayName) LIKE CONCAT(LOWER(:name), '%')") + , + @NamedQuery( + name = "Asset.countFilterByFolderAndName", + query = "SELECT COUNT(a) FROM Asset a " + + "JOIN a.categories c " + + "WHERE c.category = :folder " + + "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER + "' " + + "AND LOWER(a.displayName) LIKE CONCAT(LOWER(:name), '%')") + , + @NamedQuery( + name = "Asset.filterByFolderAndType", + query = "SELECT a FROM Asset a " + + "JOIN a.categories c " + + "WHERE c.category = :folder " + + "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER + "' " + + "AND TYPE(a) = :type") + , + @NamedQuery( + name = "Asset.countFilterByFolderAndType", + query = "SELECT COUNT(a) FROM Asset a " + + "JOIN a.categories c " + + "WHERE c.category = :folder " + + "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER + "' " + + "AND TYPE(a) = :type") + , + @NamedQuery( + name = "Asset.filterByFolderAndNameAndType", + query = "SELECT a FROM Asset a " + + "JOIN a.categories c " + + "WHERE c.category = :folder " + + "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER + "' " + + "AND LOWER(a.displayName) LIKE CONCAT(LOWER(:name), '%') " + + "AND TYPE(a) = :type") + , + @NamedQuery( + name = "Asset.countFilterByFolderAndNameAndType", + query = "SELECT COUNT(a) FROM Asset a " + + "JOIN a.categories c " + + "WHERE c.category = :folder " + + "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER + "' " + + "AND LOWER(a.displayName) LIKE CONCAT(LOWER(:name), '%') " + + "AND TYPE(a) = :type") }) public class Asset extends CcmObject implements InheritsPermissions { diff --git a/ccm-cms/src/main/java/org/librecms/assets/AssetInUseException.java b/ccm-cms/src/main/java/org/librecms/assets/AssetInUseException.java new file mode 100644 index 000000000..37e2a9f35 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/assets/AssetInUseException.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2016 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +package org.librecms.assets; + +/** + * + * @author Jens Pelzetter + */ +public class AssetInUseException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + /** + * Creates a new instance of AssetInUseException without detail message. + */ + public AssetInUseException() { + super(); + } + + + /** + * Constructs an instance of AssetInUseException with the specified detail message. + * + * @param msg The detail message. + */ + public AssetInUseException(final String msg) { + super(msg); + } + + /** + * Constructs an instance of AssetInUseException which wraps the + * specified exception. + * + * @param exception The exception to wrap. + */ + public AssetInUseException(final Exception exception) { + super(exception); + } + + /** + * Constructs an instance of AssetInUseException with the specified message which also wraps the + * specified exception. + * + * @param msg The detail message. + * @param exception The exception to wrap. + */ + public AssetInUseException(final String msg, final Exception exception) { + super(msg, exception); + } +} diff --git a/ccm-cms/src/main/java/org/librecms/assets/AssetRepository.java b/ccm-cms/src/main/java/org/librecms/assets/AssetRepository.java index 6a2116a7a..726f93ed9 100644 --- a/ccm-cms/src/main/java/org/librecms/assets/AssetRepository.java +++ b/ccm-cms/src/main/java/org/librecms/assets/AssetRepository.java @@ -18,25 +18,48 @@ */ package org.librecms.assets; +import com.arsdigita.util.UncheckedWrapperException; + import org.libreccm.auditing.AbstractAuditedEntityRepository; +import org.libreccm.categorization.Category; +import org.libreccm.categorization.CategoryManager; +import org.libreccm.categorization.ObjectNotAssignedToCategoryException; +import org.libreccm.core.CcmObjectRepository; +import org.libreccm.security.AuthorizationRequired; +import org.libreccm.security.RequiresPrivilege; +import org.librecms.CmsConstants; +import org.librecms.contentsection.Folder; +import java.util.List; import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; +import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.TypedQuery; +import javax.transaction.Transactional; /** + * An repository for {@link Assets}. * * @author Jens Pelzetter */ +@RequestScoped public class AssetRepository extends AbstractAuditedEntityRepository { @Inject private EntityManager entityManager; + @Inject + private CcmObjectRepository ccmObjectRepo; + + @Inject + private CategoryManager categoryManager; + @Override public Long getEntityId(final Asset asset) { return asset.getObjectId(); @@ -52,6 +75,69 @@ public class AssetRepository return asset.getObjectId() == 0; } + /** + * Set the UUID of a new asset. + * + * @param asset + */ + @Override + public void initNewEntity(final Asset asset) { + super.initNewEntity(asset); + if (asset.getUuid() == null) { + final String uuid = UUID.randomUUID().toString(); + asset.setUuid(uuid); + } + } + + /** + * Deletes an unused Asset. If the {@link Asset} is in use + * (linked to at least one ContentItem) an {@link AssetInUseException} is + * thrown. Use {@link AssetManager#isAssetInUse} to check if an + * {@link Asset} is used. + * + * @param asset The {@link Asset} to delete. + * + * @throws AssetInUseException if the {@link Asset} to delete is in use. + */ + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + @Override + public void delete( + @RequiresPrivilege(CmsConstants.PRIVILEGE_ITEMS_DELETE) + final Asset asset) { + + if (asset.getItemAttachments().isEmpty()) { + final List categories = asset.getCategories() + .stream() + .map(categorization -> categorization.getCategory()) + .collect(Collectors.toList()); + + for (final Category category : categories) { + try { + categoryManager.removeObjectFromCategory(asset, category); + } catch (ObjectNotAssignedToCategoryException ex) { + throw new UncheckedWrapperException(ex); + } + } + + ccmObjectRepo.delete(asset); + } else { + throw new AssetInUseException(String.format("Asset %s is in use.", + asset.getUuid())); + } + } + + /** + * Find an {@link Asset} by its UUID. This method does distinguish between + * shared and non shared assets. + * + * @param uuid The UUID of the {@link Asset}. + * + * @return An {@link Optional} containing the {@link Asset} with the + * provided {@code uuid} if there is an asset with that + * {@code uuid}. Otherwise an empty {@link Optional} is returned. + */ + @Transactional(Transactional.TxType.REQUIRED) public Optional findByUuid(final String uuid) { final TypedQuery query = entityManager.createNamedQuery( "Asset.findByUuid", Asset.class); @@ -64,13 +150,26 @@ public class AssetRepository } } + /** + * Finds an {@link Asset} by its UUID and type. This method + * does distinguish between shared and non shared assets. + * + * @param uuid The UUID of the asset to retrieve. + * @param type The type of the asset to retrieve. + * + * @return An {@link Optional} containing the {@link Asset} with the + * provided {@code uuid} if there is an asset with that {@code uuid} + * and the provided {@code type}. Otherwise an empty + * {@link Optional} is returned. + */ + @Transactional(Transactional.TxType.REQUIRED) public Optional findByUuidAndType( - final String uuid, final Class clazz) { + final String uuid, final Class type) { final TypedQuery query = entityManager.createNamedQuery( "Asset.findByUuidAndType", Asset.class); query.setParameter("uuid", uuid); - query.setParameter("type", clazz.getName()); + query.setParameter("type", type); try { return Optional.of(query.getSingleResult()); @@ -79,18 +178,194 @@ public class AssetRepository } } - public Optional findByType( - final String uuid, final Class clazz) { + /** + * Finds all shared {@link Asset}s of the specified type. + * + * @param type The type of the assets to find. + * + * @return A list containing all shared assets of the specified + * {@code type}. + */ + @Transactional(Transactional.TxType.REQUIRED) + public List findByType(final Class type) { final TypedQuery query = entityManager.createNamedQuery( "Asset.findByType", Asset.class); - query.setParameter("type", clazz.getName()); + query.setParameter("type", type); - try { - return Optional.of(query.getSingleResult()); - } catch (NoResultException ex) { - return Optional.empty(); - } + return query.getResultList(); + } + + /** + * Finds all shared {@link Asset}s in a specific {@link Folder}. + * + * @param folder The {@link Folder} which contains the assets. + * + * @return A list of all assets in the {@link Folder}. + */ + @Transactional(Transactional.TxType.REQUIRED) + public List findByFolder(final Folder folder) { + final TypedQuery query = entityManager.createNamedQuery( + "Asset.findByFolder", Asset.class); + query.setParameter("folder", folder); + + return query.getResultList(); + } + + /** + * Counts all shared {@link Asset}s in a specific {@link Folder}. + * + * @param folder The {@link Folder} which contains the assets. + * + * @return The number of {@link Asset}s in the {@link Folder}. + */ + @Transactional(Transactional.TxType.REQUIRED) + public long countAssetsInFolder(final Folder folder) { + final TypedQuery query = entityManager.createNamedQuery( + "Asset.countInFolder", Long.class); + query.setParameter("folder", folder); + + return query.getSingleResult(); + } + + /** + * Finds all {@link Asset}s in a specific {@link Folder} which name starts + * with the provided string. + * + * @param folder The {@link Folder} which {@link Asset}s are filtered using + * the provided {@code name}. + * @param name The string used to fiter the {@link Assets} in the provided + * {@code folder}. + * + * @return A list with all {@link Asset}s in the provided {@link Folder} + * which name starts with the provided string. + */ + @Transactional(Transactional.TxType.REQUIRED) + public List filterByFolderAndName(final Folder folder, + final String name) { + final TypedQuery query = entityManager.createNamedQuery( + "Asset.filterByFolderAndName", Asset.class); + query.setParameter("folder", folder); + query.setParameter("name", name); + + return query.getResultList(); + } + + /** + * Counts all {@link Asset}s in a specific {@link Folder} which name starts + * with the provided string. + * + * @param folder The {@link Folder} which {@link Asset}s are filtered using + * the provided {@code name}. + * @param name The string used to fiter the {@link Assets} in the provided + * {@code folder}. + * + * @return The number of {@link Asset}s in the provided {@link Folder} which + * name starts with the provided string. + */ + @Transactional(Transactional.TxType.REQUIRED) + public long countFilterByFolderAndName(final Folder folder, + final String name) { + final TypedQuery query = entityManager.createNamedQuery( + "Asset.countFilterByFolderAndName", Long.class); + query.setParameter("folder", folder); + query.setParameter("name", name); + + return query.getSingleResult(); + } + + /** + * Finds all {@link Asset}s of a specific type in a specific folder. + * + * @param folder The {@link Folder} which contains the {@link Asset}s. + * @param type The type of the {@link Asset}s. + * + * @return A list containing all {@link Asset}s of the provided {@code type} + * in the provided {@link Folder}. + */ + @Transactional(Transactional.TxType.REQUIRED) + public List filterByFolderAndType( + final Folder folder, + final Class type) { + + final TypedQuery query = entityManager.createNamedQuery( + "Asset.filterByFolderAndType", Asset.class); + query.setParameter("folder", folder); + query.setParameter("type", type); + + return query.getResultList(); + } + + /** + * Counts the {@link Asset}s of a specific type in a specific folder. + * + * @param folder The {@link Folder} which contains the {@link Asset}s. + * @param type The type of the {@link Asset}s. + * + * @return The number of {@link Asset}s of the provided {@code type} in the + * provided {@link Folder}. + */ + @Transactional(Transactional.TxType.REQUIRED) + public long countFilterByFolderAndType(final Folder folder, + final Class type) { + final TypedQuery query = entityManager.createNamedQuery( + "Asset.countFilterByFolderAndType", Long.class); + query.setParameter("folder", folder); + query.setParameter("type", type); + + return query.getSingleResult(); + } + + /** + * Finds all assets of a specific type which name starts with a provided + * string in a specific folder. + * + * @param folder The {@link Folder} which contains the assets. + * @param type The type of the {@link Asset}s. + * @param name The name to filter the {@link Asset}s for. + * + * @return A list of all {@link Asset}s of the provided type which name + * starts with the provided string in the provided folder. + */ + @Transactional(Transactional.TxType.REQUIRED) + public List filterByFolderAndTypeAndName( + final Folder folder, + final Class type, + final String name) { + + final TypedQuery query = entityManager.createNamedQuery( + "Asset.filterByFolderAndNameAndType", Asset.class); + query.setParameter("folder", folder); + query.setParameter("type", type); + query.setParameter("name", name); + + return query.getResultList(); + } + + /** + * Counts the assets of a specific type which name starts with a provided + * string in a specific folder. + * + * @param folder The {@link Folder} which contains the assets. + * @param type The type of the {@link Asset}s. + * @param name The name to filter the {@link Asset}s for. + * + * @return The number of {@link Asset}s of the provided type which name + * starts with the provided string in the provided folder. + */ + @Transactional(Transactional.TxType.REQUIRED) + public long countFilterByFolderAndTypeAndName( + final Folder folder, + final Class type, + final String name) { + + final TypedQuery query = entityManager.createNamedQuery( + "Asset.countFilterByFolderAndNameAndType", Long.class); + query.setParameter("folder", folder); + query.setParameter("type", type); + query.setParameter("name", name); + + return query.getSingleResult(); } } diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItem.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItem.java index 2d64742ff..6dc54c975 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItem.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItem.java @@ -203,8 +203,7 @@ public class ContentItem extends CcmObject implements Serializable, @Column(name = "ANCESTORS", length = 1024) private String ancestors; - @OneToMany - @JoinColumn(name = "CONTENT_ITEM_ID") + @OneToMany(mappedBy = "item") private List attachments; @OneToOne diff --git a/ccm-cms/src/test/java/org/librecms/assets/AssetRepositoryTest.java b/ccm-cms/src/test/java/org/librecms/assets/AssetRepositoryTest.java new file mode 100644 index 000000000..0d4cac5f7 --- /dev/null +++ b/ccm-cms/src/test/java/org/librecms/assets/AssetRepositoryTest.java @@ -0,0 +1,455 @@ +/* + * Copyright (C) 2016 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.assets; + +import static org.libreccm.testutils.DependenciesHelpers.*; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.ShouldThrowException; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.junit.InSequence; +import org.jboss.arquillian.persistence.CreateSchema; +import org.jboss.arquillian.persistence.PersistenceTest; +import org.jboss.arquillian.persistence.ShouldMatchDataSet; +import org.jboss.arquillian.persistence.UsingDataSet; +import org.jboss.arquillian.transaction.api.annotation.TransactionMode; +import org.jboss.arquillian.transaction.api.annotation.Transactional; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.libreccm.security.Shiro; +import org.libreccm.tests.categories.IntegrationTest; +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.Folder; +import org.librecms.contentsection.FolderRepository; + +import java.util.List; +import java.util.Optional; + +import javax.inject.Inject; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +/** + * Tests for the {@link AssetRepository}. + * + * @author Jens Pelzetter + */ +@org.junit.experimental.categories.Category(IntegrationTest.class) +@RunWith(Arquillian.class) +@PersistenceTest +@Transactional(TransactionMode.COMMIT) +@CreateSchema({"create_ccm_cms_schema.sql"}) +public class AssetRepositoryTest { + + @Inject + private AssetRepository assetRepo; + + @Inject + private FolderRepository folderRepo; + + @Inject + private Shiro shiro; + + public AssetRepositoryTest() { + } + + @BeforeClass + public static void setUpClass() { + } + + @AfterClass + public static void tearDownClass() { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + @Deployment + public static WebArchive createDeployment() { + return ShrinkWrap + .create(WebArchive.class, + "LibreCCM-org.librecms.assets.AssetRepositoryTest.war") + .addPackage(org.libreccm.auditing.CcmRevision.class.getPackage()) + .addPackage(org.libreccm.categorization.Categorization.class + .getPackage()) + .addPackage(org.libreccm.cdi.utils.CdiUtil.class.getPackage()) + .addPackage(org.libreccm.configuration.Configuration.class + .getPackage()) + .addPackage(org.libreccm.core.CcmCore.class.getPackage()) + .addPackage(org.libreccm.jpa.EntityManagerProducer.class + .getPackage()) + .addPackage(org.libreccm.jpa.utils.MimeTypeConverter.class + .getPackage()) + .addPackage(org.libreccm.l10n.LocalizedString.class + .getPackage()) + .addPackage(org.libreccm.security.Permission.class.getPackage()) + .addPackage(org.libreccm.web.CcmApplication.class.getPackage()) + .addPackage(org.libreccm.workflow.Workflow.class.getPackage()) + .addPackage(com.arsdigita.bebop.Component.class.getPackage()) + .addPackage(com.arsdigita.bebop.util.BebopConstants.class + .getPackage()) + .addClass(com.arsdigita.kernel.KernelConfig.class) + .addClass(com.arsdigita.runtime.CCMResourceManager.class) + .addClass( + com.arsdigita.ui.admin.applications.AbstractAppInstanceForm.class) + .addClass( + com.arsdigita.ui.admin.applications.AbstractAppSettingsPane.class) + .addClass( + com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm.class) + .addClass( + com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane.class) + .addClass(com.arsdigita.cms.dispatcher.ItemResolver.class) + .addPackage(com.arsdigita.util.Lockable.class.getPackage()) + .addPackage(com.arsdigita.web.BaseServlet.class.getPackage()) + .addPackage(org.librecms.Cms.class.getPackage()) + .addPackage(org.librecms.assets.Asset.class.getPackage()) + .addPackage(org.librecms.attachments.AttachmentList.class + .getPackage()) + .addPackage(org.librecms.lifecycle.Lifecycle.class.getPackage()) + .addPackage(org.librecms.contentsection.ContentSection.class + .getPackage()) + .addPackage(org.librecms.contenttypes.Article.class.getPackage()). + addClass(com.arsdigita.kernel.security.SecurityConfig.class) + .addPackage(org.libreccm.tests.categories.IntegrationTest.class + .getPackage()) + // .addAsLibraries(getModuleDependencies()) + .addAsLibraries(getCcmCoreDependencies()) + .addAsResource("configs/shiro.ini", "shiro.ini") + .addAsResource( + "configs/org/librecms/contentsection/ContentItemManagerTest/log4j2.xml", + "log4j2.xml") + .addAsResource("test-persistence.xml", + "META-INF/persistence.xml") + .addAsWebInfResource("test-web.xml", "web.xml") + .addAsWebInfResource(EmptyAsset.INSTANCE, "WEB-INF/beans.xml"); + } + + /** + * Verify that dependencies have been injected. + */ + @Test + @InSequence(1) + public void checkInjections() { + assertThat(shiro, is(not(nullValue()))); + assertThat(assetRepo, is(not(nullValue()))); + assertThat(folderRepo, is(not(nullValue()))); + } + + /** + * Verify that Shiro is working. + */ + @Test + @InSequence(20) + public void checkShiro() { + assertThat(shiro.getSecurityManager(), is(not(nullValue()))); + assertThat(shiro.getSystemUser(), is(not(nullValue()))); + } + + /** + * Tries to delete an unused {@link Asset} using + * {@link AssetRepository#delete(org.librecms.assets.Asset)} and verifies + * that the {@link Asset} has been removed from the database. + */ + @Test + @InSequence(100) + @UsingDataSet("datasets/org/librecms/assets/AssetRepositoryTest/data.xml") + @ShouldMatchDataSet( + value = "datasets/org/librecms/assets/AssetRepositoryTest/" + + "after-delete.xml", + excludeColumns = {"timestamp", "object_order"} + ) + public void deleteUnusedAsset() { + final Asset asset = assetRepo.findById(-800L); + + assertThat(asset, is(not(nullValue()))); + + assetRepo.delete(asset); + } + + /** + * Verifies that an {@link Asset} which is associated to at least one + * {@link ContentItem} can't be deleted by using + * {@link AssetRepository#delete(org.librecms.assets.Asset)}. + */ + @Test(expected = AssetInUseException.class) + @InSequence(110) + @UsingDataSet("datasets/org/librecms/assets/AssetRepositoryTest/data.xml") + @ShouldMatchDataSet("datasets/org/librecms/assets/AssetRepositoryTest/" + + "data.xml") + @ShouldThrowException(AssetInUseException.class) + public void deleteUsedAsset() { + final Asset asset = assetRepo.findById(-700L); + + assertThat(asset, is(not(nullValue()))); + + assetRepo.delete(asset); + } + + /** + * Tries to find various {@link Assets} by their UUID using + * {@link AssetRepository#findByUuid(java.lang.String)}. + */ + @Test + @InSequence(200) + @UsingDataSet("datasets/org/librecms/assets/AssetRepositoryTest/data.xml") + public void findAssetByUuid() { + final Optional header = assetRepo.findByUuid( + "4635589f-b87a-46d9-979e-6af14af063e5"); + final Optional phb = assetRepo.findByUuid( + "0a192e98-3b28-49d0-833f-bc9ff5f9d1d4"); + final Optional datasheet = assetRepo.findByUuid( + "0393840f-06a6-4ec3-aeb3-a612f845ad60"); + final Optional none = assetRepo.findByUuid( + "5211bf56-c20b-40b3-8ef8-0c7d35325fda"); + + assertThat(header.isPresent(), is(true)); + assertThat(phb.isPresent(), is(true)); + assertThat(datasheet.isPresent(), is(true)); + assertThat(none.isPresent(), is(false)); + + assertThat(header.get().getDisplayName(), is(equalTo("header.png"))); + assertThat(phb.get().getDisplayName(), is(equalTo("the-phb.png"))); + assertThat(datasheet.get().getDisplayName(), is(equalTo( + "product1-datasheet.pdf"))); + + } + + /** + * Tries to find various {@link Assets} by their UUID and type using + * {@link AssetRepository#findByUuidAndType(java.lang.String, java.lang.Class)}. + */ + @Test + @InSequence(210) + @UsingDataSet("datasets/org/librecms/assets/AssetRepositoryTest/data.xml") + public void findAssetByUuidAndType() { + final Optional asset = assetRepo.findByUuidAndType( + "4635589f-b87a-46d9-979e-6af14af063e5", Image.class); + final Optional none = assetRepo.findByUuidAndType( + "4635589f-b87a-46d9-979e-6af14af063e5", File.class); + + assertThat(asset.isPresent(), is(true)); + assertThat(asset.get().getDisplayName(), is(equalTo("header.png"))); + + assertThat(none.isPresent(), is(false)); + } + + /** + * Tries to find various {@link Assets} by their type using + * {@link AssetRepository#findByType(java.lang.Class)}. + */ + @Test + @InSequence(300) + @UsingDataSet("datasets/org/librecms/assets/AssetRepositoryTest/data.xml") + public void findAssetByType() { + final List images = assetRepo.findByType(Image.class); + final List files = assetRepo.findByType(File.class); + + assertThat(images.isEmpty(), is(false)); + assertThat(files.isEmpty(), is(false)); + + assertThat(images.size(), is(3)); + assertThat(files.size(), is(2)); + + assertThat(images.get(0).getDisplayName(), is(equalTo("header.png"))); + assertThat(images.get(1).getDisplayName(), is(equalTo("the-phb.png"))); + assertThat(images.get(2).getDisplayName(), + is(equalTo("services-header.png"))); + + assertThat(files.get(0).getDisplayName(), + is(equalTo("product1-datasheet.pdf"))); + assertThat(files.get(1).getDisplayName(), is(equalTo("catalog.pdf"))); + } + + /** + * Tries all {@link Assets} in a specific {@link Folder} using + * {@link AssetRepository#findByFolder(org.librecms.contentsection.Folder)}. + */ + @Test + @InSequence(400) + @UsingDataSet("datasets/org/librecms/assets/AssetRepositoryTest/data.xml") + public void findAssetsByFolder() { + final Folder media = folderRepo.findById(-400L); + final Folder data = folderRepo.findById(-500L); + + final List mediaAssets = assetRepo.findByFolder(media); + final List dataAssets = assetRepo.findByFolder(data); + + assertThat(mediaAssets.size(), is(5)); + assertThat(dataAssets.size(), is(0)); + } + + /** + * Tries to find out the number of {@link Asset}s in a specific + * {@link Folder} using + * {@link AssetRepository#countAssetsInFolder(org.librecms.contentsection.Folder)}. + */ + @Test + @InSequence(410) + @UsingDataSet("datasets/org/librecms/assets/AssetRepositoryTest/data.xml") + public void countAssetsInFolder() { + final Folder media = folderRepo.findById(-400L); + final Folder data = folderRepo.findById(-500L); + + assertThat(assetRepo.countAssetsInFolder(media), is(5L)); + assertThat(assetRepo.countAssetsInFolder(data), is(0L)); + } + + /** + * Tries to find {@link Asset}s in a {@link Folder} by using + * {@link AssetRepository#filterByFolderAndName(org.librecms.contentsection.Folder, java.lang.String)}. + */ + @Test + @InSequence(500) + @UsingDataSet("datasets/org/librecms/assets/AssetRepositoryTest/data.xml") + public void filterAssetByFolderAndName() { + final Folder media = folderRepo.findById(-400L); + + final List result1 = assetRepo.filterByFolderAndName(media, + "hea"); + final List result2 = assetRepo.filterByFolderAndName(media, + "photo"); + + assertThat(result1.size(), is(1)); + assertThat(result2.size(), is(0)); + + assertThat(result1.get(0).getDisplayName(), is(equalTo("header.png"))); + } + + /** + * Tries to count the {@link Asset}s in a {@link Folder} matching a name + * pattern by using + * {@link AssetRepository#countFilterByFolderAndName(org.librecms.contentsection.Folder, java.lang.String)}. + */ + @Test + @InSequence(510) + @UsingDataSet("datasets/org/librecms/assets/AssetRepositoryTest/data.xml") + public void countFilterAssetByFolderAndName() { + final Folder media = folderRepo.findById(-400L); + + assertThat(assetRepo.countFilterByFolderAndName(media, "hea"), + is(1L)); + assertThat(assetRepo.countFilterByFolderAndName(media, "photo"), + is(0L)); + } + + /** + * Tries to filter the {@link Asset}s in a {@link Folder} by their type + * using + * {@link AssetRepository#filterByFolderAndType(org.librecms.contentsection.Folder, java.lang.Class)}. + */ + @Test + @InSequence(600) + @UsingDataSet("datasets/org/librecms/assets/AssetRepositoryTest/data.xml") + public void filterAssetsByFolderAndType() { + final Folder media = folderRepo.findById(-400L); + + final List images = assetRepo.filterByFolderAndType(media, + Image.class); + final List files = assetRepo.filterByFolderAndType(media, + File.class); + final List videos = assetRepo.filterByFolderAndType( + media, VideoAsset.class); + + assertThat(images.size(), is(3)); + assertThat(files.size(), is(2)); + assertThat(videos.size(), is(0)); + + assertThat(images.get(0).getDisplayName(), is(equalTo("header.png"))); + assertThat(images.get(1).getDisplayName(), is(equalTo("the-phb.png"))); + assertThat(images.get(2).getDisplayName(), + is(equalTo("services-header.png"))); + + assertThat(files.get(0).getDisplayName(), + is(equalTo("product1-datasheet.pdf"))); + assertThat(files.get(1).getDisplayName(), is(equalTo("catalog.pdf"))); + } + + /** + * Tries to count the {@link Asset}s of a specific type in a {@link Folder} + * using + * {@link AssetRepository#countFilterByFolderAndType(org.librecms.contentsection.Folder, java.lang.Class)}. + */ + @Test + @InSequence(610) + @UsingDataSet("datasets/org/librecms/assets/AssetRepositoryTest/data.xml") + public void countFilterAssetsByFolderAndType() { + final Folder media = folderRepo.findById(-400L); + + assertThat(assetRepo.countFilterByFolderAndType(media, Image.class), + is(3L)); + assertThat(assetRepo.countFilterByFolderAndType(media, File.class), + is(2L)); + assertThat(assetRepo.countFilterByFolderAndType(media, VideoAsset.class), + is(0L)); + } + + /** + * Tries to filter the {@link Asset}s in a {@link Folder} by their type and + * name using + * {@link AssetRepository#filterByFolderAndTypeAndName(org.librecms.contentsection.Folder, java.lang.Class, java.lang.String)}. + */ + @Test + @InSequence(600) + @UsingDataSet("datasets/org/librecms/assets/AssetRepositoryTest/data.xml") + public void filterAssetsByFolderAndTypeAndName() { + final Folder media = folderRepo.findById(-400L); + + final List result1 = assetRepo.filterByFolderAndTypeAndName( + media, Image.class, "hea"); + final List result2 = assetRepo.filterByFolderAndTypeAndName( + media, File.class, "hea"); + + assertThat(result1.size(), is(1)); + assertThat(result2.size(), is(0)); + + } + + /** + * Tries to count the {@link Asset}s in a {@link Folder} which are of a + * specific type and which name matches a specific pattern using + * {@link AssetRepository#filterByFolderAndTypeAndName(org.librecms.contentsection.Folder, java.lang.Class, java.lang.String)}. + */ + @Test + @InSequence(610) + @UsingDataSet("datasets/org/librecms/assets/AssetRepositoryTest/data.xml") + public void countFilterAssetsByFolderAndTypeAndName() { + final Folder media = folderRepo.findById(-400L); + + assertThat(assetRepo.countFilterByFolderAndTypeAndName( + media, Image.class, "hea"), + is(1L)); + assertThat(assetRepo.countFilterByFolderAndTypeAndName( + media, File.class, "hea"), + is(0L)); + } + +} diff --git a/ccm-cms/src/test/java/org/librecms/assets/DatasetsTest.java b/ccm-cms/src/test/java/org/librecms/assets/DatasetsTest.java new file mode 100644 index 000000000..568b2b6c7 --- /dev/null +++ b/ccm-cms/src/test/java/org/librecms/assets/DatasetsTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2016 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.assets; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.libreccm.tests.categories.UnitTest; +import org.libreccm.testutils.DatasetType; +import org.libreccm.testutils.DatasetsVerifier; + +import java.util.Arrays; +import java.util.Collection; + +/** + * Verify the datasets for the tests in {@code org.librecms.assets}. + * + * @author Jens Pelzetter + */ +@RunWith(Parameterized.class) +@Category(UnitTest.class) +public class DatasetsTest extends DatasetsVerifier { + + @Parameterized.Parameters(name = "Dataset {0}") + public static Collection data() { + return Arrays.asList(new String[]{ + "/datasets/org/librecms/assets/AssetRepositoryTest/data.xml", + "/datasets/org/librecms/assets/AssetRepositoryTest/after-delete.xml" + }); + } + + public DatasetsTest(final String datasetPath) { + super(datasetPath); + } + + @Override + public DatasetType getDatasetType() { + return DatasetType.FLAT_XML; + } + + @Override + public String[] getSchemas() { + return new String[]{"ccm_core", "ccm_cms"}; + } + + @Override + public String[] getDdlFiles() { + return new String[]{"/datasets/create_ccm_cms_schema.sql"}; + } + + @BeforeClass + public static void setUpClass() { + } + + @AfterClass + public static void tearDownClass() { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + +} diff --git a/ccm-cms/src/test/resources/datasets/org/librecms/assets/AssetRepositoryTest/after-delete.xml b/ccm-cms/src/test/resources/datasets/org/librecms/assets/AssetRepositoryTest/after-delete.xml new file mode 100644 index 000000000..dd4acbeb2 --- /dev/null +++ b/ccm-cms/src/test/resources/datasets/org/librecms/assets/AssetRepositoryTest/after-delete.xml @@ -0,0 +1,447 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ccm-cms/src/test/resources/datasets/org/librecms/assets/AssetRepositoryTest/data.xml b/ccm-cms/src/test/resources/datasets/org/librecms/assets/AssetRepositoryTest/data.xml new file mode 100644 index 000000000..6b18efe26 --- /dev/null +++ b/ccm-cms/src/test/resources/datasets/org/librecms/assets/AssetRepositoryTest/data.xml @@ -0,0 +1,450 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ccm-cms/src/test/resources/scripts/h2-cleanup.sql b/ccm-cms/src/test/resources/scripts/h2-cleanup.sql index c362037da..13713f8fc 100644 --- a/ccm-cms/src/test/resources/scripts/h2-cleanup.sql +++ b/ccm-cms/src/test/resources/scripts/h2-cleanup.sql @@ -1,3 +1,31 @@ +DELETE FROM ccm_cms.attachments_aud; + +DELETE FROM ccm_cms.attachments; + +DELETE FROM ccm_cms.attachment_lists_aud; + +DELETE FROM ccm_cms.attachment_lists; + +DELETE FROM ccm_cms.images_aud; + +DELETE FROM ccm_cms.images; + +DELETE FROM ccm_cms.files_aud; + +DELETE FROM ccm_cms.files; + +DELETE FROM ccm_cms.binary_assets_aud; + +DELETE FROM ccm_cms.binary_assets; + +DELETE FROM ccm_cms.asset_titles_aud; + +DELETE FROM ccm_cms.asset_titles; + +DELETE FROM ccm_cms.assets_aud; + +DELETE FROM ccm_cms.assets; + DELETE FROM ccm_cms.news_texts; DELETE FROM ccm_cms.news; diff --git a/ccm-cms/src/test/resources/scripts/pgsql-cleanup.sql b/ccm-cms/src/test/resources/scripts/pgsql-cleanup.sql index fe5ce169c..c96f53f86 100644 --- a/ccm-cms/src/test/resources/scripts/pgsql-cleanup.sql +++ b/ccm-cms/src/test/resources/scripts/pgsql-cleanup.sql @@ -1,3 +1,31 @@ +DELETE FROM ccm_cms.attachments_aud; + +DELETE FROM ccm_cms.attachments; + +DELETE FROM ccm_cms.attachment_lists_aud; + +DELETE FROM ccm_cms.attachment_lists; + +DELETE FROM ccm_cms.images_aud; + +DELETE FROM ccm_cms.images; + +DELETE FROM ccm_cms.files_aud; + +DELETE FROM ccm_cms.files; + +DELETE FROM ccm_cms.binary_assets_aud; + +DELETE FROM ccm_cms.binary_assets; + +DELETE FROM ccm_cms.asset_titles_aud; + +DELETE FROM ccm_cms.asset_titles; + +DELETE FROM ccm_cms.assets_aud; + +DELETE FROM ccm_cms.assets; + DELETE FROM ccm_cms.news_texts; DELETE FROM ccm_cms.news;