001/*
002 * (C) Copyright 2010 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 - initial API and implementation
018 */
019
020package org.nuxeo.ecm.platform.content.template.factories;
021
022import org.nuxeo.ecm.core.api.DocumentModel;
023import org.nuxeo.ecm.core.api.IterableQueryResult;
024import org.nuxeo.ecm.core.query.sql.NXQL;
025import org.nuxeo.ecm.platform.content.template.listener.RepositoryInitializationListener;
026import org.nuxeo.ecm.platform.content.template.service.TemplateItemDescriptor;
027
028/**
029 * Specific factory for Root. Since some other {@link RepositoryInitializationListener} have run before, root won't be
030 * empty but we may still have to run this initializer.
031 *
032 * @author Thierry Delprat
033 */
034public class SimpleTemplateBasedRootFactory extends SimpleTemplateBasedFactory {
035
036    @Override
037    public void createContentStructure(DocumentModel eventDoc) {
038        initSession(eventDoc);
039
040        boolean initRootAcl = shouldInitAcl(eventDoc);
041
042        for (TemplateItemDescriptor item : template) {
043            if (!shouldCreateDocument(eventDoc.getId(), item.getId(), item.getTypeName())) {
044                continue;
045            }
046
047            String itemPath = eventDoc.getPathAsString();
048            if (item.getPath() != null) {
049                itemPath += "/" + item.getPath();
050            }
051            DocumentModel newChild = session.createDocumentModel(itemPath, item.getId(), item.getTypeName());
052            newChild.setProperty("dublincore", "title", item.getTitle());
053            newChild.setProperty("dublincore", "description", item.getDescription());
054            setProperties(item.getProperties(), newChild);
055            newChild = session.createDocument(newChild);
056            setAcl(item.getAcl(), newChild.getRef());
057            session.save();
058        }
059        // init root ACL if really empty
060        if (initRootAcl) {
061            setAcl(acl, eventDoc.getRef());
062        }
063    }
064
065    /**
066     * @return {@code true} if we should create the document with the given {@code parentId}, {@code childName} and
067     *         {@code childType}, {@code false} otherwise
068     */
069    protected boolean shouldCreateDocument(String parentId, String childName, String childType) {
070        String query = String.format("SELECT %s FROM Document WHERE %s = '%s' AND %s = '%s' AND %s = '%s'",
071                NXQL.ECM_UUID, //
072                NXQL.ECM_PARENTID, parentId, //
073                NXQL.ECM_NAME, childName, //
074                NXQL.ECM_PRIMARYTYPE, childType);
075
076        try (IterableQueryResult it = session.queryAndFetch(query, NXQL.NXQL)) {
077            return !it.iterator().hasNext();
078        }
079    }
080
081    /**
082     * Checks if we should init the acl of the root document.
083     * <p>
084     * The root init acl should occur only once, At the beginning where root document doesn't contain any child.
085     *
086     * @return {@code true} if the root document doesn't contain any child of template document type, {@code false}
087     *         otherwise
088     */
089    protected boolean shouldInitAcl(DocumentModel rootDoc) {
090        for (TemplateItemDescriptor item : template) {
091            String query = String.format("SELECT %s FROM Document WHERE %s = '%s' AND %s = '%s'", //
092                    NXQL.ECM_UUID, //
093                    NXQL.ECM_PARENTID, rootDoc.getId(), //
094                    NXQL.ECM_PRIMARYTYPE, item.getTypeName());
095            try (IterableQueryResult it = session.queryAndFetch(query, NXQL.NXQL)) {
096                if (it.iterator().hasNext()) {
097                    return false;
098                }
099            }
100        }
101        return true;
102    }
103
104}