/* * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. * * 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. */ package com.agiletec.apsadmin.category; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.beanutils.BeanComparator; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.agiletec.aps.system.common.tree.ITreeNode; import com.agiletec.aps.system.services.category.Category; import com.agiletec.aps.system.services.category.CategoryManager; import com.agiletec.aps.system.services.category.ICategoryManager; import com.agiletec.aps.system.services.category.ReloadingCategoryReferencesThread; import com.agiletec.aps.system.services.lang.Lang; import com.agiletec.aps.util.ApsProperties; import com.agiletec.apsadmin.category.helper.ICategoryActionHelper; import com.agiletec.apsadmin.system.AbstractTreeAction; import com.agiletec.apsadmin.system.ApsAdminSystemConstants; import com.agiletec.apsadmin.system.BaseActionHelper; import com.agiletec.apsadmin.system.TreeNodeWrapper; /** * Action class which handles categories. * @author E.Santoboni - G.Cocco */ public class CategoryAction extends AbstractTreeAction { private static final Logger _logger = LoggerFactory.getLogger(CategoryAction.class); @Override public void validate() { super.validate(); this.checkCode(); this.checkTitles(); } public Integer getServiceStatus() { return this.getCategoryManager().getMoveTreeStatus(); } public Map<String, Integer> getServiceStatusMap() { return this.getCategoryManager().getReloadStatus(); } public List<TreeNodeWrapper> getAvailableNodesForMoveTreeAjax() { List<TreeNodeWrapper> result = new ArrayList<TreeNodeWrapper>(); try { System.out.println("ENTRATO getAvailableNodesForMoveTreeAjax"); String startCategoryCode = this.getSelectedNode(); if (StringUtils.isBlank(startCategoryCode)) { _logger.warn("required parameter 'selectedNode' missing"); return result; } Category nodeToMove = this.getCategory(startCategoryCode); if (null == nodeToMove) { _logger.warn("category {} is null", startCategoryCode); return result; } List<String> allowedGroupCodes = new ArrayList<String>(); allowedGroupCodes.add(nodeToMove.getGroup()); //XXX FIX JS this.setCategoryCodeToken(super.getParameter("categoryCodeToken")); List<Category> searchResult = this.getCategoryManager().searchCategories(this.getCategoryCodeToken()); if (null == searchResult || searchResult.isEmpty()) return result; BeanComparator comparator = new BeanComparator("code"); Collections.sort(result, comparator); int maxIndex = 30; String maxParam = super.getParameter("max"); if (StringUtils.isNotBlank(maxParam) && StringUtils.isNumeric(maxParam)) maxIndex = new Integer(maxParam).intValue(); Iterator<Category> it = searchResult.iterator(); while (result.size() < maxIndex && it.hasNext()) { ITreeNode candidate = it.next(); if (!candidate.isChildOf(nodeToMove.getCode()) && !candidate.getCode().equals(nodeToMove.getParentCode())) { result.add(new TreeNodeWrapper(candidate, this.getCurrentLang().getCode())); } } } catch (Throwable t) { _logger.error("Error on searching categories ajax", t); throw new RuntimeException("Error on searching categories ajax", t); } return result; } private void checkTitles() { Iterator<Lang> langsIter = this.getLangManager().getLangs().iterator(); while (langsIter.hasNext()) { Lang lang = (Lang) langsIter.next(); String titleKey = "lang"+lang.getCode(); String title = this.getRequest().getParameter(titleKey); if (null != title) { this.getTitles().put(lang.getCode(), title.trim()); } if (null == title || title.trim().length() == 0) { String[] args = {lang.getDescr()}; this.addFieldError(titleKey, this.getText("error.category.insertTitle", args)); } } } private void checkCode() { String code = this.getCategoryCode(); if ((this.getStrutsAction() == ApsAdminSystemConstants.ADD || this.getStrutsAction() == ApsAdminSystemConstants.PASTE) && null != code && code.trim().length() > 0) { String currectCode = BaseActionHelper.purgeString(code.trim()); if (currectCode.length() > 0 && null != this.getCategoryManager().getCategory(currectCode)) { String[] args = {currectCode}; this.addFieldError("categoryCode", this.getText("error.category.duplicateCode", args)); } this.setCategoryCode(currectCode); } } public String add() { String selectedNode = this.getSelectedNode(); try { Category category = this.getCategory(selectedNode); if (null == category) { this.addActionError(this.getText("error.category.selectCategory")); return "categoryTree"; } this.setStrutsAction(ApsAdminSystemConstants.ADD); this.setParentCategoryCode(selectedNode); } catch (Throwable t) { _logger.error("error in add", t); return FAILURE; } return SUCCESS; } public String edit() { this.setStrutsAction(ApsAdminSystemConstants.EDIT); return this.extractCategoryFormValues(); } public String showDetail() { String result = this.extractCategoryFormValues(); if (!result.equals(SUCCESS)) return result; this.extractReferencingObjects(this.getSelectedNode()); return result; } protected String extractCategoryFormValues() { String selectedNode = this.getSelectedNode(); try { Category category = this.getCategory(selectedNode); if (null == category) { this.addActionError(this.getText("error.category.selectCategory")); return "categoryTree"; } this.setParentCategoryCode(category.getParentCode()); this.setCategoryCode(category.getCode()); this.setTitles(category.getTitles()); } catch (Throwable t) { _logger.error("error in extractCategoryFormValues", t); return FAILURE; } return SUCCESS; } public String trash() { try { String check = this.chechDelete(); if (null != check) return check; } catch (Throwable t) { _logger.error("error in trash", t); return FAILURE; } return SUCCESS; } public String delete() { String selectedNode = this.getSelectedNode(); try { String check = this.chechDelete(); if (null != check) return check; Category currentCategory = this.getCategory(selectedNode); this.getCategoryManager().deleteCategory(selectedNode); this.setSelectedNode(currentCategory.getParent().getCode()); } catch (Throwable t) { _logger.error("error in delete", t); return FAILURE; } return SUCCESS; } /** * Perform all the needed checks before deleting a category. * When errors are detected a new actionMessaged, containing the appropriate error code and messaged, is created. * @return null if the deletion operation is successful, otherwise the error code */ protected String chechDelete() { Category currentCategory = this.getCategory(this.getSelectedNode()); if (null == currentCategory) { _logger.info("Required a selected node"); this.addActionError(this.getText("error.category.selectCategory")); return "categoryTree"; } if (currentCategory.getCode().equals(currentCategory.getParentCode())) { _logger.info("Home category not deletable"); this.addActionError(this.getText("error.category.homeDelete.notAllowed")); return "categoryTree"; } if (currentCategory.getChildren().length != 0) { _logger.info("Category with children not deletable"); this.addActionError(this.getText("error.category.deleteWithChildren.notAllowed")); return "categoryTree"; } this.extractReferencingObjects(this.getSelectedNode()); if (null != this.getReferences() && this.getReferences().size() > 0) { return "references"; } return null; } protected void extractReferencingObjects(String categoryCode) { try { Category category = this.getCategoryManager().getCategory(categoryCode); if (null != category) { Map references = this.getHelper().getReferencingObjects(category, this.getRequest()); if (references.size() > 0) { this.setReferences(references); } } } catch (Throwable t) { _logger.error("Error extracting referenced objects by category {}", categoryCode, t); } } public String save() { try { if (this.getStrutsAction() == ApsAdminSystemConstants.EDIT) { Category category = this.getCategory(this.getCategoryCode()); category.setTitles(this.getTitles()); this.getCategoryManager().updateCategory(category); _logger.debug("Updated category {}", category.getCode()); } else { Category category = this.getHelper().buildNewCategory(this.getCategoryCode(), this.getParentCategoryCode(), this.getTitles()); this.getCategoryManager().addCategory(category); _logger.debug("Added new category {}", this.getCategoryCode()); } } catch (Exception e) { _logger.error("error in save", e); return FAILURE; } return SUCCESS; } public String moveTree() { String selectedNode = this.getSelectedNode(); String parentCategoryCode = this.getRequest().getParameter("parentCategoryCode"); try { String check = this.checkMoveCategory(selectedNode, parentCategoryCode); if (null != check) { return check; } this.extractReferencingObjectsForMove(this.getSelectedNode()); if (null != this.getReferences() && this.getReferences().size() > 0) { return "moveReferences"; } Category currentCategory = this.getCategory(this.getSelectedNode()); Category parent = this.getCategory(parentCategoryCode); this.getCategoryManager().moveCategory(currentCategory, parent); } catch (Throwable t) { _logger.error("error in move category", t); return FAILURE; } return SUCCESS; } public String executeMoveTree() { String selectedNode = this.getSelectedNode(); String parentCategoryCode = this.getRequest().getParameter("parentCategoryCode"); try { String check = this.checkMoveCategory(selectedNode, parentCategoryCode); if (null != check) return check; Category currentCategory = this.getCategory(this.getSelectedNode()); Category parent = this.getCategory(parentCategoryCode); this.getCategoryManager().moveCategory(currentCategory, parent); } catch (Throwable t) { _logger.error("error in move executeMoveTree", t); return FAILURE; } return SUCCESS; } protected String checkMoveCategory(String selectedNode, String parentCategoryCode) { if (this.getCategoryManager().getMoveTreeStatus() != CategoryManager.STATUS_READY) { this.addActionError(this.getText("error.category.move.updateReferencesRunning")); return "categoryTree"; } Category currentCategory = this.getCategory(this.getSelectedNode()); if (null == currentCategory) { _logger.info("Required a selected node"); this.addActionError(this.getText("error.category.selectCategory")); return "categoryTree"; } if (currentCategory.getCode().equals(this.getCategoryManager().getRoot().getCode())) { _logger.info("Root category cannot be moved"); this.addActionError(this.getText("error.category.move.rootNotAllowed")); return "categoryTree"; } if ("".equals(parentCategoryCode) || null == this.getCategoryManager().getCategory(parentCategoryCode)) { this.addActionError(this.getText("error.category.move.selectCategoryParent")); return "categoryTree"; } Category parent = this.getCategory(parentCategoryCode); if (null == parent) { _logger.info("Required a selected node"); this.addActionError(this.getText("error.category.selectCategoryParent")); return "categoryTree"; } if (parent.getCode().equals(currentCategory.getParentCode())) { _logger.debug("trying to move a node under it's own parent.."); return "categoryTree"; } if (parent.isChildOf(selectedNode)) { List<String> args = new ArrayList<String>(); args.add(parent.getCode()); args.add(selectedNode); this.addActionError(this.getText("error.category.move.parentUnderChild.notAllowed")); return "categoryTree"; } return null; } protected void extractReferencingObjectsForMove(String categoryCode) { try { Category category = this.getCategoryManager().getCategory(categoryCode); if (null != category) { Map references = this.getHelper().getReferencingObjectsForMove(category, this.getRequest()); if (references.size() > 0) { this.setReferences(references); } } } catch (Throwable t) { _logger.error("Error extracting referenced objects for move by category {}", categoryCode, t); } } /** * provide the result for the progress bar * @return */ public Map<String, Integer> getUpdateReferencesStatus() { int total = 0; int done = 0; ThreadGroup currentGroup = Thread.currentThread().getThreadGroup(); int numThreads = currentGroup.activeCount(); Thread[] listOfThreads = new Thread[numThreads]; currentGroup.enumerate(listOfThreads); for (int i = 0; i < numThreads; i++) { if (listOfThreads[i].getName().startsWith(CategoryManager.RELOAD_CATEGORY_REFERENCES_THREAD_NAME_PREFIX)) { ReloadingCategoryReferencesThread thread = (ReloadingCategoryReferencesThread) listOfThreads[i]; total = total + thread.getListSize(); done = done + thread.getListIndex(); } } Map<String, Integer> result = new HashMap<String, Integer>(); result.put("total", total); result.put("done", done); return result; } public Category getCategory(String categoryCode) { return this.getCategoryManager().getCategory(categoryCode); } @Deprecated public Category getRoot() { return this.getCategoryManager().getRoot(); } public ITreeNode getTreeRootNode() { ITreeNode node = null; try { node = this.getHelper().getAllowedTreeRoot(new ArrayList<String>()); } catch (Throwable t) { _logger.error("error in getTreeRootNode", t); } return node; } public List<Lang> getLangs() { return this.getLangManager().getLangs(); } public List<Category> getBreadCrumbsTargets(String categoryCode) { Category category = this.getCategoryManager().getCategory(categoryCode); if (null == category) return null; List<Category> categories = new ArrayList<Category>(); this.getSubBreadCrumbsTargets(categories, category); return categories; } private void getSubBreadCrumbsTargets(List<Category> categories, Category current) { categories.add(0, current); Category parent = current.getParent(); if (parent != null && !parent.getCode().equals(current.getCode())) { this.getSubBreadCrumbsTargets(categories, parent); } } public int getStrutsAction() { return _strutsAction; } public void setStrutsAction(int strutsAction) { this._strutsAction = strutsAction; } public String getCategoryCode() { return _categoryCode; } public void setCategoryCode(String categoryCode) { this._categoryCode = categoryCode; } public String getParentCategoryCode() { return _parentCategoryCode; } public void setParentCategoryCode(String parentCategoryCode) { this._parentCategoryCode = parentCategoryCode; } public ApsProperties getTitles() { return _titles; } public void setTitles(ApsProperties titles) { this._titles = titles; } protected ICategoryManager getCategoryManager() { return _categoryManager; } public void setCategoryManager(ICategoryManager categoryManager) { this._categoryManager = categoryManager; } protected ICategoryActionHelper getHelper() { return (ICategoryActionHelper) super.getTreeHelper(); } public Map getReferences() { return _references; } protected void setReferences(Map references) { this._references = references; } public String getSelectedNode() { return _selectedNode; } public void setSelectedNode(String selectedNode) { super.getTreeNodesToOpen().add(selectedNode); this._selectedNode = selectedNode; } public String getCategoryCodeToken() { return _categoryCodeToken; } public void setCategoryCodeToken(String categoryCodeToken) { this._categoryCodeToken = categoryCodeToken; } private int _strutsAction; private String _categoryCode; private String _parentCategoryCode; private String _selectedNode; private String _categoryCodeToken; private ApsProperties _titles = new ApsProperties(); private ICategoryManager _categoryManager; private Map _references; }