001/*
002 * (C) Copyright 2010-2016 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 */
019package org.nuxeo.ecm.localconf;
020
021import static org.jboss.seam.ScopeType.CONVERSATION;
022import static org.nuxeo.ecm.platform.types.localconfiguration.UITypesConfigurationConstants
023        .UI_TYPES_CONFIGURATION_FACET;
024import static org.nuxeo.ecm.platform.types.localconfiguration.UITypesConfigurationConstants
025        .UI_TYPES_DEFAULT_NEEDED_SCHEMA;
026
027import java.io.Serializable;
028import java.util.ArrayList;
029import java.util.Collections;
030import java.util.Comparator;
031import java.util.Iterator;
032import java.util.List;
033import java.util.Map;
034
035import org.jboss.seam.annotations.In;
036import org.jboss.seam.annotations.Install;
037import org.jboss.seam.annotations.Name;
038import org.jboss.seam.annotations.Scope;
039import org.nuxeo.ecm.core.api.CoreSession;
040import org.nuxeo.ecm.core.api.DocumentModel;
041import org.nuxeo.ecm.core.api.DocumentRef;
042import org.nuxeo.ecm.core.api.security.SecurityConstants;
043import org.nuxeo.ecm.core.schema.DocumentType;
044import org.nuxeo.ecm.core.schema.SchemaManager;
045import org.nuxeo.ecm.platform.types.Type;
046import org.nuxeo.ecm.platform.types.TypeManager;
047import org.nuxeo.ecm.platform.types.localconfiguration.UITypesConfiguration;
048import org.nuxeo.ecm.platform.ui.web.api.NavigationContext;
049import org.nuxeo.runtime.api.Framework;
050
051/**
052 * @author <a href="mailto:troger@nuxeo.com">Thomas Roger</a>
053 */
054@Name("typesConfigurationActions")
055@Scope(CONVERSATION)
056@Install(precedence = Install.FRAMEWORK)
057public class UITypesConfigurationActions implements Serializable {
058
059    private static final long serialVersionUID = 1L;
060
061    @In(create = true)
062    protected Map<String, String> messages;
063
064    /**
065     * @since 5.9.1
066     */
067    protected static class TypeLabelAlphabeticalOrder implements Comparator<Type> {
068
069        private final Map<String, String> messages;
070
071        public TypeLabelAlphabeticalOrder(Map<String, String> messages) {
072            super();
073            this.messages = messages;
074        }
075
076        @Override
077        public int compare(Type type1, Type type2) {
078            String label1 = messages.get(type1.getLabel());
079            String label2 = messages.get(type2.getLabel());
080            return label1.compareTo(label2);
081        }
082    }
083
084    @In(create = true)
085    protected transient TypeManager typeManager;
086
087    @In(create = true)
088    protected transient NavigationContext navigationContext;
089
090    @In(create = true, required = false)
091    protected transient CoreSession documentManager;
092
093    protected transient SchemaManager schemaManager;
094
095    public List<Type> getNotSelectedTypes() {
096        DocumentModel currentDoc = navigationContext.getCurrentDocument();
097        return getNotSelectedTypes(currentDoc);
098    }
099
100    /**
101     * Returns a List of type not selected for the domain given as parameter
102     *
103     * @param document the domain to configure
104     * @return a List of type of document, not currently selected for the domain
105     * @since 5.5
106     */
107    public List<Type> getNotSelectedTypes(DocumentModel document) {
108        if (!document.hasFacet(UI_TYPES_CONFIGURATION_FACET)) {
109            return Collections.emptyList();
110        }
111
112        List<String> allowedTypes = getAllowedTypes(document);
113
114        List<Type> notSelectedTypes = new ArrayList<>(typeManager.findAllAllowedSubTypesFrom(document.getType()));
115
116        for (Iterator<Type> it = notSelectedTypes.iterator(); it.hasNext();) {
117            Type type = it.next();
118            if (allowedTypes.contains(type.getId())) {
119                it.remove();
120            }
121        }
122
123        Collections.sort(notSelectedTypes, new TypeLabelAlphabeticalOrder(messages));
124
125        return notSelectedTypes;
126    }
127
128    protected List<String> getAllowedTypes(DocumentModel doc) {
129        UITypesConfiguration uiTypesConfiguration = doc.getAdapter(UITypesConfiguration.class);
130        if (uiTypesConfiguration == null) {
131            return Collections.emptyList();
132        }
133        List<String> allowedTypes = new ArrayList<>(uiTypesConfiguration.getAllowedTypes());
134        if (allowedTypes.isEmpty()) {
135            allowedTypes = computeAllowedTypes(doc);
136        }
137        return allowedTypes;
138    }
139
140    public List<Type> getSelectedTypes() {
141        DocumentModel currentDoc = navigationContext.getCurrentDocument();
142        return getSelectedTypes(currentDoc);
143    }
144
145    /**
146     * Returns a List of type selected for the domain given as parameter
147     *
148     * @param document the domain to configure
149     * @return List of documen type selected for the domain
150     * @since 5.5
151     */
152    public List<Type> getSelectedTypes(DocumentModel document) {
153        if (!document.hasFacet(UI_TYPES_CONFIGURATION_FACET)) {
154            return Collections.emptyList();
155        }
156
157        List<String> allowedTypes = getAllowedTypes(document);
158
159        List<Type> selectedTypes = new ArrayList<>();
160        for (String type : allowedTypes) {
161            Type existingType = typeManager.getType(type);
162            if (existingType != null) {
163                selectedTypes.add(existingType);
164            }
165        }
166
167        Collections.sort(selectedTypes, new TypeLabelAlphabeticalOrder(messages));
168        return selectedTypes;
169    }
170
171    protected List<String> computeAllowedTypes(DocumentModel currentDoc) {
172        List<String> types = new ArrayList<>();
173
174        DocumentModel parent = documentManager.getRootDocument();
175
176        DocumentRef parentRef = currentDoc.getParentRef();
177        if (parentRef != null && documentManager.hasPermission(parentRef, SecurityConstants.READ)) {
178            parent = documentManager.getDocument(parentRef);
179        }
180
181        for (Type type : typeManager.findAllAllowedSubTypesFrom(currentDoc.getType(), parent)) {
182            types.add(type.getId());
183        }
184
185        return types;
186    }
187
188    public List<Type> getTypesWithSchemaFile() {
189        DocumentModel document = navigationContext.getCurrentDocument();
190        return getTypesWithSchemaFile(document);
191    }
192
193    /**
194     * Returns a List of Document Types associated with Schema file for the domain given as parameter, if they're
195     * allowed for it.
196     *
197     * @param document the domain
198     * @return List of Document types which have assoctiated Schema files.
199     * @Since 5.5
200     */
201    public List<Type> getTypesWithSchemaFile(DocumentModel document) {
202        List<Type> types = new ArrayList<>();
203        for (String type : getAllowedTypes(document)) {
204            DocumentType documentType = getSchemaManager().getDocumentType(type);
205            if (documentType != null && documentType.hasSchema(UI_TYPES_DEFAULT_NEEDED_SCHEMA)) {
206                types.add(typeManager.getType(type));
207            }
208        }
209        Collections.sort(types, new TypeLabelAlphabeticalOrder(messages));
210        return Collections.unmodifiableList(types);
211    }
212
213    protected SchemaManager getSchemaManager() {
214        if (schemaManager == null) {
215            schemaManager = Framework.getService(SchemaManager.class);
216        }
217        return schemaManager;
218    }
219
220}