jp.aegif.nemaki.cmis.factory.CmisService.java Source code

Java tutorial

Introduction

Here is the source code for jp.aegif.nemaki.cmis.factory.CmisService.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.factory;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.data.Acl;
import org.apache.chemistry.opencmis.commons.data.AllowableActions;
import org.apache.chemistry.opencmis.commons.data.BulkUpdateObjectIdAndChangeToken;
import org.apache.chemistry.opencmis.commons.data.ContentStream;
import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
import org.apache.chemistry.opencmis.commons.data.FailedToDeleteData;
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.Properties;
import org.apache.chemistry.opencmis.commons.data.PropertyData;
import org.apache.chemistry.opencmis.commons.data.RenditionData;
import org.apache.chemistry.opencmis.commons.data.RepositoryCapabilities;
import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionContainer;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionList;
import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.CapabilityAcl;
import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
import org.apache.chemistry.opencmis.commons.enums.RelationshipDirection;
import org.apache.chemistry.opencmis.commons.enums.UnfileObject;
import org.apache.chemistry.opencmis.commons.enums.VersioningState;
import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
import org.apache.chemistry.opencmis.commons.impl.server.AbstractCmisService;
import org.apache.chemistry.opencmis.commons.impl.server.ObjectInfoImpl;
import org.apache.chemistry.opencmis.commons.impl.server.RenditionInfoImpl;
import org.apache.chemistry.opencmis.commons.server.CallContext;
import org.apache.chemistry.opencmis.commons.server.ObjectInfo;
import org.apache.chemistry.opencmis.commons.server.RenditionInfo;
import org.apache.chemistry.opencmis.commons.spi.Holder;
import org.apache.chemistry.opencmis.server.support.wrapper.CallContextAwareCmisService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import jp.aegif.nemaki.cmis.service.AclService;
import jp.aegif.nemaki.cmis.service.DiscoveryService;
import jp.aegif.nemaki.cmis.service.NavigationService;
import jp.aegif.nemaki.cmis.service.ObjectService;
import jp.aegif.nemaki.cmis.service.PolicyService;
import jp.aegif.nemaki.cmis.service.RelationshipService;
import jp.aegif.nemaki.cmis.service.RepositoryService;
import jp.aegif.nemaki.cmis.service.VersioningService;

/**
 * Nemaki CMIS service.
 */
public class CmisService extends AbstractCmisService implements CallContextAwareCmisService {

    /**
     * Context data of the current CMIS call.
     */
    private CallContext context;

    /**
     * Map containing all Nemaki repositories.
     */

    private AclService aclService;
    private DiscoveryService discoveryService;
    private NavigationService navigationService;
    private ObjectService objectService;
    private RepositoryService repositoryService;
    private VersioningService versioningService;
    private PolicyService policyService;
    private RelationshipService relationshipService;

    private static final Log log = LogFactory.getLog(CmisService.class);

    /**
     * Create a new NemakiCmisService.
     */
    public CmisService() {

    }

    // --- Navigation Service Implementation ---

    private ObjectInfo setObjectInfo(String repositoryId, ObjectData object) {
        ObjectInfo info = null;
        // object info has not been found -> create one
        try {
            info = getObjectInfoIntern(repositoryId, object);
            // add object info
            addObjectInfo(info);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

        }
        return info;
    }

    private void setObjectInfoInTree(String repositoryId, List<ObjectInFolderContainer> list) {
        // Set ObjecInfo
        if (CollectionUtils.isNotEmpty(list)) {
            for (ObjectInFolderContainer o : list) {
                setObjectInfo(repositoryId, o.getObject().getObject());
                // TODO traverse descendant
                if (CollectionUtils.isNotEmpty(o.getChildren())) {
                    setObjectInfoInTree(repositoryId, o.getChildren());
                }
            }
        }
    }

    /**
     * This method is customized based on OpenCMIS code
     */
    @Override
    protected ObjectInfo getObjectInfoIntern(String repositoryId, ObjectData object) {
        // if the object has no properties, stop here
        if (object.getProperties() == null || object.getProperties().getProperties() == null) {
            throw new CmisRuntimeException("No properties!");
        }

        ObjectInfoImpl info = new ObjectInfoImpl();

        // get the repository info
        RepositoryInfo repositoryInfo = getRepositoryInfo(repositoryId, null);

        // general properties
        info.setObject(object);
        info.setId(object.getId());
        info.setName(getStringProperty(object, PropertyIds.NAME));
        info.setCreatedBy(getStringProperty(object, PropertyIds.CREATED_BY));
        info.setCreationDate(getDateTimeProperty(object, PropertyIds.CREATED_BY));
        info.setLastModificationDate(getDateTimeProperty(object, PropertyIds.LAST_MODIFICATION_DATE));
        info.setTypeId(getIdProperty(object, PropertyIds.OBJECT_TYPE_ID));
        info.setBaseType(object.getBaseTypeId());

        // versioning
        info.setIsCurrentVersion(object.getBaseTypeId() == BaseTypeId.CMIS_DOCUMENT);
        info.setWorkingCopyId(null);
        info.setWorkingCopyOriginalId(null);

        info.setVersionSeriesId(getIdProperty(object, PropertyIds.VERSION_SERIES_ID));
        if (info.getVersionSeriesId() != null) {
            Boolean isLatest = getBooleanProperty(object, PropertyIds.IS_LATEST_VERSION);
            info.setIsCurrentVersion(isLatest == null ? true : isLatest.booleanValue());

            Boolean isCheckedOut = getBooleanProperty(object, PropertyIds.IS_VERSION_SERIES_CHECKED_OUT);
            if (isCheckedOut != null && isCheckedOut.booleanValue()) {
                info.setWorkingCopyId(getIdProperty(object, PropertyIds.VERSION_SERIES_CHECKED_OUT_ID));

                // get latest version
                // // Nemaki Cusomization START ////
                /*
                 * List<ObjectData> versions = getAllVersions(repositoryId,
                 * object.getId(), info.getVersionSeriesId(), null,
                 * Boolean.FALSE, null); if (versions != null && versions.size()
                 * > 0) {
                 * info.setWorkingCopyOriginalId(versions.get(0).getId()); }
                 */

                // NOTE:Spec2.2.7.6 only says the first element of
                // getAllVersions MUST be PWC.
                // When isCheckedOut = true, PWC MUST exsits, and
                // cmis:versionSeriesCheckedOutId is PWC id(2.1.13.5.1).
                info.setWorkingCopyOriginalId(getIdProperty(object, PropertyIds.VERSION_SERIES_CHECKED_OUT_ID));
                // // Nemaki Cusomization END ////
            }
        }

        // content
        String fileName = getStringProperty(object, PropertyIds.CONTENT_STREAM_FILE_NAME);
        String mimeType = getStringProperty(object, PropertyIds.CONTENT_STREAM_MIME_TYPE);
        String streamId = getIdProperty(object, PropertyIds.CONTENT_STREAM_ID);
        BigInteger length = getIntegerProperty(object, PropertyIds.CONTENT_STREAM_LENGTH);
        boolean hasContent = fileName != null || mimeType != null || streamId != null || length != null;
        if (hasContent) {
            info.setHasContent(hasContent);
            info.setContentType(mimeType);
            info.setFileName(fileName);
        } else {
            info.setHasContent(false);
            info.setContentType(null);
            info.setFileName(null);
        }

        // parents
        if (object.getBaseTypeId() == BaseTypeId.CMIS_RELATIONSHIP) {
            info.setHasParent(false);
        } else if (object.getBaseTypeId() == BaseTypeId.CMIS_FOLDER) {
            info.setHasParent(!object.getId().equals(repositoryInfo.getRootFolderId()));
            // // Nemaki Cusomization START ////
            /*
             * } else { try { List<ObjectParentData> parents =
             * getObjectParents(repositoryId, object.getId(), null,
             * Boolean.FALSE, IncludeRelationships.NONE, "cmis:none",
             * Boolean.FALSE, null); info.setHasParent(parents.size() > 0); }
             * catch (CmisInvalidArgumentException e) {
             * info.setHasParent(false); } }
             */
        } else {
            String objecTypeId = getIdProperty(object, PropertyIds.OBJECT_TYPE_ID);
            TypeDefinition typeDefinition = getTypeDefinition(repositoryId, objecTypeId, null);

            if (typeDefinition.isFileable()) {
                boolean unfiling = (repositoryInfo.getCapabilities().isUnfilingSupported() == null) ? false
                        : repositoryInfo.getCapabilities().isUnfilingSupported();
                if (unfiling) {
                    List<ObjectParentData> parents = getObjectParents(repositoryId, object.getId(), null,
                            Boolean.FALSE, IncludeRelationships.NONE, "cmis:none", Boolean.FALSE, null);
                    info.setHasParent(parents != null && parents.size() >= 0);
                } else {
                    info.setHasParent(true);
                }
            } else {
                info.setHasParent(false);
            }
        }
        // // Nemaki Cusomization END ////

        // policies and relationships
        info.setSupportsRelationships(false);
        info.setSupportsPolicies(false);

        TypeDefinitionList baseTypesList = getTypeChildren(repositoryId, null, Boolean.FALSE, BigInteger.valueOf(4),
                BigInteger.ZERO, null);
        for (TypeDefinition type : baseTypesList.getList()) {
            if (BaseTypeId.CMIS_RELATIONSHIP.value().equals(type.getId())) {
                info.setSupportsRelationships(true);
            } else if (BaseTypeId.CMIS_POLICY.value().equals(type.getId())) {
                info.setSupportsPolicies(true);
            }
        }

        // renditions
        info.setRenditionInfos(null);
        List<RenditionData> renditions = object.getRenditions();
        if (renditions != null && renditions.size() > 0) {
            List<RenditionInfo> renditionInfos = new ArrayList<RenditionInfo>();
            for (RenditionData rendition : renditions) {
                RenditionInfoImpl renditionInfo = new RenditionInfoImpl();
                renditionInfo.setId(rendition.getStreamId());
                renditionInfo.setKind(rendition.getKind());
                renditionInfo.setContentType(rendition.getMimeType());
                renditionInfo.setTitle(rendition.getTitle());
                renditionInfo.setLength(rendition.getBigLength());
                renditionInfos.add(renditionInfo);
            }
            info.setRenditionInfos(renditionInfos);
        }

        // relationships
        info.setRelationshipSourceIds(null);
        info.setRelationshipTargetIds(null);
        List<ObjectData> relationships = object.getRelationships();
        if (relationships != null && relationships.size() > 0) {
            List<String> sourceIds = new ArrayList<String>();
            List<String> targetIds = new ArrayList<String>();
            for (ObjectData relationship : relationships) {
                String sourceId = getIdProperty(relationship, PropertyIds.SOURCE_ID);
                String targetId = getIdProperty(relationship, PropertyIds.TARGET_ID);
                if (object.getId().equals(sourceId)) {
                    sourceIds.add(relationship.getId());
                }
                if (object.getId().equals(targetId)) {
                    targetIds.add(relationship.getId());
                }
            }
            if (sourceIds.size() > 0) {
                info.setRelationshipSourceIds(sourceIds);
            }
            if (targetIds.size() > 0) {
                info.setRelationshipTargetIds(targetIds);
            }
        }

        // global settings
        info.setHasAcl(false);
        info.setSupportsDescendants(false);
        info.setSupportsFolderTree(false);

        RepositoryCapabilities capabilities = repositoryInfo.getCapabilities();
        if (capabilities != null) {
            info.setHasAcl(capabilities.getAclCapability() == CapabilityAcl.DISCOVER
                    || capabilities.getAclCapability() == CapabilityAcl.MANAGE);
            if (object.getBaseTypeId() == BaseTypeId.CMIS_FOLDER) {
                info.setSupportsDescendants(Boolean.TRUE.equals(capabilities.isGetDescendantsSupported()));
                info.setSupportsFolderTree(Boolean.TRUE.equals(capabilities.isGetFolderTreeSupported()));
            }
        }

        return info;
    }

    // --- Navigation Service Implementation ---

    /**
     * Gets the list of child objects contained in the specified folder.
     */
    @Override
    public ObjectInFolderList getChildren(String repositoryId, String folderId, String filter, String orderBy,
            Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
            Boolean includePathSegment, BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {
        Holder<ObjectData> parentObjectData = new Holder<ObjectData>(null);

        ObjectInFolderList children = navigationService.getChildren(getCallContext(), repositoryId, folderId,
                filter, orderBy, includeAllowableActions, null, null, includePathSegment, maxItems, skipCount,
                extension, parentObjectData);

        if (parentObjectData != null && parentObjectData.getValue() != null) {
            setObjectInfo(repositoryId, parentObjectData.getValue());
        }
        if (children != null) {
            for (ObjectInFolderData o : children.getObjects()) {
                setObjectInfo(repositoryId, o.getObject());
            }
        }

        return children;
    }

    /**
     * Gets the set of descendant objects contained in the specified folder or
     * any of its child folders.
     */
    @Override
    public List<ObjectInFolderContainer> getDescendants(String repositoryId, String folderId, BigInteger depth,
            String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships,
            String renditionFilter, Boolean includePathSegment, ExtensionsData extension) {
        Holder<ObjectData> anscestorObjectData = new Holder<ObjectData>(null);

        List<ObjectInFolderContainer> result = navigationService.getDescendants(getCallContext(), repositoryId,
                folderId, depth, filter, includeAllowableActions, includeRelationships, renditionFilter,
                includePathSegment, false, extension, anscestorObjectData);

        if (anscestorObjectData != null && anscestorObjectData.getValue() != null) {
            setObjectInfo(repositoryId, anscestorObjectData.getValue());
        }
        setObjectInfoInTree(repositoryId, result);

        return result;
    }

    /**
     * Gets the set of descendant folder objects contained in the specified
     * folder.
     */
    @Override
    public List<ObjectInFolderContainer> getFolderTree(String repositoryId, String folderId, BigInteger depth,
            String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships,
            String renditionFilter, Boolean includePathSegment, ExtensionsData extension) {
        Holder<ObjectData> anscestorObjectData = new Holder<ObjectData>(null);

        List<ObjectInFolderContainer> result = navigationService.getDescendants(getCallContext(), repositoryId,
                folderId, depth, filter, includeAllowableActions, includeRelationships, renditionFilter,
                includePathSegment, true, extension, anscestorObjectData);

        if (anscestorObjectData != null && anscestorObjectData.getValue() != null) {
            setObjectInfo(repositoryId, anscestorObjectData.getValue());
        }
        setObjectInfoInTree(repositoryId, result);

        return result;
    }

    /**
     * Gets the parent folder object for the specified folder object.
     */
    @Override
    public ObjectData getFolderParent(String repositoryId, String folderId, String filter,
            ExtensionsData extension) {
        return navigationService.getFolderParent(getCallContext(), repositoryId, folderId, filter);
    }

    /**
     * Gets the parent folder(s) for the specified non-folder, fileable object.
     */
    @Override
    public List<ObjectParentData> getObjectParents(String repositoryId, String objectId, String filter,
            Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
            Boolean includeRelativePathSegment, ExtensionsData extension) {
        List<ObjectParentData> parents = navigationService.getObjectParents(getCallContext(), repositoryId,
                objectId, filter, includeAllowableActions, includeRelationships, renditionFilter,
                includeRelativePathSegment, extension);
        return parents;
    }

    /**
     * Gets the list of documents that are checked out that the user has access
     * to. No checkout for now, so empty.
     */
    @Override
    public ObjectList getCheckedOutDocs(String repositoryId, String folderId, String filter, String orderBy,
            Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
            BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {

        return navigationService.getCheckedOutDocs(getCallContext(), repositoryId, folderId, filter, orderBy,
                includeAllowableActions, includeRelationships, renditionFilter, maxItems, skipCount, extension);

    }

    // ---- Object Service Implementation ---

    /**
     * Creates a new document, folder or policy. The property
     * "cmis:objectTypeId" defines the type and implicitly the base type.
     */
    @Override
    public String create(String repositoryId, Properties properties, String folderId, ContentStream contentStream,
            VersioningState versioningState, List<String> policies, ExtensionsData extension) {
        ObjectData object = objectService.create(getCallContext(), repositoryId, properties, folderId,
                contentStream, versioningState, policies, extension);

        setObjectInfo(repositoryId, object);

        return object.getId();
    }

    /**
     * Creates a document object of the specified type (given by the
     * cmis:objectTypeId property) in the (optionally) specified location.
     */
    @Override
    public String createDocument(String repositoryId, Properties properties, String folderId,
            ContentStream contentStream, VersioningState versioningState, List<String> policies, Acl addAces,
            Acl removeAces, ExtensionsData extension) {
        return objectService.createDocument(getCallContext(), repositoryId, properties, folderId, contentStream,
                versioningState, policies, addAces, removeAces);
    }

    /**
     * Creates a document object as a copy of the given source document in the
     * (optionally) specified location.
     */
    @Override
    public String createDocumentFromSource(String repositoryId, String sourceId, Properties properties,
            String folderId, VersioningState versioningState, List<String> policies, Acl addAces, Acl removeAces,
            ExtensionsData extension) {
        return objectService.createDocumentFromSource(getCallContext(), repositoryId, sourceId, properties,
                folderId, versioningState, policies, addAces, removeAces);
    }

    /**
     * Creates a folder object of the specified type (given by the
     * cmis:objectTypeId property) in the specified location.
     */
    @Override
    public String createFolder(String repositoryId, Properties properties, String folderId, List<String> policies,
            Acl addAces, Acl removeAces, ExtensionsData extension) {
        return objectService.createFolder(getCallContext(), repositoryId, properties, folderId, policies, addAces,
                removeAces, extension);
    }

    @Override
    public String createRelationship(String repositoryId, Properties properties, List<String> policies, Acl addAces,
            Acl removeAces, ExtensionsData extension) {
        return objectService.createRelationship(getCallContext(), repositoryId, properties, policies, addAces,
                removeAces, extension);
    }

    @Override
    public String createPolicy(String repositoryId, Properties properties, String folderId, List<String> policies,
            Acl addAces, Acl removeAces, ExtensionsData extension) {
        return objectService.createPolicy(getCallContext(), repositoryId, properties, folderId, policies, addAces,
                removeAces, extension);
    }

    /**
     * Deletes the content stream for the specified document object.
     */
    @Override
    public void deleteContentStream(String repositoryId, Holder<String> objectId, Holder<String> changeToken,
            ExtensionsData extension) {
        objectService.deleteContentStream(getCallContext(), repositoryId, objectId, changeToken, extension);
    }

    /**
     * Deletes an object or cancels a check out. For the Web Services binding
     * this is always an object deletion. For the AtomPub it depends on the
     * referenced object. If it is a checked out document then the check out
     * must be canceled. If the object is not a checked out document then the
     * object must be deleted.
     */
    @Override
    public void deleteObjectOrCancelCheckOut(String repositoryId, String objectId, Boolean allVersions,
            ExtensionsData extension) {
        // TODO When checkOut implemented, implement switching the two methods
        ObjectData o = getObject(repositoryId, objectId, null, false, IncludeRelationships.NONE, null, null, null,
                null);
        PropertyData<?> isPWC = o.getProperties().getProperties().get(PropertyIds.IS_PRIVATE_WORKING_COPY);
        if (isPWC != null && isPWC.getFirstValue().equals(true)) {
            versioningService.cancelCheckOut(getCallContext(), repositoryId, objectId, null);
        } else {
            objectService.deleteObject(getCallContext(), repositoryId, objectId, allVersions);
        }

    }

    /**
     * Deletes the specified folder object and all of its child- and
     * descendant-objects.
     */
    @Override
    public FailedToDeleteData deleteTree(String repositoryId, String folderId, Boolean allVersions,
            UnfileObject unfileObjects, Boolean continueOnFailure, ExtensionsData extension) {
        return objectService.deleteTree(getCallContext(), repositoryId, folderId, allVersions, unfileObjects,
                continueOnFailure, extension);
    }

    /**
     * Gets the list of allowable actions for an object.
     */
    @Override
    public AllowableActions getAllowableActions(String repositoryId, String objectId, ExtensionsData extension) {
        return objectService.getAllowableActions(getCallContext(), repositoryId, objectId);
    }

    /**
     * Gets the content stream for the specified document object, or gets a
     * rendition stream for a specified rendition of a document or folder
     * object.
     */
    @Override
    public ContentStream getContentStream(String repositoryId, String objectId, String streamId, BigInteger offset,
            BigInteger length, ExtensionsData extension) {
        return objectService.getContentStream(getCallContext(), repositoryId, objectId, streamId, offset, length);
    }

    /**
     * Gets the specified information for the object specified by id.
     */
    @Override
    public ObjectData getObject(String repositoryId, String objectId, String filter,
            Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
            Boolean includePolicyIds, Boolean includeAcl, ExtensionsData extension) {
        ObjectData objectData = objectService.getObject(getCallContext(), repositoryId, objectId, filter,
                includeAllowableActions, includeRelationships, renditionFilter, includePolicyIds, includeAcl,
                extension);
        setObjectInfo(repositoryId, objectData);
        return objectData;
    }

    /**
     * Gets the specified information for the object specified by path.
     */
    @Override
    public ObjectData getObjectByPath(String repositoryId, String path, String filter,
            Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
            Boolean includePolicyIds, Boolean includeAcl, ExtensionsData extension) {
        ObjectData objectData = objectService.getObjectByPath(getCallContext(), repositoryId, path, filter,
                includeAllowableActions, includeRelationships, renditionFilter, includePolicyIds, includeAcl,
                extension);
        setObjectInfo(repositoryId, objectData);
        return objectData;
    }

    /**
     * Gets the list of properties for an object.
     */
    @Override
    public Properties getProperties(String repositoryId, String objectId, String filter, ExtensionsData extension) {
        ObjectData object = objectService.getObject(getCallContext(), repositoryId, objectId, filter, false,
                IncludeRelationships.NONE, null, false, false, extension);
        return object.getProperties();
    }

    /**
     * Gets the list of associated renditions for the specified object. Only
     * rendition attributes are returned, not rendition stream. No renditions,
     * so empty.
     */
    @Override
    public List<RenditionData> getRenditions(String repositoryId, String objectId, String renditionFilter,
            BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {

        return objectService.getRenditions(getCallContext(), repositoryId, objectId, renditionFilter, maxItems,
                skipCount, extension);
    }

    /**
     * Moves the specified file-able object from one folder to another.
     */
    @Override
    public void moveObject(String repositoryId, Holder<String> objectId, String targetFolderId,
            String sourceFolderId, ExtensionsData extension) {
        // TODO Implement permission check here
        // PermissionMapping.CAN_GET_PROPERTIES_OBJECT

        objectService.moveObject(getCallContext(), repositoryId, objectId, sourceFolderId, targetFolderId);
    }

    /**
     * Sets the content stream for the specified document object.
     */
    @Override
    public void setContentStream(String repositoryId, Holder<String> objectId, Boolean overwriteFlag,
            Holder<String> changeToken, ContentStream contentStream, ExtensionsData extension) {
        objectService.setContentStream(getCallContext(), repositoryId, objectId, overwriteFlag, contentStream,
                changeToken);
    }

    /**
     * Updates properties of the specified object.
     */
    @Override
    public void updateProperties(String repositoryId, Holder<String> objectId, Holder<String> changeToken,
            Properties properties, ExtensionsData extension) {
        objectService.updateProperties(getCallContext(), repositoryId, objectId, properties, changeToken);
    }

    // --- Versioning Service Implementation ---
    @Override
    public void checkOut(String repositoryId, Holder<String> objectId, ExtensionsData extension,
            Holder<Boolean> contentCopied) {
        versioningService.checkOut(getCallContext(), repositoryId, objectId, extension, contentCopied);
    }

    @Override
    public void cancelCheckOut(String repositoryId, String objectId, ExtensionsData extension) {
        versioningService.cancelCheckOut(getCallContext(), repositoryId, objectId, extension);
    }

    @Override
    public void checkIn(String repositoryId, Holder<String> objectId, Boolean major, Properties properties,
            ContentStream contentStream, String checkinComment, List<String> policies, Acl addAces, Acl removeAces,
            ExtensionsData extension) {
        versioningService.checkIn(getCallContext(), repositoryId, objectId, major, properties, contentStream,
                checkinComment, policies, addAces, removeAces, extension);
    }

    /**
     * Returns the list of all document objects in the specified version series,
     * sorted by the property "cmis:creationDate" descending.
     */
    @Override
    public List<ObjectData> getAllVersions(String repositoryId, String objectId, String versionSeriesId,
            String filter, Boolean includeAllowableActions, ExtensionsData extension) {

        List<ObjectData> result = versioningService.getAllVersions(getCallContext(), repositoryId, objectId,
                versionSeriesId, filter, includeAllowableActions, extension);
        if (CollectionUtils.isNotEmpty(result)) {
            for (ObjectData o : result) {
                setObjectInfo(repositoryId, o);
            }
        }
        return result;
    }

    /**
     * Get the latest document object in the version series.
     */
    @Override
    public ObjectData getObjectOfLatestVersion(String repositoryId, String objectId, String versionSeriesId,
            Boolean major, String filter, Boolean includeAllowableActions,
            IncludeRelationships includeRelationships, String renditionFilter, Boolean includePolicyIds,
            Boolean includeAcl, ExtensionsData extension) {
        return versioningService.getObjectOfLatestVersion(context, repositoryId, objectId, versionSeriesId, major,
                filter, includeAllowableActions, includeRelationships, renditionFilter, includePolicyIds,
                includeAcl, extension);

    }

    /**
     * Get a subset of the properties for the latest document object in the
     * version series.
     */
    @Override
    public Properties getPropertiesOfLatestVersion(String repositoryId, String objectId, String versionSeriesId,
            Boolean major, String filter, ExtensionsData extension) {
        ObjectData object = getObjectOfLatestVersion(repositoryId, objectId, versionSeriesId, major, filter, false,
                IncludeRelationships.NONE, null, false, false, extension);
        return object.getProperties();
    }

    // --- ACL Service Implementation ---

    /**
     * Applies a new ACL (Access Control List) to an object. Since it is not
     * possible to transmit an "add ACL" and a "remove ACL" via AtomPub, the
     * merging has to be done on the client side. The ACEs provided here is
     * supposed to the new complete ACL.
     */
    @Override
    public Acl applyAcl(String repositoryId, String objectId, Acl aces, AclPropagation aclPropagation) {
        return aclService.applyAcl(getCallContext(), repositoryId, objectId, aces, aclPropagation);
    }

    /**
     * Get the ACL (Access Control List) currently applied to the specified
     * object.
     */
    @Override
    public Acl getAcl(String repositoryId, String objectId, Boolean onlyBasicPermissions,
            ExtensionsData extension) {
        return aclService.getAcl(getCallContext(), repositoryId, objectId, onlyBasicPermissions);
    }

    // --- Repository Service Implementation ---

    /**
     * Returns information about the CMIS repository, the optional capabilities
     * it supports and its access control information.
     */
    @Override
    public RepositoryInfo getRepositoryInfo(String repositoryId, ExtensionsData extension) {

        RepositoryInfo info = repositoryService.getRepositoryInfo(repositoryId);
        if (info == null) {
            throw new CmisObjectNotFoundException("Unknown repository '" + repositoryId + "'!");
        } else {
            return info;
        }
    }

    /**
     * Returns a list of CMIS repository information available from this CMIS
     * service endpoint. In contrast to the CMIS specification this method
     * returns repository infos not only repository ids. (See OpenCMIS doc)
     */
    @Override
    public List<RepositoryInfo> getRepositoryInfos(ExtensionsData arg0) {
        return repositoryService.getRepositoryInfos();
    }

    /**
     * Returns the list of object types defined for the repository that are
     * children of the specified type.
     */
    @Override
    public TypeDefinitionList getTypeChildren(String repositoryId, String typeId,
            Boolean includePropertyDefinitions, BigInteger maxItems, BigInteger skipCount,
            ExtensionsData extension) {
        return repositoryService.getTypeChildren(getCallContext(), repositoryId, typeId, includePropertyDefinitions,
                maxItems, skipCount);
    }

    /**
     * Gets the definition of the specified object type.
     */
    @Override
    public TypeDefinition getTypeDefinition(String repositoryId, String typeId, ExtensionsData extension) {
        return repositoryService.getTypeDefinition(getCallContext(), repositoryId, typeId);
    }

    /**
     * Returns the set of descendant object type defined for the repository
     * under the specified type.
     */
    @Override
    public List<TypeDefinitionContainer> getTypeDescendants(String repositoryId, String typeId, BigInteger depth,
            Boolean includePropertyDefinitions, ExtensionsData extension) {
        return repositoryService.getTypeDescendants(getCallContext(), repositoryId, typeId, depth,
                includePropertyDefinitions);
    }

    // --- Discovery Service Implementation ---

    /**
     * Executes a CMIS query statement against the contents of the repository.
     */
    @Override
    public ObjectList query(String repositoryId, String statement, Boolean searchAllVersions,
            Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
            BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {
        return discoveryService.query(getCallContext(), repositoryId, statement, searchAllVersions,
                includeAllowableActions, includeRelationships, renditionFilter, maxItems, skipCount, extension);
    }

    @Override
    public ObjectList getContentChanges(String repositoryId, Holder<String> changeLogToken,
            Boolean includeProperties, String filter, Boolean includePolicyIds, Boolean includeAcl,
            BigInteger maxItems, ExtensionsData extension) {

        return discoveryService.getContentChanges(getCallContext(), repositoryId, changeLogToken, includeProperties,
                filter, includePolicyIds, includeAcl, maxItems, extension);
    }

    // --- Relationship Service Implementation ---
    @Override
    public ObjectList getObjectRelationships(String repositoryId, String objectId,
            Boolean includeSubRelationshipTypes, RelationshipDirection relationshipDirection, String typeId,
            String filter, Boolean includeAllowableActions, BigInteger maxItems, BigInteger skipCount,
            ExtensionsData extension) {
        return relationshipService.getObjectRelationships(getCallContext(), repositoryId, objectId,
                includeSubRelationshipTypes, relationshipDirection, typeId, filter, includeAllowableActions,
                maxItems, skipCount, extension);
    }

    // --- Policy Service Implementation ---
    @Override
    public void applyPolicy(String repositoryId, String policyId, String objectId, ExtensionsData extension) {
        policyService.applyPolicy(getCallContext(), repositoryId, policyId, objectId, extension);
    }

    @Override
    public void removePolicy(String repositoryId, String policyId, String objectId, ExtensionsData extension) {
        policyService.removePolicy(getCallContext(), repositoryId, policyId, objectId, extension);
    }

    @Override
    public List<ObjectData> getAppliedPolicies(String repositoryId, String objectId, String filter,
            ExtensionsData extension) {
        return policyService.getAppliedPolicies(getCallContext(), repositoryId, objectId, filter, extension);
    }

    // --- Multi-filing Service Implementation ---
    @Override
    public void addObjectToFolder(String repositoryId, String objectId, String folderId, Boolean allVersions,
            ExtensionsData extension) {
        // TODO Auto-generated method stub
        super.addObjectToFolder(repositoryId, objectId, folderId, allVersions, extension);
    }

    @Override
    public void removeObjectFromFolder(String repositoryId, String objectId, String folderId,
            ExtensionsData extension) {
        // TODO Auto-generated method stub
        super.removeObjectFromFolder(repositoryId, objectId, folderId, extension);
    }

    @Override
    public void appendContentStream(String repositoryId, Holder<String> objectId, Holder<String> changeToken,
            ContentStream contentStream, boolean isLastChunk, ExtensionsData extension) {
        objectService.appendContentStream(getCallContext(), repositoryId, objectId, changeToken, contentStream,
                isLastChunk, extension);
        ;
    }

    @Override
    public List<BulkUpdateObjectIdAndChangeToken> bulkUpdateProperties(String repositoryId,
            List<BulkUpdateObjectIdAndChangeToken> objectIdAndChangeToken, Properties properties,
            List<String> addSecondaryTypeIds, List<String> removeSecondaryTypeIds, ExtensionsData extension) {
        return objectService.bulkUpdateProperties(getCallContext(), repositoryId, objectIdAndChangeToken,
                properties, addSecondaryTypeIds, removeSecondaryTypeIds, extension);
    }

    @Override
    public String createItem(String repositoryId, Properties properties, String folderId, List<String> policies,
            Acl addAces, Acl removeAces, ExtensionsData extension) {
        return objectService.createItem(getCallContext(), repositoryId, properties, folderId, policies, addAces,
                removeAces, extension);
    }

    @Override
    public TypeDefinition createType(String repositoryId, TypeDefinition type, ExtensionsData extension) {
        return repositoryService.createType(getCallContext(), repositoryId, type, extension);
    }

    @Override
    public void deleteType(String repositoryId, String typeId, ExtensionsData extension) {
        repositoryService.deleteType(getCallContext(), repositoryId, typeId, extension);
    }

    @Override
    public TypeDefinition updateType(String repositoryId, TypeDefinition type, ExtensionsData extension) {
        return repositoryService.updateType(getCallContext(), repositoryId, type, extension);
    }

    /*
     * Setters/Getters
     */
    public void setCallContext(CallContext context) {
        this.context = context;

        if (log.isTraceEnabled()) {
            log.trace("nemaki_log[FACTORY]" + "CmisService@" + this.hashCode() + " with CallContext@"
                    + this.context.hashCode() + "[repositoryId=" + context.getRepositoryId() + ", userId="
                    + context.getUsername() + "] has benn changed to CallContext@" + context.hashCode()
                    + "[repositoryId=" + context.getRepositoryId() + ", userId=" + context.getUsername() + "]");
        }
    }

    public CallContext getCallContext() {
        return context;
    }

    public void setAclService(AclService aclService) {
        this.aclService = aclService;
    }

    public void setDiscoveryService(DiscoveryService discoveryService) {
        this.discoveryService = discoveryService;
    }

    public void setNavigationService(NavigationService navigationService) {
        this.navigationService = navigationService;
    }

    public void setObjectService(ObjectService objectService) {
        this.objectService = objectService;
    }

    public void setRepositoryService(RepositoryService repositoryService) {
        this.repositoryService = repositoryService;
    }

    public void setVersioningService(VersioningService versioningService) {
        this.versioningService = versioningService;
    }

    public void setPolicyService(PolicyService policyService) {
        this.policyService = policyService;
    }

    public void setRelationshipService(RelationshipService relationshipService) {
        this.relationshipService = relationshipService;
    }

    @Override
    public void close() {
        if (log.isTraceEnabled()) {
            log.trace("nemaki_log[FACTORY]" + "CmisService@" + this.hashCode() + " with CallContext@"
                    + context.hashCode() + "[repositoryId=" + context.getRepositoryId() + ", userId="
                    + context.getUsername() + "] is closed");
        }

        super.close();

    }

}