| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.chemistry.opencmis.inmemory; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| |
| 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.exceptions.CmisNotSupportedException; |
| import org.apache.chemistry.opencmis.commons.impl.dataobjects.AbstractPropertyDefinition; |
| import org.apache.chemistry.opencmis.commons.impl.dataobjects.TypeDefinitionContainerImpl; |
| import org.apache.chemistry.opencmis.inmemory.types.DocumentTypeCreationHelper; |
| import org.apache.chemistry.opencmis.inmemory.types.TypeUtil; |
| import org.apache.chemistry.opencmis.server.support.TypeManager; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * Class that manages a type system for a repository types can be added, the |
| * inheritance can be managed and type can be retrieved for a given type id. |
| */ |
| public class TypeManagerImpl implements TypeManager { |
| |
| private static final Logger LOG = LoggerFactory.getLogger(TypeManagerImpl.class.getName()); |
| /** |
| * map from repository id to a types map. |
| */ |
| private final Map<String, TypeDefinitionContainer> fTypesMap = new HashMap<String, TypeDefinitionContainer>(); |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.apache.chemistry.opencmis.inmemory.TypeManager#getTypeById(java.lang |
| * .String) |
| */ |
| @Override |
| public TypeDefinitionContainer getTypeById(String typeId) { |
| return fTypesMap.get(typeId); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.apache.chemistry.opencmis.inmemory.TypeManager#getTypeByQueryName |
| * (java.lang.String) |
| */ |
| @Override |
| public TypeDefinition getTypeByQueryName(String typeQueryName) { |
| for (Entry<String, TypeDefinitionContainer> entry : fTypesMap.entrySet()) { |
| if (entry.getValue().getTypeDefinition().getQueryName().equals(typeQueryName)) { |
| return entry.getValue().getTypeDefinition(); |
| } |
| } |
| return null; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.apache.chemistry.opencmis.inmemory.TypeManager#getTypeDefinitionList |
| * () |
| */ |
| @Override |
| public Collection<TypeDefinitionContainer> getTypeDefinitionList() { |
| return Collections.unmodifiableCollection(fTypesMap.values()); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.chemistry.opencmis.inmemory.TypeManager#getRootTypes() |
| */ |
| @Override |
| public List<TypeDefinitionContainer> getRootTypes() { |
| // just take first repository |
| List<TypeDefinitionContainer> rootTypes = new ArrayList<TypeDefinitionContainer>(); |
| |
| for (TypeDefinitionContainer type : fTypesMap.values()) { |
| if (isRootType(type)) { |
| rootTypes.add(type); |
| } |
| } |
| |
| return rootTypes; |
| } |
| |
| /** |
| * Initialize the type system with the given types. This list must not |
| * contain the CMIS default types. The default type are always contained by |
| * default. |
| * |
| * @param typesList |
| * list of types to add to the repository |
| * |
| * @param createCmisDefaultTypes |
| * indicates if CMIS base types should be added to list |
| */ |
| public void initTypeSystem(List<TypeDefinition> typesList, boolean createCmisDefaultTypes) { |
| |
| if (createCmisDefaultTypes) { |
| createCmisDefaultTypes(); |
| } |
| |
| // merge all types from the list and build the correct hierachy with |
| // children and property lists |
| if (null != typesList) { |
| for (TypeDefinition typeDef : typesList) { |
| addTypeDefinition(typeDef, true); |
| } |
| } |
| |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.apache.chemistry.opencmis.inmemory.storedobj.api.TypeManagerCreatable |
| * #addTypeDefinition(org.apache.chemistry.opencmis.commons.definitions. |
| * TypeDefinition, boolean) |
| */ |
| @Override |
| public void addTypeDefinition(TypeDefinition cmisType, boolean addInheritedProperties) { |
| |
| LOG.info("Adding type definition with name " + cmisType.getLocalName() + " and id " + cmisType.getId() |
| + " to repository."); |
| TypeDefinitionContainerImpl typeContainer = new TypeDefinitionContainerImpl(cmisType); |
| |
| if (null != cmisType.getParentTypeId()) { |
| // add new type to children of parent types |
| TypeDefinitionContainer parentTypeContainer = fTypesMap.get(cmisType.getParentTypeId()); |
| parentTypeContainer.getChildren().add(typeContainer); |
| |
| if (addInheritedProperties) { |
| // recursively add inherited properties |
| Map<String, PropertyDefinition<?>> propDefs = typeContainer.getTypeDefinition() |
| .getPropertyDefinitions(); |
| addInheritedProperties(propDefs, parentTypeContainer.getTypeDefinition()); |
| } |
| } |
| // add type to type map |
| fTypesMap.put(cmisType.getId(), typeContainer); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.apache.chemistry.opencmis.inmemory.storedobj.api.TypeManagerCreatable |
| * #updateTypeDefinition(org.apache.chemistry.opencmis.commons.definitions. |
| * TypeDefinition) |
| */ |
| @Override |
| public void updateTypeDefinition(TypeDefinition typeDefinition) { |
| throw new CmisNotSupportedException("updating a type definition is not supported."); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.apache.chemistry.opencmis.inmemory.storedobj.api.TypeManagerCreatable |
| * #deleteTypeDefinition(java.lang.String) |
| */ |
| @Override |
| public void deleteTypeDefinition(String typeId) { |
| TypeDefinitionContainer typeDef = fTypesMap.remove(typeId); |
| // remove type from children of parent types |
| TypeDefinitionContainer parentTypeContainer = fTypesMap.get(typeDef.getTypeDefinition().getParentTypeId()); |
| parentTypeContainer.getChildren().remove(typeDef); |
| fTypesMap.remove(typeId); |
| } |
| |
| /** |
| * Remove all types from the type system. After this call only the default |
| * CMIS types are present in the type system. Use this method with care, its |
| * mainly intended for unit tests |
| * |
| * @param repositoryId |
| */ |
| public void clearTypeSystem() { |
| fTypesMap.clear(); |
| createCmisDefaultTypes(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.apache.chemistry.opencmis.inmemory.TypeManager#getPropertyIdForQueryName |
| * (org.apache.chemistry.opencmis.commons.definitions.TypeDefinition, |
| * java.lang.String) |
| */ |
| @Override |
| public String getPropertyIdForQueryName(TypeDefinition typeDefinition, String propQueryName) { |
| for (PropertyDefinition<?> pd : typeDefinition.getPropertyDefinitions().values()) { |
| if (pd.getQueryName().equals(propQueryName)) { |
| return pd.getId(); |
| } |
| } |
| return null; |
| } |
| |
| private void addInheritedProperties(Map<String, PropertyDefinition<?>> propDefs, TypeDefinition typeDefinition) { |
| |
| if (null == typeDefinition) { |
| return; |
| } |
| |
| if (null != typeDefinition.getPropertyDefinitions()) { |
| addInheritedPropertyDefinitions(propDefs, typeDefinition.getPropertyDefinitions()); |
| } |
| |
| TypeDefinitionContainer parentTypeContainer = fTypesMap.get(typeDefinition.getParentTypeId()); |
| TypeDefinition parentType = (null == parentTypeContainer ? null : parentTypeContainer.getTypeDefinition()); |
| addInheritedProperties(propDefs, parentType); |
| } |
| |
| private static void addInheritedPropertyDefinitions(Map<String, PropertyDefinition<?>> propDefs, |
| Map<String, PropertyDefinition<?>> superPropDefs) { |
| |
| for (Entry<String, PropertyDefinition<?>> superProp : superPropDefs.entrySet()) { |
| PropertyDefinition<?> superPropDef = superProp.getValue(); |
| PropertyDefinition<?> clone = clonePropertyDefinition(superPropDef); |
| ((AbstractPropertyDefinition<?>) clone).setIsInherited(true); |
| propDefs.put(superProp.getKey(), clone); |
| } |
| } |
| |
| private void createCmisDefaultTypes() { |
| List<TypeDefinition> typesList = DocumentTypeCreationHelper.createDefaultTypes(); |
| for (TypeDefinition typeDef : typesList) { |
| TypeDefinitionContainerImpl typeContainer = new TypeDefinitionContainerImpl(typeDef); |
| fTypesMap.put(typeDef.getId(), typeContainer); |
| } |
| } |
| |
| private static boolean isRootType(TypeDefinitionContainer c) { |
| return (c.getTypeDefinition().getId().equals(c.getTypeDefinition().getBaseTypeId().value())); |
| } |
| |
| private static PropertyDefinition<?> clonePropertyDefinition(PropertyDefinition<?> src) { |
| PropertyDefinition<?> clone = TypeUtil.clonePropertyDefinition(src); |
| return clone; |
| } |
| |
| } |