001/*
002 * (C) Copyright 2010 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Nuxeo - initial API and implementation
018 *
019 */
020package org.nuxeo.ecm.webapp.directory;
021
022import static org.jboss.seam.ScopeType.CONVERSATION;
023import static org.jboss.seam.annotations.Install.FRAMEWORK;
024
025import java.io.Serializable;
026import java.util.ArrayList;
027import java.util.HashMap;
028import java.util.List;
029import java.util.Locale;
030import java.util.Map;
031
032import javax.faces.context.FacesContext;
033
034import org.apache.commons.lang3.StringUtils;
035import org.apache.commons.logging.Log;
036import org.apache.commons.logging.LogFactory;
037import org.jboss.seam.annotations.Install;
038import org.jboss.seam.annotations.Name;
039import org.jboss.seam.annotations.Observer;
040import org.jboss.seam.annotations.Scope;
041import org.nuxeo.ecm.core.api.DocumentModel;
042import org.nuxeo.ecm.directory.Directory;
043import org.nuxeo.ecm.directory.DirectoryException;
044import org.nuxeo.ecm.directory.Session;
045import org.nuxeo.ecm.directory.api.DirectoryService;
046import org.nuxeo.ecm.webapp.helpers.EventNames;
047import org.nuxeo.runtime.api.Framework;
048
049/**
050 * Manage localized vocabulary trees. These trees use {@code VocabularyTreeNode}
051 *
052 * @since 5.5
053 * @author <a href="mailto:qlamerand@nuxeo.com">Quentin Lamerand</a>
054 */
055@Scope(CONVERSATION)
056@Name("vocabularyTreeActions")
057@Install(precedence = FRAMEWORK)
058public class VocabularyTreeActions implements Serializable {
059
060    private static final long serialVersionUID = 1L;
061
062    private static final Log log = LogFactory.getLog(VocabularyTreeActions.class);
063
064    /**
065     * @deprecated since 5.9.2.
066     */
067    @Deprecated
068    public static final String L10NVOCABULARY_SCHEMA = "l10nvocabulary";
069
070    /**
071     * @deprecated since 5.9.2.
072     */
073    @Deprecated
074    public static final String L10NXVOCABULARY_SCHEMA = "l10nxvocabulary";
075
076    protected transient Map<String, VocabularyTreeNode> treeModels;
077
078    public VocabularyTreeNode get(String vocabularyName, boolean displayObsoleteEntries, char keySeparator,
079            String orderingField) {
080        if (treeModels == null) {
081            treeModels = new HashMap<String, VocabularyTreeNode>();
082        }
083        VocabularyTreeNode treeModel = treeModels.get(vocabularyName);
084        if (treeModel != null) {
085            // return cached model
086            return treeModel;
087        }
088        DirectoryService directoryService = Framework.getService(DirectoryService.class);
089        try {
090            Directory directory = Framework.getService(DirectoryService.class).getDirectory(vocabularyName);
091            if (directory == null) {
092                throw new DirectoryException(vocabularyName + " is not a registered directory");
093            }
094        } catch (DirectoryException e) {
095            throw new RuntimeException(e);
096        }
097
098        treeModel = new VocabularyTreeNode(0, "", "", "", vocabularyName, directoryService, displayObsoleteEntries,
099                keySeparator, orderingField);
100
101        treeModels.put(vocabularyName, treeModel);
102        return treeModel;
103    }
104
105    public List<VocabularyTreeNode> getRoots(String vocabularyName, boolean displayObsoleteEntries, char keySeparator,
106            String orderingField) {
107        return get(vocabularyName, displayObsoleteEntries, keySeparator, orderingField).getChildren();
108    }
109
110    public String getLabelFor(String vocabularyName, String path, char keySeparator) {
111        Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
112        String schemaName = null;
113        List<String> labels = new ArrayList<String>();
114        DirectoryService directoryService = Framework.getService(DirectoryService.class);
115        try (Session session = directoryService.open(vocabularyName)) {
116            schemaName = directoryService.getDirectorySchema(vocabularyName);
117            for (String id : StringUtils.split(path, keySeparator)) {
118                DocumentModel entry = session.getEntry(id);
119                if (entry != null) {
120                    String computeLabel = VocabularyTreeNode.computeLabel(locale, entry, schemaName);
121                    if (computeLabel == null) {
122                        labels.add(id);
123                    } else {
124                        labels.add(computeLabel);
125                    }
126                } else {
127                    labels.add(id);
128                }
129            }
130        } catch (DirectoryException e) {
131            log.error("Error while accessing directory " + vocabularyName, e);
132        }
133
134        if (labels.isEmpty()) {
135            return null;
136        } else {
137            return StringUtils.join(labels, keySeparator);
138        }
139    }
140
141    @Observer(EventNames.DIRECTORY_CHANGED)
142    public void invalidate(String vocabularyName) {
143        if (treeModels != null) {
144            treeModels.remove(vocabularyName);
145        }
146    }
147
148}