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

Java tutorial

Introduction

Here is the source code for jp.aegif.nemaki.cmis.service.impl.RepositoryServiceImpl.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.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import jp.aegif.nemaki.businesslogic.ContentService;
import jp.aegif.nemaki.businesslogic.TypeService;
import jp.aegif.nemaki.cmis.aspect.ExceptionService;
import jp.aegif.nemaki.cmis.aspect.type.TypeManager;
import jp.aegif.nemaki.cmis.factory.info.RepositoryInfo;
import jp.aegif.nemaki.cmis.factory.info.RepositoryInfoMap;
import jp.aegif.nemaki.cmis.service.RepositoryService;
import jp.aegif.nemaki.model.NemakiPropertyDefinition;
import jp.aegif.nemaki.model.NemakiPropertyDefinitionCore;
import jp.aegif.nemaki.model.NemakiPropertyDefinitionDetail;
import jp.aegif.nemaki.model.NemakiTypeDefinition;
import jp.aegif.nemaki.util.constant.DomainType;

import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
import org.apache.chemistry.opencmis.commons.definitions.DocumentTypeDefinition;
import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
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.definitions.TypeMutability;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AbstractTypeDefinition;
import org.apache.chemistry.opencmis.commons.server.CallContext;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.InitializingBean;

public class RepositoryServiceImpl implements RepositoryService, InitializingBean {

    private RepositoryInfoMap repositoryInfoMap;
    private TypeManager typeManager;
    private TypeService typeService;
    private ContentService contentService;
    private ExceptionService exceptionService;

    @Override
    public boolean hasThisRepositoryId(String repositoryId) {
        return (repositoryInfoMap.get(repositoryId) != null);
    }

    @Override
    public RepositoryInfo getRepositoryInfo(String repositoryId) {
        RepositoryInfo info = repositoryInfoMap.get(repositoryId);
        info.setLatestChangeLogToken(contentService.getLatestChangeToken(repositoryId));
        return info;
    }

    public List<org.apache.chemistry.opencmis.commons.data.RepositoryInfo> getRepositoryInfos() {
        List<org.apache.chemistry.opencmis.commons.data.RepositoryInfo> result = new ArrayList<org.apache.chemistry.opencmis.commons.data.RepositoryInfo>();
        for (String key : repositoryInfoMap.keys()) {
            result.add(repositoryInfoMap.get(key));
        }
        return result;
    }

    /**
     * CMIS Service method
     */
    @Override
    public TypeDefinitionList getTypeChildren(CallContext callContext, String repositoryId, String typeId,
            Boolean includePropertyDefinitions, BigInteger maxItems, BigInteger skipCount) {

        return typeManager.getTypesChildren(callContext, repositoryId, typeId, includePropertyDefinitions, maxItems,
                skipCount);
    }

    @Override
    public List<TypeDefinitionContainer> getTypeDescendants(CallContext callContext, String repositoryId,
            String typeId, BigInteger depth, Boolean includePropertyDefinitions) {
        return typeManager.getTypesDescendants(repositoryId, typeId, depth, includePropertyDefinitions);
    }

    @Override
    public TypeDefinition getTypeDefinition(CallContext callContext, String repositoryId, String typeId) {
        TypeDefinition typeDefinition = typeManager.getTypeDefinition(repositoryId, typeId);
        exceptionService.objectNotFound(DomainType.OBJECT_TYPE, typeDefinition, typeId);
        return typeDefinition;
    }

    @Override
    public TypeDefinition createType(CallContext callContext, String repositoryId, TypeDefinition type,
            ExtensionsData extension) {
        // //////////////////
        // General Exception
        // //////////////////
        exceptionService.perimissionAdmin(callContext, repositoryId);
        exceptionService.invalidArgumentRequired("typeDefinition", type);
        exceptionService.invalidArgumentCreatableType(repositoryId, type);
        exceptionService.constraintDuplicatePropertyDefinition(repositoryId, type);

        // //////////////////
        // Body of the method
        // //////////////////
        // Attributes
        NemakiTypeDefinition ntd = setNemakiTypeDefinitionAttributes(repositoryId, type);

        // Property definitions
        List<String> systemIds = typeManager.getSystemPropertyIds();
        Map<String, PropertyDefinition<?>> propDefs = type.getPropertyDefinitions();

        ntd.setProperties(new ArrayList<String>());
        if (MapUtils.isNotEmpty(propDefs)) {
            for (String key : propDefs.keySet()) {
                PropertyDefinition<?> propDef = propDefs.get(key);
                if (!systemIds.contains(key)) {
                    //Check PropertyDefinition
                    exceptionService.constraintQueryName(propDef);
                    exceptionService.constraintPropertyDefinition(type, propDef);

                    NemakiPropertyDefinition create = new NemakiPropertyDefinition(propDef);
                    NemakiPropertyDefinitionDetail created = typeService.createPropertyDefinition(repositoryId,
                            create);

                    List<String> l = ntd.getProperties();
                    l.add(created.getId());
                    ntd.setProperties(l);
                }
            }
        }

        // Create
        NemakiTypeDefinition created = typeService.createTypeDefinition(repositoryId, ntd);
        typeManager.refreshTypes();

        // Sort the order of properties
        return sortPropertyDefinitions(repositoryId, created, type);
    }

    @Override
    public void deleteType(CallContext callContext, String repositoryId, String typeId, ExtensionsData extension) {
        // //////////////////
        // General Exception
        // //////////////////
        exceptionService.perimissionAdmin(callContext, repositoryId);
        exceptionService.invalidArgumentRequiredString("typeId", typeId);
        exceptionService.invalidArgumentDoesNotExistType(repositoryId, typeId);
        exceptionService.invalidArgumentDeletableType(repositoryId, typeId);
        exceptionService.constraintOnlyLeafTypeDefinition(repositoryId, typeId);
        exceptionService.constraintObjectsStillExist(repositoryId, typeId);

        // //////////////////
        // Body of the method
        // //////////////////
        typeService.deleteTypeDefinition(repositoryId, typeId);
        typeManager.refreshTypes();
    }

    @Override
    public TypeDefinition updateType(CallContext callContext, String repositoryId, TypeDefinition type,
            ExtensionsData extension) {
        // //////////////////
        // General Exception
        // //////////////////
        exceptionService.perimissionAdmin(callContext, repositoryId);
        exceptionService.invalidArgumentRequired("typeDefinition", type);
        exceptionService.invalidArgumentDoesNotExistType(repositoryId, type.getId());
        exceptionService.invalidArgumentUpdatableType(type);
        exceptionService.constraintOnlyLeafTypeDefinition(repositoryId, type.getId());
        exceptionService.constraintDuplicatePropertyDefinition(repositoryId, type);

        // //////////////////
        // Body of the method
        // //////////////////
        NemakiTypeDefinition existingType = typeService.getTypeDefinition(repositoryId, type.getId());

        // Attributes
        NemakiTypeDefinition ntd = setNemakiTypeDefinitionAttributes(repositoryId, type);

        // Property definitions
        List<String> systemIds = typeManager.getSystemPropertyIds();
        Map<String, PropertyDefinition<?>> propDefs = type.getPropertyDefinitions();

        ntd.setProperties(new ArrayList<String>());
        if (MapUtils.isNotEmpty(propDefs)) {
            for (String key : propDefs.keySet()) {
                PropertyDefinition<?> propDef = propDefs.get(key);
                if (systemIds.contains(key))
                    continue;

                List<String> existingPropertyNodeIds = (CollectionUtils.isEmpty(existingType.getProperties()))
                        ? new ArrayList<String>()
                        : existingType.getProperties();

                String propNodeId = typeService.getPropertyDefinitionCoreByPropertyId(repositoryId, key).getId();
                if (existingPropertyNodeIds.contains(propNodeId)) {
                    // update
                    PropertyDefinition<?> oldPropDef = typeManager
                            .getTypeDefinition(repositoryId, existingType.getTypeId()).getPropertyDefinitions()
                            .get(propNodeId);
                    exceptionService.constraintUpdatePropertyDefinition(propDef, oldPropDef);
                    exceptionService.constraintQueryName(propDef);
                    exceptionService.constraintPropertyDefinition(type, propDef);

                    NemakiPropertyDefinition _update = new NemakiPropertyDefinition(propDef);
                    NemakiPropertyDefinitionCore core = typeService
                            .getPropertyDefinitionCoreByPropertyId(repositoryId, _update.getPropertyId());
                    NemakiPropertyDefinitionDetail update = new NemakiPropertyDefinitionDetail(_update,
                            core.getId());
                    typeService.updatePropertyDefinitionDetail(repositoryId, update);
                } else {
                    // create
                    exceptionService.constraintQueryName(propDef);
                    NemakiPropertyDefinition create = new NemakiPropertyDefinition(propDef);
                    NemakiPropertyDefinitionDetail created = typeService.createPropertyDefinition(repositoryId,
                            create);

                    List<String> l = ntd.getProperties();
                    l.add(created.getId());
                    ntd.setProperties(l);
                }

            }
        }

        // Update
        NemakiTypeDefinition updated = typeService.updateTypeDefinition(repositoryId, ntd);
        typeManager.refreshTypes();

        // Sort
        return sortPropertyDefinitions(repositoryId, updated, type);
    }

    private NemakiTypeDefinition setNemakiTypeDefinitionAttributes(String repositoryId,
            TypeDefinition typeDefinition) {
        NemakiTypeDefinition ntd = new NemakiTypeDefinition();

        // To avoid the conflict of typeId, add suffix
        if (typeManager.getTypeById(repositoryId, typeDefinition.getId()) == null) {
            ntd.setTypeId(typeDefinition.getId());
        } else {
            ntd.setTypeId(typeDefinition.getId() + "_" + String.valueOf(System.currentTimeMillis()));
        }
        ntd.setLocalName(typeDefinition.getLocalName());
        ntd.setLocalNameSpace(typeDefinition.getLocalNamespace());
        ntd.setQueryName(typeDefinition.getQueryName());
        ntd.setDisplayName(typeDefinition.getDisplayName());
        ntd.setBaseId(typeDefinition.getBaseTypeId());
        ntd.setParentId(typeDefinition.getParentTypeId());
        ntd.setDescription(typeDefinition.getDescription());
        ntd.setCreatable(typeDefinition.isCreatable());
        ntd.setFilable(typeDefinition.isFileable());
        ntd.setQueryable(typeDefinition.isQueryable());
        ntd.setControllablePolicy(typeDefinition.isControllablePolicy());
        ntd.setControllableACL(typeDefinition.isControllableAcl());
        ntd.setFulltextIndexed(typeDefinition.isFulltextIndexed());
        ntd.setIncludedInSupertypeQuery(typeDefinition.isIncludedInSupertypeQuery());
        TypeMutability typeMutability = typeDefinition.getTypeMutability();
        if (typeMutability != null) {
            ntd.setTypeMutabilityCreate(typeMutability.canCreate());
            ntd.setTypeMutabilityDelete(typeMutability.canDelete());
            ntd.setTypeMutabilityUpdate(typeMutability.canUpdate());
        } else {
            // These default values are repository-specific.
            ntd.setTypeMutabilityCreate(true);
            ntd.setTypeMutabilityDelete(true);
            ntd.setTypeMutabilityUpdate(true);
        }

        //specific to DocumentTypeDefinition
        if (typeDefinition instanceof DocumentTypeDefinition) {
            DocumentTypeDefinition dtdf = (DocumentTypeDefinition) typeDefinition;
            ntd.setVersionable(dtdf.isVersionable());
            ntd.setContentStreamAllowed(dtdf.getContentStreamAllowed());
        }

        return ntd;
    }

    private TypeDefinition sortPropertyDefinitions(String repositoryId, NemakiTypeDefinition nemakiTypeDefinition,
            TypeDefinition criterion) {
        AbstractTypeDefinition tdf = typeManager.buildTypeDefinitionFromDB(repositoryId, nemakiTypeDefinition);
        Map<String, PropertyDefinition<?>> propDefs = tdf.getPropertyDefinitions();

        LinkedHashMap<String, PropertyDefinition<?>> map = new LinkedHashMap<String, PropertyDefinition<?>>();
        LinkedHashMap<String, PropertyDefinition<?>> sorted = new LinkedHashMap<String, PropertyDefinition<?>>();
        if (MapUtils.isNotEmpty(criterion.getPropertyDefinitions())) {
            // Not updated property definitions
            for (Entry<String, PropertyDefinition<?>> propDef : propDefs.entrySet()) {
                if (!criterion.getPropertyDefinitions().containsKey(propDef.getKey())) {
                    map.put(propDef.getKey(), propDef.getValue());
                }
            }

            // Sorted updated property definitions
            for (Entry<String, PropertyDefinition<?>> entry : criterion.getPropertyDefinitions().entrySet()) {
                sorted.put(entry.getKey(), entry.getValue());
            }

            // Merge
            for (Entry<String, PropertyDefinition<?>> entry : sorted.entrySet()) {
                map.put(entry.getKey(), entry.getValue());
            }
            tdf.setPropertyDefinitions(map);
        }

        return tdf;
    }

    /**
     * Sets CMIS optional capabilities for Nemaki repository.
     */
    @Override
    public void afterPropertiesSet() throws Exception {
    }

    public void setRepositoryInfoMap(RepositoryInfoMap repositoryInfoMap) {
        this.repositoryInfoMap = repositoryInfoMap;
    }

    public void setTypeManager(TypeManager typeManager) {
        this.typeManager = typeManager;
    }

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

    public void setTypeService(TypeService typeService) {
        this.typeService = typeService;
    }

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