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 extends Asset> clazz) {
+ final String uuid, final Class extends Asset> 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 extends Asset> 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 extends Asset> 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 extends Asset> 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 extends Asset> 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 extends Asset> 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 extends Asset> 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;