/* * (C) Copyright 2007 Nuxeo SAS (http://nuxeo.com/) and contributors. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser General Public License * (LGPL) version 2.1 which accompanies this distribution, and is available at * http://www.gnu.org/licenses/lgpl.html * * 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. * * Contributors: * Nuxeo - initial API and implementation * * $Id: DirectoryTreeManagerBean.java 28950 2008-01-11 13:35:06Z tdelprat $ */ package org.nuxeo.ecm.webapp.directory; import static org.jboss.seam.ScopeType.CONVERSATION; import static org.nuxeo.ecm.webapp.directory.DirectoryTreeNode.PARENT_FIELD_ID; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; import org.nuxeo.ecm.core.api.CoreSession; import org.nuxeo.ecm.core.schema.SchemaManager; import org.nuxeo.ecm.core.schema.types.Schema; import org.nuxeo.ecm.directory.Directory; import org.nuxeo.ecm.directory.DirectoryException; import org.nuxeo.ecm.directory.api.DirectoryService; import org.nuxeo.ecm.platform.ui.web.directory.DirectoryHelper; import org.nuxeo.ecm.webapp.seam.NuxeoSeamHotReloader; import org.nuxeo.runtime.api.Framework; /** * Manage trees defined by xvocabulary directories. Update the associated * QueryModel when a node is selected and return a parameterized faces * navigation case. * * @author <a href="mailto:ogrisel@nuxeo.com">Olivier Grisel</a> */ @Scope(CONVERSATION) @Name("directoryTreeManager") public class DirectoryTreeManagerBean implements DirectoryTreeManager { private static final long serialVersionUID = -5250556791009032616L; private static final Log log = LogFactory.getLog(DirectoryTreeManagerBean.class); public static final String NODE_SELECTED_MARKER = DirectoryTreeManagerBean.class.getName() + "_NODE_SELECTED_MARKER"; @In(create = true, required = false) protected transient CoreSession documentManager; @In(create = true) protected NuxeoSeamHotReloader seamReload; @In(create = true) protected Map<String, String> messages; protected transient Map<String, DirectoryTreeNode> treeModels; protected Long treeModelsTimestamp; protected transient DirectoryTreeService directoryTreeService; protected String selectedTree; private transient List<DirectoryTreeNode> directoryTrees; /* * The directoryTrees need a working core session in order to perform * search actions. */ public boolean isInitialized() { return documentManager != null; } public DirectoryTreeNode get(String treeName) { DirectoryTreeService dirTreeService = getDirectoryTreeService(); if (seamReload.isDevModeSet() && seamReload.shouldResetCache(dirTreeService, treeModelsTimestamp)) { treeModels = null; } if (treeModels == null) { treeModels = new HashMap<String, DirectoryTreeNode>(); treeModelsTimestamp = dirTreeService.getLastModified(); } // lazy loading of tree models DirectoryTreeNode treeModel = treeModels.get(treeName); if (treeModel != null) { // return cached model return treeModel; } DirectoryTreeDescriptor config = dirTreeService.getDirectoryTreeDescriptor(treeName); if (config == null) { log.error("no DirectoryTreeDescriptor registered as " + treeName); return null; } // check that each required directory exists and has the xvocabulary // schema String[] directories = config.getDirectories(); DirectoryService directoryService = DirectoryHelper.getDirectoryService(); SchemaManager schemaManager = Framework.getLocalService(SchemaManager.class); try { boolean isFirst = true; for (String directoryName : directories) { Directory directory = directoryService.getDirectory(directoryName); if (directory == null) { throw new DirectoryException(directoryName + " is not a registered directory"); } if (!isFirst) { Schema schema = schemaManager.getSchema(directory.getSchema()); if (!schema.hasField(PARENT_FIELD_ID)) { throw new DirectoryException(directoryName + "does not have the required field: " + PARENT_FIELD_ID); } } isFirst = false; } } catch (DirectoryException e) { throw new RuntimeException(e); } treeModel = new DirectoryTreeNode(0, config, config.getName(), config.getLabel(), "", null); // store the build tree to reuse it the next time in the same state treeModels.put(treeName, treeModel); return treeModel; } public List<String> getDirectoryTreeNames() { return getDirectoryTreeService().getDirectoryTrees(); } public List<DirectoryTreeNode> getDirectoryTrees() { if (directoryTrees == null) { directoryTrees = new LinkedList<DirectoryTreeNode>(); for (String treeName : getDirectoryTreeNames()) { directoryTrees.add(get(treeName)); } } return directoryTrees; } public String getSelectedTreeName() { if (selectedTree == null) { List<String> names = getDirectoryTreeNames(); if (!names.isEmpty()) { selectedTree = names.get(0); } } return selectedTree; } public void setSelectedTreeName(String treeName) { selectedTree = treeName; } public List<DirectoryTreeNode> getSelectedTreeAsList() { List<DirectoryTreeNode> res = new ArrayList<>(); DirectoryTreeNode selected = getSelectedTree(); if (selected != null) { res.add(selected); } return res; } public DirectoryTreeNode getSelectedTree() { return get(getSelectedTreeName()); } protected DirectoryTreeService getDirectoryTreeService() { if (directoryTreeService != null) { return directoryTreeService; } directoryTreeService = (DirectoryTreeService) Framework.getRuntime().getComponent( DirectoryTreeService.NAME); return directoryTreeService; } public String getLabelFor(String directoryTreeName, String fullPath) { return getLabelFor(directoryTreeName, fullPath, false); } public String getLabelFor(String directoryTreeName, String fullPath, boolean includeDirectoryTreeLabel) { DirectoryTreeNode rootNode = get(directoryTreeName); List<String> labels = new ArrayList<String>(); computeLabels(labels, rootNode, fullPath, includeDirectoryTreeLabel); List<String> translatedLabels = translateLabels(labels); return StringUtils.join(translatedLabels, "/"); } protected void computeLabels(List<String> labels, DirectoryTreeNode node, String fullPath, boolean includeDirectoryTreeLabel) { // add label for the root path only if specified if (!node.getPath().isEmpty() || (node.getPath().isEmpty() && includeDirectoryTreeLabel)) { labels.add(node.getDescription()); } if (fullPath.equals(node.getPath())) { return; } for (DirectoryTreeNode treeNode : node.getChildren()) { if (fullPath.startsWith(treeNode.getPath())) { computeLabels(labels, treeNode, fullPath, includeDirectoryTreeLabel); } } } protected List<String> translateLabels(List<String> labels) { List<String> translatedLabels = new ArrayList<String>(labels.size()); for (String label : labels) { translatedLabels.add(messages.get(label)); } return translatedLabels; } public void resetCurrentTree() { if (treeModels != null && selectedTree != null) { treeModels.remove(selectedTree); } } }