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);
}
/*