001/* 002 * (C) Copyright 2009 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 * Thierry Delprat 018 */ 019package org.nuxeo.ecm.platform.publisher.impl.finder; 020 021import java.util.ArrayList; 022import java.util.Arrays; 023import java.util.HashSet; 024import java.util.List; 025import java.util.Set; 026 027import org.apache.commons.logging.Log; 028import org.apache.commons.logging.LogFactory; 029import org.nuxeo.ecm.core.api.CoreSession; 030import org.nuxeo.ecm.core.api.DocumentModel; 031import org.nuxeo.ecm.core.api.DocumentModelList; 032import org.nuxeo.ecm.core.api.DocumentNotFoundException; 033import org.nuxeo.ecm.core.api.DocumentRef; 034import org.nuxeo.ecm.core.api.Filter; 035import org.nuxeo.ecm.core.api.IdRef; 036import org.nuxeo.ecm.core.api.LifeCycleConstants; 037import org.nuxeo.ecm.core.api.PathRef; 038import org.nuxeo.ecm.core.api.UnrestrictedSessionRunner; 039import org.nuxeo.ecm.core.api.impl.CompoundFilter; 040import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl; 041import org.nuxeo.ecm.core.api.impl.FacetFilter; 042import org.nuxeo.ecm.core.api.impl.LifeCycleFilter; 043import org.nuxeo.ecm.core.api.security.SecurityConstants; 044import org.nuxeo.ecm.core.schema.FacetNames; 045import org.nuxeo.ecm.core.schema.SchemaManager; 046import org.nuxeo.ecm.platform.publisher.helper.RootSectionFinder; 047import org.nuxeo.runtime.api.Framework; 048 049public abstract class AbstractRootSectionsFinder extends UnrestrictedSessionRunner implements RootSectionFinder { 050 051 public static final String SCHEMA_PUBLISHING = "publishing"; 052 053 public static final String SECTIONS_PROPERTY_NAME = "publish:sections"; 054 055 protected static Set<String> sectionRootTypes; 056 057 protected static Set<String> sectionTypes; 058 059 protected CoreSession userSession; 060 061 protected List<String> unrestrictedSectionRootFromWorkspaceConfig; 062 063 protected List<String> unrestrictedDefaultSectionRoot; 064 065 protected DocumentModelList accessibleSectionRoots; 066 067 protected DocumentModel currentDocument; 068 069 protected static final Log log = LogFactory.getLog(AbstractRootSectionsFinder.class); 070 071 protected abstract void computeUserSectionRoots(DocumentModel currentDoc); 072 073 protected abstract String buildQuery(String path); 074 075 protected abstract void computeUnrestrictedRoots(CoreSession session); 076 077 public AbstractRootSectionsFinder(CoreSession userSession) { 078 super(userSession); 079 this.userSession = userSession; 080 } 081 082 @Override 083 public void reset() { 084 this.currentDocument = null; 085 } 086 087 @Override 088 public DocumentModelList getAccessibleSectionRoots(DocumentModel currentDoc) { 089 if ((currentDocument == null) || (!currentDocument.getRef().equals(currentDoc.getRef()))) { 090 computeUserSectionRoots(currentDoc); 091 } 092 return accessibleSectionRoots; 093 } 094 095 @Override 096 public DocumentModelList getSectionRootsForWorkspace(DocumentModel currentDoc, boolean addDefaultSectionRoots) 097 { 098 if ((currentDocument == null) || (!currentDocument.getRef().equals(currentDoc.getRef()))) { 099 computeUserSectionRoots(currentDoc); 100 } 101 102 if (unrestrictedDefaultSectionRoot.isEmpty() && addDefaultSectionRoots) { 103 if (unrestrictedDefaultSectionRoot == null || unrestrictedDefaultSectionRoot.isEmpty()) { 104 DocumentModelList defaultSectionRoots = getDefaultSectionRoots(session); 105 unrestrictedDefaultSectionRoot = new ArrayList<String>(); 106 for (DocumentModel root : defaultSectionRoots) { 107 unrestrictedDefaultSectionRoot.add(root.getPathAsString()); 108 } 109 } 110 } 111 112 return getFiltredSectionRoots(unrestrictedSectionRootFromWorkspaceConfig, true); 113 } 114 115 @Override 116 public DocumentModelList getSectionRootsForWorkspace(DocumentModel currentDoc) { 117 return getSectionRootsForWorkspace(currentDoc, false); 118 } 119 120 @Override 121 public DocumentModelList getDefaultSectionRoots(boolean onlyHeads, boolean addDefaultSectionRoots) 122 { 123 if (unrestrictedDefaultSectionRoot == null) { 124 computeUserSectionRoots(null); 125 } 126 127 if (unrestrictedDefaultSectionRoot.isEmpty() && addDefaultSectionRoots) { 128 if (unrestrictedDefaultSectionRoot == null || unrestrictedDefaultSectionRoot.isEmpty()) { 129 DocumentModelList defaultSectionRoots = getDefaultSectionRoots(session); 130 unrestrictedDefaultSectionRoot = new ArrayList<String>(); 131 for (DocumentModel root : defaultSectionRoots) { 132 unrestrictedDefaultSectionRoot.add(root.getPathAsString()); 133 } 134 } 135 } 136 137 return getFiltredSectionRoots(unrestrictedDefaultSectionRoot, onlyHeads); 138 } 139 140 @Override 141 public DocumentModelList getDefaultSectionRoots(boolean onlyHeads) { 142 return getDefaultSectionRoots(onlyHeads, false); 143 } 144 145 protected DocumentModelList getFiltredSectionRoots(List<String> rootPaths, boolean onlyHeads) 146 { 147 List<DocumentRef> filtredDocRef = new ArrayList<DocumentRef>(); 148 List<DocumentRef> trashedDocRef = new ArrayList<DocumentRef>(); 149 150 for (String rootPath : rootPaths) { 151 DocumentRef rootRef = new PathRef(rootPath); 152 if (userSession.hasPermission(rootRef, SecurityConstants.READ)) { 153 filtredDocRef.add(rootRef); 154 } else { 155 DocumentModelList accessibleSections = userSession.query(buildQuery(rootPath)); 156 for (DocumentModel section : accessibleSections) { 157 if (onlyHeads 158 && ((filtredDocRef.contains(section.getParentRef())) || (trashedDocRef.contains(section.getParentRef())))) { 159 trashedDocRef.add(section.getRef()); 160 } else { 161 filtredDocRef.add(section.getRef()); 162 } 163 } 164 } 165 } 166 DocumentModelList documents = userSession.getDocuments(filtredDocRef.toArray(new DocumentRef[filtredDocRef.size()])); 167 return filterDocuments(documents); 168 } 169 170 protected DocumentModelList filterDocuments(DocumentModelList docs) { 171 DocumentModelList filteredDocuments = new DocumentModelListImpl(); 172 FacetFilter facetFilter = new FacetFilter(Arrays.asList(FacetNames.FOLDERISH), 173 Arrays.asList(FacetNames.HIDDEN_IN_NAVIGATION)); 174 LifeCycleFilter lfFilter = new LifeCycleFilter(LifeCycleConstants.DELETED_STATE, false); 175 Filter filter = new CompoundFilter(facetFilter, lfFilter); 176 for (DocumentModel doc : docs) { 177 if (filter.accept(doc)) { 178 filteredDocuments.add(doc); 179 } 180 } 181 return filteredDocuments; 182 } 183 184 protected DocumentModelList getDefaultSectionRoots(CoreSession session) { 185 // XXX replace by a query !!! 186 DocumentModelList sectionRoots = new DocumentModelListImpl(); 187 DocumentModelList domains = session.getChildren(session.getRootDocument().getRef(), "Domain"); 188 for (DocumentModel domain : domains) { 189 for (String sectionRootNameType : getSectionRootTypes()) { 190 DocumentModelList children = session.getChildren(domain.getRef(), sectionRootNameType); 191 sectionRoots.addAll(children); 192 } 193 } 194 return sectionRoots; 195 } 196 197 protected DocumentModelList getSectionRootsFromWorkspaceConfig(DocumentModel workspace, CoreSession session) 198 { 199 200 DocumentModelList selectedSections = new DocumentModelListImpl(); 201 202 if (workspace.hasSchema(SCHEMA_PUBLISHING)) { 203 String[] sectionIdsArray = (String[]) workspace.getPropertyValue(SECTIONS_PROPERTY_NAME); 204 205 List<String> sectionIdsList = new ArrayList<String>(); 206 207 if (sectionIdsArray != null && sectionIdsArray.length > 0) { 208 sectionIdsList = Arrays.asList(sectionIdsArray); 209 } 210 211 if (sectionIdsList != null) { 212 for (String currentSectionId : sectionIdsList) { 213 try { 214 DocumentModel sectionToAdd = session.getDocument(new IdRef(currentSectionId)); 215 selectedSections.add(sectionToAdd); 216 } catch (DocumentNotFoundException e) { 217 log.warn("Section with ID=" + currentSectionId + " not found for document with ID=" 218 + workspace.getId()); 219 } 220 } 221 } 222 } 223 return selectedSections; 224 } 225 226 @Override 227 public void run() { 228 computeUnrestrictedRoots(session); 229 } 230 231 protected Set<String> getSectionRootTypes() { 232 if (sectionRootTypes == null) { 233 sectionRootTypes = getTypeNamesForFacet(FacetNames.MASTER_PUBLISH_SPACE); 234 if (sectionRootTypes == null) { 235 sectionRootTypes = new HashSet<String>(); 236 } 237 } 238 return sectionRootTypes; 239 } 240 241 protected Set<String> getTypeNamesForFacet(String facetName) { 242 SchemaManager schemaManager = Framework.getLocalService(SchemaManager.class); 243 Set<String> publishRoots = schemaManager.getDocumentTypeNamesForFacet(facetName); 244 if (publishRoots == null || publishRoots.isEmpty()) { 245 return null; 246 } 247 return publishRoots; 248 } 249 250 protected Set<String> getSectionTypes() { 251 if (sectionTypes == null) { 252 sectionTypes = getTypeNamesForFacet(FacetNames.MASTER_PUBLISH_SPACE); 253 if (sectionTypes == null) { 254 sectionTypes = new HashSet<String>(); 255 } 256 } 257 return sectionTypes; 258 } 259 260}