CMIS Dictionary Refactor

- follows pattern of Alfresco Dictionary
- simplified and much reduced DictionaryService interface
- model now compiled and cached (no more lots of small continuous object creations)
- walk model via simple getters
- validated (no dangling references)
- fix up property inheritance
- fix up sub-types for all types
- implements strict mode only for now (i.e. doesn't go outside of CMIS doc, folder, rel and policy)
- abstract helper for building other CMIS dictionaries (e.g. mapping all types in Alfresco)

Alfresco Dictionary:
- add event for initialized or re-initialized

Fix up usage in CMIS REST, Web Services and query. Tests pass.

REST support for custom sub-types and properties now reliable as constrained by validated CMIS model.

TODO:
- hook property value accessors into CMIS Dictionary

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13768 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
David Caruana
2009-03-27 23:13:29 +00:00
parent df3e143e1c
commit 8fcebdc7cf
51 changed files with 2937 additions and 2095 deletions

View File

@@ -0,0 +1,381 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program 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 2
* of the License, or (at your option) any later version.
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.cmis.dictionary;
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.TreeMap;
import org.alfresco.cmis.CMISDataTypeEnum;
import org.alfresco.repo.dictionary.DictionaryDAO;
import org.alfresco.repo.dictionary.DictionaryListener;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.AbstractLifecycleBean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationEvent;
/**
* Common CMIS Dictionary Support including registry of Types.
*
* @author davidc
*/
public abstract class AbstractCMISDictionaryService extends AbstractLifecycleBean implements CMISDictionaryService, DictionaryListener
{
// Logger
protected static final Log logger = LogFactory.getLog(AbstractCMISDictionaryService.class);
// service dependencies
private DictionaryDAO dictionaryDAO;
protected CMISMapping cmisMapping;
protected DictionaryService dictionaryService;
/**
* Set the mapping service
*
* @param cmisMapping
*/
public void setCMISMapping(CMISMapping cmisMapping)
{
this.cmisMapping = cmisMapping;
}
/**
* Set the dictionary Service
*
* @param dictionaryService
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* Set the dictionary DAO
*
* @param dictionaryDAO
*/
public void setDictionaryDAO(DictionaryDAO dictionaryDAO)
{
this.dictionaryDAO = dictionaryDAO;
}
// TODO: Handle tenants
// TODO: read / write locks
private DictionaryRegistry registry;
/**
* CMIS Dictionary registry
*
* Index of CMIS Type Definitions
*/
/*package*/ class DictionaryRegistry
{
// Type Definitions Index
Map<QName, CMISObjectTypeDefinition> typeDefsByQName = new HashMap<QName, CMISObjectTypeDefinition>();
Map<QName, CMISObjectTypeDefinition> assocDefsByQName = new HashMap<QName, CMISObjectTypeDefinition>();
Map<CMISTypeId, CMISObjectTypeDefinition> objectDefsByTypeId = new HashMap<CMISTypeId, CMISObjectTypeDefinition>();
Map<CMISTypeId, CMISTypeDefinition> typeDefsByTypeId = new HashMap<CMISTypeId, CMISTypeDefinition>();
Map<String, CMISTypeDefinition> typeDefsByTable = new HashMap<String, CMISTypeDefinition>();
// Property Definitions Index
Map<String, CMISPropertyDefinition> propDefsByName = new HashMap<String, CMISPropertyDefinition>();
Map<QName, CMISPropertyDefinition> propDefsByQName = new HashMap<QName, CMISPropertyDefinition>();
Map<CMISPropertyId, CMISPropertyDefinition> propDefsByPropId = new HashMap<CMISPropertyId, CMISPropertyDefinition>();
/**
* Register Type Definition
*
* @param typeDefinition
*/
public void registerTypeDefinition(CMISObjectTypeDefinition typeDefinition)
{
QName typeQName = typeDefinition.getTypeId().getQName();
if (typeQName != null)
{
if (typeDefinition instanceof CMISRelationshipTypeDefinition)
{
assocDefsByQName.put(typeQName, typeDefinition);
}
else
{
typeDefsByQName.put(typeQName, typeDefinition);
}
}
objectDefsByTypeId.put(typeDefinition.getTypeId(), typeDefinition);
typeDefsByTypeId.put(typeDefinition.getTypeId(), typeDefinition);
typeDefsByTable.put(typeDefinition.getQueryName().toLowerCase(), typeDefinition);
}
/**
* Registry Property Definition
*
* @param propDef
*/
public void registerPropertyDefinition(CMISPropertyDefinition propDef)
{
propDefsByPropId.put(propDef.getPropertyId(), propDef);
propDefsByQName.put(propDef.getPropertyId().getQName(), propDef);
propDefsByName.put(propDef.getPropertyId().getName().toLowerCase(), propDef);
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("DictionaryRegistry[");
builder.append("Types=").append(typeDefsByTypeId.size()).append(", ");
builder.append("Properties=").append(propDefsByPropId.size());
builder.append("]");
return builder.toString();
}
}
/*
* (non-Javadoc)
* @see org.alfresco.cmis.dictionary.CMISDictionaryService#getTypeId(java.lang.String)
*/
public CMISTypeId getTypeId(String typeId)
{
return cmisMapping.getCmisTypeId(typeId);
}
/*
* (non-Javadoc)
* @see org.alfresco.cmis.dictionary.CMISDictionaryService#getTypeId(org.alfresco.service.namespace.QName, org.alfresco.cmis.dictionary.CMISScope)
*/
public CMISTypeId getTypeId(QName clazz, CMISScope matchingScope)
{
CMISTypeDefinition typeDef = null;
if (matchingScope != null && matchingScope == CMISScope.RELATIONSHIP)
{
typeDef = registry.assocDefsByQName.get(clazz);
}
else
{
typeDef = registry.typeDefsByQName.get(clazz);
}
CMISTypeDefinition matchingTypeDef = null;
if (matchingScope == null)
{
matchingTypeDef = typeDef;
}
else
{
if (typeDef != null && typeDef.getTypeId().getScope() == matchingScope)
{
matchingTypeDef = typeDef;
}
}
return matchingTypeDef == null ? null : matchingTypeDef.getTypeId();
}
/*
* (non-Javadoc)
* @see org.alfresco.cmis.dictionary.CMISDictionaryService#getTypeIdFromTable(java.lang.String)
*/
public CMISTypeId getTypeIdFromTable(String table)
{
CMISTypeDefinition typeDef = registry.typeDefsByTable.get(table.toLowerCase());
return (typeDef == null) ? null : typeDef.getTypeId();
}
/*
* (non-Javadoc)
* @see org.alfresco.cmis.dictionary.CMISDictionaryService#getType(org.alfresco.cmis.dictionary.CMISTypeId)
*/
public CMISTypeDefinition getType(CMISTypeId typeId)
{
return registry.objectDefsByTypeId.get(typeId);
}
/*
* (non-Javadoc)
* @see org.alfresco.cmis.dictionary.CMISDictionaryService#getAllTypes()
*/
public Collection<CMISTypeDefinition> getAllTypes()
{
return Collections.unmodifiableCollection(registry.typeDefsByTypeId.values());
}
/*
* (non-Javadoc)
* @see org.alfresco.cmis.dictionary.CMISDictionaryService#getProperty(org.alfresco.cmis.dictionary.CMISPropertyId)
*/
public CMISPropertyDefinition getProperty(CMISPropertyId propertyId)
{
return registry.propDefsByPropId.get(propertyId);
}
/*
* (non-Javadoc)
* @see org.alfresco.cmis.dictionary.CMISDictionaryService#getPropertyId(java.lang.String)
*/
public CMISPropertyId getPropertyId(String property)
{
CMISPropertyDefinition propDef = registry.propDefsByName.get(property.toLowerCase());
return (propDef == null) ? null : propDef.getPropertyId();
}
/*
* (non-Javadoc)
* @see org.alfresco.cmis.dictionary.CMISDictionaryService#getPropertyId(org.alfresco.service.namespace.QName)
*/
public CMISPropertyId getPropertyId(QName property)
{
CMISPropertyDefinition propDef = registry.propDefsByQName.get(property);
return (propDef == null) ? null : propDef.getPropertyId();
}
/*
* (non-Javadoc)
* @see org.alfresco.cmis.dictionary.CMISDictionaryService#getDataType(org.alfresco.service.namespace.QName)
*/
public CMISDataTypeEnum getDataType(QName dataType)
{
return cmisMapping.getDataType(dataType);
}
/**
* Factory for creating CMIS Definitions
*
* @param registry
*/
abstract protected void createDefinitions(DictionaryRegistry registry);
/**
* Dictionary Initialisation - creates a new registry
*/
private void init()
{
DictionaryRegistry registry = new DictionaryRegistry();
// phase 1: construct type definitions
createDefinitions(registry);
for (CMISObjectTypeDefinition objectTypeDef : registry.objectDefsByTypeId.values())
{
Map<CMISPropertyId, CMISPropertyDefinition> propDefs = objectTypeDef.createProperties(cmisMapping, dictionaryService);
for (CMISPropertyDefinition propDef : propDefs.values())
{
registry.registerPropertyDefinition(propDef);
}
objectTypeDef.createSubTypes(cmisMapping, dictionaryService);
}
// phase 2: link together
for (CMISObjectTypeDefinition objectTypeDef : registry.objectDefsByTypeId.values())
{
objectTypeDef.resolveDependencies(registry);
}
// phase 3: resolve inheritance
Map<Integer,List<CMISObjectTypeDefinition>> order = new TreeMap<Integer, List<CMISObjectTypeDefinition>>();
for (CMISObjectTypeDefinition typeDef : registry.objectDefsByTypeId.values())
{
// calculate class depth in hierarchy
int depth = 0;
CMISTypeDefinition parent = typeDef.getParentType();
while (parent != null)
{
depth = depth +1;
parent = parent.getParentType();
}
// map class to depth
List<CMISObjectTypeDefinition> classes = order.get(depth);
if (classes == null)
{
classes = new ArrayList<CMISObjectTypeDefinition>();
order.put(depth, classes);
}
classes.add(typeDef);
}
for (int depth = 0; depth < order.size(); depth++)
{
for (CMISObjectTypeDefinition typeDef : order.get(depth))
{
typeDef.resolveInheritance(registry);
}
}
// publish new registry
this.registry = registry;
if (logger.isDebugEnabled())
logger.debug("Initialized CMIS Dictionary. Types:" + registry.typeDefsByTypeId.size() + ", Properties:" + registry.propDefsByPropId.size());
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryListener#onInit()
*/
public void onDictionaryInit()
{
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.dictionary.DictionaryListener#afterInit()
*/
public void afterDictionaryInit()
{
init();
}
/*
* (non-Javadoc)
* @see org.alfresco.util.AbstractLifecycleBean#onBootstrap(org.springframework.context.ApplicationEvent)
*/
protected void onBootstrap(ApplicationEvent event)
{
afterDictionaryInit();
dictionaryDAO.register(this);
}
/*
* (non-Javadoc)
* @see org.alfresco.util.AbstractLifecycleBean#onShutdown(org.springframework.context.ApplicationEvent)
*/
protected void onShutdown(ApplicationEvent event)
{
}
}

View File

@@ -65,7 +65,7 @@ public abstract class BaseCMISTest extends TestCase
protected CMISMapping cmisMapping;
protected CMISDictionaryService cmisDictionaryService;
protected DictionaryService dictionaryService;
protected TransactionService transactionService;
@@ -103,7 +103,7 @@ public abstract class BaseCMISTest extends TestCase
serviceRegistry = (ServiceRegistry) ctx.getBean("ServiceRegistry");
cmisDictionaryService = (CMISDictionaryService) ctx.getBean("CMISDictionaryService");
cmisMapping = cmisDictionaryService.getCMISMapping();
cmisMapping = (CMISMapping) ctx.getBean("CMISMapping");
cmisPropertyService = (CMISPropertyService) ctx.getBean("CMISPropertyService");
cmisQueryService = (CMISQueryService) ctx.getBean("CMISQueryService");
cmisService = (CMISService) ctx.getBean("CMISService");

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program 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 2
* of the License, or (at your option) any later version.
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.cmis.dictionary;
import org.alfresco.model.ContentModel;
/**
* CMIS <-> Alfresco mappings
*
* @author andyh
*/
public interface CMISDictionaryModel
{
/**
* Type id for CMIS documents, from the spec.
*/
public static String DOCUMENT_OBJECT_TYPE = "Document";
/**
* Type is for CMIS folders, from the spec.
*/
public static String FOLDER_OBJECT_TYPE = "Folder";
/**
* Type Id for CMIS Relationships, from the spec.
*/
public static String RELATIONSHIP_OBJECT_TYPE = "Relationship";
/**
* Type Id for CMIS Policies, from the spec.
*/
public static String POLICY_OBJECT_TYPE = "Policy";
// TODO: spec issue - objectTypeEnum is lower cased - object type ids are repository specific in spec
public static CMISTypeId DOCUMENT_TYPE_ID = new CMISTypeId(CMISScope.DOCUMENT, DOCUMENT_OBJECT_TYPE.toLowerCase(), ContentModel.TYPE_CONTENT);
public static CMISTypeId FOLDER_TYPE_ID = new CMISTypeId(CMISScope.FOLDER, FOLDER_OBJECT_TYPE.toLowerCase(), ContentModel.TYPE_FOLDER);
public static CMISTypeId RELATIONSHIP_TYPE_ID = new CMISTypeId(CMISScope.RELATIONSHIP, RELATIONSHIP_OBJECT_TYPE.toLowerCase(), CMISMapping.RELATIONSHIP_QNAME);
public static CMISTypeId POLICY_TYPE_ID = new CMISTypeId(CMISScope.POLICY, POLICY_OBJECT_TYPE.toLowerCase(), CMISMapping.POLICY_QNAME);
// CMIS properties
public static String PROP_OBJECT_ID = "ObjectId";
public static String PROP_URI = "Uri";
public static String PROP_OBJECT_TYPE_ID = "ObjectTypeId";
public static String PROP_CREATED_BY = "CreatedBy";
public static String PROP_CREATION_DATE = "CreationDate";
public static String PROP_LAST_MODIFIED_BY = "LastModifiedBy";
public static String PROP_LAST_MODIFICATION_DATE = "LastModificationDate";
public static String PROP_CHANGE_TOKEN = "ChangeToken";
public static String PROP_NAME = "Name";
public static String PROP_IS_IMMUTABLE = "IsImmutable";
public static String PROP_IS_LATEST_VERSION = "IsLatestVersion";
public static String PROP_IS_MAJOR_VERSION = "IsMajorVersion";
public static String PROP_IS_LATEST_MAJOR_VERSION = "IsLatestMajorVersion";
public static String PROP_VERSION_LABEL = "VersionLabel";
public static String PROP_VERSION_SERIES_ID = "VersionSeriesId";
public static String PROP_IS_VERSION_SERIES_CHECKED_OUT = "IsVersionSeriesCheckedOut";
public static String PROP_VERSION_SERIES_CHECKED_OUT_BY = "VersionSeriesCheckedOutBy";
public static String PROP_VERSION_SERIES_CHECKED_OUT_ID = "VersionSeriesCheckedOutId";
public static String PROP_CHECKIN_COMMENT = "CheckinComment";
public static String PROP_CONTENT_STREAM_ALLOWED = "ContentStreamAllowed";
public static String PROP_CONTENT_STREAM_LENGTH = "ContentStreamLength";
public static String PROP_CONTENT_STREAM_MIME_TYPE = "ContentStreamMimeType";
public static String PROP_CONTENT_STREAM_FILENAME = "ContentStreamFilename";
public static String PROP_CONTENT_STREAM_URI = "ContentStreamUri";
public static String PROP_PARENT_ID = "ParentId";
public static String PROP_ALLOWED_CHILD_OBJECT_TYPE_IDS = "AllowedChildObjectTypeIds";
public static String PROP_SOURCE_ID = "SourceId";
public static String PROP_TARGET_ID = "TargetId";
}

View File

@@ -25,371 +25,97 @@
package org.alfresco.cmis.dictionary;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.cmis.CMISDataTypeEnum;
import org.alfresco.service.namespace.QName;
/**
* Service to query the CMIS meta model
*
* @author andyh
* @author davidc
*/
public class CMISDictionaryService
public interface CMISDictionaryService
{
private CMISMapping cmisMapping;
private DictionaryService dictionaryService;
private boolean strict = true;
/**
* Set the mapping service
*
* @param cmisMapping
*/
public void setCMISMapping(CMISMapping cmisMapping)
{
this.cmisMapping = cmisMapping;
}
/**
* @return cmis mapping service
*/
public CMISMapping getCMISMapping()
{
return cmisMapping;
}
/**
* Set the dictionary Service
*
* @param dictionaryService
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* Gets the dictionary service
*
* @return dictionaryService
*/
/* package */DictionaryService getDictionaryService()
{
return this.dictionaryService;
}
/**
* Is the service strict (CMIS types only)
*
* @return
*/
public boolean isStrict()
{
return strict;
}
/**
* Set strict mode. In strict mode only CMIS types and properties are returned
*
* @param strict
*/
public void setStrict(boolean strict)
{
this.strict = strict;
}
/**
* Get the all the object types ids TODO: Note there can be name collisions between types and associations. e.g.
* app:configurations
*
* @return
*/
public Collection<CMISTypeId> getAllObjectTypeIds()
{
Collection<QName> alfrescoTypeQNames;
Collection<QName> alfrescoAssociationQNames;
if (strict)
{
alfrescoTypeQNames = dictionaryService.getTypes(CMISMapping.CMIS_MODEL_QNAME);
alfrescoAssociationQNames = dictionaryService.getAssociations(CMISMapping.CMIS_MODEL_QNAME);
}
else
{
alfrescoTypeQNames = dictionaryService.getAllTypes();
alfrescoAssociationQNames = dictionaryService.getAllAssociations();
}
Collection<CMISTypeId> answer = new HashSet<CMISTypeId>(alfrescoTypeQNames.size() + alfrescoAssociationQNames.size());
for (QName typeQName : alfrescoTypeQNames)
{
if (cmisMapping.isValidCmisDocument(typeQName))
{
answer.add(cmisMapping.getCmisTypeId(CMISScope.DOCUMENT, typeQName));
}
else if (cmisMapping.isValidCmisFolder(typeQName))
{
answer.add(cmisMapping.getCmisTypeId(CMISScope.FOLDER, typeQName));
}
else if (typeQName.equals(CMISMapping.RELATIONSHIP_QNAME))
{
answer.add(cmisMapping.getCmisTypeId(CMISScope.RELATIONSHIP, typeQName));
}
// TODO: Policy
// For now, policies are not reported
}
for (QName associationName : alfrescoAssociationQNames)
{
if (cmisMapping.isValidCmisRelationship(associationName))
{
answer.add(cmisMapping.getCmisTypeId(CMISScope.RELATIONSHIP, associationName));
}
}
return answer;
}
/**
* Gets all the object type ids within a type hierarchy
*
* @param typeId
* @param descendants
* true => include all descendants, false => children only
* @return
*/
public Collection<CMISTypeId> getChildTypeIds(CMISTypeId typeId, boolean descendants)
{
switch (typeId.getScope())
{
case RELATIONSHIP:
if (typeId.equals(CMISMapping.RELATIONSHIP_TYPE_ID))
{
// all associations are sub-type of RELATIONSHIP_OBJECT_TYPE
// NOTE: ignore descendants
Collection<QName> alfrescoAssociationQNames = dictionaryService.getAllAssociations();
Collection<CMISTypeId> types = new HashSet<CMISTypeId>(alfrescoAssociationQNames.size());
for (QName associationName : alfrescoAssociationQNames)
{
if (cmisMapping.isValidCmisRelationship(associationName))
{
types.add(cmisMapping.getCmisTypeId(CMISScope.RELATIONSHIP, associationName));
}
}
return types;
}
else
{
return Collections.emptySet();
}
case DOCUMENT:
case FOLDER:
TypeDefinition typeDefinition = dictionaryService.getType(typeId.getQName());
if (typeDefinition != null)
{
if (cmisMapping.isValidCmisType(typeId.getQName()))
{
QName alfrescoQName = cmisMapping.getAlfrescoType(typeId.getQName());
Collection<QName> alfrescoTypeQNames = dictionaryService.getSubTypes(alfrescoQName, descendants);
Collection<CMISTypeId> types = new HashSet<CMISTypeId>(alfrescoTypeQNames.size());
for (QName typeQName : alfrescoTypeQNames)
{
CMISTypeId subTypeId = cmisMapping.getCmisTypeId(typeQName);
if (typeId != null)
{
types.add(subTypeId);
}
}
return types;
}
else
{
return Collections.emptySet();
}
}
else
{
return Collections.emptySet();
}
case POLICY:
// TODO: Policy
default:
return Collections.emptySet();
}
}
/**
* Get the object type definition TODO: Note there can be name collisions between types and associations. e.g.
* app:configurations Currently clashing types will give inconsistent behaviour
* Get Type Id
*
* @param typeId
* @return
*/
public CMISTypeDefinition getType(CMISTypeId typeId)
{
switch (typeId.getScope())
{
case RELATIONSHIP:
// Associations
if (cmisMapping.isValidCmisRelationship(typeId.getQName()))
{
return new CMISTypeDefinition(this, typeId);
}
else
{
return null;
}
case DOCUMENT:
case FOLDER:
TypeDefinition typeDefinition = dictionaryService.getType(typeId.getQName());
if (typeDefinition != null)
{
if (cmisMapping.isValidCmisType(typeId.getQName()))
{
return new CMISTypeDefinition(this, typeId);
}
else
{
return null;
}
}
else
{
return null;
}
case POLICY:
// TODO: Policy
default:
return null;
}
}
public CMISTypeId getTypeId(String typeId);
/**
* Get Type Id from Table Name
*
* @param table
* @return
*/
public CMISTypeId getTypeIdFromTable(String table);
/**
* Get Type Id from Alfresco Class Name
*
* @param clazz
* @param matchingScope if provided, only return type id matching scope
* @return
*/
public CMISTypeId getTypeId(QName clazz, CMISScope matchingScope);
/**
* Get all the property definitions for a type
* Get Type Definition
*
* @param typeId
* @return
*/
public Map<String, CMISPropertyDefinition> getPropertyDefinitions(CMISTypeId typeId)
{
HashMap<String, CMISPropertyDefinition> properties = new HashMap<String, CMISPropertyDefinition>();
switch (typeId.getScope())
{
case RELATIONSHIP:
// Associations - only have CMIS properties
AssociationDefinition associationDefinition = dictionaryService.getAssociation(typeId.getQName());
if (associationDefinition != null)
{
if (cmisMapping.isValidCmisRelationship(typeId.getQName()))
{
return getPropertyDefinitions(CMISMapping.RELATIONSHIP_TYPE_ID);
}
break;
}
if (!typeId.getQName().equals(CMISMapping.RELATIONSHIP_QNAME))
{
break;
}
// Fall through for CMISMapping.RELATIONSHIP_QNAME
case DOCUMENT:
case FOLDER:
TypeDefinition typeDefinition = dictionaryService.getType(typeId.getQName());
if (typeDefinition != null)
{
if (cmisMapping.isValidCmisDocumentOrFolder(typeId.getQName()) || typeId.getQName().equals(CMISMapping.RELATIONSHIP_QNAME))
{
for (QName qname : typeDefinition.getProperties().keySet())
{
if (cmisMapping.getPropertyType(qname) != null)
{
CMISPropertyDefinition cmisPropDefinition = new CMISPropertyDefinition(this, qname, typeDefinition.getName());
properties.put(cmisPropDefinition.getPropertyName(), cmisPropDefinition);
}
}
for (AspectDefinition aspect : typeDefinition.getDefaultAspects())
{
for (QName qname : aspect.getProperties().keySet())
{
if (cmisMapping.getPropertyType(qname) != null)
{
CMISPropertyDefinition cmisPropDefinition = new CMISPropertyDefinition(this, qname, typeDefinition.getName());
properties.put(cmisPropDefinition.getPropertyName(), cmisPropDefinition);
}
}
}
}
if (cmisMapping.isValidCmisDocumentOrFolder(typeId.getQName()))
{
// Add CMIS properties if required
if (!cmisMapping.isCmisCoreType(typeId.getQName()))
{
properties.putAll(getPropertyDefinitions(typeId.getRootTypeId()));
}
}
}
break;
case POLICY:
AspectDefinition aspectDefinition = dictionaryService.getAspect(typeId.getQName());
if (aspectDefinition != null)
{
for (QName qname : aspectDefinition.getProperties().keySet())
{
if (cmisMapping.getPropertyType(qname) != null)
{
CMISPropertyDefinition cmisPropDefinition = new CMISPropertyDefinition(this, qname, aspectDefinition.getName());
properties.put(cmisPropDefinition.getPropertyName(), cmisPropDefinition);
}
}
for (AspectDefinition aspect : aspectDefinition.getDefaultAspects())
{
for (QName qname : aspect.getProperties().keySet())
{
if (cmisMapping.getPropertyType(qname) != null)
{
CMISPropertyDefinition cmisPropDefinition = new CMISPropertyDefinition(this, qname, aspectDefinition.getName());
properties.put(cmisPropDefinition.getPropertyName(), cmisPropDefinition);
}
}
}
// Add CMIS properties if required
if (!cmisMapping.isCmisCoreType(typeId.getQName()))
{
properties.putAll(getPropertyDefinitions(typeId.getRootTypeId()));
}
}
break;
case UNKNOWN:
default:
break;
}
return properties;
}
public CMISTypeDefinition getType(CMISTypeId typeId);
/**
* Get a single property definition
* Get All Type Definitions
*
* @param typeId
* @param propertyName
* @return
*/
public CMISPropertyDefinition getPropertyDefinition(CMISTypeId typeId, String propertyName)
{
return getPropertyDefinitions(typeId).get(propertyName);
}
public Collection<CMISTypeDefinition> getAllTypes();
/**
* Get Property Id for Alfresco property name
*
* @param property
* @return
*/
public CMISPropertyId getPropertyId(QName property);
/**
* Get Property Id
*
* @param propertyId
* @return
*/
public CMISPropertyId getPropertyId(String propertyId);
/**
* Get Property
*
* @param propertyId
* @return
*/
public CMISPropertyDefinition getProperty(CMISPropertyId propertyId);
/**
* Get Data Type
*
* @param dataType
* @return
*/
public CMISDataTypeEnum getDataType(QName dataType);
// public CMISTypeDef findType(CMISTypeId typeId)
// public CMISTypeDef findType(String typeId)
// public CMISTypeDef findTypeForClass(QName clazz, CMISScope matchingScope, ...)
// public CMISTypeDef findTypeForTable(String tableName)
// public CMISTypeDef getAllTypes();
// public CMISPropertyDefinition getProperty(QName property)
// public CMISPropertyDefinition getProperty(CMISTypeDef typeDef, String property)
// public CMISDataTypeEnum getDataType(QName dataType)
}

View File

@@ -28,99 +28,48 @@ public class CMISDictionaryTest extends BaseCMISTest
{
public void testBasicTypes()
{
cmisDictionaryService.setStrict(true);
for (CMISTypeId name : cmisDictionaryService.getAllObjectTypeIds())
for (CMISTypeDefinition type : cmisDictionaryService.getAllTypes())
{
System.out.println(name);
System.out.println(type);
}
assertEquals(3, cmisDictionaryService.getAllObjectTypeIds().size());
}
public void testBasicTypeDefinitions()
{
cmisDictionaryService.setStrict(false);
for (CMISTypeId name : cmisDictionaryService.getAllObjectTypeIds())
{
System.out.println(cmisDictionaryService.getType(name));
}
}
public void testSubTypes()
{
cmisDictionaryService.setStrict(true);
for (CMISTypeId name : cmisDictionaryService.getAllObjectTypeIds())
for (CMISTypeDefinition type : cmisDictionaryService.getAllTypes())
{
System.out.println(name + " children (strict)");
for (CMISTypeId subName :cmisDictionaryService.getChildTypeIds(name, false))
System.out.println(type.getTypeId() + " children:");
for (CMISTypeDefinition subType : type.getSubTypes(false))
{
System.out.println(" " + subName);
System.out.println(" " + subType.getTypeId());
}
System.out.println(name + " descendants (strict)");
for (CMISTypeId subName :cmisDictionaryService.getChildTypeIds(name, true))
System.out.println(type.getTypeId() + " descendants:");
for (CMISTypeDefinition subType : type.getSubTypes(true))
{
System.out.println(" " + subName);
}
}
cmisDictionaryService.setStrict(false);
for (CMISTypeId name : cmisDictionaryService.getAllObjectTypeIds())
{
System.out.println(name + " children");
for (CMISTypeId subName :cmisDictionaryService.getChildTypeIds(name, false))
{
System.out.println(" " + subName);
}
System.out.println(name + " descendants");
for (CMISTypeId subName :cmisDictionaryService.getChildTypeIds(name, true))
{
System.out.println(" " + subName);
System.out.println(" " + subType.getTypeId());
}
}
}
public void testTypeIds()
{
cmisDictionaryService.setStrict(false);
for (CMISTypeId name : cmisDictionaryService.getAllObjectTypeIds())
for (CMISTypeDefinition typeDef : cmisDictionaryService.getAllTypes())
{
String typeId = name.getTypeId();
CMISTypeId lookup = cmisMapping.getCmisTypeId(typeId);
assertEquals(name, lookup);
System.out.println(name + " => " + lookup);
CMISTypeDefinition type = cmisDictionaryService.getType(lookup);
assertNotNull(type);
assertEquals(lookup, type.getObjectTypeId());
CMISTypeId typeId = typeDef.getTypeId();
CMISTypeDefinition typeDefLookup = cmisDictionaryService.getType(typeId);
assertNotNull(typeDefLookup);
assertEquals(typeDef, typeDefLookup);
}
}
public void testBasicProperties()
{
cmisDictionaryService.setStrict(false);
for (CMISTypeId name : cmisDictionaryService.getAllObjectTypeIds())
{
for (String propertyName : cmisDictionaryService.getPropertyDefinitions(name).keySet())
{
System.out.println(name +" -> "+ propertyName);
}
}
}
public void testBasicPropertyDefinitions()
{
cmisDictionaryService.setStrict(true);
for (CMISTypeId name : cmisDictionaryService.getAllObjectTypeIds())
for (CMISTypeDefinition type : cmisDictionaryService.getAllTypes())
{
for (CMISPropertyDefinition proDef : cmisDictionaryService.getPropertyDefinitions(name).values())
System.out.println(type.getTypeId() + " properties:");
for (CMISPropertyDefinition proDef : type.getPropertyDefinitions().values())
{
System.out.println(proDef);
}
}
cmisDictionaryService.setStrict(false);
for (CMISTypeId name : cmisDictionaryService.getAllObjectTypeIds())
{
for (CMISPropertyDefinition proDef : cmisDictionaryService.getPropertyDefinitions(name).values())
{
System.out.println(proDef);
System.out.println(" " + proDef);
}
}
}

View File

@@ -0,0 +1,148 @@
/*
* Copyright (C) 2005-20079 Alfresco Software Limited.
*
* This program 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 2
* of the License, or (at your option) any later version.
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.cmis.dictionary;
import java.util.List;
import org.alfresco.cmis.CMISContentStreamAllowedEnum;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.namespace.QName;
/**
* CMIS Document Type Definition
*
* @author davidc
*/
public class CMISDocumentTypeDefinition extends CMISObjectTypeDefinition
{
private static final long serialVersionUID = -7209732754962781522L;
// document specific properties
protected boolean fileable;
protected boolean versionable;
protected CMISContentStreamAllowedEnum contentStreamAllowed;
/**
* Construct
*
* @param cmisMapping
* @param typeId
* @param cmisClassDef
*/
public CMISDocumentTypeDefinition(CMISMapping cmisMapping, CMISTypeId typeId, ClassDefinition cmisClassDef)
{
// Object type properties
this.cmisClassDef = cmisClassDef;
objectTypeId = typeId;
objectTypeQueryName = (typeId == CMISDictionaryModel.DOCUMENT_TYPE_ID) ? typeId.getId() : cmisMapping.buildPrefixEncodedString(typeId.getQName(), false);
displayName = (cmisClassDef.getTitle() != null) ? cmisClassDef.getTitle() : typeId.getId();
QName parentQName = cmisMapping.getCmisType(cmisClassDef.getParentName());
if (cmisMapping.isValidCmisDocument(parentQName))
{
parentTypeId = cmisMapping.getCmisTypeId(CMISScope.DOCUMENT, parentQName);
}
description = cmisClassDef.getDescription();
creatable = true;
queryable = true;
controllable = false;
includeInSuperTypeQuery = true;
// Document type properties
versionable = false;
List<AspectDefinition> defaultAspects = cmisClassDef.getDefaultAspects();
for (AspectDefinition aspectDefinition : defaultAspects)
{
if (aspectDefinition.getName().equals(ContentModel.ASPECT_VERSIONABLE))
{
versionable = true;
break;
}
}
fileable = true;
contentStreamAllowed = CMISContentStreamAllowedEnum.ALLOWED;
}
/**
* Are objects of this type fileable?
*
* @return
*/
public boolean isFileable()
{
return fileable;
}
/**
* Is this type versionable? If true this implies all instances of the type are versionable.
*
* @return true if versionable
*/
public boolean isVersionable()
{
return versionable;
}
/**
* Is a content stream allowed for this type? It may be disallowed, optional or mandatory.
*
* @return
*/
public CMISContentStreamAllowedEnum getContentStreamAllowed()
{
return contentStreamAllowed;
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("CMISDocumentTypeDefinition[");
builder.append("ObjectTypeId=").append(getTypeId()).append(", ");
builder.append("ObjectTypeQueryName=").append(getQueryName()).append(", ");
builder.append("ObjectTypeDisplayName=").append(getDisplayName()).append(", ");
builder.append("ParentTypeId=").append(getParentType() == null ? "<none>" : getParentType().getTypeId()).append(", ");
builder.append("Description=").append(getDescription()).append(", ");
builder.append("Creatable=").append(isCreatable()).append(", ");
builder.append("Queryable=").append(isQueryable()).append(", ");
builder.append("Controllable=").append(isControllable()).append(", ");
builder.append("IncludeInSuperTypeQuery=").append(isIncludeInSuperTypeQuery()).append(", ");
builder.append("Fileable=").append(isFileable()).append(", ");
builder.append("Versionable=").append(isVersionable()).append(", ");
builder.append("ContentStreamAllowed=").append(getContentStreamAllowed()).append(", ");
builder.append("SubTypes=").append(getSubTypes(false).size()).append(", ");
builder.append("Properties=").append(getPropertyDefinitions().size());
builder.append("]");
return builder.toString();
}
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program 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 2
* of the License, or (at your option) any later version.
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.cmis.dictionary;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.namespace.QName;
/**
* CMIS Folder Type Definition
*
* @author davidc
*/
public class CMISFolderTypeDefinition extends CMISObjectTypeDefinition
{
private static final long serialVersionUID = 7526155195125799106L;
/**
* Construct
* @param cmisMapping
* @param typeId
* @param cmisClassDef
*/
public CMISFolderTypeDefinition(CMISMapping cmisMapping, CMISTypeId typeId, ClassDefinition cmisClassDef)
{
// Object type properties
this.cmisClassDef = cmisClassDef;
objectTypeId = typeId;
objectTypeQueryName = (typeId == CMISDictionaryModel.FOLDER_TYPE_ID) ? typeId.getId() : cmisMapping.buildPrefixEncodedString(typeId.getQName(), false);
displayName = (cmisClassDef.getTitle() != null) ? cmisClassDef.getTitle() : typeId.getId();
QName parentQName = cmisMapping.getCmisType(cmisClassDef.getParentName());
if (cmisMapping.isValidCmisFolder(parentQName))
{
parentTypeId = cmisMapping.getCmisTypeId(CMISScope.FOLDER, parentQName);
}
description = cmisClassDef.getDescription();
creatable = true;
queryable = true;
controllable = false;
includeInSuperTypeQuery = true;
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("CMISFolderTypeDefinition[");
builder.append("ObjectTypeId=").append(getTypeId()).append(", ");
builder.append("ObjectTypeQueryName=").append(getQueryName()).append(", ");
builder.append("ObjectTypeDisplayName=").append(getDisplayName()).append(", ");
builder.append("ParentTypeId=").append(getParentType() == null ? "<none>" : getParentType().getTypeId()).append(", ");
builder.append("Description=").append(getDescription()).append(", ");
builder.append("Creatable=").append(isCreatable()).append(", ");
builder.append("Queryable=").append(isQueryable()).append(", ");
builder.append("Controllable=").append(isControllable()).append(", ");
builder.append("IncludeInSuperTypeQuery=").append(isIncludeInSuperTypeQuery()).append(", ");
builder.append("SubTypes=").append(getSubTypes(false).size()).append(", ");
builder.append("Properties=").append(getPropertyDefinitions().size());
builder.append("]");
return builder.toString();
}
}

View File

@@ -27,14 +27,13 @@ package org.alfresco.cmis.dictionary;
import java.util.Collection;
import java.util.HashMap;
import org.alfresco.cmis.CMISPropertyTypeEnum;
import org.alfresco.cmis.CMISDataTypeEnum;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.namespace.NamespaceException;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
@@ -61,143 +60,40 @@ public class CMISMapping
*/
public static QName CMIS_MODEL_QNAME = QName.createQName(CMIS_MODEL_URI, CMIS_MODEL_NAME);
/**
* The QNames for CMIS Data Types.
*/
// CMIS Data Types
public static QName CMIS_DATATYPE_ID = QName.createQName(CMIS_MODEL_URI, "id");
public static QName CMIS_DATATYPE_URI = QName.createQName(CMIS_MODEL_URI, "uri");
public static QName CMIS_DATATYPE_XML = QName.createQName(CMIS_MODEL_URI, "xml");
public static QName CMIS_DATATYPE_HTML = QName.createQName(CMIS_MODEL_URI, "html");
/**
* Type id for CMIS documents, from the spec.
*/
public static String DOCUMENT_OBJECT_TYPE = "Document";
// CMIS Types
public static QName DOCUMENT_QNAME = QName.createQName(CMIS_MODEL_URI, CMISDictionaryModel.DOCUMENT_OBJECT_TYPE);
public static QName FOLDER_QNAME = QName.createQName(CMIS_MODEL_URI, CMISDictionaryModel.FOLDER_OBJECT_TYPE);
public static QName RELATIONSHIP_QNAME = QName.createQName(CMIS_MODEL_URI, CMISDictionaryModel.RELATIONSHIP_OBJECT_TYPE);
public static QName POLICY_QNAME = QName.createQName(CMIS_MODEL_URI, CMISDictionaryModel.POLICY_OBJECT_TYPE);
/**
* Type is for CMIS folders, from the spec.
*/
public static String FOLDER_OBJECT_TYPE = "Folder";
/**
* Type Id for CMIS Relationships, from the spec.
*/
public static String RELATIONSHIP_OBJECT_TYPE = "Relationship";
/**
* Type Id for CMIS Policies, from the spec.
*/
public static String POLICY_OBJECT_TYPE = "Policy";
/**
* QName for CMIS documents in the Alfresco CMIS model.
*/
public static QName DOCUMENT_QNAME = QName.createQName(CMIS_MODEL_URI, DOCUMENT_OBJECT_TYPE);
/**
* QName for CMIS folders in the Alfresco CMIS model
*/
public static QName FOLDER_QNAME = QName.createQName(CMIS_MODEL_URI, FOLDER_OBJECT_TYPE);
/**
* QName for CMIS relationships in the the Alfresco CMIS model.
*/
public static QName RELATIONSHIP_QNAME = QName.createQName(CMIS_MODEL_URI, RELATIONSHIP_OBJECT_TYPE);
public static QName POLICY_QNAME = QName.createQName(CMIS_MODEL_URI, POLICY_OBJECT_TYPE);
// TODO: spec issue - objectTypeEnum is lower cased - object type ids are repository specific in spec
public static CMISTypeId DOCUMENT_TYPE_ID = new CMISTypeId(CMISScope.DOCUMENT, DOCUMENT_QNAME, DOCUMENT_OBJECT_TYPE.toLowerCase());
public static CMISTypeId FOLDER_TYPE_ID = new CMISTypeId(CMISScope.FOLDER, FOLDER_QNAME, FOLDER_OBJECT_TYPE.toLowerCase());
public static CMISTypeId RELATIONSHIP_TYPE_ID = new CMISTypeId(CMISScope.RELATIONSHIP, RELATIONSHIP_QNAME, RELATIONSHIP_OBJECT_TYPE.toLowerCase());
public static CMISTypeId POLICY_TYPE_ID = new CMISTypeId(CMISScope.POLICY, POLICY_QNAME, POLICY_OBJECT_TYPE.toLowerCase());
// CMIS properties
public static String PROP_OBJECT_ID = "ObjectId";
public static String PROP_URI = "Uri";
public static String PROP_OBJECT_TYPE_ID = "ObjectTypeId";
public static String PROP_CREATED_BY = "CreatedBy";
public static String PROP_CREATION_DATE = "CreationDate";
public static String PROP_LAST_MODIFIED_BY = "LastModifiedBy";
public static String PROP_LAST_MODIFICATION_DATE = "LastModificationDate";
public static String PROP_CHANGE_TOKEN = "ChangeToken";
public static String PROP_NAME = "Name";
public static String PROP_IS_IMMUTABLE = "IsImmutable";
public static String PROP_IS_LATEST_VERSION = "IsLatestVersion";
public static String PROP_IS_MAJOR_VERSION = "IsMajorVersion";
public static String PROP_IS_LATEST_MAJOR_VERSION = "IsLatestMajorVersion";
public static String PROP_VERSION_LABEL = "VersionLabel";
public static String PROP_VERSION_SERIES_ID = "VersionSeriesId";
public static String PROP_IS_VERSION_SERIES_CHECKED_OUT = "IsVersionSeriesCheckedOut";
public static String PROP_VERSION_SERIES_CHECKED_OUT_BY = "VersionSeriesCheckedOutBy";
public static String PROP_VERSION_SERIES_CHECKED_OUT_ID = "VersionSeriesCheckedOutId";
public static String PROP_CHECKIN_COMMENT = "CheckinComment";
public static String PROP_CONTENT_STREAM_ALLOWED = "ContentStreamAllowed";
public static String PROP_CONTENT_STREAM_LENGTH = "ContentStreamLength";
public static String PROP_CONTENT_STREAM_MIME_TYPE = "ContentStreamMimeType";
public static String PROP_CONTENT_STREAM_FILENAME = "ContentStreamFilename";
public static String PROP_CONTENT_STREAM_URI = "ContentStreamUri";
public static String PROP_PARENT_ID = "ParentId";
public static String PROP_ALLOWED_CHILD_OBJECT_TYPE_IDS = "AllowedChildObjectTypeIds";
public static String PROP_SOURCE_ID = "SourceId";
public static String PROP_TARGET_ID = "TargetId";
// QNames
public static QName PROP_OBJECT_ID_QNAME = QName.createQName(CMIS_MODEL_URI, PROP_OBJECT_ID);
// Properties
public static QName PROP_OBJECT_ID_QNAME = QName.createQName(CMIS_MODEL_URI, CMISDictionaryModel.PROP_OBJECT_ID);
// Mappings
// - no entry means no mapping and pass through as is
private static HashMap<QName, CMISTypeId> qNameToCmisTypeId = new HashMap<QName, CMISTypeId>();
private static HashMap<QName, QName> cmisToAlfrecsoTypes = new HashMap<QName, QName>();
private static HashMap<QName, QName> alfrescoToCmisTypes = new HashMap<QName, QName>();
private static HashMap<QName, CMISDataTypeEnum> alfrescoPropertyTypesToCmisPropertyTypes = new HashMap<QName, CMISDataTypeEnum>();
private static HashMap<QName, CMISPropertyTypeEnum> alfrescoPropertyTypesToCmisPropertyTypes = new HashMap<QName, CMISPropertyTypeEnum>();
/**
* Set up mappings
*/
static
{
qNameToCmisTypeId.put(DOCUMENT_QNAME, DOCUMENT_TYPE_ID);
qNameToCmisTypeId.put(FOLDER_QNAME, FOLDER_TYPE_ID);
qNameToCmisTypeId.put(RELATIONSHIP_QNAME, RELATIONSHIP_TYPE_ID);
qNameToCmisTypeId.put(POLICY_QNAME, POLICY_TYPE_ID);
qNameToCmisTypeId.put(DOCUMENT_QNAME, CMISDictionaryModel.DOCUMENT_TYPE_ID);
qNameToCmisTypeId.put(FOLDER_QNAME, CMISDictionaryModel.FOLDER_TYPE_ID);
qNameToCmisTypeId.put(RELATIONSHIP_QNAME, CMISDictionaryModel.RELATIONSHIP_TYPE_ID);
qNameToCmisTypeId.put(POLICY_QNAME, CMISDictionaryModel.POLICY_TYPE_ID);
cmisToAlfrecsoTypes.put(DOCUMENT_QNAME, ContentModel.TYPE_CONTENT);
cmisToAlfrecsoTypes.put(FOLDER_QNAME, ContentModel.TYPE_FOLDER);
@@ -209,30 +105,29 @@ public class CMISMapping
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.ANY, null);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.ASSOC_REF, null);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.BOOLEAN, CMISPropertyTypeEnum.BOOLEAN);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.CATEGORY, CMISPropertyTypeEnum.ID);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.BOOLEAN, CMISDataTypeEnum.BOOLEAN);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.CATEGORY, CMISDataTypeEnum.ID);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.CHILD_ASSOC_REF, null);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.CONTENT, null);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.DATE, CMISPropertyTypeEnum.DATETIME);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.DATETIME, CMISPropertyTypeEnum.DATETIME);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.DOUBLE, CMISPropertyTypeEnum.DECIMAL);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.FLOAT, CMISPropertyTypeEnum.DECIMAL);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.INT, CMISPropertyTypeEnum.INTEGER);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.DATE, CMISDataTypeEnum.DATETIME);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.DATETIME, CMISDataTypeEnum.DATETIME);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.DOUBLE, CMISDataTypeEnum.DECIMAL);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.FLOAT, CMISDataTypeEnum.DECIMAL);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.INT, CMISDataTypeEnum.INTEGER);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.LOCALE, null);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.LONG, CMISPropertyTypeEnum.INTEGER);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.MLTEXT, CMISPropertyTypeEnum.STRING);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.NODE_REF, CMISPropertyTypeEnum.ID);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.LONG, CMISDataTypeEnum.INTEGER);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.MLTEXT, CMISDataTypeEnum.STRING);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.NODE_REF, CMISDataTypeEnum.ID);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.PATH, null);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.QNAME, null);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.TEXT, CMISPropertyTypeEnum.STRING);
alfrescoPropertyTypesToCmisPropertyTypes.put(CMIS_DATATYPE_ID, CMISPropertyTypeEnum.ID);
alfrescoPropertyTypesToCmisPropertyTypes.put(CMIS_DATATYPE_URI, CMISPropertyTypeEnum.URI);
alfrescoPropertyTypesToCmisPropertyTypes.put(CMIS_DATATYPE_XML, CMISPropertyTypeEnum.XML);
alfrescoPropertyTypesToCmisPropertyTypes.put(CMIS_DATATYPE_HTML, CMISPropertyTypeEnum.HTML);
alfrescoPropertyTypesToCmisPropertyTypes.put(DataTypeDefinition.TEXT, CMISDataTypeEnum.STRING);
alfrescoPropertyTypesToCmisPropertyTypes.put(CMIS_DATATYPE_ID, CMISDataTypeEnum.ID);
alfrescoPropertyTypesToCmisPropertyTypes.put(CMIS_DATATYPE_URI, CMISDataTypeEnum.URI);
alfrescoPropertyTypesToCmisPropertyTypes.put(CMIS_DATATYPE_XML, CMISDataTypeEnum.XML);
alfrescoPropertyTypesToCmisPropertyTypes.put(CMIS_DATATYPE_HTML, CMISDataTypeEnum.HTML);
}
private DictionaryService dictionaryService;
private NamespaceService namespaceService;
/**
@@ -270,47 +165,35 @@ public class CMISMapping
*
* @return namespaceService
*/
/* package */NamespaceService getNamespaceService()
/*package*/ NamespaceService getNamespaceService()
{
return this.namespaceService;
}
/**
* Id this a CMIS core type defined in the Alfresco CMIS model
*
* @param typeQName
* @return
*/
public boolean isCmisCoreType(QName typeQName)
{
return qNameToCmisTypeId.get(typeQName) != null;
}
/**
* Gets the CMIS Type Id given the serialized type Id
*
* @param typeId
* type id in the form of <ROOT_TYPE_ID>/<PREFIX>_<LOCALNAME>
* @param typeId type id in the form of <ROOT_TYPE_ID>/<PREFIX>_<LOCALNAME>
* @return
*/
public CMISTypeId getCmisTypeId(String typeId)
{
// Is it a CMIS root object type id?
if (typeId.equalsIgnoreCase(DOCUMENT_TYPE_ID.getTypeId()))
if (typeId.equalsIgnoreCase(CMISDictionaryModel.DOCUMENT_TYPE_ID.getId()))
{
return DOCUMENT_TYPE_ID;
return CMISDictionaryModel.DOCUMENT_TYPE_ID;
}
else if (typeId.equalsIgnoreCase(FOLDER_TYPE_ID.getTypeId()))
else if (typeId.equalsIgnoreCase(CMISDictionaryModel.FOLDER_TYPE_ID.getId()))
{
return FOLDER_TYPE_ID;
return CMISDictionaryModel.FOLDER_TYPE_ID;
}
else if (typeId.equalsIgnoreCase(RELATIONSHIP_TYPE_ID.getTypeId()))
else if (typeId.equalsIgnoreCase(CMISDictionaryModel.RELATIONSHIP_TYPE_ID.getId()))
{
return RELATIONSHIP_TYPE_ID;
return CMISDictionaryModel.RELATIONSHIP_TYPE_ID;
}
else if (typeId.equalsIgnoreCase(POLICY_TYPE_ID.getTypeId()))
else if (typeId.equalsIgnoreCase(CMISDictionaryModel.POLICY_TYPE_ID.getId()))
{
return POLICY_TYPE_ID;
return CMISDictionaryModel.POLICY_TYPE_ID;
}
// Is it an Alfresco type id?
@@ -328,7 +211,7 @@ public class CMISMapping
QName typeQName = QName.resolveToQName(namespaceService, typeId.substring(2).replace('_', ':'));
// Construct CMIS Type Id
return new CMISTypeId(scope, typeQName, typeId);
return new CMISTypeId(scope, typeId, typeQName);
}
/**
@@ -346,7 +229,7 @@ public class CMISMapping
builder.append(scope.discriminator());
builder.append("/");
builder.append(buildPrefixEncodedString(typeQName, false));
return new CMISTypeId(scope, typeQName, builder.toString());
return new CMISTypeId(scope, builder.toString(), typeQName);
}
else
{
@@ -354,56 +237,45 @@ public class CMISMapping
}
}
public CMISTypeId getCmisTypeId(QName typeQName)
public CMISTypeId getCmisTypeId(QName classQName)
{
if (isValidCmisDocument(typeQName))
if (classQName.equals(ContentModel.TYPE_CONTENT))
{
return getCmisTypeId(CMISScope.DOCUMENT, getCmisType(typeQName));
return getCmisTypeId(CMISScope.DOCUMENT, classQName);
}
else if (isValidCmisFolder(typeQName))
if (classQName.equals(ContentModel.TYPE_FOLDER))
{
return getCmisTypeId(CMISScope.FOLDER, getCmisType(typeQName));
return getCmisTypeId(CMISScope.FOLDER, classQName);
}
else if (typeQName.equals(CMISMapping.RELATIONSHIP_QNAME))
if (classQName.equals(CMISMapping.RELATIONSHIP_QNAME))
{
return getCmisTypeId(CMISScope.RELATIONSHIP, getCmisType(typeQName));
return getCmisTypeId(CMISScope.RELATIONSHIP, classQName);
}
else if (typeQName.equals(ContentModel.TYPE_CONTENT))
if (classQName.equals(CMISMapping.POLICY_QNAME))
{
return getCmisTypeId(CMISScope.DOCUMENT, getCmisType(typeQName));
return getCmisTypeId(CMISScope.POLICY, classQName);
}
else if (typeQName.equals(ContentModel.TYPE_FOLDER))
if (isValidCmisDocument(classQName))
{
return getCmisTypeId(CMISScope.FOLDER, getCmisType(typeQName));
return getCmisTypeId(CMISScope.DOCUMENT, classQName);
}
else
if (isValidCmisFolder(classQName))
{
ClassDefinition classDef = dictionaryService.getClass(typeQName);
if (classDef.isAspect())
{
return getCmisTypeId(CMISScope.POLICY, getCmisType(typeQName));
}
else
{
return null;
}
return getCmisTypeId(CMISScope.FOLDER, classQName);
}
if (isValidCmisRelationship(classQName))
{
return getCmisTypeId(CMISScope.RELATIONSHIP, classQName);
}
if (isValidCmisPolicy(classQName))
{
return getCmisTypeId(CMISScope.POLICY, classQName);
}
return null;
}
/**
* Get the query name for Alfresco qname
*
* @param namespaceService
* @param typeQName
* @return
*/
public String getQueryName(QName typeQName)
{
return buildPrefixEncodedString(typeQName, false);
}
private String buildPrefixEncodedString(QName qname, boolean upperCase)
/*package*/ String buildPrefixEncodedString(QName qname, boolean upperCase)
{
StringBuilder builder = new StringBuilder(128);
@@ -424,21 +296,6 @@ public class CMISMapping
return builder.toString();
}
/**
* Is this a valid CMIS type The type must be a core CMIS type or extend cm:content or cm:folder The alfresco types
* cm:content and cm:folder are hidden by the CMIS types
*
* @param dictionaryService
* @param typeQName
* @return
*/
public boolean isValidCmisType(QName typeQName)
{
// TODO: Policy: Include aspects types as policies
// TODO: Policy: Add isValidCmispolicy(QName typeQName)
return isValidCmisFolder(typeQName) || isValidCmisDocument(typeQName) || isValidCmisRelationship(typeQName);
}
/**
* Is this a valid cmis document or folder type (not a relationship)
*
@@ -513,10 +370,41 @@ public class CMISMapping
return true;
}
}
return false;
}
/**
* Is this a valid CMIS policy type?
*
* @param dictionaryService
* @param typeQName
* @return
*/
public boolean isValidCmisPolicy(QName typeQName)
{
if (typeQName == null)
{
return false;
}
if (typeQName.equals(POLICY_QNAME))
{
return true;
}
AspectDefinition aspectDef = dictionaryService.getAspect(typeQName);
if (aspectDef == null)
{
return false;
}
if (aspectDef.getName().equals(ContentModel.ASPECT_VERSIONABLE) ||
aspectDef.getName().equals(ContentModel.ASPECT_AUDITABLE))
{
return false;
}
return true;
}
/**
* Is an association valid in CMIS? It must be a non-child relationship and the source and target must both be valid
* CMIS types.
@@ -572,6 +460,17 @@ public class CMISMapping
return typeQName;
}
/**
* Is Alfresco Type mapped to an alternative CMIS Type?
*
* @param typeQName
* @return
*/
public boolean isRemappedType(QName typeQName)
{
return alfrescoToCmisTypes.containsKey(typeQName);
}
/**
* Given a CMIS model type map it to the appropriate Alfresco type.
*
@@ -600,21 +499,6 @@ public class CMISMapping
return buildPrefixEncodedString(propertyQName, false);
}
public CMISTypeId getCmisTypeForProperty(QName propertyQName)
{
PropertyDefinition pDef = dictionaryService.getProperty(propertyQName);
if (pDef != null)
{
QName typeQName = pDef.getContainerClass().getName();
return getCmisTypeId(typeQName);
}
else
{
return null;
}
}
/**
* Get the CMIS property type for a property
*
@@ -622,22 +506,14 @@ public class CMISMapping
* @param propertyQName
* @return
*/
public CMISPropertyTypeEnum getPropertyType(QName propertyQName)
public CMISDataTypeEnum getDataType(DataTypeDefinition datatype)
{
PropertyDefinition propertyDefinition = dictionaryService.getProperty(propertyQName);
DataTypeDefinition dataTypeDefinition;
if (propertyDefinition != null)
{
dataTypeDefinition = propertyDefinition.getDataType();
}
else
{
dataTypeDefinition = dictionaryService.getDataType(propertyQName);
}
QName dQName = dataTypeDefinition.getName();
return alfrescoPropertyTypesToCmisPropertyTypes.get(dQName);
return getDataType(datatype.getName());
}
public CMISDataTypeEnum getDataType(QName dataType)
{
return alfrescoPropertyTypesToCmisPropertyTypes.get(dataType);
}
/**
@@ -712,86 +588,6 @@ public class CMISMapping
}
return null;
}
/**
* @param tableName
* @return
*/
public QName getAlfrescoClassQNameFromCmisTableName(String tableName)
{
if (tableName.equalsIgnoreCase(DOCUMENT_TYPE_ID.getTypeId()))
{
return ContentModel.TYPE_CONTENT;
}
else if (tableName.equalsIgnoreCase(FOLDER_TYPE_ID.getTypeId()))
{
return ContentModel.TYPE_FOLDER;
}
else if (tableName.equalsIgnoreCase(RELATIONSHIP_TYPE_ID.getTypeId()))
{
return null;
}
else if (tableName.equalsIgnoreCase(POLICY_TYPE_ID.getTypeId()))
{
return null;
}
// Find prefix and property name - in upper case
int split = tableName.indexOf('_');
if (split == -1)
{
return null;
}
String prefix = tableName.substring(0, split);
String localName = tableName.substring(split + 1);
// Try lower case version first.
QName classQName = QName.createQName(prefix.toLowerCase(), localName.toLowerCase(), namespaceService);
if (dictionaryService.getClass(classQName) != null)
{
return classQName;
}
// Full case insensitive hunt
for (String test : namespaceService.getPrefixes())
{
if (test.equalsIgnoreCase(prefix))
{
prefix = test;
break;
}
}
String uri = namespaceService.getNamespaceURI(prefix);
for (QName qname : dictionaryService.getAllTypes())
{
if (qname.getNamespaceURI().equals(uri))
{
if (qname.getLocalName().equalsIgnoreCase(localName))
{
return qname;
}
}
}
for (QName qname : dictionaryService.getAllAspects())
{
if (qname.getNamespaceURI().equals(uri))
{
if (qname.getLocalName().equalsIgnoreCase(localName))
{
return qname;
}
}
}
return null;
}
/**
@@ -808,7 +604,6 @@ public class CMISMapping
else
{
return propertyQName.toString();
}
}
}

View File

@@ -0,0 +1,405 @@
/*
* Copyright (C) 2005-20079 Alfresco Software Limited.
*
* This program 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 2
* of the License, or (at your option) any later version.
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.cmis.dictionary;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import org.alfresco.cmis.CMISContentStreamAllowedEnum;
import org.alfresco.cmis.dictionary.AbstractCMISDictionaryService.DictionaryRegistry;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.namespace.QName;
/**
* CMIS Object Type Definition
*
* @author davidc
*/
public class CMISObjectTypeDefinition implements CMISTypeDefinition, Serializable
{
private static final long serialVersionUID = -3131505923356013430L;
// Object type properties
protected ClassDefinition cmisClassDef;
protected CMISTypeId objectTypeId;
protected String objectTypeQueryName;
protected String displayName;
protected CMISTypeId parentTypeId;
protected CMISTypeDefinition parentType;
protected CMISTypeDefinition rootType;
protected String description;
protected boolean creatable;
protected boolean queryable;
protected boolean controllable;
protected boolean includeInSuperTypeQuery;
protected Collection<CMISTypeId> subTypeIds = new ArrayList<CMISTypeId>();
protected Collection<CMISTypeDefinition> subTypes = new ArrayList<CMISTypeDefinition>();
protected Map<CMISPropertyId, CMISPropertyDefinition> properties = new HashMap<CMISPropertyId, CMISPropertyDefinition>();
protected Map<CMISPropertyId, CMISPropertyDefinition> inheritedProperties = new HashMap<CMISPropertyId, CMISPropertyDefinition>();
/**
* Construct
*
* @param cmisMapping
* @param dictionaryService
* @return
*/
/*package*/ Map<CMISPropertyId, CMISPropertyDefinition> createProperties(CMISMapping cmisMapping, DictionaryService dictionaryService)
{
// map properties directly defined on this type
for (PropertyDefinition propDef : cmisClassDef.getProperties().values())
{
if (propDef.getContainerClass().equals(cmisClassDef))
{
if (cmisMapping.getDataType(propDef.getDataType()) != null)
{
CMISPropertyDefinition cmisPropDef = createProperty(cmisMapping, propDef);
properties.put(cmisPropDef.getPropertyId(), cmisPropDef);
}
}
}
// map properties directly defined on default aspects
for (AspectDefinition aspectDef : cmisClassDef.getDefaultAspects(false))
{
for (PropertyDefinition propDef : aspectDef.getProperties().values())
{
if (cmisMapping.getDataType(propDef.getDataType()) != null)
{
CMISPropertyDefinition cmisPropDef = createProperty(cmisMapping, propDef);
properties.put(cmisPropDef.getPropertyId(), cmisPropDef);
}
}
}
return properties;
}
/**
* Create Property Definition
*
* @param cmisMapping
* @param propDef
* @return
*/
private CMISPropertyDefinition createProperty(CMISMapping cmisMapping, PropertyDefinition propDef)
{
QName propertyQName = propDef.getName();
String propertyName = cmisMapping.getCmisPropertyName(propertyQName);
String propertyId = cmisMapping.getCmisPropertyId(propertyQName);
CMISPropertyId cmisPropertyId = new CMISPropertyId(propertyName, propertyId, propertyQName);
return new CMISPropertyDefinition(cmisMapping, cmisPropertyId, propDef, this);
}
/**
* Create Sub Types
*
* @param cmisMapping
* @param dictionaryService
*/
/*package*/ void createSubTypes(CMISMapping cmisMapping, DictionaryService dictionaryService)
{
Collection<QName> subTypes = dictionaryService.getSubTypes(objectTypeId.getQName(), false);
for (QName subType : subTypes)
{
if (cmisMapping.isValidCmisDocumentOrFolder(subType))
{
CMISTypeId subTypeId = cmisMapping.getCmisTypeId(subType);
if (subTypeId != null)
{
subTypeIds.add(subTypeId);
}
}
}
}
/**
* Resolve Dependencies
*
* @param registry
*/
/*package*/ void resolveDependencies(DictionaryRegistry registry)
{
if (parentTypeId != null)
{
parentType = registry.typeDefsByTypeId.get(parentTypeId);
if (parentType == null)
{
throw new AlfrescoRuntimeException("Failed to retrieve parent type for type id " + parentTypeId);
}
}
CMISTypeId rootTypeId = objectTypeId.getRootTypeId();
if (rootTypeId != null)
{
rootType = registry.typeDefsByTypeId.get(rootTypeId);
if (rootType == null)
{
throw new AlfrescoRuntimeException("Failed to retrieve root type for type id " + rootTypeId);
}
}
for (CMISTypeId subTypeId : subTypeIds)
{
CMISTypeDefinition subType = registry.typeDefsByTypeId.get(subTypeId);
if (subType == null)
{
throw new AlfrescoRuntimeException("Failed to retrieve sub type for type id " + subTypeId + " for parent type " + objectTypeId);
}
subTypes.add(subType);
}
}
/**
* Resolve Inheritance
*
* @param registry
*/
/*package*/ void resolveInheritance(DictionaryRegistry registry)
{
inheritedProperties.putAll(properties);
if (parentType != null)
{
inheritedProperties.putAll(parentType.getPropertyDefinitions());
}
}
/**
* Get the unique identifier for the type
*
* @return - the type id
*/
public CMISTypeId getTypeId()
{
return objectTypeId;
}
/**
* Get the table name used for queries against the type. This is also a unique identifier for the type. The string
* conforms to SQL table naming conventions. TODO: Should we impose a maximum length and if so how do we avoid
* collisions from truncations?
*
* @return the sql table name
*/
public String getQueryName()
{
return objectTypeQueryName;
}
/**
* Get the display name for the type.
*
* @return - the display name
*/
public String getDisplayName()
{
return displayName;
}
/**
* Get parent type
*
* @return
*/
public CMISTypeDefinition getParentType()
{
return parentType;
}
/**
* Get the root type
*
* @return
*/
public CMISTypeDefinition getRootType()
{
return rootType;
}
/**
* Get sub types
*
* @return
*/
public Collection<CMISTypeDefinition> getSubTypes(boolean includeDescendants)
{
if (!includeDescendants)
{
return subTypes;
}
// recurse sub-type hierarchy
Collection<CMISTypeDefinition> descendants = new ArrayList<CMISTypeDefinition>();
LinkedList<CMISTypeDefinition> stack = new LinkedList<CMISTypeDefinition>();
stack.addLast(this);
while (stack.size() > 0)
{
CMISTypeDefinition current = stack.removeLast();
if (!current.equals(this)) // do not add this type
{
descendants.add(current);
}
// descend...
for (CMISTypeDefinition type : current.getSubTypes(false))
{
stack.addLast(type);
}
}
return descendants;
}
/**
* Get the description for the type
*
* @return - the description
*/
public String getDescription()
{
return description;
}
/**
* Can objects of this type be created?
*
* @return
*/
public boolean isCreatable()
{
return creatable;
}
/**
* Is this type queryable? If not, the type may not appear in the FROM clause of a query. This property of the type
* is not inherited in the type hierarchy. It is set on each type.
*
* @return true if queryable
*/
public boolean isQueryable()
{
return queryable;
}
/**
* Are objects of this type controllable.
*
* @return
*/
public boolean isControllable()
{
return controllable;
}
/**
* Are objects of this type included in super type queries
*
* @return
*/
public boolean isIncludeInSuperTypeQuery()
{
return includeInSuperTypeQuery;
}
/**
* Gets the property definitions for this type
*
* @return property definitions
*/
public Map<CMISPropertyId, CMISPropertyDefinition> getPropertyDefinitions()
{
return inheritedProperties;
}
//
// Document Type specific
//
/**
* Is Fileable?
*
* @return
*/
public boolean isFileable()
{
return false;
}
/**
* Is Versionable?
*
* @return
*/
public boolean isVersionable()
{
return false;
}
/**
* Is Content Stream Allowed?
*
* @return
*/
public CMISContentStreamAllowedEnum getContentStreamAllowed()
{
return CMISContentStreamAllowedEnum.NOT_ALLOWED;
}
//
// Relationship Type specific
//
/**
* Get allowed source types
*
* @return
*/
public Collection<CMISTypeDefinition> getAllowedSourceTypes()
{
return Collections.emptyList();
}
/**
* Get allowed target types
*
* @return
*/
public Collection<CMISTypeDefinition> getAllowedTargetTypes()
{
return Collections.emptyList();
}
}

View File

@@ -0,0 +1,127 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program 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 2
* of the License, or (at your option) any later version.
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.cmis.dictionary;
import java.util.Collection;
import org.alfresco.cmis.dictionary.AbstractCMISDictionaryService.DictionaryRegistry;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.namespace.QName;
/**
* CMIS Policy Type Definition
*
* @author davidc
*/
public class CMISPolicyTypeDefinition extends CMISObjectTypeDefinition
{
private static final long serialVersionUID = 1621538303752395828L;
/**
* Construct
*
* @param cmisMapping
* @param typeId
* @param cmisClassDef
*/
public CMISPolicyTypeDefinition(CMISMapping cmisMapping, CMISTypeId typeId, ClassDefinition cmisClassDef)
{
this.cmisClassDef = cmisClassDef;
objectTypeId = typeId;
displayName = (cmisClassDef.getTitle() != null) ? cmisClassDef.getTitle() : typeId.getId();
if (typeId == CMISDictionaryModel.POLICY_TYPE_ID)
{
objectTypeQueryName = typeId.getId();
}
else
{
objectTypeQueryName = cmisMapping.buildPrefixEncodedString(typeId.getQName(), false);
parentTypeId = CMISDictionaryModel.POLICY_TYPE_ID;
}
description = cmisClassDef.getDescription();
creatable = false;
queryable = false;
controllable = false;
}
/*
* (non-Javadoc)
* @see org.alfresco.cmis.dictionary.CMISObjectTypeDefinition#createSubTypes(org.alfresco.cmis.dictionary.CMISMapping, org.alfresco.service.cmr.dictionary.DictionaryService)
*/
@Override
/*package*/ void createSubTypes(CMISMapping cmisMapping, DictionaryService dictionaryService)
{
if (objectTypeId.equals(CMISDictionaryModel.POLICY_TYPE_ID))
{
// all aspects are sub-type of POLICY_OBJECT_TYPE
Collection<QName> aspects = dictionaryService.getAllAspects();
for (QName aspect : aspects)
{
if (cmisMapping.isValidCmisPolicy(aspect))
{
subTypeIds.add(cmisMapping.getCmisTypeId(CMISScope.POLICY, aspect));
}
}
}
}
/*
* (non-Javadoc)
* @see org.alfresco.cmis.dictionary.CMISObjectTypeDefinition#resolveInheritance(org.alfresco.cmis.dictionary.AbstractCMISDictionaryService.DictionaryRegistry)
*/
@Override
/*package*/ void resolveInheritance(DictionaryRegistry registry)
{
// NOTE: Force no inheritance of base Policy type
inheritedProperties.putAll(properties);
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("CMISPolicyTypeDefinition[");
builder.append("ObjectTypeId=").append(getTypeId()).append(", ");
builder.append("ObjectTypeQueryName=").append(getQueryName()).append(", ");
builder.append("ObjectTypeDisplayName=").append(getDisplayName()).append(", ");
builder.append("ParentTypeId=").append(getParentType() == null ? "<none>" : getParentType().getTypeId()).append(", ");
builder.append("Description=").append(getDescription()).append(", ");
builder.append("Creatable=").append(isCreatable()).append(", ");
builder.append("Queryable=").append(isQueryable()).append(", ");
builder.append("Controllable=").append(isControllable()).append(", ");
builder.append("IncludeInSuperTypeQuery=").append(isIncludeInSuperTypeQuery()).append(", ");
builder.append("SubTypes=").append(getSubTypes(false).size()).append(", ");
builder.append("Properties=").append(getPropertyDefinitions().size());
builder.append("]");
return builder.toString();
}
}

View File

@@ -29,7 +29,7 @@ import java.util.Collection;
import java.util.HashSet;
import org.alfresco.cmis.CMISCardinalityEnum;
import org.alfresco.cmis.CMISPropertyTypeEnum;
import org.alfresco.cmis.CMISDataTypeEnum;
import org.alfresco.cmis.CMISUpdatabilityEnum;
import org.alfresco.repo.dictionary.IndexTokenisationMode;
import org.alfresco.repo.dictionary.constraint.ListOfValuesConstraint;
@@ -44,171 +44,129 @@ import org.alfresco.repo.search.impl.lucene.analysis.VerbatimAnalyser;
import org.alfresco.service.cmr.dictionary.Constraint;
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.namespace.QName;
/**
* A CMIS property definition
* CMIS Property Definition
*
* @author andyh
*/
public class CMISPropertyDefinition implements Serializable
{
/**
*
*/
private static final long serialVersionUID = -8119257313852558466L;
private String propertyName;
private String propertyId;
// Properties of Property
private CMISTypeDefinition typeDef;
private CMISPropertyId propertyId;
private String displayName;
private String description;
private boolean isInherited;
private CMISPropertyTypeEnum propertyType;
private CMISDataTypeEnum propertyType;
private CMISCardinalityEnum cardinality;
private int maximumLength = -1;
private String schemaURI = null;
private String encoding = null;
private Collection<CMISChoice> choices = new HashSet<CMISChoice>();
private boolean isOpenChoice = false;
private boolean required;
private String defaultValue;
private CMISUpdatabilityEnum updatability;
private boolean queryable;
private boolean orderable;
public CMISPropertyDefinition(CMISDictionaryService cmisDictionary, QName propertyQName, QName typeQName)
/**
* Construct
*
* @param cmisMapping
* @param propertyId
* @param propDef
* @param typeDef
*/
public CMISPropertyDefinition(CMISMapping cmisMapping, CMISPropertyId propertyId, PropertyDefinition propDef, CMISTypeDefinition typeDef)
{
CMISMapping cmisMapping = cmisDictionary.getCMISMapping();
PropertyDefinition propDef = cmisDictionary.getDictionaryService().getProperty(propertyQName);
if (propDef.getContainerClass().getName().equals(CMISMapping.RELATIONSHIP_QNAME))
this.propertyId = propertyId;
this.typeDef = typeDef;
displayName = (propDef.getTitle() != null) ? propDef.getTitle() : propertyId.getName();
description = propDef.getDescription();
propertyType = cmisMapping.getDataType(propDef.getDataType());
cardinality = propDef.isMultiValued() ? CMISCardinalityEnum.MULTI_VALUED : CMISCardinalityEnum.SINGLE_VALUED;
for (ConstraintDefinition constraintDef : propDef.getConstraints())
{
// Properties of associations - all the same
propertyName = cmisMapping.getCmisPropertyName(propertyQName);
propertyId = cmisMapping.getCmisPropertyId(propertyQName);
displayName = (propDef.getTitle() != null) ? propDef.getTitle() : propertyName;
description = propDef.getDescription();
isInherited = false;
propertyType = cmisMapping.getPropertyType(propertyQName);
cardinality = propDef.isMultiValued() ? CMISCardinalityEnum.MULTI_VALUED : CMISCardinalityEnum.SINGLE_VALUED;
required = propDef.isMandatory();
defaultValue = propDef.getDefaultValue();
updatability = propDef.isProtected() ? CMISUpdatabilityEnum.READ_ONLY : CMISUpdatabilityEnum.READ_AND_WRITE;
queryable = false;
orderable = false;
Constraint constraint = constraintDef.getConstraint();
if (constraint instanceof ListOfValuesConstraint)
{
int position = 1; // CMIS is 1 based (according to XSDs)
ListOfValuesConstraint lovc = (ListOfValuesConstraint) constraint;
for (String allowed : lovc.getAllowedValues())
{
CMISChoice choice = new CMISChoice(allowed, allowed, position++);
choices.add(choice);
}
}
if (constraint instanceof StringLengthConstraint)
{
StringLengthConstraint slc = (StringLengthConstraint) constraint;
maximumLength = slc.getMaxLength();
}
}
required = propDef.isMandatory();
defaultValue = propDef.getDefaultValue();
updatability = propDef.isProtected() ? CMISUpdatabilityEnum.READ_ONLY : CMISUpdatabilityEnum.READ_AND_WRITE;
queryable = propDef.isIndexed();
if (queryable)
{
IndexTokenisationMode indexTokenisationMode = IndexTokenisationMode.TRUE;
if (propDef.getIndexTokenisationMode() != null)
{
indexTokenisationMode = propDef.getIndexTokenisationMode();
}
switch (indexTokenisationMode)
{
case BOTH:
case FALSE:
orderable = true;
break;
case TRUE:
default:
String analyserClassName = propDef.getDataType().getAnalyserClassName();
if (analyserClassName.equals(DateTimeAnalyser.class.getCanonicalName())
|| analyserClassName.equals(DoubleAnalyser.class.getCanonicalName()) || analyserClassName.equals(FloatAnalyser.class.getCanonicalName())
|| analyserClassName.equals(IntegerAnalyser.class.getCanonicalName()) || analyserClassName.equals(LongAnalyser.class.getCanonicalName())
|| analyserClassName.equals(PathAnalyser.class.getCanonicalName()) || analyserClassName.equals(VerbatimAnalyser.class.getCanonicalName()))
{
orderable = true;
}
else
{
orderable = false;
}
}
}
else
{
propertyName = cmisMapping.getCmisPropertyName(propertyQName);
propertyId = cmisMapping.getCmisPropertyId(propertyQName);
displayName = (propDef.getTitle() != null) ? propDef.getTitle() : propertyName;
description = propDef.getDescription();
if(propDef.getContainerClass().isAspect())
{
isInherited = false;
}
else
{
isInherited = !propDef.getContainerClass().equals(typeQName);
}
propertyType = cmisMapping.getPropertyType(propertyQName);
cardinality = propDef.isMultiValued() ? CMISCardinalityEnum.MULTI_VALUED : CMISCardinalityEnum.SINGLE_VALUED;
for (ConstraintDefinition constraintDef : propDef.getConstraints())
{
Constraint constraint = constraintDef.getConstraint();
if (constraint instanceof ListOfValuesConstraint)
{
int position = 1; // CMIS is 1 based (according to XSDs)
ListOfValuesConstraint lovc = (ListOfValuesConstraint) constraint;
for (String allowed : lovc.getAllowedValues())
{
CMISChoice choice = new CMISChoice(allowed, allowed, position++);
choices.add(choice);
}
}
if (constraint instanceof StringLengthConstraint)
{
StringLengthConstraint slc = (StringLengthConstraint) constraint;
maximumLength = slc.getMaxLength();
}
}
required = propDef.isMandatory();
defaultValue = propDef.getDefaultValue();
updatability = propDef.isProtected() ? CMISUpdatabilityEnum.READ_ONLY : CMISUpdatabilityEnum.READ_AND_WRITE;
queryable = propDef.isIndexed();
if (queryable)
{
IndexTokenisationMode indexTokenisationMode = IndexTokenisationMode.TRUE;
if (propDef.getIndexTokenisationMode() != null)
{
indexTokenisationMode = propDef.getIndexTokenisationMode();
}
switch (indexTokenisationMode)
{
case BOTH:
case FALSE:
orderable = true;
break;
case TRUE:
default:
String analyserClassName = propDef.getDataType().getAnalyserClassName();
if (analyserClassName.equals(DateTimeAnalyser.class.getCanonicalName())
|| analyserClassName.equals(DoubleAnalyser.class.getCanonicalName()) || analyserClassName.equals(FloatAnalyser.class.getCanonicalName())
|| analyserClassName.equals(IntegerAnalyser.class.getCanonicalName()) || analyserClassName.equals(LongAnalyser.class.getCanonicalName())
|| analyserClassName.equals(PathAnalyser.class.getCanonicalName()) || analyserClassName.equals(VerbatimAnalyser.class.getCanonicalName()))
{
orderable = true;
}
else
{
orderable = false;
}
}
}
else
{
orderable = false;
}
orderable = false;
}
}
/**
* Get the property name
* Get Property Id
*
* @return
*/
public String getPropertyName()
{
return propertyName;
}
/**
* Get the property id
*
* @return
*/
public String getPropertyId()
public CMISPropertyId getPropertyId()
{
return propertyId;
}
/**
* Get Owning Type
*
* @return
*/
public CMISTypeDefinition getOwningType()
{
return typeDef;
}
/**
* Get the display name
*
@@ -228,23 +186,13 @@ public class CMISPropertyDefinition implements Serializable
{
return description;
}
/**
* Is the property definition inherited?
*
* @return
*/
public boolean isInherited()
{
return isInherited;
}
/**
* Get the property type
*
* @return
*/
public CMISPropertyTypeEnum getPropertyType()
public CMISDataTypeEnum getDataType()
{
return propertyType;
}
@@ -359,16 +307,21 @@ public class CMISPropertyDefinition implements Serializable
return orderable;
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("CMISPropertyDefinition[");
builder.append("PropertyName=").append(getPropertyName()).append(", ");
builder.append("PropertyId=").append(getPropertyId()).append(", ");
builder.append("OwningTypeId=").append(getOwningType().getTypeId()).append(", ");
builder.append("PropertyName=").append(getPropertyId().getName()).append(", ");
builder.append("PropertyId=").append(getPropertyId().getId()).append(", ");
builder.append("DisplayName=").append(getDisplayName()).append(", ");
builder.append("Description=").append(getDescription()).append(", ");
builder.append("IsInherited=").append(isInherited()).append(", ");
builder.append("PropertyType=").append(getPropertyType()).append(", ");
builder.append("PropertyType=").append(getDataType()).append(", ");
builder.append("Cardinality=").append(getCardinality()).append(", ");
builder.append("MaximumLength=").append(getMaximumLength()).append(", ");
builder.append("SchemaURI=").append(getSchemaURI()).append(", ");

View File

@@ -0,0 +1,138 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program 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 2
* of the License, or (at your option) any later version.
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.cmis.dictionary;
import java.io.Serializable;
import org.alfresco.service.namespace.QName;
/**
* CMIS Property Id
*
* @author davidc
*/
public class CMISPropertyId implements Serializable
{
private static final long serialVersionUID = 4094778633095367606L;
// Id properties
private String propertyName;
private String propertyId;
private QName qName;
/**
* Construct
*
* @param propertyName
* @param propertyId
* @param qName
*/
public CMISPropertyId(String propertyName, String propertyId, QName qName)
{
this.propertyName = propertyName;
this.propertyId = propertyId;
this.qName = qName;
}
/**
* Get property name
*
* @return
*/
public String getName()
{
return propertyName;
}
/**
* Get property id
*
* @return
*/
public String getId()
{
return propertyId;
}
/**
* Get the Alfresco model QName associated with the property
*
* @return alfresco QName
*/
public QName getQName()
{
return qName;
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
return getName();
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((propertyName == null) ? 0 : propertyName.hashCode());
return result;
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final CMISPropertyId other = (CMISPropertyId) obj;
if (propertyName == null)
{
if (other.propertyName != null)
return false;
}
else if (!propertyName.equals(other.propertyName))
return false;
return true;
}
}

View File

@@ -0,0 +1,240 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program 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 2
* of the License, or (at your option) any later version.
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.cmis.dictionary;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.alfresco.cmis.dictionary.AbstractCMISDictionaryService.DictionaryRegistry;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.namespace.QName;
/**
* CMIS Relationship Type Definition
*
* @author davidc
*/
public class CMISRelationshipTypeDefinition extends CMISObjectTypeDefinition
{
private static final long serialVersionUID = 5291428171784061346L;
// Relationship properties
private List<CMISTypeId> allowedSourceTypeIds = new ArrayList<CMISTypeId>();
private List<CMISTypeDefinition> allowedSourceTypes = new ArrayList<CMISTypeDefinition>();
private List<CMISTypeDefinition> inheritedAllowedSourceTypes = new ArrayList<CMISTypeDefinition>();
private List<CMISTypeId> allowedTargetTypeIds = new ArrayList<CMISTypeId>();
private List<CMISTypeDefinition> allowedTargetTypes = new ArrayList<CMISTypeDefinition>();
private List<CMISTypeDefinition> inheritedAllowedTargetTypes = new ArrayList<CMISTypeDefinition>();
/**
* Construct
*
* @param cmisMapping
* @param typeId
* @param cmisClassDef
* @param assocDef
*/
public CMISRelationshipTypeDefinition(CMISMapping cmisMapping, CMISTypeId typeId, ClassDefinition cmisClassDef, AssociationDefinition assocDef)
{
this.cmisClassDef = cmisClassDef;
objectTypeId = typeId;
creatable = false;
queryable = false;
controllable = false;
if (assocDef == null)
{
// TODO: Add CMIS Association mapping??
displayName = (cmisClassDef.getTitle() != null) ? cmisClassDef.getTitle() : typeId.getId();
objectTypeQueryName = typeId.getId();
parentTypeId = null;
description = cmisClassDef.getDescription();
}
else
{
displayName = (assocDef.getTitle() != null) ? assocDef.getTitle() : typeId.getId();
objectTypeQueryName = cmisMapping.buildPrefixEncodedString(typeId.getQName(), false);
parentTypeId = CMISDictionaryModel.RELATIONSHIP_TYPE_ID;
description = assocDef.getDescription();
CMISTypeId sourceTypeId = cmisMapping.getCmisTypeId(cmisMapping.getCmisType(assocDef.getSourceClass().getName()));
if (sourceTypeId != null && (sourceTypeId.getScope() == CMISScope.DOCUMENT || sourceTypeId.getScope() == CMISScope.FOLDER))
{
allowedSourceTypeIds.add(sourceTypeId);
}
CMISTypeId targetTypeId = cmisMapping.getCmisTypeId(cmisMapping.getCmisType(assocDef.getTargetClass().getName()));
if (targetTypeId != null && (targetTypeId.getScope() == CMISScope.DOCUMENT || targetTypeId.getScope() == CMISScope.FOLDER))
{
allowedTargetTypeIds.add(targetTypeId);
}
}
}
/*
* (non-Javadoc)
* @see org.alfresco.cmis.dictionary.CMISObjectTypeDefinition#createProperties(org.alfresco.cmis.dictionary.CMISMapping, org.alfresco.service.cmr.dictionary.DictionaryService)
*/
@Override
/*package*/ Map<CMISPropertyId, CMISPropertyDefinition> createProperties(CMISMapping cmisMapping, DictionaryService dictionaryService)
{
if (objectTypeId.equals(CMISDictionaryModel.RELATIONSHIP_TYPE_ID))
{
return super.createProperties(cmisMapping, dictionaryService);
}
return properties;
}
/*
* (non-Javadoc)
* @see org.alfresco.cmis.dictionary.CMISObjectTypeDefinition#createSubTypes(org.alfresco.cmis.dictionary.CMISMapping, org.alfresco.service.cmr.dictionary.DictionaryService)
*/
@Override
/*package*/ void createSubTypes(CMISMapping cmisMapping, DictionaryService dictionaryService)
{
if (objectTypeId.equals(CMISDictionaryModel.RELATIONSHIP_TYPE_ID))
{
// all associations are sub-type of RELATIONSHIP_OBJECT_TYPE
Collection<QName> assocs = dictionaryService.getAllAssociations();
for (QName assoc : assocs)
{
if (cmisMapping.isValidCmisRelationship(assoc))
{
subTypeIds.add(cmisMapping.getCmisTypeId(CMISScope.RELATIONSHIP, assoc));
}
}
}
}
/*
* (non-Javadoc)
* @see org.alfresco.cmis.dictionary.CMISObjectTypeDefinition#resolveDependencies(org.alfresco.cmis.dictionary.AbstractCMISDictionaryService.DictionaryRegistry)
*/
@Override
/*package*/ void resolveDependencies(DictionaryRegistry registry)
{
super.resolveDependencies(registry);
for (CMISTypeId sourceTypeId : allowedSourceTypeIds)
{
CMISTypeDefinition type = registry.typeDefsByTypeId.get(sourceTypeId);
if (type == null)
{
throw new AlfrescoRuntimeException("Failed to retrieve allowed source type for type id " + sourceTypeId);
}
allowedSourceTypes.add(type);
}
for (CMISTypeId targetTypeId : allowedTargetTypeIds)
{
CMISTypeDefinition type = registry.typeDefsByTypeId.get(targetTypeId);
if (type == null)
{
throw new AlfrescoRuntimeException("Failed to retrieve allowed target type for type id " + targetTypeId);
}
allowedTargetTypes.add(registry.typeDefsByTypeId.get(targetTypeId));
}
}
/*
* (non-Javadoc)
* @see org.alfresco.cmis.dictionary.CMISObjectTypeDefinition#resolveInheritance(org.alfresco.cmis.dictionary.AbstractCMISDictionaryService.DictionaryRegistry)
*/
@Override
/*package*/ void resolveInheritance(DictionaryRegistry registry)
{
super.resolveInheritance(registry);
inheritedAllowedSourceTypes.addAll(allowedSourceTypes);
inheritedAllowedTargetTypes.addAll(allowedTargetTypes);
if (parentType != null)
{
inheritedAllowedSourceTypes.addAll(parentType.getAllowedSourceTypes());
inheritedAllowedTargetTypes.addAll(parentType.getAllowedTargetTypes());
}
}
/**
* For an association, get the collection of valid source types. For non-associations the collection will be empty.
*
* @return
*/
public Collection<CMISTypeDefinition> getAllowedSourceTypes()
{
return inheritedAllowedSourceTypes;
}
/**
* For an association, get the collection of valid target types. For non-associations the collection will be empty.
*
* @return
*/
public Collection<CMISTypeDefinition> getAllowedTargetTypes()
{
return inheritedAllowedTargetTypes;
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("CMISRelationshipTypeDefinition[");
builder.append("ObjectTypeId=").append(getTypeId()).append(", ");
builder.append("ObjectTypeQueryName=").append(getQueryName()).append(", ");
builder.append("ObjectTypeDisplayName=").append(getDisplayName()).append(", ");
builder.append("ParentTypeId=").append(getParentType() == null ? "<none>" : getParentType().getTypeId()).append(", ");
builder.append("Description=").append(getDescription()).append(", ");
builder.append("Creatable=").append(isCreatable()).append(", ");
builder.append("Queryable=").append(isQueryable()).append(", ");
builder.append("Controllable=").append(isControllable()).append(", ");
builder.append("IncludeInSuperTypeQuery=").append(isIncludeInSuperTypeQuery()).append(", ");
builder.append("AllowedSourceTypes=[");
for (CMISTypeDefinition type : getAllowedSourceTypes())
{
builder.append(type.getTypeId()).append(",");
}
builder.append("], ");
builder.append("AllowedTargetTypes=[");
for (CMISTypeDefinition type : getAllowedTargetTypes())
{
builder.append(type.getTypeId()).append(",");
}
builder.append("], ");
builder.append("SubTypes=").append(getSubTypes(false).size()).append(", ");
builder.append("Properties=").append(getPropertyDefinitions().size());
builder.append("]");
return builder.toString();
}
}

View File

@@ -0,0 +1,121 @@
/*
* Copyright (C) 2005-20079 Alfresco Software Limited.
*
* This program 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 2
* of the License, or (at your option) any later version.
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.cmis.dictionary;
import java.util.Collection;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.namespace.QName;
/**
* CMIS Dictionary which provides Types that strictly conform to the CMIS specification.
*
* That is, only maps types to one of root Document, Folder, Relationship & Policy.
*
* @author davidc
*/
public class CMISStrictDictionaryService extends AbstractCMISDictionaryService
{
/*
* (non-Javadoc)
* @see org.alfresco.cmis.dictionary.AbstractCMISDictionaryService#createDefinitions(org.alfresco.cmis.dictionary.AbstractCMISDictionaryService.DictionaryRegistry)
*/
@Override
protected void createDefinitions(DictionaryRegistry registry)
{
createTypeDefs(registry, dictionaryService.getAllTypes());
createAssocDefs(registry, dictionaryService.getAllAssociations());
createTypeDefs(registry, dictionaryService.getAllAspects());
}
/**
* Create Type Definitions
*
* @param registry
* @param classQNames
*/
private void createTypeDefs(DictionaryRegistry registry, Collection<QName> classQNames)
{
for (QName classQName : classQNames)
{
// skip items that are remapped to CMIS model
if (cmisMapping.isRemappedType(classQName))
continue;
// skip all items that are not mapped to CMIS model
CMISTypeId typeId = cmisMapping.getCmisTypeId(classQName);
if (typeId == null)
continue;
// create appropriate kind of type definition
ClassDefinition classDef = dictionaryService.getClass(cmisMapping.getCmisType(typeId.getQName()));
CMISObjectTypeDefinition objectTypeDef = null;
if (typeId.getScope() == CMISScope.DOCUMENT)
{
objectTypeDef = new CMISDocumentTypeDefinition(cmisMapping, typeId, classDef);
}
else if (typeId.getScope() == CMISScope.FOLDER)
{
objectTypeDef = new CMISFolderTypeDefinition(cmisMapping, typeId, classDef);
}
else if (typeId.getScope() == CMISScope.RELATIONSHIP)
{
AssociationDefinition assocDef = dictionaryService.getAssociation(classQName);
objectTypeDef = new CMISRelationshipTypeDefinition(cmisMapping, typeId, classDef, assocDef);
}
else if (typeId.getScope() == CMISScope.POLICY)
{
objectTypeDef = new CMISPolicyTypeDefinition(cmisMapping, typeId, classDef);
}
registry.registerTypeDefinition(objectTypeDef);
}
}
/**
* Create Relationship Definitions
*
* @param registry
* @param classQNames
*/
private void createAssocDefs(DictionaryRegistry registry, Collection<QName> classQNames)
{
for (QName classQName : classQNames)
{
if (!cmisMapping.isValidCmisRelationship(classQName))
continue;
// create appropriate kind of type definition
CMISTypeId typeId = cmisMapping.getCmisTypeId(CMISScope.RELATIONSHIP, classQName);
AssociationDefinition assocDef = dictionaryService.getAssociation(classQName);
CMISObjectTypeDefinition objectTypeDef = new CMISRelationshipTypeDefinition(cmisMapping, typeId, null, assocDef);
registry.registerTypeDefinition(objectTypeDef);
}
}
}

View File

@@ -22,249 +22,26 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.cmis.dictionary;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.alfresco.cmis.CMISContentStreamAllowedEnum;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.namespace.QName;
/**
* The base type definition for CMIS
*
* @author andyh
*/
public class CMISTypeDefinition implements Serializable
public interface CMISTypeDefinition
{
/**
*
*/
private static final long serialVersionUID = -2216695347624799934L;
private CMISDictionaryService cmisDictionary;
private CMISTypeId objectTypeId;
private String objectTypeQueryName;
private String displayName;
private CMISTypeId parentTypeId;
private String rootTypeQueryName;
private String description;
private boolean creatable;
private boolean fileable;
private boolean queryable;
// TODO: Policy - report controllable true as policies can be applied
private boolean controllable;
private boolean versionable;
private boolean includedInSupertypeQuery;
private CMISContentStreamAllowedEnum contentStreamAllowed;
private boolean isAssociation;
private ArrayList<CMISTypeId> allowedSourceTypes = new ArrayList<CMISTypeId>(1);
private ArrayList<CMISTypeId> allowedTargetTypes = new ArrayList<CMISTypeId>(1);
/**
* Construct
*
* @param cmisDictionary
* @param typeId
*/
public CMISTypeDefinition(CMISDictionaryService cmisDictionary, CMISTypeId typeId)
{
this.cmisDictionary = cmisDictionary;
DictionaryService dictionaryService = this.cmisDictionary.getDictionaryService();
CMISMapping cmisMapping = cmisDictionary.getCMISMapping();
switch (typeId.getScope())
{
case RELATIONSHIP:
AssociationDefinition associationDefinition = dictionaryService.getAssociation(typeId.getQName());
if (associationDefinition != null)
{
objectTypeId = typeId;
objectTypeQueryName = cmisMapping.getQueryName(typeId.getQName());
displayName = (associationDefinition.getTitle() != null) ? associationDefinition.getTitle() : typeId.getTypeId();
parentTypeId = CMISMapping.RELATIONSHIP_TYPE_ID;
rootTypeQueryName = cmisMapping.getQueryName(CMISMapping.RELATIONSHIP_QNAME);
description = associationDefinition.getDescription();
creatable = false;
fileable = false;
queryable = false;
controllable = false;
versionable = false;
includedInSupertypeQuery = true;
contentStreamAllowed = CMISContentStreamAllowedEnum.NOT_ALLOWED;
isAssociation = true;
QName sourceType = cmisMapping.getCmisType(associationDefinition.getSourceClass().getName());
if (cmisMapping.isValidCmisDocument(sourceType))
{
allowedSourceTypes.add(cmisMapping.getCmisTypeId(CMISScope.DOCUMENT, sourceType));
}
else if (cmisMapping.isValidCmisFolder(sourceType))
{
allowedSourceTypes.add(cmisMapping.getCmisTypeId(CMISScope.FOLDER, sourceType));
}
QName targetType = cmisMapping.getCmisType(associationDefinition.getTargetClass().getName());
if (cmisMapping.isValidCmisDocument(targetType))
{
allowedTargetTypes.add(cmisMapping.getCmisTypeId(CMISScope.DOCUMENT, targetType));
}
else if (cmisMapping.isValidCmisFolder(targetType))
{
allowedTargetTypes.add(cmisMapping.getCmisTypeId(CMISScope.FOLDER, targetType));
}
}
else
{
// TODO: Add CMIS Association mapping??
TypeDefinition typeDefinition = dictionaryService.getType(typeId.getQName());
objectTypeId = typeId;
objectTypeQueryName = cmisMapping.getQueryName(typeId.getQName());
displayName = (typeDefinition.getTitle() != null) ? typeDefinition.getTitle() : typeId.getTypeId();
parentTypeId = null;
rootTypeQueryName = cmisMapping.getQueryName(CMISMapping.RELATIONSHIP_QNAME);
description = typeDefinition.getDescription();
creatable = false;
fileable = false;
queryable = false;
controllable = false;
versionable = false;
includedInSupertypeQuery = true;
contentStreamAllowed = CMISContentStreamAllowedEnum.NOT_ALLOWED;
isAssociation = true;
}
break;
case DOCUMENT:
case FOLDER:
ClassDefinition typeDefinition = dictionaryService.getType(typeId.getQName());
if (typeDefinition != null)
{
objectTypeId = typeId;
objectTypeQueryName = cmisMapping.getQueryName(typeId.getQName());
displayName = (typeDefinition.getTitle() != null) ? typeDefinition.getTitle() : typeId.getTypeId();
QName parentTypeQName = cmisMapping.getCmisType(typeDefinition.getParentName());
if (parentTypeQName == null)
{
// Core and unknown types
parentTypeId = null;
}
else
{
if (cmisMapping.isValidCmisDocument(parentTypeQName))
{
parentTypeId = cmisMapping.getCmisTypeId(CMISScope.DOCUMENT, parentTypeQName);
}
else if (cmisMapping.isValidCmisFolder(parentTypeQName))
{
parentTypeId = cmisMapping.getCmisTypeId(CMISScope.FOLDER, parentTypeQName);
}
}
rootTypeQueryName = cmisMapping.getQueryName(typeId.getRootTypeId().getQName());
description = typeDefinition.getDescription();
creatable = true;
fileable = true;
queryable = true;
controllable = false;
versionable = false;
includedInSupertypeQuery = true;
if (typeId.getScope() == CMISScope.DOCUMENT)
{
List<AspectDefinition> defaultAspects = typeDefinition.getDefaultAspects();
for (AspectDefinition aspectDefinition : defaultAspects)
{
if (aspectDefinition.getName().equals(ContentModel.ASPECT_VERSIONABLE))
{
versionable = true;
break;
}
}
}
if (typeId.getScope() == CMISScope.DOCUMENT)
{
contentStreamAllowed = CMISContentStreamAllowedEnum.ALLOWED;
}
else
{
contentStreamAllowed = CMISContentStreamAllowedEnum.NOT_ALLOWED;
}
}
break;
case POLICY:
ClassDefinition classDefinition = dictionaryService.getType(typeId.getQName());
if (classDefinition != null)
{
objectTypeId = typeId;
objectTypeQueryName = cmisMapping.getQueryName(typeId.getQName());
displayName = (classDefinition.getTitle() != null) ? classDefinition.getTitle() : typeId.getTypeId();
parentTypeId = CMISMapping.POLICY_TYPE_ID;
rootTypeQueryName = cmisMapping.getQueryName(CMISMapping.POLICY_QNAME);
description = classDefinition.getDescription();
creatable = false;
fileable = false;
queryable = false;
controllable = false;
versionable = false;
includedInSupertypeQuery = true;
contentStreamAllowed = CMISContentStreamAllowedEnum.NOT_ALLOWED;
}
break;
case UNKNOWN:
default:
break;
}
}
/**
* Get the unique identifier for the type
*
* @return - the type id
*/
public CMISTypeId getObjectTypeId()
{
return objectTypeId;
}
public CMISTypeId getTypeId();
/**
* Get the table name used for queries against the type. This is also a unique identifier for the type. The string
@@ -273,80 +50,50 @@ public class CMISTypeDefinition implements Serializable
*
* @return the sql table name
*/
public String getObjectTypeQueryName()
{
return objectTypeQueryName;
}
public String getQueryName();
/**
* Get the display name for the type.
*
* @return - the display name
*/
public String getObjectTypeDisplayName()
{
return displayName;
}
public String getDisplayName();
/**
* Get the type id for the parent
*
* @return - the parent type id
*/
public CMISTypeId getParentTypeId()
{
return parentTypeId;
}
public CMISTypeDefinition getParentType();
public Collection<CMISTypeDefinition> getSubTypes(boolean descendants);
/**
* Get the root type id
* @return - the root type id
*/
public CMISTypeId getRootTypeId()
{
return objectTypeId.getRootTypeId();
}
public CMISTypeDefinition getRootType();
/**
* Get the sql table name for the root type of this type This will be getObjectTypeQueryName() for the base folder,
* document or association
*
* @return - the sql table name for the root type
*/
public String getRootTypeQueryName()
{
return rootTypeQueryName;
}
/**
* Get the description for the type
*
* @return - the description
*/
public String getDescription()
{
return description;
}
public String getDescription();
/**
* Can objects of this type be created?
*
* @return
*/
public boolean isCreatable()
{
return creatable;
}
public boolean isCreatable();
/**
* Are objects of this type fileable?
*
* @return
*/
public boolean isFileable()
{
return fileable;
}
public boolean isFileable();
/**
* Is this type queryable? If not, the type may not appear in the FROM clause of a query. This property of the type
@@ -354,112 +101,55 @@ public class CMISTypeDefinition implements Serializable
*
* @return true if queryable
*/
public boolean isQueryable()
{
return queryable;
}
public boolean isQueryable();
/**
* Are objects of this type controllable.
*
* @return
*/
public boolean isControllable()
{
return controllable;
}
public boolean isControllable();
/**
* Are objects of this type included in super type queries
*
* @return
*/
public boolean isIncludedInSupertypeQuery()
{
return includedInSupertypeQuery;
}
public boolean isIncludeInSuperTypeQuery();
/**
* Is this type versionable? If true this implies all instances of the type are versionable.
*
* @return true if versionable
*/
public boolean isVersionable()
{
return versionable;
}
public boolean isVersionable();
/**
* Is a content stream allowed for this type? It may be disallowed, optional or mandatory.
*
* @return
*/
public CMISContentStreamAllowedEnum getContentStreamAllowed()
{
return contentStreamAllowed;
}
/**
* Is this an association type?
*
* @return true for an association type.
*/
public boolean isAssociation()
{
return isAssociation;
}
public CMISContentStreamAllowedEnum getContentStreamAllowed();
/**
* For an association, get the collection of valid source types. For non-associations the collection will be empty.
*
* @return
*/
public Collection<CMISTypeId> getAllowedSourceTypes()
{
return allowedSourceTypes;
}
public Collection<CMISTypeDefinition> getAllowedSourceTypes();
/**
* For an association, get the collection of valid target types. For non-associations the collection will be empty.
*
* @return
*/
public Collection<CMISTypeId> getAllowedTargetTypes()
{
return allowedTargetTypes;
}
public Collection<CMISTypeDefinition> getAllowedTargetTypes();
/**
* Gets the property definitions for this type
*
* @return property definitions
*/
public Map<String, CMISPropertyDefinition> getPropertyDefinitions()
{
return cmisDictionary.getPropertyDefinitions(objectTypeId);
}
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("CMISTypeDefinition[");
builder.append("ObjectTypeId=").append(getObjectTypeId()).append(", ");
builder.append("ObjectTypeQueryName=").append(getObjectTypeQueryName()).append(", ");
builder.append("ObjectTypeDisplayName=").append(getObjectTypeDisplayName()).append(", ");
builder.append("ParentTypeId=").append(getParentTypeId()).append(", ");
builder.append("RootTypeQueryName=").append(getRootTypeQueryName()).append(", ");
builder.append("Description=").append(getDescription()).append(", ");
builder.append("Creatable=").append(isCreatable()).append(", ");
builder.append("Fileable=").append(isFileable()).append(", ");
builder.append("Queryable=").append(isQueryable()).append(", ");
builder.append("Controllable=").append(isControllable()).append(", ");
builder.append("Versionable=").append(isVersionable()).append(", ");
builder.append("ContentStreamAllowed=").append(getContentStreamAllowed()).append(", ");
builder.append("IsAssociation=").append(isAssociation()).append(", ");
builder.append("AllowedSourceTypes=").append(getAllowedSourceTypes()).append(", ");
builder.append("AllowedTargetTypes=").append(getAllowedTargetTypes());
builder.append("]");
return builder.toString();
}
public Map<CMISPropertyId, CMISPropertyDefinition> getPropertyDefinitions();
}

View File

@@ -29,49 +29,42 @@ import java.io.Serializable;
import org.alfresco.service.namespace.QName;
/**
* A CMIS property type id
* CMIS Type Id
*
* @author andyh
*
*/
public class CMISTypeId implements Serializable
{
/**
*
*/
private static final long serialVersionUID = -4709046883083948302L;
private String typeId;
private CMISScope scope;
private QName qName;
public CMISTypeId(CMISScope scope, QName qName, String typeId)
/**
* Construct
*
* @param scope
* @param typeId
* @param qName
*/
public CMISTypeId(CMISScope scope, String typeId, QName qName)
{
this.scope = scope;
this.qName = qName;
this.typeId = typeId;
this.qName = qName;
}
/**
* Get the CMIS type id string
* @return
*/
public String getTypeId()
public String getId()
{
return typeId;
}
/**
* Get the Alfresco model QName associated with the type
* @return
*/
public QName getQName()
{
return qName;
}
/**
* Get the scope for the type (Doc, Folder, Relationship or unknown)
* @return
@@ -81,6 +74,16 @@ public class CMISTypeId implements Serializable
return scope;
}
/**
* Get the Alfresco model QName associated with the type
*
* @return alfresco QName
*/
public QName getQName()
{
return qName;
}
/**
* Get the root type id
* @return
@@ -90,13 +93,13 @@ public class CMISTypeId implements Serializable
switch (scope)
{
case DOCUMENT:
return CMISMapping.DOCUMENT_TYPE_ID;
return CMISDictionaryModel.DOCUMENT_TYPE_ID;
case FOLDER:
return CMISMapping.FOLDER_TYPE_ID;
return CMISDictionaryModel.FOLDER_TYPE_ID;
case RELATIONSHIP:
return CMISMapping.RELATIONSHIP_TYPE_ID;
return CMISDictionaryModel.RELATIONSHIP_TYPE_ID;
case POLICY:
return CMISMapping.POLICY_TYPE_ID;
return CMISDictionaryModel.POLICY_TYPE_ID;
case UNKNOWN:
default:
return null;
@@ -105,7 +108,7 @@ public class CMISTypeId implements Serializable
public String toString()
{
return getTypeId();
return getId();
}
@Override