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