Java tutorial
/* * 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.opencms.cmis; import org.opencms.file.CmsObject; import org.opencms.file.CmsPropertyDefinition; import org.opencms.main.CmsException; import org.opencms.main.CmsLog; import org.opencms.relations.CmsRelationType; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.chemistry.opencmis.commons.PropertyIds; 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.enums.BaseTypeId; import org.apache.chemistry.opencmis.commons.enums.Cardinality; import org.apache.chemistry.opencmis.commons.enums.ContentStreamAllowed; import org.apache.chemistry.opencmis.commons.enums.PropertyType; import org.apache.chemistry.opencmis.commons.enums.Updatability; import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException; import org.apache.chemistry.opencmis.commons.impl.WSConverter; import org.apache.chemistry.opencmis.commons.impl.dataobjects.AbstractPropertyDefinition; import org.apache.chemistry.opencmis.commons.impl.dataobjects.AbstractTypeDefinition; import org.apache.chemistry.opencmis.commons.impl.dataobjects.DocumentTypeDefinitionImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.FolderTypeDefinitionImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyBooleanDefinitionImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDateTimeDefinitionImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDecimalDefinitionImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyHtmlDefinitionImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIdDefinitionImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIntegerDefinitionImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringDefinitionImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyUriDefinitionImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.RelationshipTypeDefinitionImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.TypeDefinitionContainerImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.TypeDefinitionListImpl; import org.apache.commons.logging.Log; /** * This class keeps track of all the types which should be available for a {@link I_CmsCmisRepository}. */ public class CmsCmisTypeManager { /** CMIS type id for documents. */ public static final String DOCUMENT_TYPE_ID = BaseTypeId.CMIS_DOCUMENT.value(); /** CMIS type id for folders. */ public static final String FOLDER_TYPE_ID = BaseTypeId.CMIS_FOLDER.value(); /** Prefix for inherited properties. */ public static final String INHERITED_PREFIX = "opencms-inherited:"; /** CMIS type id for policies. */ public static final String POLICY_TYPE_ID = BaseTypeId.CMIS_POLICY.value(); /** The prefix used for normal OpenCms resource properties. */ public static final String PROPERTY_PREFIX = "opencms:"; /** Prefix for dynamic properties. */ public static final String PROPERTY_PREFIX_DYNAMIC = "opencms-dynamic:"; /** The prefix for special properties. */ public static final String PROPERTY_PREFIX_SPECIAL = "opencms-special:"; /** The name of the propery containing the resource type name. */ public static final String PROPERTY_RESOURCE_TYPE = PROPERTY_PREFIX_SPECIAL + "resource-type"; /** CMIS type id for relationships. */ public static final String RELATIONSHIP_TYPE_ID = BaseTypeId.CMIS_RELATIONSHIP.value(); /** Need to refresh property data after this time. */ public static final long UPDATE_INTERVAL = 1000 * 60 * 5; /** The logger instance for this class. */ static final Log LOG = CmsLog.getLog(CmsCmisTypeManager.class); /** The namespace used for properties. */ private static final String NAMESPACE = "http://opencms.org/opencms-cmis"; /** The admin CMS context. */ private CmsObject m_adminCms; /** The list of OpenCms property definitions. */ private List<CmsPropertyDefinition> m_cmsPropertyDefinitions; /** The last update time. */ private long m_lastUpdate; /** List of dynamic property providers. */ private List<I_CmsPropertyProvider> m_propertyProviders = new ArrayList<I_CmsPropertyProvider>(); /** The internal list of type definitions. */ private List<TypeDefinitionContainer> m_typeList; /** The internal map of type definitions. */ private Map<String, TypeDefinitionContainerImpl> m_types; /** * Creates a new type manager instance.<p> * * @param adminCms a CMS context with admin privileges * @param propertyProviders list which will be filled with property providers * * @throws CmsException if something goes wrong */ public CmsCmisTypeManager(CmsObject adminCms, List<I_CmsPropertyProvider> propertyProviders) throws CmsException { m_adminCms = adminCms; m_propertyProviders = propertyProviders; setup(); } /** * Adds the base CMIS property definitions common to folders and documents.<p> * * @param type the type definition to which the property definitions should be added */ private static void addBasePropertyDefinitions(AbstractTypeDefinition type) { type.addPropertyDefinition(createPropDef(PropertyIds.BASE_TYPE_ID, "Base Type Id", "Base Type Id", PropertyType.ID, Cardinality.SINGLE, Updatability.READONLY, false, false)); type.addPropertyDefinition(createPropDef(PropertyIds.OBJECT_ID, "Object Id", "Object Id", PropertyType.ID, Cardinality.SINGLE, Updatability.READONLY, false, false)); type.addPropertyDefinition(createPropDef(PropertyIds.OBJECT_TYPE_ID, "Type Id", "Type Id", PropertyType.ID, Cardinality.SINGLE, Updatability.ONCREATE, false, true)); type.addPropertyDefinition(createPropDef(PropertyIds.NAME, "Name", "Name", PropertyType.STRING, Cardinality.SINGLE, Updatability.READWRITE, false, true)); type.addPropertyDefinition(queryableAndOrderable(createPropDef(PropertyIds.CREATED_BY, "Created By", "Created By", PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false))); type.addPropertyDefinition(queryableAndOrderable(createPropDef(PropertyIds.CREATION_DATE, "Creation Date", "Creation Date", PropertyType.DATETIME, Cardinality.SINGLE, Updatability.READONLY, false, false))); type.addPropertyDefinition(queryableAndOrderable( createPropDef(PropertyIds.LAST_MODIFIED_BY, "Last Modified By", "Last Modified By", PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false))); type.addPropertyDefinition(queryableAndOrderable(createPropDef(PropertyIds.LAST_MODIFICATION_DATE, "Last Modification Date", "Last Modification Date", PropertyType.DATETIME, Cardinality.SINGLE, Updatability.READONLY, false, false))); type.addPropertyDefinition(createPropDef(PropertyIds.CHANGE_TOKEN, "Change Token", "Change Token", PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false)); } /** * Adds CMIS property definitions for documents.<p> * * @param type the document type */ private static void addDocumentPropertyDefinitions(DocumentTypeDefinitionImpl type) { type.addPropertyDefinition(createPropDef(PropertyIds.IS_IMMUTABLE, "Is Immutable", "Is Immutable", PropertyType.BOOLEAN, Cardinality.SINGLE, Updatability.READONLY, false, false)); type.addPropertyDefinition( createPropDef(PropertyIds.IS_LATEST_VERSION, "Is Latest Version", "Is Latest Version", PropertyType.BOOLEAN, Cardinality.SINGLE, Updatability.READONLY, false, false)); type.addPropertyDefinition(createPropDef(PropertyIds.IS_MAJOR_VERSION, "Is Major Version", "Is Major Version", PropertyType.BOOLEAN, Cardinality.SINGLE, Updatability.READONLY, false, false)); type.addPropertyDefinition(createPropDef(PropertyIds.IS_LATEST_MAJOR_VERSION, "Is Latest Major Version", "Is Latest Major Version", PropertyType.BOOLEAN, Cardinality.SINGLE, Updatability.READONLY, false, false)); type.addPropertyDefinition(createPropDef(PropertyIds.VERSION_LABEL, "Version Label", "Version Label", PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false)); type.addPropertyDefinition(createPropDef(PropertyIds.VERSION_SERIES_ID, "Version Series Id", "Version Series Id", PropertyType.ID, Cardinality.SINGLE, Updatability.READONLY, false, false)); type.addPropertyDefinition(createPropDef(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT, "Is Verison Series Checked Out", "Is Verison Series Checked Out", PropertyType.BOOLEAN, Cardinality.SINGLE, Updatability.READONLY, false, false)); type.addPropertyDefinition(createPropDef(PropertyIds.VERSION_SERIES_CHECKED_OUT_ID, "Version Series Checked Out Id", "Version Series Checked Out Id", PropertyType.ID, Cardinality.SINGLE, Updatability.READONLY, false, false)); type.addPropertyDefinition(createPropDef(PropertyIds.VERSION_SERIES_CHECKED_OUT_BY, "Version Series Checked Out By", "Version Series Checked Out By", PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false)); type.addPropertyDefinition(createPropDef(PropertyIds.CHECKIN_COMMENT, "Checkin Comment", "Checkin Comment", PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false)); type.addPropertyDefinition( createPropDef(PropertyIds.CONTENT_STREAM_LENGTH, "Content Stream Length", "Content Stream Length", PropertyType.INTEGER, Cardinality.SINGLE, Updatability.READONLY, false, false)); type.addPropertyDefinition(createPropDef(PropertyIds.CONTENT_STREAM_MIME_TYPE, "MIME Type", "MIME Type", PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false)); type.addPropertyDefinition(createPropDef(PropertyIds.CONTENT_STREAM_FILE_NAME, "Filename", "Filename", PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false)); type.addPropertyDefinition(createPropDef(PropertyIds.CONTENT_STREAM_ID, "Content Stream Id", "Content Stream Id", PropertyType.ID, Cardinality.SINGLE, Updatability.READONLY, false, false)); } /** * Adds folder specific CMIS property definitions.<p> * * @param type the folder type */ private static void addFolderPropertyDefinitions(FolderTypeDefinitionImpl type) { type.addPropertyDefinition(createPropDef(PropertyIds.PARENT_ID, "Parent Id", "Parent Id", PropertyType.ID, Cardinality.SINGLE, Updatability.READONLY, false, false)); type.addPropertyDefinition(createPropDef(PropertyIds.ALLOWED_CHILD_OBJECT_TYPE_IDS, "Allowed Child Object Type Ids", "Allowed Child Object Type Ids", PropertyType.ID, Cardinality.MULTI, Updatability.READONLY, false, false)); type.addPropertyDefinition(createPropDef(PropertyIds.PATH, "Path", "Path", PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false)); } /** * Helper method to add the property definitions specific to relationship types.<p> * * @param type the type definition to which the property definitions should be added */ private static void addRelationPropertyDefinitions(RelationshipTypeDefinitionImpl type) { type.addPropertyDefinition(createPropDef(PropertyIds.SOURCE_ID, "Source", "Source", PropertyType.ID, Cardinality.SINGLE, Updatability.ONCREATE, false, true)); type.addPropertyDefinition(createPropDef(PropertyIds.TARGET_ID, "Target", "Target", PropertyType.ID, Cardinality.SINGLE, Updatability.ONCREATE, false, true)); } /** * Copies a type definition.<p> * * @param type the type definition to copy * * @return the copied type definition */ private static TypeDefinition copyTypeDefintion(TypeDefinition type) { return WSConverter.convert(WSConverter.convert(type)); } /** * Creates a property definition.<p> * * @param id the property definition id * @param displayName the property display name * @param description the property description * @param datatype the property type * @param cardinality the property cardinality * @param updateability the property updatability * @param inherited the property inheritance status * @param required true true if the property is required * * @return the property definition */ private static AbstractPropertyDefinition<?> createPropDef(String id, String displayName, String description, PropertyType datatype, Cardinality cardinality, Updatability updateability, boolean inherited, boolean required) { AbstractPropertyDefinition<?> result = null; switch (datatype) { case BOOLEAN: result = new PropertyBooleanDefinitionImpl(); break; case DATETIME: result = new PropertyDateTimeDefinitionImpl(); break; case DECIMAL: result = new PropertyDecimalDefinitionImpl(); break; case HTML: result = new PropertyHtmlDefinitionImpl(); break; case ID: result = new PropertyIdDefinitionImpl(); break; case INTEGER: result = new PropertyIntegerDefinitionImpl(); break; case STRING: result = new PropertyStringDefinitionImpl(); break; case URI: result = new PropertyUriDefinitionImpl(); break; default: throw new RuntimeException("Unknown datatype! Spec change?"); } result.setId(id); result.setLocalName(id); result.setDisplayName(displayName); result.setDescription(description); result.setPropertyType(datatype); result.setCardinality(cardinality); result.setUpdatability(updateability); result.setIsInherited(Boolean.valueOf(inherited)); result.setIsRequired(Boolean.valueOf(required)); result.setIsQueryable(Boolean.FALSE); result.setIsOrderable(Boolean.FALSE); result.setQueryName(id); return result; } /** * Helper method to make a property definition queryable and orderable.<p> * * @param propDef the property definition * * @return the modified property definition */ private static AbstractPropertyDefinition<?> queryableAndOrderable(AbstractPropertyDefinition<?> propDef) { propDef.setIsQueryable(Boolean.TRUE); propDef.setIsOrderable(Boolean.TRUE); return propDef; } /** * Gets a list of names of OpenCms property definitions.<p> * * @return the list of OpenCms property names */ public List<String> getCmsPropertyNames() { refresh(); List<String> result = new ArrayList<String>(); for (CmsPropertyDefinition propDef : m_cmsPropertyDefinitions) { result.add(propDef.getName()); } return result; } /** * Gets the property provider for a given key.<p> * * @param key the property nme * * @return the property provider for the given name, or null if there isn't any */ public I_CmsPropertyProvider getPropertyProvider(String key) { if (key.startsWith(PROPERTY_PREFIX_DYNAMIC)) { key = key.substring(PROPERTY_PREFIX_DYNAMIC.length()); } for (I_CmsPropertyProvider provider : m_propertyProviders) { if (provider.getName().equals(key)) { return provider; } } return null; } /** * Gets the list of all property providers.<p> * * @return the list of property providers */ public List<I_CmsPropertyProvider> getPropertyProviders() { return Collections.unmodifiableList(m_propertyProviders); } /** * Gets a type definition by id.<p> * * @param typeId the type id * @return the type definition */ public TypeDefinition getType(String typeId) { refresh(); TypeDefinitionContainer tc = m_types.get(typeId); if (tc == null) { return null; } return tc.getTypeDefinition(); } /** * Collects the children of a type.<p> * * @param typeId the id of the type * @param includePropertyDefinitions true if the property definitions should be included * @param maxItems the maximum number of items to return * @param skipCount the number of items to skip * * @return the children of the type */ public TypeDefinitionList getTypeChildren( String typeId, boolean includePropertyDefinitions, BigInteger maxItems, BigInteger skipCount) { refresh(); TypeDefinitionListImpl result = new TypeDefinitionListImpl(new ArrayList<TypeDefinition>()); int skip = (skipCount == null ? 0 : skipCount.intValue()); if (skip < 0) { skip = 0; } int max = (maxItems == null ? Integer.MAX_VALUE : maxItems.intValue()); if (max < 1) { return result; } if (typeId == null) { if (skip < 1) { result.getList().add(copyTypeDefintion(m_types.get(FOLDER_TYPE_ID).getTypeDefinition())); max--; } if ((skip < 2) && (max > 0)) { result.getList().add(copyTypeDefintion(m_types.get(DOCUMENT_TYPE_ID).getTypeDefinition())); max--; } result.setHasMoreItems(Boolean.valueOf((result.getList().size() + skip) < 2)); result.setNumItems(BigInteger.valueOf(2)); } else { TypeDefinitionContainer tc = m_types.get(typeId); if ((tc == null) || (tc.getChildren() == null)) { return result; } for (TypeDefinitionContainer child : tc.getChildren()) { if (skip > 0) { skip--; continue; } result.getList().add(copyTypeDefintion(child.getTypeDefinition())); max--; if (max == 0) { break; } } result.setHasMoreItems(Boolean.valueOf((result.getList().size() + skip) < tc.getChildren().size())); result.setNumItems(BigInteger.valueOf(tc.getChildren().size())); } if (!includePropertyDefinitions) { for (TypeDefinition type : result.getList()) { type.getPropertyDefinitions().clear(); } } return result; } /** * Gets the type definition for a given id in the given call context.<p> * * @param typeId the type id * * @return the matching type definition */ public TypeDefinition getTypeDefinition(String typeId) { refresh(); TypeDefinitionContainer tc = m_types.get(typeId); if (tc == null) { throw new CmisObjectNotFoundException("Type '" + typeId + "' is unknown!"); } return copyTypeDefintion(tc.getTypeDefinition()); } /** * Gets the descendants of a type.<p> * * @param typeId the parent type id * @param depth the depth up to which the descendant types should be collected * @param includePropertyDefinitions true if the property definitions should be included * * @return the descendants of the type */ public List<TypeDefinitionContainer> getTypeDescendants( String typeId, BigInteger depth, boolean includePropertyDefinitions) { refresh(); List<TypeDefinitionContainer> result = new ArrayList<TypeDefinitionContainer>(); // check depth int d = (depth == null ? -1 : depth.intValue()); if (d == 0) { throw new CmisInvalidArgumentException("Depth must not be 0!"); } if (typeId == null) { result.add(getTypeDescendants(d, m_types.get(FOLDER_TYPE_ID), includePropertyDefinitions)); result.add(getTypeDescendants(d, m_types.get(DOCUMENT_TYPE_ID), includePropertyDefinitions)); result.add(getTypeDescendants(d, m_types.get(RELATIONSHIP_TYPE_ID), includePropertyDefinitions)); } else { TypeDefinitionContainer tc = m_types.get(typeId); if (tc != null) { result.add(getTypeDescendants(d, tc, includePropertyDefinitions)); } } return result; } /** * Creates the CMIS property definition for an OpenCms resource property definition.<p> * * @param cmsDef the OpenCms property definition * * @return the CMIS property definition */ PropertyDefinition<?> createOpenCmsPropertyDefinition(CmsPropertyDefinition cmsDef) { return createPropDef(PROPERTY_PREFIX + cmsDef.getName(), cmsDef.getName(), cmsDef.getName(), PropertyType.STRING, Cardinality.SINGLE, Updatability.READWRITE, false, false); } /** * Creates the base types. * * @throws CmsException if something goes wrong */ void setup() throws CmsException { m_types = new HashMap<String, TypeDefinitionContainerImpl>(); m_typeList = new ArrayList<TypeDefinitionContainer>(); m_cmsPropertyDefinitions = m_adminCms.readAllPropertyDefinitions(); // folder type FolderTypeDefinitionImpl folderType = new FolderTypeDefinitionImpl(); folderType.setBaseTypeId(BaseTypeId.CMIS_FOLDER); folderType.setIsControllableAcl(Boolean.TRUE); folderType.setIsControllablePolicy(Boolean.FALSE); folderType.setIsCreatable(Boolean.TRUE); folderType.setDescription("Folder"); folderType.setDisplayName("Folder"); folderType.setIsFileable(Boolean.TRUE); folderType.setIsFulltextIndexed(Boolean.FALSE); folderType.setIsIncludedInSupertypeQuery(Boolean.TRUE); folderType.setLocalName("Folder"); folderType.setLocalNamespace(NAMESPACE); folderType.setIsQueryable(Boolean.TRUE); folderType.setQueryName("cmis:folder"); folderType.setId(FOLDER_TYPE_ID); addBasePropertyDefinitions(folderType); addFolderPropertyDefinitions(folderType); addCmsPropertyDefinitions(folderType); addProviderPropertyDefinitions(folderType); addTypeInternal(folderType); // document type DocumentTypeDefinitionImpl documentType = new DocumentTypeDefinitionImpl(); documentType.setBaseTypeId(BaseTypeId.CMIS_DOCUMENT); documentType.setIsControllableAcl(Boolean.TRUE); documentType.setIsControllablePolicy(Boolean.FALSE); documentType.setIsCreatable(Boolean.TRUE); documentType.setDescription("Document"); documentType.setDisplayName("Document"); documentType.setIsFileable(Boolean.TRUE); documentType.setIsFulltextIndexed(Boolean.FALSE); documentType.setIsIncludedInSupertypeQuery(Boolean.TRUE); documentType.setLocalName("Document"); documentType.setLocalNamespace(NAMESPACE); documentType.setIsQueryable(Boolean.TRUE); documentType.setQueryName("cmis:document"); documentType.setId(DOCUMENT_TYPE_ID); documentType.setIsVersionable(Boolean.FALSE); documentType.setContentStreamAllowed(ContentStreamAllowed.REQUIRED); addBasePropertyDefinitions(documentType); addDocumentPropertyDefinitions(documentType); addCmsPropertyDefinitions(documentType); addProviderPropertyDefinitions(documentType); addTypeInternal(documentType); // relationship types RelationshipTypeDefinitionImpl relationshipType = new RelationshipTypeDefinitionImpl(); relationshipType.setBaseTypeId(BaseTypeId.CMIS_RELATIONSHIP); relationshipType.setIsControllableAcl(Boolean.FALSE); relationshipType.setIsControllablePolicy(Boolean.FALSE); relationshipType.setIsCreatable(Boolean.FALSE); relationshipType.setDescription("Relationship"); relationshipType.setDisplayName("Relationship"); relationshipType.setIsFileable(Boolean.FALSE); relationshipType.setIsIncludedInSupertypeQuery(Boolean.TRUE); relationshipType.setLocalName("Relationship"); relationshipType.setLocalNamespace(NAMESPACE); relationshipType.setIsQueryable(Boolean.FALSE); relationshipType.setQueryName("cmis:relationship"); relationshipType.setId(RELATIONSHIP_TYPE_ID); List<String> typeList = new ArrayList<String>(); typeList.add("cmis:document"); typeList.add("cmis:folder"); relationshipType.setAllowedSourceTypes(typeList); relationshipType.setAllowedTargetTypes(typeList); addBasePropertyDefinitions(relationshipType); addRelationPropertyDefinitions(relationshipType); addTypeInternal(relationshipType); for (CmsRelationType relType : CmsRelationType.getAll()) { createRelationshipType(relType); } m_lastUpdate = System.currentTimeMillis(); } /** * Adds the CMIS property definitions corresponding to the OpenCms property definitions to a CMIS type definition.<p> * * @param type the type to which the property definitions should be added */ private void addCmsPropertyDefinitions(AbstractTypeDefinition type) { for (CmsPropertyDefinition propDef : m_cmsPropertyDefinitions) { type.addPropertyDefinition(createOpenCmsPropertyDefinition(propDef)); type.addPropertyDefinition( createPropDef(INHERITED_PREFIX + propDef.getName(), propDef.getName(), propDef.getName(), PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false)); } type.addPropertyDefinition(createPropDef(PROPERTY_RESOURCE_TYPE, "Resource type", "Resource type", PropertyType.STRING, Cardinality.SINGLE, Updatability.ONCREATE, false, true)); } /** * Helper method for adding property definitions for the dynamic properties.<p> * * @param type the type definition to which the properties should be added */ private void addProviderPropertyDefinitions(AbstractTypeDefinition type) { for (I_CmsPropertyProvider provider : m_propertyProviders) { type.addPropertyDefinition(createPropDef(PROPERTY_PREFIX_DYNAMIC + provider.getName(), provider.getName(), provider.getName(), PropertyType.STRING, Cardinality.SINGLE, provider.isWritable() ? Updatability.READWRITE : Updatability.READONLY, false, false)); } } /** * Adds a type to collection with inheriting base type properties. * * @param type the type definition to add * * @return true if the type definition was added */ private boolean addType(TypeDefinition type) { if (type == null) { return false; } if (type.getBaseTypeId() == null) { return false; } // find base type TypeDefinition baseType = null; if (type.getBaseTypeId() == BaseTypeId.CMIS_DOCUMENT) { baseType = copyTypeDefintion(m_types.get(DOCUMENT_TYPE_ID).getTypeDefinition()); } else if (type.getBaseTypeId() == BaseTypeId.CMIS_FOLDER) { baseType = copyTypeDefintion(m_types.get(FOLDER_TYPE_ID).getTypeDefinition()); } else if (type.getBaseTypeId() == BaseTypeId.CMIS_RELATIONSHIP) { baseType = copyTypeDefintion(m_types.get(RELATIONSHIP_TYPE_ID).getTypeDefinition()); } else if (type.getBaseTypeId() == BaseTypeId.CMIS_POLICY) { baseType = copyTypeDefintion(m_types.get(POLICY_TYPE_ID).getTypeDefinition()); } else { return false; } AbstractTypeDefinition newType = (AbstractTypeDefinition) copyTypeDefintion(type); // copy property definition for (PropertyDefinition<?> propDef : baseType.getPropertyDefinitions().values()) { ((AbstractPropertyDefinition<?>) propDef).setIsInherited(Boolean.TRUE); newType.addPropertyDefinition(propDef); } // add it addTypeInternal(newType); return true; } /** * Internal method which adds a new type, without adding any property definitions automatically.<p> * * @param type the type to add */ private void addTypeInternal(AbstractTypeDefinition type) { if (type == null) { return; } if (m_types.containsKey(type.getId())) { // can't overwrite a type return; } TypeDefinitionContainerImpl tc = new TypeDefinitionContainerImpl(); tc.setTypeDefinition(type); // add to parent if (type.getParentTypeId() != null) { TypeDefinitionContainerImpl tdc = m_types.get(type.getParentTypeId()); if (tdc != null) { if (tdc.getChildren() == null) { tdc.setChildren(new ArrayList<TypeDefinitionContainer>()); } tdc.getChildren().add(tc); } } m_types.put(type.getId(), tc); m_typeList.add(tc); } /** * Creates a CMIS relationship subtype for a given OpenCms relation type.<p> * * @param relType the OpenCms relation type */ private void createRelationshipType(CmsRelationType relType) { // relationship types RelationshipTypeDefinitionImpl relationshipType = new RelationshipTypeDefinitionImpl(); relationshipType.setBaseTypeId(BaseTypeId.CMIS_RELATIONSHIP); relationshipType.setParentTypeId(RELATIONSHIP_TYPE_ID); relationshipType.setIsControllableAcl(Boolean.FALSE); relationshipType.setIsControllablePolicy(Boolean.FALSE); relationshipType.setIsCreatable(Boolean.valueOf(!relType.isDefinedInContent())); relationshipType.setDescription(relType.getName()); relationshipType.setDisplayName(relType.getName()); relationshipType.setIsFileable(Boolean.FALSE); relationshipType.setIsIncludedInSupertypeQuery(Boolean.TRUE); relationshipType.setLocalName(relType.getName()); relationshipType.setLocalNamespace(NAMESPACE); relationshipType.setIsQueryable(Boolean.FALSE); String id = "opencms:" + relType.getName().toUpperCase(); relationshipType.setQueryName(id); relationshipType.setId(id); List<String> typeList = new ArrayList<String>(); typeList.add("cmis:document"); typeList.add("cmis:folder"); relationshipType.setAllowedSourceTypes(typeList); relationshipType.setAllowedTargetTypes(typeList); addType(relationshipType); } /** * Collects the descendants of a type.<p> * * @param depth the depth up to which the descendants should be collected * @param tc the parent type * @param includePropertyDefinitions true if the property definitions should be included * * @return the descendants of the type */ private TypeDefinitionContainer getTypeDescendants(int depth, TypeDefinitionContainer tc, boolean includePropertyDefinitions) { TypeDefinitionContainerImpl result = new TypeDefinitionContainerImpl(); TypeDefinition type = copyTypeDefintion(tc.getTypeDefinition()); if (!includePropertyDefinitions) { type.getPropertyDefinitions().clear(); } result.setTypeDefinition(type); if (depth != 0) { if (tc.getChildren() != null) { result.setChildren(new ArrayList<TypeDefinitionContainer>()); for (TypeDefinitionContainer tdc : tc.getChildren()) { result.getChildren() .add(getTypeDescendants(depth < 0 ? -1 : depth - 1, tdc, includePropertyDefinitions)); } } } return result; } /** * Refreshes the internal data if the last update was longer ago than the udpate interval.<p> */ private synchronized void refresh() { try { long now = System.currentTimeMillis(); if ((now - m_lastUpdate) > UPDATE_INTERVAL) { setup(); } } catch (CmsException e) { LOG.error(e.getLocalizedMessage(), e); } } }