jp.aegif.nemaki.cmis.service.impl.NavigationServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for jp.aegif.nemaki.cmis.service.impl.NavigationServiceImpl.java

Source

/*******************************************************************************
 * Copyright (c) 2013 aegif.
 *
 * This file is part of NemakiWare.
 *
 * NemakiWare is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * NemakiWare is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with NemakiWare.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *     linzhixing(https://github.com/linzhixing) - initial API and implementation
 ******************************************************************************/
package jp.aegif.nemaki.cmis.service.impl;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.locks.Lock;

import jp.aegif.nemaki.businesslogic.ContentService;
import jp.aegif.nemaki.cmis.aspect.CompileService;
import jp.aegif.nemaki.cmis.aspect.ExceptionService;
import jp.aegif.nemaki.cmis.aspect.PermissionService;
import jp.aegif.nemaki.cmis.service.NavigationService;
import jp.aegif.nemaki.model.Content;
import jp.aegif.nemaki.model.Document;
import jp.aegif.nemaki.model.Folder;
import jp.aegif.nemaki.util.DataUtil;
import jp.aegif.nemaki.util.constant.DomainType;
import jp.aegif.nemaki.util.lock.ThreadLockService;

import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
import org.apache.chemistry.opencmis.commons.data.ObjectData;
import org.apache.chemistry.opencmis.commons.data.ObjectInFolderContainer;
import org.apache.chemistry.opencmis.commons.data.ObjectInFolderData;
import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList;
import org.apache.chemistry.opencmis.commons.data.ObjectList;
import org.apache.chemistry.opencmis.commons.data.ObjectParentData;
import org.apache.chemistry.opencmis.commons.data.PermissionMapping;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderContainerImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderDataImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderListImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectParentDataImpl;
import org.apache.chemistry.opencmis.commons.server.CallContext;
import org.apache.chemistry.opencmis.commons.spi.Holder;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

public class NavigationServiceImpl implements NavigationService {

    private ContentService contentService;
    private ExceptionService exceptionService;
    private CompileService compileService;
    private PermissionService permissionService;
    private ThreadLockService threadLockService;

    @Override
    public ObjectInFolderList getChildren(CallContext callContext, String repositoryId, String folderId,
            String filter, String orderBy, Boolean includeAllowableActions,
            IncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments,
            BigInteger maxItems, BigInteger skipCount, ExtensionsData extension,
            Holder<ObjectData> parentObjectData) {

        exceptionService.invalidArgumentRequiredString("folderId", folderId);

        Lock parentLock = threadLockService.getReadLock(repositoryId, folderId);

        try {
            parentLock.lock();

            // //////////////////
            // General Exception
            // //////////////////
            Folder folder = contentService.getFolder(repositoryId, folderId);
            exceptionService.invalidArgumentFolderId(folder, folderId);
            exceptionService.permissionDenied(callContext, repositoryId, PermissionMapping.CAN_GET_CHILDREN_FOLDER,
                    folder);

            // //////////////////
            // Body of the method
            // //////////////////
            // Set ObjectData of parent folder for ObjectInfo
            ObjectData _parent = compileService.compileObjectData(callContext, repositoryId, folder, filter,
                    includeAllowableActions, includeRelationships, renditionFilter, false);
            parentObjectData.setValue(_parent);

            return getChildrenInternal(callContext, repositoryId, folderId, filter, orderBy,
                    includeAllowableActions, includeRelationships, renditionFilter, includePathSegments, maxItems,
                    skipCount, false);
        } finally {
            parentLock.unlock();
        }
    }

    private ObjectInFolderList getChildrenInternal(CallContext callContext, String repositoryId, String folderId,
            String filter, String orderBy, Boolean includeAllowableActions,
            IncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments,
            BigInteger maxItems, BigInteger skipCount, boolean folderOnly) {

        // Prepare
        ObjectInFolderListImpl result = new ObjectInFolderListImpl();
        result.setObjects(new ArrayList<ObjectInFolderData>());
        result.setHasMoreItems(false);

        // Build ObjectList
        List<Content> contents = contentService.getChildren(repositoryId, folderId);

        List<Lock> locks = threadLockService.readLocks(repositoryId, contents);

        try {
            threadLockService.bulkLock(locks);

            contents = permissionService.getFiltered(callContext, repositoryId, contents);

            ObjectList ol = compileService.compileObjectDataList(callContext, repositoryId, contents, filter,
                    includeAllowableActions, includeRelationships, renditionFilter, false, maxItems, skipCount,
                    folderOnly, orderBy);

            // Build ObjectInFolderList
            for (ObjectData od : ol.getObjects()) {
                ObjectInFolderDataImpl objectInFolder = new ObjectInFolderDataImpl();
                objectInFolder.setObject(od);
                if (includePathSegments) {
                    String name = DataUtil.getStringProperty(od.getProperties(), PropertyIds.NAME);
                    objectInFolder.setPathSegment(name);
                }
                result.getObjects().add(objectInFolder);
            }
            result.setNumItems(ol.getNumItems());
            result.setHasMoreItems(ol.hasMoreItems());

            return result;
        } finally {
            threadLockService.bulkUnlock(locks);
        }
    }

    @Override
    public List<ObjectInFolderContainer> getDescendants(CallContext callContext, String repositoryId,
            String folderId, BigInteger depth, String filter, Boolean includeAllowableActions,
            IncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegment,
            boolean foldersOnly, ExtensionsData extension, Holder<ObjectData> anscestorObjectData) {

        exceptionService.invalidArgumentRequiredString("folderId", folderId);

        Lock parentLock = threadLockService.getReadLock(repositoryId, folderId);

        try {
            parentLock.lock();

            // //////////////////
            // General Exception
            // //////////////////
            Folder folder = contentService.getFolder(repositoryId, folderId);
            exceptionService.permissionDenied(callContext, repositoryId,
                    PermissionMapping.CAN_GET_DESCENDENTS_FOLDER, folder);

            // //////////////////
            // Specific Exception
            // //////////////////
            exceptionService.invalidArgumentFolderId(folder, folderId);
            exceptionService.invalidArgumentDepth(depth);

            // //////////////////
            // Body of the method
            // //////////////////
            // check depth
            int d = (depth == null ? 2 : depth.intValue());

            // set defaults if values not set
            boolean iaa = (includeAllowableActions == null ? false : includeAllowableActions.booleanValue());
            boolean ips = (includePathSegment == null ? false : includePathSegment.booleanValue());

            // Set ObjectData of the starting folder for ObjectInfo
            ObjectData _folder = compileService.compileObjectData(callContext, repositoryId, folder, filter,
                    includeAllowableActions, includeRelationships, renditionFilter, false);
            anscestorObjectData.setValue(_folder);

            // get the tree.
            return getDescendantsInternal(callContext, repositoryId, _folder, filter, iaa, false,
                    includeRelationships, null, ips, 0, d, foldersOnly);

        } finally {
            parentLock.unlock();
        }
    }

    private List<ObjectInFolderContainer> getDescendantsInternal(CallContext callContext, String repositoryId,
            ObjectData node, String filter, Boolean includeAllowableActions, Boolean includeAcl,
            IncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments,
            int level, int maxLevels, boolean folderOnly) {

        List<ObjectInFolderContainer> childrenOfFolder = new ArrayList<ObjectInFolderContainer>();
        // Check specified folderId is folder(if not, it's a leaf node)
        if (node.getBaseTypeId() != BaseTypeId.CMIS_FOLDER) {
            return childrenOfFolder;
        }

        String folderId = node.getId();
        if (maxLevels == -1 || level < maxLevels) {
            ObjectInFolderList children = getChildrenInternal(callContext, repositoryId, folderId, filter, null,
                    includeAllowableActions, includeRelationships, renditionFilter, includePathSegments,
                    BigInteger.valueOf(Integer.MAX_VALUE), BigInteger.valueOf(0), folderOnly);

            childrenOfFolder = new ArrayList<ObjectInFolderContainer>();
            if (null != children && CollectionUtils.isNotEmpty(children.getObjects())) {
                for (ObjectInFolderData child : children.getObjects()) {
                    ObjectInFolderContainerImpl oifc = new ObjectInFolderContainerImpl();
                    List<ObjectInFolderContainer> subChildren = getDescendantsInternal(callContext, repositoryId,
                            child.getObject(), filter, includeAllowableActions, includeAcl, includeRelationships,
                            renditionFilter, includePathSegments, level + 1, maxLevels, folderOnly);

                    oifc.setObject(child);
                    if (CollectionUtils.isNotEmpty(subChildren))
                        oifc.setChildren(subChildren);
                    childrenOfFolder.add(oifc);
                }
            }
        }
        return childrenOfFolder;
    }

    @Override
    public ObjectData getFolderParent(CallContext callContext, String repositoryId, String folderId,
            String filter) {

        exceptionService.invalidArgumentRequiredString("folderId", folderId);

        Lock childLock = threadLockService.getReadLock(repositoryId, folderId);

        try {
            childLock.lock();

            // //////////////////
            // General Exception
            // //////////////////
            Folder folder = (Folder) contentService.getContent(repositoryId, folderId);
            exceptionService.objectNotFound(DomainType.OBJECT, folder, folderId);
            exceptionService.permissionDenied(callContext, repositoryId,
                    PermissionMapping.CAN_GET_FOLDER_PARENT_OBJECT, folder);

            // //////////////////
            // Specific Exception
            // //////////////////
            Folder parent = contentService.getParent(repositoryId, folderId);

            Lock parentLock = threadLockService.getReadLock(repositoryId, parent.getId());
            try {
                parentLock.lock();

                exceptionService.objectNotFoundParentFolder(repositoryId, folderId, parent);
                exceptionService.invalidArgumentRootFolder(repositoryId, folder);

                // //////////////////
                // Body of the method
                // //////////////////
                return compileService.compileObjectData(callContext, repositoryId, parent, filter, true,
                        IncludeRelationships.NONE, null, true);

            } finally {
                parentLock.unlock();
            }
        } finally {
            childLock.unlock();
        }
    }

    @Override
    public List<ObjectParentData> getObjectParents(CallContext callContext, String repositoryId, String objectId,
            String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships,
            String renditionFilter, Boolean includeRelativePathSegment, ExtensionsData extension) {

        exceptionService.invalidArgumentRequired("objectId", objectId);

        Lock childLock = threadLockService.getReadLock(repositoryId, objectId);

        try {
            childLock.lock();

            // //////////////////
            // General Exception
            // //////////////////
            Content content = contentService.getContent(repositoryId, objectId);
            exceptionService.objectNotFound(DomainType.OBJECT, content, objectId);
            exceptionService.permissionDenied(callContext, repositoryId, PermissionMapping.CAN_GET_PARENTS_FOLDER,
                    content);

            //Get parent
            Folder parent = contentService.getParent(repositoryId, objectId);
            Lock parentLock = threadLockService.getReadLock(repositoryId, parent.getId());

            try {
                parentLock.lock();

                // //////////////////
                // Specific Exception
                // //////////////////
                exceptionService.objectNotFoundParentFolder(repositoryId, objectId, parent);
                exceptionService.invalidArgumentRootFolder(repositoryId, content);

                // //////////////////
                // Body of the method
                // //////////////////
                ObjectParentDataImpl result = new ObjectParentDataImpl();
                ObjectData o = compileService.compileObjectData(callContext, repositoryId, parent, filter,
                        includeAllowableActions, includeRelationships, null, true);
                result.setObject(o);
                boolean irps = (includeRelativePathSegment == null ? false
                        : includeRelativePathSegment.booleanValue());
                if (irps) {
                    result.setRelativePathSegment(content.getName());
                }

                return Collections.singletonList((ObjectParentData) result);

            } finally {
                parentLock.unlock();
            }

        } finally {
            childLock.unlock();
        }
    }

    @Override
    public ObjectList getCheckedOutDocs(CallContext callContext, String repositoryId, String folderId,
            String filter, String orderBy, Boolean includeAllowableActions,
            IncludeRelationships includeRelationships, String renditionFilter, BigInteger maxItems,
            BigInteger skipCount, ExtensionsData extension) {
        // //////////////////
        // General Exception
        // //////////////////
        // NONE

        // //////////////////
        // Specific Exception
        // //////////////////
        //Folder ID can be null, which means all PWCs are returned.
        if (StringUtils.isNotBlank(folderId)) {
            Folder folder = contentService.getFolder(repositoryId, folderId);
            exceptionService.objectNotFoundParentFolder(repositoryId, folderId, folder);
        }
        exceptionService.invalidArgumentOrderBy(repositoryId, orderBy);

        // //////////////////
        // Body of the method
        // //////////////////
        //Folder ID can be null, which means all PWCs are returned.
        List<Document> checkedOuts = contentService.getCheckedOutDocs(repositoryId, folderId, orderBy, extension);

        List<Lock> locks = threadLockService.readLocks(repositoryId, checkedOuts);

        try {
            threadLockService.bulkLock(locks);

            ObjectList list = compileService.compileObjectDataList(callContext, repositoryId, checkedOuts, filter,
                    includeAllowableActions, includeRelationships, renditionFilter, false, maxItems, skipCount,
                    false, orderBy);

            return list;

        } finally {
            threadLockService.bulkUnlock(locks);
        }
    }

    public void setContentService(ContentService contentService) {
        this.contentService = contentService;
    }

    public void setExceptionService(ExceptionService exceptionService) {
        this.exceptionService = exceptionService;
    }

    public void setCompileService(CompileService compileService) {
        this.compileService = compileService;
    }

    public void setPermissionService(PermissionService permissionService) {
        this.permissionService = permissionService;
    }

    public void setThreadLockService(ThreadLockService threadLockService) {
        this.threadLockService = threadLockService;
    }
}