From 9af0a34a98d5063d2574ce7e70f199687a586e0f Mon Sep 17 00:00:00 2001 From: jensp Date: Wed, 22 Feb 2017 09:45:48 +0000 Subject: [PATCH] CCM NG/ccm-cms FolderBrowser: Link for deleting empty folders now shows up. git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4589 8810af33-2d31-482b-a856-94f89814c4df --- .../ui/folder/FolderBrowserController.java | 6 + .../org/libreccm/categorization/Category.java | 15 +- .../categorization/CategoryManager.java | 320 ++++++++++-------- 3 files changed, 198 insertions(+), 143 deletions(-) diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserController.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserController.java index 0ce23171a..b53b8a580 100644 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserController.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserController.java @@ -21,6 +21,7 @@ package com.arsdigita.cms.ui.folder; import com.arsdigita.kernel.KernelConfig; import org.libreccm.categorization.Categorization; +import org.libreccm.categorization.CategoryManager; import org.libreccm.configuration.ConfigurationManager; import org.libreccm.core.CcmObject; import org.libreccm.core.CcmObjectRepository; @@ -71,6 +72,9 @@ public class FolderBrowserController { @Inject private EntityManager entityManager; + @Inject + private CategoryManager categoryManager; + @Inject private CcmObjectRepository objectRepo; @@ -326,6 +330,8 @@ public class FolderBrowserController { row.setTitle(folder.getTitle().getValue(defaultLocale)); } row.setFolder(true); + row.setDeletable(!categoryManager.hasSubCategories(folder) + && !categoryManager.hasObjects(folder)); return row; } diff --git a/ccm-core/src/main/java/org/libreccm/categorization/Category.java b/ccm-core/src/main/java/org/libreccm/categorization/Category.java index c15513709..d1fcf8b46 100644 --- a/ccm-core/src/main/java/org/libreccm/categorization/Category.java +++ b/ccm-core/src/main/java/org/libreccm/categorization/Category.java @@ -78,14 +78,25 @@ import javax.xml.bind.annotation.XmlRootElement; @NamedQuery( name = "Category.findByName", query = "SELECT c FROM Category c WHERE c.name = :name") + , + @NamedQuery( + name = "Category.hasObjects", + query = "SELECT (CASE WHEN COUNT(c) > 0 THEN true ELSE false END) " + + "FROM Categorization c " + + "WHERE c.category = :category") + , + @NamedQuery( + name = "Category.hasSubCategories", + query = "SELECT (CASE WHEN COUNT(c) > 0 THEN true ELSE false END) " + + "FROM Category c " + + "WHERE c.parentCategory = :category") }) @NamedEntityGraphs({ @NamedEntityGraph( name = "Category.withSubCategoriesAndObjects", attributeNodes = { @NamedAttributeNode(value = "subCategories" - ), - } + ),} ) }) @XmlRootElement(name = "category", namespace = CAT_XML_NS) diff --git a/ccm-core/src/main/java/org/libreccm/categorization/CategoryManager.java b/ccm-core/src/main/java/org/libreccm/categorization/CategoryManager.java index 0adf35ef9..507f68d22 100644 --- a/ccm-core/src/main/java/org/libreccm/categorization/CategoryManager.java +++ b/ccm-core/src/main/java/org/libreccm/categorization/CategoryManager.java @@ -53,7 +53,7 @@ import javax.transaction.Transactional; public class CategoryManager { private static final Logger LOGGER = LogManager.getLogger( - CategoryManager.class); + CategoryManager.class); /** * A {@link CategoryRepository} instance used to interact with the database. @@ -85,17 +85,17 @@ public class CategoryManager { * {@code null} an {@link IllegalArgumentException} is thrown because * passing {@code null} to this method indicates a programming error. * - * @param object The object to assign to the category. Can never be - * {@code null}. + * @param object The object to assign to the category. Can never be + * {@code null}. * @param category The category to which the object should be assigned. Can - * never be {@code null}. + * never be {@code null}. */ @AuthorizationRequired @Transactional(Transactional.TxType.REQUIRED) public void addObjectToCategory( - final CcmObject object, - @RequiresPrivilege(PRIVILEGE_MANAGE_CATEGORY_OBJECTS) - final Category category) { + final CcmObject object, + @RequiresPrivilege(PRIVILEGE_MANAGE_CATEGORY_OBJECTS) + final Category category) { addObjectToCategory(object, category, null); } @@ -112,28 +112,28 @@ public class CategoryManager { * {@code null} an {@link IllegalArgumentException} is thrown because * passing {@code null} to this method indicates a programming error. * - * @param object The object to assign to the category. Can never be - * {@code null}. + * @param object The object to assign to the category. Can never be + * {@code null}. * @param category The category to which the object should be assigned. Can - * never be {@code null}. - * @param type Type of the categorisation. + * never be {@code null}. + * @param type Type of the categorisation. */ @AuthorizationRequired @Transactional(Transactional.TxType.REQUIRED) public void addObjectToCategory( - final CcmObject object, - @RequiresPrivilege(PRIVILEGE_MANAGE_CATEGORY_OBJECTS) - final Category category, - final String type) { + final CcmObject object, + @RequiresPrivilege(PRIVILEGE_MANAGE_CATEGORY_OBJECTS) + final Category category, + final String type) { if (object == null) { throw new IllegalArgumentException( - "Null can't be added to a category."); + "Null can't be added to a category."); } if (category == null) { throw new IllegalArgumentException( - "Can't add an object to category 'null'."); + "Can't add an object to category 'null'."); } final Categorization categorization = new Categorization(); @@ -158,13 +158,39 @@ public class CategoryManager { }); } + public boolean hasSubCategories(final Category category) { + + Objects.requireNonNull( + category, + "Can't determine if Category null has sub categories."); + + final TypedQuery query = entityManager.createNamedQuery( + "Category.hasSubCategories", Boolean.class); + query.setParameter("category", category); + + return query.getSingleResult(); + } + + public boolean hasObjects(final Category category) { + + Objects.requireNonNull(category, + "Can't determine if category null has objects."); + + final TypedQuery query = entityManager.createNamedQuery( + "Category.hasObjects", Boolean.class); + query.setParameter("category", category); + + return query.getSingleResult(); + } + /** * Check if an object is assigned to a category. * * @param category The category - * @param object The object + * @param object The object + * * @return {@code true} if the provided {@code object} is assigned to the - * provided {@code category}, {@code false} otherwise. + * provided {@code category}, {@code false} otherwise. */ public boolean isAssignedToCategory(final Category category, final CcmObject object) { @@ -172,7 +198,7 @@ public class CategoryManager { Objects.requireNonNull(object); final TypedQuery query = entityManager.createNamedQuery( - "Categorization.isAssignedTo", Boolean.class); + "Categorization.isAssignedTo", Boolean.class); query.setParameter("category", category); query.setParameter("object", object); @@ -186,11 +212,12 @@ public class CategoryManager { * {@link #isAssignedToCategory(org.libreccm.categorization.Category, org.libreccm.core.CcmObject)}. * * @param category The category - * @param object The object - * @param type The type with which the object has been assigned to the - * category. the type may be {@code null}. + * @param object The object + * @param type The type with which the object has been assigned to the + * category. the type may be {@code null}. + * * @return {@code true} if the provided {@code object} is assigned to the - * provided {@code category} using the provided {@code type}. + * provided {@code category} using the provided {@code type}. */ public boolean isAssignedToCategoryWithType(final Category category, final CcmObject object, @@ -199,7 +226,7 @@ public class CategoryManager { Objects.requireNonNull(object); final TypedQuery query = entityManager.createNamedQuery( - "Categorization.isAssignedTo", Boolean.class); + "Categorization.isAssignedTo", Boolean.class); query.setParameter("category", category); query.setParameter("object", object); query.setParameter("type", type); @@ -218,35 +245,35 @@ public class CategoryManager { * because passing {@code null} to either parameter indicates a programming * error. * - * @param object The object to remove from the category. Can never be - * {@code null}. + * @param object The object to remove from the category. Can never be + * {@code null}. * @param category The category from which the object should be removed. Can - * never be {@code null}. + * never be {@code null}. * * @throws ObjectNotAssignedToCategoryException Thrown is the provided - * object is not + * object is not * assigned to the provided category. */ @AuthorizationRequired @Transactional(Transactional.TxType.REQUIRED) public void removeObjectFromCategory( - final CcmObject object, - @RequiresPrivilege(PRIVILEGE_MANAGE_CATEGORY_OBJECTS) - final Category category) - throws ObjectNotAssignedToCategoryException { + final CcmObject object, + @RequiresPrivilege(PRIVILEGE_MANAGE_CATEGORY_OBJECTS) + final Category category) + throws ObjectNotAssignedToCategoryException { if (object == null) { throw new IllegalArgumentException( - "Can't remove object 'null' from a category"); + "Can't remove object 'null' from a category"); } if (category == null) { throw new IllegalArgumentException( - "Can't remove an object from category 'null'"); + "Can't remove an object from category 'null'"); } final TypedQuery query = entityManager.createNamedQuery( - "Categorization.find", Categorization.class); + "Categorization.find", Categorization.class); query.setParameter("category", category); query.setParameter("object", object); @@ -255,10 +282,10 @@ public class CategoryManager { categorization = query.getSingleResult(); } catch (NoResultException ex) { LOGGER.warn(String.format( - "No categorization for category %s and object %s found." - + "Ignoring. Orginal exception: ", - category.toString(), - object.toString()), + "No categorization for category %s and object %s found." + + "Ignoring. Orginal exception: ", + category.toString(), + object.toString()), ex); return; } @@ -289,21 +316,22 @@ public class CategoryManager { * The value of the {@code order} property of the object after the provided * is decreased by one. Effectively the two objects are swapped. * - * @param object The object which {@code order} property is decreased. Can't - * be {@code null}. + * @param object The object which {@code order} property is decreased. + * Can't be {@code null}. * @param category The category to which the object is assigned. Can't be - * {@code null}. + * {@code null}. * * @throws ObjectNotAssignedToCategoryException Throws if the provided - * object is not assigned to the provided category. + * object is not assigned to + * the provided category. */ @AuthorizationRequired @Transactional(Transactional.TxType.REQUIRED) public void increaseObjectOrder( - final CcmObject object, - @RequiresPrivilege(PRIVILEGE_MANAGE_CATEGORY_OBJECTS) - final Category category) - throws ObjectNotAssignedToCategoryException { + final CcmObject object, + @RequiresPrivilege(PRIVILEGE_MANAGE_CATEGORY_OBJECTS) + final Category category) + throws ObjectNotAssignedToCategoryException { if (object == null) { throw new IllegalArgumentException("The object can't be null."); @@ -319,7 +347,7 @@ public class CategoryManager { Categorization current = null; int index = 0; final List objects = new ArrayList<>(category - .getObjects()); + .getObjects()); objects.sort((o1, o2) -> { return Long.compare(o1.getObjectOrder(), o2.getObjectOrder()); }); @@ -342,10 +370,10 @@ public class CategoryManager { if (categorization == null) { //Object is not part of the category. throw new ObjectNotAssignedToCategoryException(String.format( - "The object %s is not assigned to the category %s (UUID: %s).", - object.getUuid(), - category.getName(), - category.getUuid())); + "The object %s is not assigned to the category %s (UUID: %s).", + object.getUuid(), + category.getName(), + category.getUuid())); } final long order = categorization.getObjectOrder(); @@ -362,21 +390,22 @@ public class CategoryManager { * The value of the {@code order} property of the object before the provided * is increased by one. Effectively the two objects are swapped. * - * @param object The object which {@code order} property is decreased. Can't - * be {@code null}. + * @param object The object which {@code order} property is decreased. + * Can't be {@code null}. * @param category The category to which the object is assigned. Can't be - * {@code null}. + * {@code null}. * * @throws ObjectNotAssignedToCategoryException Throws if the provided - * object is not assigned to the provided category. + * object is not assigned to + * the provided category. */ @AuthorizationRequired @Transactional(Transactional.TxType.REQUIRED) public void decreaseObjectOrder( - final CcmObject object, - @RequiresPrivilege(PRIVILEGE_MANAGE_CATEGORY_OBJECTS) - final Category category) - throws ObjectNotAssignedToCategoryException { + final CcmObject object, + @RequiresPrivilege(PRIVILEGE_MANAGE_CATEGORY_OBJECTS) + final Category category) + throws ObjectNotAssignedToCategoryException { if (object == null) { throw new IllegalArgumentException("The object can't be null."); @@ -392,7 +421,7 @@ public class CategoryManager { Categorization current = null; int index = 0; final List objects = new ArrayList<>(category - .getObjects()); + .getObjects()); objects.sort((o1, o2) -> { return Long.compare(o1.getObjectOrder(), o2.getObjectOrder()); }); @@ -415,10 +444,10 @@ public class CategoryManager { if (categorization == null) { //Object is not part of the category. throw new ObjectNotAssignedToCategoryException(String.format( - "The object %s is not assigned to the category %s (UUID: %s).", - object.getUuid(), - category.getName(), - category.getUuid())); + "The object %s is not assigned to the category %s (UUID: %s).", + object.getUuid(), + category.getName(), + category.getUuid())); } final long order = categorization.getObjectOrder(); @@ -435,13 +464,15 @@ public class CategoryManager { * of the {@code order} property of the {@link Categorization} of the * provided objects are swapped. * - * @param objectA Th first object. Can't be {@code null}. - * @param objectB The second object. Can't be {@code null}. + * @param objectA Th first object. Can't be {@code null}. + * @param objectB The second object. Can't be {@code null}. * @param category Can't be {@code null}. The category to which both objects - * are assigned. Can't be {@code null}. + * are assigned. Can't be {@code null}. * * @throws ObjectNotAssignedToCategoryException Thrown if one or both of the - * provided objects are not assigned to the provided category. + * provided objects are not + * assigned to the provided + * category. */ // public void swapObjects(final CcmObject objectA, // final CcmObject objectB, @@ -454,17 +485,17 @@ public class CategoryManager { * Adds a category as an subcategory to another category. If the category is * assigned to another category that association is removed. * - * @param subCategory The category to add as subcategory. Can't be - * {@code null}. + * @param subCategory The category to add as subcategory. Can't be + * {@code null}. * @param parentCategory The category to which the category is added as - * subcategory. Can't be {@code null}. + * subcategory. Can't be {@code null}. */ @AuthorizationRequired @Transactional(Transactional.TxType.REQUIRED) public void addSubCategoryToCategory( - final Category subCategory, - @RequiresPrivilege(PRIVILEGE_MANAGE_CATEGORY) - final Category parentCategory) { + final Category subCategory, + @RequiresPrivilege(PRIVILEGE_MANAGE_CATEGORY) + final Category parentCategory) { if (subCategory == null) { throw new IllegalArgumentException("subCategory can't be null."); @@ -474,21 +505,21 @@ public class CategoryManager { } final Optional sub = categoryRepo.findById(subCategory - .getObjectId()); + .getObjectId()); final Optional parent = categoryRepo.findById(parentCategory - .getObjectId()); + .getObjectId()); if (!sub.isPresent()) { throw new IllegalArgumentException(String.format( - "The provided category to add as sub category {} was not found " + "The provided category to add as sub category {} was not found " + "in the database.", - subCategory.toString())); + subCategory.toString())); } if (!parent.isPresent()) { throw new IllegalArgumentException(String.format( - "The category {} provided as parent category was not found in " + "The category {} provided as parent category was not found in " + "the database.", - parentCategory.toString())); + parentCategory.toString())); } if (sub.get().getParentCategory() != null) { @@ -512,26 +543,27 @@ public class CategoryManager { * assigned to another parent category (or as root category to a * {@link Domain} the category becomes orphaned. * - * @param subCategory The subcategory to remove from the parent category. - * Can't be {@code null}. + * @param subCategory The subcategory to remove from the parent category. + * Can't be {@code null}. * @param parentCategory The parent category. Can't be {@code null}. * * @throws IllegalArgumentException If the provided subcategory is not - * assigned to the provided parent category. + * assigned to the provided parent + * category. */ @AuthorizationRequired @Transactional(Transactional.TxType.REQUIRED) public void removeSubCategoryFromCategory( - final Category subCategory, - @RequiresPrivilege(PRIVILEGE_MANAGE_CATEGORY) - final Category parentCategory) { + final Category subCategory, + @RequiresPrivilege(PRIVILEGE_MANAGE_CATEGORY) + final Category parentCategory) { if (subCategory.getParentCategory() == null - || !subCategory.getParentCategory().equals(parentCategory)) { + || !subCategory.getParentCategory().equals(parentCategory)) { throw new IllegalArgumentException(String.format( - "Category %s is not a subcategory of category %s.", - subCategory.toString(), - parentCategory.toString())); + "Category %s is not a subcategory of category %s.", + subCategory.toString(), + parentCategory.toString())); } parentCategory.removeSubCategory(subCategory); @@ -555,20 +587,21 @@ public class CategoryManager { * objects is decreased by one. If the object is the last one this method * has not effect. * - * @param subCategory The category which order property is increased. Can't - * be {@code null}. + * @param subCategory The category which order property is increased. + * Can't be {@code null}. * @param parentCategory The parent category of the category. Can't be - * {@code null}. + * {@code null}. * * @throws IllegalArgumentException If the provided subcategory is not a - * subcategory of the provided parent category. + * subcategory of the provided parent + * category. */ @AuthorizationRequired @Transactional(Transactional.TxType.REQUIRED) public void increaseCategoryOrder( - final Category subCategory, - @RequiresPrivilege(PRIVILEGE_MANAGE_CATEGORY) - final Category parentCategory) { + final Category subCategory, + @RequiresPrivilege(PRIVILEGE_MANAGE_CATEGORY) + final Category parentCategory) { if (parentCategory == null) { throw new IllegalArgumentException("parentCategory can't be null."); @@ -581,7 +614,7 @@ public class CategoryManager { boolean found = false; int index = 0; final List subCategories = new ArrayList<>(parentCategory - .getSubCategories()); + .getSubCategories()); subCategories.sort((c1, c2) -> { return Long.compare(c1.getCategoryOrder(), c2.getCategoryOrder()); }); @@ -595,12 +628,12 @@ public class CategoryManager { if (!found) { throw new IllegalArgumentException(String.format( - "The category %s (UUID: %s) is not a subcategory of the " - + "category %s (UUID: %s)", - subCategory.getName(), - subCategory.getUuid(), - parentCategory.getName(), - parentCategory.getUuid())); + "The category %s (UUID: %s) is not a subcategory of the " + + "category %s (UUID: %s)", + subCategory.getName(), + subCategory.getUuid(), + parentCategory.getName(), + parentCategory.getUuid())); } final Category nextCategory; @@ -629,20 +662,21 @@ public class CategoryManager { * preceeding objects is increased by one. If the object is the last one * this method has not effect. * - * @param subCategory The category which order property is increased. Can't - * be {@code null}. + * @param subCategory The category which order property is increased. + * Can't be {@code null}. * @param parentCategory The parent category of the category. Can't be - * {@code null}. + * {@code null}. * * @throws IllegalArgumentException If the provided subcategory is not a - * subcategory of the provided parent category. + * subcategory of the provided parent + * category. */ @AuthorizationRequired @Transactional(Transactional.TxType.REQUIRED) public void decreaseCategoryOrder( - final Category subCategory, - @RequiresPrivilege(PRIVILEGE_MANAGE_CATEGORY) - final Category parentCategory) { + final Category subCategory, + @RequiresPrivilege(PRIVILEGE_MANAGE_CATEGORY) + final Category parentCategory) { if (parentCategory == null) { throw new IllegalArgumentException("parentCategory can't be null."); @@ -655,7 +689,7 @@ public class CategoryManager { boolean found = false; int index = 0; final List subCategories = new ArrayList<>(parentCategory - .getSubCategories()); + .getSubCategories()); subCategories.sort((c1, c2) -> { return Long.compare(c1.getCategoryOrder(), c2.getCategoryOrder()); }); @@ -669,12 +703,12 @@ public class CategoryManager { if (!found) { throw new IllegalArgumentException(String.format( - "The category %s (UUID: %s) is not a subcategory of the " - + "category %s (UUID: %s)", - subCategory.getName(), - subCategory.getUuid(), - parentCategory.getName(), - parentCategory.getUuid())); + "The category %s (UUID: %s) is not a subcategory of the " + + "category %s (UUID: %s)", + subCategory.getName(), + subCategory.getUuid(), + parentCategory.getName(), + parentCategory.getUuid())); } final Category prevCategory; @@ -724,7 +758,7 @@ public class CategoryManager { public boolean hasIndexObject(final Category category) { final TypedQuery query = entityManager - .createNamedQuery("Categorization.hasIndexObject", Boolean.class); + .createNamedQuery("Categorization.hasIndexObject", Boolean.class); query.setParameter("category", category); return query.getSingleResult(); @@ -736,15 +770,15 @@ public class CategoryManager { * object! * * @param category The category of which the index object should be - * retrieved. + * retrieved. * * @return An {@link Optional} containing the index object of the provided - * category if the category has an index object. + * category if the category has an index object. */ public Optional getIndexObject(final Category category) { if (hasIndexObject(category)) { final TypedQuery query = entityManager.createNamedQuery( - "Categorization.findIndexObject", CcmObject.class); + "Categorization.findIndexObject", CcmObject.class); query.setParameter("category", category); return Optional.of(query.getSingleResult()); @@ -762,15 +796,18 @@ public class CategoryManager { * {@code true} for this categorisation. * * @param category The category whose index object is set or changed. - * @param object The new index object for the category. The object must be - * assigned to the category. + * @param object The new index object for the category. The object must be + * assigned to the category. + * * @throws ObjectNotAssignedToCategoryException If the provided - * {@code object} is not assigned to the provided {@code category}. + * {@code object} is not + * assigned to the provided + * {@code category}. */ @Transactional(Transactional.TxType.REQUIRED) public void setIndexObject(final Category category, final CcmObject object) - throws ObjectNotAssignedToCategoryException { + throws ObjectNotAssignedToCategoryException { Objects.requireNonNull(category); Objects.requireNonNull(object); @@ -779,10 +816,10 @@ public class CategoryManager { // category. if (!isAssignedToCategory(category, object)) { throw new ObjectNotAssignedToCategoryException(String.format( - "The provided object %s is not assigned to the provided category %s " - + "and can therefore not be an index object of the category.", - Objects.toString(category), - Objects.toString(object))); + "The provided object %s is not assigned to the provided category %s " + + "and can therefore not be an index object of the category.", + Objects.toString(category), + Objects.toString(object))); } // If the category has already an index object we need to reset the @@ -793,7 +830,7 @@ public class CategoryManager { // Now find the categorization for the provided object and set // index = true final TypedQuery query = entityManager.createNamedQuery( - "Categorization.find", Categorization.class); + "Categorization.find", Categorization.class); query.setParameter("category", category); query.setParameter("object", object); @@ -802,13 +839,13 @@ public class CategoryManager { categorization = query.getSingleResult(); } catch (NoResultException ex) { throw new ObjectNotAssignedToCategoryException(String.format( - "Strange. The previous check if the provided object %s is " - + "assigned to the provided category %s returned " - + "true, but the query for the categorization " - + "object returned no result. This should not happen. " + "Strange. The previous check if the provided object %s is " + + "assigned to the provided category %s returned " + + "true, but the query for the categorization " + + "object returned no result. This should not happen. " + "Please report a bug.", - Objects.toString(object), - Objects.toString(category)), + Objects.toString(object), + Objects.toString(category)), ex); } @@ -828,12 +865,13 @@ public class CategoryManager { @Transactional(Transactional.TxType.REQUIRED) public void resetIndexObject(final Category category) { final TypedQuery query = entityManager.createNamedQuery( - "Categorization.findIndexObjectCategorization", - Categorization.class); + "Categorization.findIndexObjectCategorization", + Categorization.class); query.setParameter("category", category); final List result = query.getResultList(); result.forEach(categorization -> categorization.setIndex(false)); result.forEach(categorization -> entityManager.merge(categorization)); } + }