diff --git a/source/java/org/alfresco/cmis/CMISServices.java b/source/java/org/alfresco/cmis/CMISServices.java index 0eee7e4502..7e167f4228 100644 --- a/source/java/org/alfresco/cmis/CMISServices.java +++ b/source/java/org/alfresco/cmis/CMISServices.java @@ -23,6 +23,7 @@ import java.io.Serializable; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.NodeRef; @@ -151,7 +152,7 @@ public interface CMISServices public AssociationRef[] getRelationships(NodeRef node, CMISTypeDefinition relDef, boolean includeSubTypes, CMISRelationshipDirectionEnum direction) throws CMISInvalidArgumentException; /** - * Get a single property for a node. + * Get a single property belonging to the node's type. * * @param nodeRef * the node @@ -163,6 +164,22 @@ public interface CMISServices */ public Serializable getProperty(NodeRef nodeRef, String propertyName) throws CMISInvalidArgumentException; + /** + * Get a single property, optionally constrained to a given node type or aspect + * + * @param nodeRef + * the node + * @param typeDef + * the node type or aspect or null if any property can be returned + * @param propertyName + * the property name + * @return value + * @throws CMISInvalidArgumentException + * if an argument is invalid + */ + public Serializable getProperty(NodeRef nodeRef, CMISTypeDefinition typeDef, String propertyName) + throws CMISInvalidArgumentException; + /** * Get a single property for an association. * @@ -175,7 +192,7 @@ public interface CMISServices public Serializable getProperty(AssociationRef assocRef, String propertyName); /** - * Get all properties. + * Get all properties of a node's type. * * @param nodeRef * the node ref @@ -186,7 +203,32 @@ public interface CMISServices public Map getProperties(NodeRef nodeRef) throws CMISInvalidArgumentException; /** - * Set a single property. + * Get all of a node's values for the properties in the given type or aspect. + * + * @param nodeRef + * the node ref + * @param typeDef + * the type or aspect definition + * @return the properties + * @throws CMISInvalidArgumentException + * if an argument is invalid + */ + public Map getProperties(NodeRef nodeRef, CMISTypeDefinition typeDef) + throws CMISInvalidArgumentException; + + /** + * Gets the aspects applied to a node. + * + * @param nodeRef + * the node ref + * @return the aspect definitions + * @throws CMISInvalidArgumentException + * if an argument is invalid + */ + public Set getAspects(NodeRef nodeRef); + + /** + * Set a single property belonging to the node's type. * * @param nodeRef * the node ref @@ -196,9 +238,47 @@ public interface CMISServices * the value * @throws CMISInvalidArgumentException * if an argument is invalid + * @throws CMISConstraintException + * if the property cannot be set */ - public void setProperty(NodeRef nodeRef, String propertyName, Serializable value) throws CMISInvalidArgumentException; - + public void setProperty(NodeRef nodeRef, String propertyName, Serializable value) + throws CMISInvalidArgumentException, CMISConstraintException; + + /** + * Set a single property, optionally constrained to a given node type or aspect + * + * @param nodeRef + * the node ref + * @param typeDef + * the node type or aspect or null if any valid property should be set (corresponding aspect + * added automatically). + * @param propertyName + * the property name + * @param value + * the value + * @throws CMISInvalidArgumentException + * if an argument is invalid + * @throws CMISConstraintException + * if the property cannot be set + */ + public void setProperty(NodeRef nodeRef, CMISTypeDefinition typeDef, String propertyName, Serializable value) + throws CMISInvalidArgumentException, CMISConstraintException; + + /** + * Sets the aspects on a node (Alfresco extension). + * + * @param node + * the node + * @param aspectsToRemove + * the aspects to remove + * @param aspectsToAdd + * the aspects to add + * @throws CMISInvalidArgumentException + * if an argument is invalid + */ + public void setAspects(NodeRef node, Iterable aspectsToRemove, Iterable aspectsToAdd) + throws CMISInvalidArgumentException; + /** * Applies a versioning state to a new node, potentially resulting in a new node. * diff --git a/source/java/org/alfresco/cmis/mapping/CMISServicesImpl.java b/source/java/org/alfresco/cmis/mapping/CMISServicesImpl.java index 8043ede029..312d035e55 100644 --- a/source/java/org/alfresco/cmis/mapping/CMISServicesImpl.java +++ b/source/java/org/alfresco/cmis/mapping/CMISServicesImpl.java @@ -26,9 +26,11 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -36,6 +38,7 @@ import java.util.regex.Pattern; import org.alfresco.cmis.CMISConstraintException; import org.alfresco.cmis.CMISContentAlreadyExistsException; import org.alfresco.cmis.CMISContentStreamAllowedEnum; +import org.alfresco.cmis.CMISDataTypeEnum; import org.alfresco.cmis.CMISDictionaryModel; import org.alfresco.cmis.CMISDictionaryService; import org.alfresco.cmis.CMISFilterNotValidException; @@ -54,6 +57,7 @@ import org.alfresco.cmis.CMISServices; import org.alfresco.cmis.CMISStreamNotSupportedException; import org.alfresco.cmis.CMISTypeDefinition; import org.alfresco.cmis.CMISTypesFilterEnum; +import org.alfresco.cmis.CMISUpdatabilityEnum; import org.alfresco.cmis.CMISVersioningException; import org.alfresco.cmis.CMISVersioningStateEnum; import org.alfresco.cmis.dictionary.CMISFolderTypeDefinition; @@ -74,10 +78,12 @@ import org.alfresco.service.cmr.coci.CheckOutCheckInService; import org.alfresco.service.cmr.coci.CheckOutCheckInServiceException; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.InvalidAspectException; import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.MimetypeService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; @@ -699,12 +705,24 @@ public class CMISServicesImpl implements CMISServices, ApplicationContextAware, */ public Serializable getProperty(NodeRef nodeRef, String propertyName) throws CMISInvalidArgumentException { - CMISTypeDefinition typeDef = getTypeDefinition(nodeRef); + return getProperty(nodeRef, getTypeDefinition(nodeRef), propertyName); + } + + public Serializable getProperty(NodeRef nodeRef, CMISTypeDefinition typeDef, String propertyName) + throws CMISInvalidArgumentException + { CMISPropertyDefinition propDef = cmisDictionaryService.findProperty(propertyName, typeDef); if (propDef == null) { - throw new CMISInvalidArgumentException("Property " + propertyName + " not found for type " - + typeDef.getTypeId() + " in CMIS Dictionary"); + if (typeDef == null) + { + throw new CMISInvalidArgumentException("Property " + propertyName + " not found in CMIS Dictionary"); + } + else + { + throw new CMISInvalidArgumentException("Property " + propertyName + " not found for type " + + typeDef.getTypeId() + " in CMIS Dictionary"); + } } return propDef.getPropertyAccessor().getValue(nodeRef); } @@ -796,31 +814,143 @@ public class CMISServicesImpl implements CMISServices, ApplicationContextAware, */ public Map getProperties(NodeRef nodeRef) throws CMISInvalidArgumentException { - CMISTypeDefinition typeDef = getTypeDefinition(nodeRef); + return getProperties(nodeRef, getTypeDefinition(nodeRef)); + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#getProperties(org.alfresco.service.cmr.repository.NodeRef, + * org.alfresco.cmis.CMISTypeDefinition) + */ + public Map getProperties(NodeRef nodeRef, CMISTypeDefinition typeDef) + throws CMISInvalidArgumentException + { Map propDefs = typeDef.getPropertyDefinitions(); - Map values = new HashMap(propDefs.size()); + Map values = new HashMap(propDefs.size() * 2); for (CMISPropertyDefinition propDef : propDefs.values()) { values.put(propDef.getPropertyId().getId(), propDef.getPropertyAccessor().getValue(nodeRef)); } return values; } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#getAspects(org.alfresco.service.cmr.repository.NodeRef) + */ + public Set getAspects(NodeRef nodeRef) + { + Set aspects = nodeService.getAspects(nodeRef); + Set result = new HashSet(aspects.size() * 2); + for (QName aspect : aspects) + { + CMISTypeDefinition typeDef = cmisDictionaryService.findTypeForClass(aspect, CMISScope.POLICY); + if (typeDef != null) + { + result.add(typeDef); + } + } + return result; + } /* * (non-Javadoc) * @see org.alfresco.cmis.CMISServices#setProperty(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, java.io.Serializable) */ public void setProperty(NodeRef nodeRef, String propertyName, Serializable value) - throws CMISInvalidArgumentException + throws CMISInvalidArgumentException, CMISConstraintException + { + setProperty(nodeRef, getTypeDefinition(nodeRef), propertyName, value); + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#setProperty(org.alfresco.service.cmr.repository.NodeRef, + * org.alfresco.cmis.CMISTypeDefinition, java.lang.String, java.io.Serializable) + */ + public void setProperty(NodeRef nodeRef, CMISTypeDefinition typeDef, String propertyName, Serializable value) + throws CMISInvalidArgumentException, CMISConstraintException { - CMISTypeDefinition typeDef = getTypeDefinition(nodeRef); CMISPropertyDefinition propDef = cmisDictionaryService.findProperty(propertyName, typeDef); if (propDef == null) { - throw new AlfrescoRuntimeException("Property " + propertyName + " not found for type " - + typeDef.getTypeId() + " in CMIS Dictionary"); + if (typeDef == null) + { + throw new CMISInvalidArgumentException("Property " + propertyName + " not found in CMIS Dictionary"); + } + else + { + throw new CMISInvalidArgumentException("Property " + propertyName + " not found for type " + + typeDef.getTypeId() + " in CMIS Dictionary"); + } + } + + CMISUpdatabilityEnum updatability = propDef.getUpdatability(); + if (updatability == CMISUpdatabilityEnum.READ_ONLY + || updatability == CMISUpdatabilityEnum.READ_AND_WRITE_WHEN_CHECKED_OUT + && !nodeService.hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY)) + { + throw new CMISConstraintException("Unable to update read-only property" + propertyName); + } + + if (propDef.isRequired() && value == null) + { + throw new CMISConstraintException("Property " + propertyName + " is required"); + } + + if (propDef.getDataType() == CMISDataTypeEnum.STRING && propDef.getMaximumLength() > 0 && value != null + && value.toString().length() > propDef.getMaximumLength()) + { + throw new CMISConstraintException("Value is too long for property " + propertyName); + } + + QName property = propDef.getPropertyAccessor().getMappedProperty(); + if (property == null) + { + throw new CMISConstraintException("Unable to set property " + propertyName); + } + nodeService.setProperty(nodeRef, property, value); + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#setAspects(org.alfresco.service.cmr.repository.NodeRef, java.lang.Iterable, + * java.lang.Iterable) + */ + public void setAspects(NodeRef node, Iterable aspectsToRemove, Iterable aspectsToAdd) + throws CMISInvalidArgumentException + { + for (String aspectType : aspectsToRemove) + { + try + { + nodeService.removeAspect(node, getTypeDefinition(aspectType).getTypeId().getQName()); + } + catch (InvalidAspectException e) + { + throw new CMISInvalidArgumentException("Invalid aspect " + aspectType); + } + catch (InvalidNodeRefException e) + { + throw new CMISInvalidArgumentException("Invalid node " + node); + } + } + for (String aspectType : aspectsToAdd) + { + try + { + nodeService.addAspect(node, getTypeDefinition(aspectType).getTypeId().getQName(), Collections + . emptyMap()); + } + catch (InvalidAspectException e) + { + throw new CMISInvalidArgumentException("Invalid aspect " + aspectType); + } + catch (InvalidNodeRefException e) + { + throw new CMISInvalidArgumentException("Invalid node " + node); + } } - propDef.getPropertyAccessor().setValue(nodeRef, value); } /*