001/*
002 * (C) Copyright 2006-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 *     Nuxeo
018 */
019
020package org.nuxeo.ecm.platform.publisher.impl.core;
021
022import java.util.ArrayList;
023import java.util.Arrays;
024import java.util.Collections;
025import java.util.List;
026
027import org.nuxeo.ecm.core.api.CoreSession;
028import org.nuxeo.ecm.core.api.DocumentModel;
029import org.nuxeo.ecm.core.api.DocumentModelList;
030import org.nuxeo.ecm.core.api.DocumentRef;
031import org.nuxeo.ecm.core.api.Filter;
032import org.nuxeo.ecm.core.api.impl.CompoundFilter;
033import org.nuxeo.ecm.core.api.impl.FacetFilter;
034import org.nuxeo.ecm.core.api.security.SecurityConstants;
035import org.nuxeo.ecm.core.api.tree.DefaultDocumentTreeSorter;
036import org.nuxeo.ecm.core.schema.FacetNames;
037import org.nuxeo.ecm.platform.publisher.api.AbstractPublicationNode;
038import org.nuxeo.ecm.platform.publisher.api.PublicationNode;
039import org.nuxeo.ecm.platform.publisher.api.PublicationTree;
040import org.nuxeo.ecm.platform.publisher.api.PublishedDocument;
041import org.nuxeo.ecm.platform.publisher.api.PublishedDocumentFactory;
042
043/**
044 * Implementation of the {@link PublicationNode} for Simple Core Folders.
045 *
046 * @author tiry
047 */
048public class CoreFolderPublicationNode extends AbstractPublicationNode {
049
050    private static final long serialVersionUID = 1L;
051
052    private static final String DEFAULT_SORT_PROP_NAME = "dc:title";
053
054    protected DocumentModel folder;
055
056    protected PublicationNode parent;
057
058    protected List<PublicationNode> childrenNodes;
059
060    protected PublishedDocumentFactory factory;
061
062    public CoreFolderPublicationNode(DocumentModel doc, PublicationTree tree, PublicationNode parent,
063            PublishedDocumentFactory factory) {
064        super(tree);
065        this.folder = doc;
066        this.parent = parent;
067        this.factory = factory;
068    }
069
070    public CoreFolderPublicationNode(DocumentModel doc, PublicationTree tree, PublishedDocumentFactory factory) {
071        super(tree);
072        this.folder = doc;
073        this.factory = factory;
074    }
075
076    protected CoreSession getCoreSession() {
077        return folder.getCoreSession();
078    }
079
080    protected String buildChildrenWhereClause(boolean queryDocuments) {
081        String clause = String.format("ecm:parentId = '%s' AND ecm:isTrashed = 0", folder.getId());
082        if (queryDocuments) {
083            clause += String.format(" AND ecm:mixinType NOT IN ('%s', '%s')", FacetNames.PUBLISH_SPACE,
084                    FacetNames.HIDDEN_IN_NAVIGATION);
085        } else {
086            clause += String.format("AND ecm:mixinType IN ('%s') AND ecm:mixinType NOT IN ('%s')",
087                    FacetNames.PUBLISH_SPACE, FacetNames.HIDDEN_IN_NAVIGATION);
088        }
089        return clause;
090    }
091
092    @Override
093    public List<PublishedDocument> getChildrenDocuments() {
094        DocumentModelList children = getSortedChildren(true);
095        List<PublishedDocument> childrenDocs = new ArrayList<>();
096        for (DocumentModel child : children) {
097            childrenDocs.add(factory.wrapDocumentModel(child));
098        }
099        return childrenDocs;
100    }
101
102    @Override
103    public List<PublicationNode> getChildrenNodes() {
104        if (childrenNodes == null) {
105            DocumentModelList children = getSortedChildren(false);
106            childrenNodes = new ArrayList<>();
107            for (DocumentModel child : children) {
108                childrenNodes.add(new CoreFolderPublicationNode(child, tree, this, factory));
109            }
110        }
111        return childrenNodes;
112    }
113
114    protected DocumentModelList getOrderedChildren() {
115        return getCoreSession().getChildren(folder.getRef(), null, null, computeGetChildrenFilter(), null);
116    }
117
118    protected Filter computeGetChildrenFilter() {
119        FacetFilter facetFilter = new FacetFilter(Arrays.asList(FacetNames.FOLDERISH),
120                Arrays.asList(FacetNames.HIDDEN_IN_NAVIGATION));
121        Filter trashedFilter = docModel -> !docModel.isTrashed();
122        return new CompoundFilter(facetFilter, trashedFilter);
123    }
124
125    protected DocumentModelList getSortedChildren(boolean queryDocuments) {
126        String whereClause = buildChildrenWhereClause(queryDocuments);
127        DocumentModelList children = getCoreSession().query("SELECT * FROM Document WHERE " + whereClause);
128        if (!folder.hasFacet(FacetNames.ORDERABLE)) {
129            DefaultDocumentTreeSorter sorter = new DefaultDocumentTreeSorter();
130            sorter.setSortPropertyPath(DEFAULT_SORT_PROP_NAME);
131            Collections.sort(children, sorter);
132        }
133        return children;
134    }
135
136    @Override
137    public String getTitle() {
138        return folder.getTitle();
139    }
140
141    @Override
142    public String getName() {
143        return folder.getName();
144    }
145
146    @Override
147    public PublicationNode getParent() {
148        if (parent == null) {
149            DocumentRef docRef = folder.getParentRef();
150            if (getCoreSession().hasPermission(docRef, SecurityConstants.READ)) {
151                parent = new CoreFolderPublicationNode(getCoreSession().getDocument(folder.getParentRef()), tree,
152                        factory);
153            } else {
154                parent = new VirtualCoreFolderPublicationNode(getCoreSession(), docRef.toString(), tree,
155                        factory);
156            }
157        }
158        return parent;
159    }
160
161    @Override
162    public String getPath() {
163        return folder.getPathAsString();
164    }
165
166    public DocumentRef getTargetDocumentRef() {
167        return folder.getRef();
168    }
169
170    public DocumentModel getTargetDocumentModel() {
171        return folder;
172    }
173
174}