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