001/*
002 * (C) Copyright 2012 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 *     Antoine Taillefer <ataillefer@nuxeo.com>
018 */
019package org.nuxeo.drive.service.impl;
020
021import java.security.Principal;
022import java.util.Map;
023
024import org.apache.commons.logging.Log;
025import org.apache.commons.logging.LogFactory;
026import org.nuxeo.drive.adapter.FileSystemItem;
027import org.nuxeo.drive.adapter.FolderItem;
028import org.nuxeo.drive.service.FileSystemItemFactory;
029import org.nuxeo.drive.service.NuxeoDriveManager;
030import org.nuxeo.ecm.core.api.DocumentModel;
031import org.nuxeo.ecm.core.api.LifeCycleConstants;
032import org.nuxeo.runtime.api.Framework;
033
034/**
035 * Base {@link FileSystemItemFactory} for a synchronization root {@link FolderItem}.
036 *
037 * @author Antoine Taillefer
038 */
039public abstract class AbstractSyncRootFolderItemFactory extends AbstractFileSystemItemFactory {
040
041    private static final Log log = LogFactory.getLog(AbstractSyncRootFolderItemFactory.class);
042
043    /**
044     * Returns the parent {@link FileSystemItem}.
045     */
046    protected abstract FolderItem getParentItem(DocumentModel doc);
047
048    /**
049     * No parameters by default.
050     */
051    @Override
052    public void handleParameters(Map<String, String> parameters) {
053        // Nothing to do as no parameters are contributed to the factory
054        if (!parameters.isEmpty()) {
055            throw new IllegalArgumentException(
056                    "Parameter map is not empty whereas no parameters are contributed to the factory.");
057        }
058        if (log.isDebugEnabled()) {
059            log.debug(String.format("Factory %s has no parameters to handle.", getName()));
060        }
061    }
062
063    /**
064     * The factory considers that a {@link DocumentModel} is adaptable as a {@link FileSystemItem} if:
065     * <ul>
066     * <li>It is Folderish</li>
067     * <li>AND it is not a version nor a proxy</li>
068     * <li>AND it is not HiddenInNavigation</li>
069     * <li>AND it is not in the "deleted" life cycle state, unless {@code includeDeleted} is true</li>
070     * <li>AND it is a synchronization root registered for the current user, unless {@code relaxSyncRootConstraint} is
071     * true</li>
072     * </ul>
073     */
074    @Override
075    public boolean isFileSystemItem(DocumentModel doc, boolean includeDeleted, boolean relaxSyncRootConstraint) {
076
077        // Check Folderish
078        if (!doc.isFolder()) {
079            if (log.isDebugEnabled()) {
080                log.debug(String.format("Document %s is not Folderish, it cannot be adapted as a FileSystemItem.",
081                        doc.getId()));
082            }
083            return false;
084        }
085        // Check version
086        if (doc.isVersion()) {
087            if (log.isDebugEnabled()) {
088                log.debug(String.format("Document %s is a version, it cannot be adapted as a FileSystemItem.",
089                        doc.getId()));
090            }
091            return false;
092        }
093        // Check proxy
094        if (doc.isProxy()) {
095            if (log.isDebugEnabled()) {
096                log.debug(String.format("Document %s is a proxy, it cannot be adapted as a FileSystemItem.",
097                        doc.getId()));
098            }
099            return false;
100        }
101        // Check HiddenInNavigation
102        if (doc.hasFacet("HiddenInNavigation")) {
103            if (log.isDebugEnabled()) {
104                log.debug(String.format("Document %s is HiddenInNavigation, it cannot be adapted as a FileSystemItem.",
105                        doc.getId()));
106            }
107            return false;
108        }
109        // Check "deleted" life cycle state
110        if (!includeDeleted && LifeCycleConstants.DELETED_STATE.equals(doc.getCurrentLifeCycleState())) {
111            if (log.isDebugEnabled()) {
112                log.debug(String.format(
113                        "Document %s is in the '%s' life cycle state, it cannot be adapted as a FileSystemItem.",
114                        doc.getId(), LifeCycleConstants.DELETED_STATE));
115            }
116            return false;
117        }
118        if (!relaxSyncRootConstraint) {
119            // Check synchronization root registered for the current user
120            NuxeoDriveManager nuxeoDriveManager = Framework.getLocalService(NuxeoDriveManager.class);
121            Principal principal = doc.getCoreSession().getPrincipal();
122            boolean isSyncRoot = nuxeoDriveManager.isSynchronizationRoot(principal, doc);
123            if (!isSyncRoot) {
124                if (log.isDebugEnabled()) {
125                    log.debug(String.format(
126                            "Document %s is not a registered synchronization root for user %s, it cannot be adapted as a FileSystemItem.",
127                            doc.getId(), principal.getName()));
128                }
129                return false;
130            }
131        }
132        return true;
133    }
134
135    /**
136     * Force parent using {@link #getParentItem(DocumentModel)}.
137     */
138    @Override
139    public FileSystemItem getFileSystemItem(DocumentModel doc, boolean includeDeleted) {
140        return getFileSystemItem(doc, getParentItem(doc), includeDeleted);
141    }
142
143    /**
144     * Force parent using {@link #getParentItem(DocumentModel)}.
145     */
146    @Override
147    public FileSystemItem getFileSystemItem(DocumentModel doc, boolean includeDeleted, boolean relaxSyncRootConstraint) {
148        return getFileSystemItem(doc, getParentItem(doc), includeDeleted, relaxSyncRootConstraint);
149    }
150
151    /**
152     * Force parent using {@link #getParentItem(DocumentModel)}.
153     */
154    @Override
155    public FileSystemItem getFileSystemItem(DocumentModel doc, boolean includeDeleted, boolean relaxSyncRootConstraint,
156            boolean getLockInfo) {
157        return getFileSystemItem(doc, getParentItem(doc), includeDeleted, relaxSyncRootConstraint, getLockInfo);
158    }
159
160}