/*
* (C) Copyright 2009 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* Thierry Delprat
*/
package org.nuxeo.ecm.platform.publisher.impl.finder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentModelList;
import org.nuxeo.ecm.core.api.DocumentNotFoundException;
import org.nuxeo.ecm.core.api.DocumentRef;
import org.nuxeo.ecm.core.api.Filter;
import org.nuxeo.ecm.core.api.IdRef;
import org.nuxeo.ecm.core.api.LifeCycleConstants;
import org.nuxeo.ecm.core.api.PathRef;
import org.nuxeo.ecm.core.api.UnrestrictedSessionRunner;
import org.nuxeo.ecm.core.api.impl.CompoundFilter;
import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl;
import org.nuxeo.ecm.core.api.impl.FacetFilter;
import org.nuxeo.ecm.core.api.impl.LifeCycleFilter;
import org.nuxeo.ecm.core.api.security.SecurityConstants;
import org.nuxeo.ecm.core.schema.FacetNames;
import org.nuxeo.ecm.core.schema.SchemaManager;
import org.nuxeo.ecm.platform.publisher.helper.RootSectionFinder;
import org.nuxeo.runtime.api.Framework;
public abstract class AbstractRootSectionsFinder extends UnrestrictedSessionRunner implements RootSectionFinder {
public static final String SCHEMA_PUBLISHING = "publishing";
public static final String SECTIONS_PROPERTY_NAME = "publish:sections";
protected static Set<String> sectionRootTypes;
protected static Set<String> sectionTypes;
protected CoreSession userSession;
protected List<String> unrestrictedSectionRootFromWorkspaceConfig;
protected List<String> unrestrictedDefaultSectionRoot;
protected DocumentModelList accessibleSectionRoots;
protected DocumentModel currentDocument;
protected static final Log log = LogFactory.getLog(AbstractRootSectionsFinder.class);
protected abstract void computeUserSectionRoots(DocumentModel currentDoc);
protected abstract String buildQuery(String path);
protected abstract void computeUnrestrictedRoots(CoreSession session);
public AbstractRootSectionsFinder(CoreSession userSession) {
super(userSession);
this.userSession = userSession;
}
@Override
public void reset() {
this.currentDocument = null;
}
@Override
public DocumentModelList getAccessibleSectionRoots(DocumentModel currentDoc) {
if ((currentDocument == null) || (!currentDocument.getRef().equals(currentDoc.getRef()))) {
computeUserSectionRoots(currentDoc);
}
return accessibleSectionRoots;
}
@Override
public DocumentModelList getSectionRootsForWorkspace(DocumentModel currentDoc, boolean addDefaultSectionRoots)
{
if ((currentDocument == null) || (!currentDocument.getRef().equals(currentDoc.getRef()))) {
computeUserSectionRoots(currentDoc);
}
if (unrestrictedDefaultSectionRoot.isEmpty() && addDefaultSectionRoots) {
if (unrestrictedDefaultSectionRoot == null || unrestrictedDefaultSectionRoot.isEmpty()) {
DocumentModelList defaultSectionRoots = getDefaultSectionRoots(session);
unrestrictedDefaultSectionRoot = new ArrayList<String>();
for (DocumentModel root : defaultSectionRoots) {
unrestrictedDefaultSectionRoot.add(root.getPathAsString());
}
}
}
return getFiltredSectionRoots(unrestrictedSectionRootFromWorkspaceConfig, true);
}
@Override
public DocumentModelList getSectionRootsForWorkspace(DocumentModel currentDoc) {
return getSectionRootsForWorkspace(currentDoc, false);
}
@Override
public DocumentModelList getDefaultSectionRoots(boolean onlyHeads, boolean addDefaultSectionRoots)
{
if (unrestrictedDefaultSectionRoot == null) {
computeUserSectionRoots(null);
}
if (unrestrictedDefaultSectionRoot.isEmpty() && addDefaultSectionRoots) {
if (unrestrictedDefaultSectionRoot == null || unrestrictedDefaultSectionRoot.isEmpty()) {
DocumentModelList defaultSectionRoots = getDefaultSectionRoots(session);
unrestrictedDefaultSectionRoot = new ArrayList<String>();
for (DocumentModel root : defaultSectionRoots) {
unrestrictedDefaultSectionRoot.add(root.getPathAsString());
}
}
}
return getFiltredSectionRoots(unrestrictedDefaultSectionRoot, onlyHeads);
}
@Override
public DocumentModelList getDefaultSectionRoots(boolean onlyHeads) {
return getDefaultSectionRoots(onlyHeads, false);
}
protected DocumentModelList getFiltredSectionRoots(List<String> rootPaths, boolean onlyHeads)
{
List<DocumentRef> filtredDocRef = new ArrayList<DocumentRef>();
List<DocumentRef> trashedDocRef = new ArrayList<DocumentRef>();
for (String rootPath : rootPaths) {
DocumentRef rootRef = new PathRef(rootPath);
if (userSession.hasPermission(rootRef, SecurityConstants.READ)) {
filtredDocRef.add(rootRef);
} else {
DocumentModelList accessibleSections = userSession.query(buildQuery(rootPath));
for (DocumentModel section : accessibleSections) {
if (onlyHeads
&& ((filtredDocRef.contains(section.getParentRef())) || (trashedDocRef.contains(section.getParentRef())))) {
trashedDocRef.add(section.getRef());
} else {
filtredDocRef.add(section.getRef());
}
}
}
}
DocumentModelList documents = userSession.getDocuments(filtredDocRef.toArray(new DocumentRef[filtredDocRef.size()]));
return filterDocuments(documents);
}
protected DocumentModelList filterDocuments(DocumentModelList docs) {
DocumentModelList filteredDocuments = new DocumentModelListImpl();
FacetFilter facetFilter = new FacetFilter(Arrays.asList(FacetNames.FOLDERISH),
Arrays.asList(FacetNames.HIDDEN_IN_NAVIGATION));
LifeCycleFilter lfFilter = new LifeCycleFilter(LifeCycleConstants.DELETED_STATE, false);
Filter filter = new CompoundFilter(facetFilter, lfFilter);
for (DocumentModel doc : docs) {
if (filter.accept(doc)) {
filteredDocuments.add(doc);
}
}
return filteredDocuments;
}
protected DocumentModelList getDefaultSectionRoots(CoreSession session) {
// XXX replace by a query !!!
DocumentModelList sectionRoots = new DocumentModelListImpl();
DocumentModelList domains = session.getChildren(session.getRootDocument().getRef(), "Domain");
for (DocumentModel domain : domains) {
for (String sectionRootNameType : getSectionRootTypes()) {
DocumentModelList children = session.getChildren(domain.getRef(), sectionRootNameType);
sectionRoots.addAll(children);
}
}
return sectionRoots;
}
protected DocumentModelList getSectionRootsFromWorkspaceConfig(DocumentModel workspace, CoreSession session)
{
DocumentModelList selectedSections = new DocumentModelListImpl();
if (workspace.hasSchema(SCHEMA_PUBLISHING)) {
String[] sectionIdsArray = (String[]) workspace.getPropertyValue(SECTIONS_PROPERTY_NAME);
List<String> sectionIdsList = new ArrayList<String>();
if (sectionIdsArray != null && sectionIdsArray.length > 0) {
sectionIdsList = Arrays.asList(sectionIdsArray);
}
if (sectionIdsList != null) {
for (String currentSectionId : sectionIdsList) {
try {
DocumentModel sectionToAdd = session.getDocument(new IdRef(currentSectionId));
selectedSections.add(sectionToAdd);
} catch (DocumentNotFoundException e) {
log.warn("Section with ID=" + currentSectionId + " not found for document with ID="
+ workspace.getId());
}
}
}
}
return selectedSections;
}
@Override
public void run() {
computeUnrestrictedRoots(session);
}
protected Set<String> getSectionRootTypes() {
if (sectionRootTypes == null) {
sectionRootTypes = getTypeNamesForFacet(FacetNames.MASTER_PUBLISH_SPACE);
if (sectionRootTypes == null) {
sectionRootTypes = new HashSet<String>();
}
}
return sectionRootTypes;
}
protected Set<String> getTypeNamesForFacet(String facetName) {
SchemaManager schemaManager = Framework.getLocalService(SchemaManager.class);
Set<String> publishRoots = schemaManager.getDocumentTypeNamesForFacet(facetName);
if (publishRoots == null || publishRoots.isEmpty()) {
return null;
}
return publishRoots;
}
protected Set<String> getSectionTypes() {
if (sectionTypes == null) {
sectionTypes = getTypeNamesForFacet(FacetNames.MASTER_PUBLISH_SPACE);
if (sectionTypes == null) {
sectionTypes = new HashSet<String>();
}
}
return sectionTypes;
}
}