ResourceCategoryHelper.java
/*
* The coLAB project
* Copyright (C) 2021-2023 AlbaSim, MEI, HEIG-VD, HES-SO
*
* Licensed under the MIT License
*/
package ch.colabproject.colab.api.controller.document;
import ch.colabproject.colab.api.controller.RequestManager;
import ch.colabproject.colab.api.controller.card.CardContentManager;
import ch.colabproject.colab.api.controller.card.CardManager;
import ch.colabproject.colab.api.controller.card.CardTypeManager;
import ch.colabproject.colab.api.model.card.AbstractCardType;
import ch.colabproject.colab.api.model.card.Card;
import ch.colabproject.colab.api.model.card.CardContent;
import ch.colabproject.colab.api.model.document.AbstractResource;
import ch.colabproject.colab.api.model.document.ResourceRef;
import ch.colabproject.colab.api.persistence.jpa.card.CardTypeDao;
import ch.colabproject.colab.api.persistence.jpa.document.ResourceDao;
import ch.colabproject.colab.generator.model.exceptions.HttpErrorMessage;
import ch.colabproject.colab.generator.model.exceptions.MessageI18nKey;
import java.util.List;
import java.util.Objects;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.inject.Inject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Resource and resource reference category specific logic
*
* @author sandra
*/
@Stateless
@LocalBean
public class ResourceCategoryHelper {
/** logger */
private static final Logger logger = LoggerFactory.getLogger(ResourceCategoryHelper.class);
// *********************************************************************************************
// injections
/**
* Resource persistence handler
*/
@Inject
private ResourceDao resourceDao;
/**
* Card type persistence handler
*/
@Inject
private CardTypeDao cardTypeDao;
/**
* Resource / resource reference related logic
*/
@Inject
private ResourceManager resourceManager;
/**
* Card type specific logic management
*/
@Inject
private CardTypeManager cardTypeManager;
/**
* Card specific logic management
*/
@Inject
private CardManager cardManager;
/**
* Card content specific logic management
*/
@Inject
private CardContentManager cardContentManager;
/**
* TO sudo
*/
@Inject
private RequestManager requestManager;
// *********************************************************************************************
// Category management
// *********************************************************************************************
/**
* Set the category of the resource.
* <p>
* Also update the resources that reference this one, as long as the category is synchronized
*
* @param resourceOrRefId the id of the resource / resource reference
* @param categoryName the name of the category that apply to the resource / resource
* reference
*/
public void changeCategory(Long resourceOrRefId, String categoryName) {
logger.debug("set category {} to abstract resource #{}", categoryName, resourceOrRefId);
AbstractResource resourceOrRef = resourceManager.assertAndGetResourceOrRef(resourceOrRefId);
String oldCategoryName = resourceOrRef.getCategory();
String newCategoryName = StringUtils.trimToNull(categoryName);
resourceOrRef.setCategory(newCategoryName);
requestManager.sudo(() -> {
// also change the resources based on the given one
// but only if the category is still synchronized
List<ResourceRef> directRefs = resourceDao.findDirectReferences(resourceOrRef);
for (ResourceRef ref : directRefs) {
if (StringUtils.equals(ref.getCategory(), oldCategoryName)) {
changeCategory(ref.getId(), newCategoryName);
}
}
});
}
/**
* Set the category of a list of resources
*
* @param resourceOrRefIds the id of the resources / resource references
* @param categoryName the name of the category that apply to the resource / resource
* reference
*/
public void changeCategory(List<Long> resourceOrRefIds, String categoryName) {
logger.debug("set category {} to abstract resources #{}", categoryName, resourceOrRefIds);
if (resourceOrRefIds == null) {
throw HttpErrorMessage.dataError(MessageI18nKey.DATA_INTEGRITY_FAILURE);
}
resourceOrRefIds.stream().forEach(resOrRefId -> changeCategory(resOrRefId, categoryName));
}
/**
* Rename the category in a card type / card type reference
*
* @param cardTypeOrRefId the id of the card type / card type reference (scope of the renaming)
* @param oldName the old name of the category
* @param newName the new name of the category
*/
public void renameCategoryInCardType(Long cardTypeOrRefId, String oldName,
String newName) {
logger.debug("rename category {} to {} in the abstract card type #{}", oldName, newName,
cardTypeOrRefId);
AbstractCardType cardTypeOrRef = cardTypeManager.assertAndGetCardTypeOrRef(cardTypeOrRefId);
requestManager.sudo(() -> {
renameCategory(cardTypeOrRef, oldName, newName);
});
}
/**
* Rename the category in a card
*
* @param cardId the id of the card
* @param oldName the old name of the category
* @param newName the new name of the category
*/
public void renameCategoryInCard(Long cardId, String oldName, String newName) {
logger.debug("rename category {} to {} in the card #{}", oldName, newName, cardId);
Card card = cardManager.assertAndGetCard(cardId);
requestManager.sudo(() -> {
renameCategory(card, oldName, newName);
});
}
/**
* Rename the category in a card content
*
* @param cardContentId the id of the card content
* @param oldName the old name of the category
* @param newName the new name of the category
*/
public void renameCategoryInCardContent(Long cardContentId, String oldName, String newName) {
logger.debug("rename category {} to {} in the card content #{}", oldName, newName,
cardContentId);
CardContent cardContent = cardContentManager.assertAndGetCardContent(cardContentId);
requestManager.sudo(() -> {
renameCategory(cardContent, oldName, newName);
});
}
/**
* Rename the category in a card type / card type reference<br>
* And do it also for the implementing cards and for its reference card types
*
* @param cardTypeOrRef the card type / card type reference (scope of the renaming)
* @param oldName the old name of the category
* @param newName the new name of the category
*/
private void renameCategory(AbstractCardType cardTypeOrRef,
String oldName, String newName) {
cardTypeOrRef.getDirectAbstractResources().stream()
.forEach(resourceOrRef -> renameCategoryIfMatch(resourceOrRef, oldName, newName));
cardTypeOrRef.getImplementingCards().stream()
.forEach(card -> renameCategory(card, oldName, newName));
cardTypeDao.findDirectReferences(cardTypeOrRef).stream()
.forEach(cardRef -> renameCategory(cardRef, oldName, newName));
}
/**
* Rename the category in a card<br>
* And do it also for each card's variants
*
* @param card the card (scope of the renaming)
* @param oldName the old name of the category
* @param newName the new name of the category
*/
private void renameCategory(Card card, String oldName, String newName) {
card.getDirectAbstractResources().stream()
.forEach(resourceOrRef -> renameCategoryIfMatch(resourceOrRef, oldName, newName));
card.getContentVariants().stream()
.forEach(cardContent -> renameCategory(cardContent, oldName, newName));
}
/**
* Rename the category in a card content<br>
* And do it also for each sub cards
*
* @param cardContent the card content (scope of the renaming)
* @param oldName the old name of the category
* @param newName the new name of the category
*/
private void renameCategory(CardContent cardContent, String oldName, String newName) {
cardContent.getDirectAbstractResources().stream()
.forEach(resourceOrRef -> renameCategoryIfMatch(resourceOrRef, oldName, newName));
cardContent.getSubCards().stream().forEach(card -> renameCategory(card, oldName, newName));
}
/**
* Replace the category of the resource if it matches the oldName
*
* @param resourceOrRef the resource or resource reference
* @param oldName the old name of the category
* @param newName the new name of the category
*/
private void renameCategoryIfMatch(AbstractResource resourceOrRef, String oldName,
String newName) {
if (Objects.equals(
StringUtils.trimToNull(resourceOrRef.getCategory()),
StringUtils.trimToNull(oldName))) {
resourceOrRef.setCategory(StringUtils.trimToNull(newName));
}
}
}