mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
Allow management of Alfresco Aspects through CMIS REST and SOAP APIs
- In CMIS methods that allow setting of node properties, the <cmis:properties> element may carry an <alf:setAspects> extension that lists - aspectsToRemove - aspectsToAdd - properties (properties to set belonging to aspects rather than the node type) - In CMIS methods that allow retrieval of node properties, the <cmis:properties> carries an <alf:getAspects> extension that lists - appliedAspects - properties (properties belonging to aspects rather than the node type) - Added extension types to Alfresco-Core.xsd and referenced in extended WSDL - Plumbed in to Web Service and REST APIs git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@19037 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -313,7 +313,6 @@
|
|||||||
<bean id="propertiesUtils" class="org.alfresco.repo.cmis.ws.utils.PropertyUtil">
|
<bean id="propertiesUtils" class="org.alfresco.repo.cmis.ws.utils.PropertyUtil">
|
||||||
<property name="cmisDictionaryService" ref="CMISDictionaryService" />
|
<property name="cmisDictionaryService" ref="CMISDictionaryService" />
|
||||||
<property name="cmisService" ref="CMISService" />
|
<property name="cmisService" ref="CMISService" />
|
||||||
<property name="nodeService" ref="NodeService" />
|
|
||||||
<property name="dictionaryService" ref="DictionaryService" />
|
<property name="dictionaryService" ref="DictionaryService" />
|
||||||
<property name="namespaceService" ref="NamespaceService" />
|
<property name="namespaceService" ref="NamespaceService" />
|
||||||
</bean>
|
</bean>
|
||||||
|
@@ -10,14 +10,33 @@
|
|||||||
</entry>
|
</entry>
|
||||||
[/#macro]
|
[/#macro]
|
||||||
|
|
||||||
|
[#macro nodeCMISProps node propfilter]
|
||||||
|
<cmis:properties>
|
||||||
|
[@typeCMISProps node cmistype(node) propfilter/]
|
||||||
|
[#-- Nest the Alfresco extension for aspects and their properties --]
|
||||||
|
<alf:getAspects>
|
||||||
|
[#list cmisaspects(node) as aspectdef]
|
||||||
|
<alf:appliedAspects>${aspectdef.typeId.id}</alf:appliedAspects>
|
||||||
|
[/#list]
|
||||||
|
<alf:properties>
|
||||||
|
[#list cmisaspects(node) as aspectdef]
|
||||||
|
[@typeCMISProps node aspectdef propfilter/]
|
||||||
|
[/#list]
|
||||||
|
</alf:properties>
|
||||||
|
</alf:getAspects>
|
||||||
|
</cmis:properties>
|
||||||
|
[/#macro]
|
||||||
|
|
||||||
[#macro objectCMISProps object propfilter]
|
[#macro objectCMISProps object propfilter]
|
||||||
<cmis:properties>
|
<cmis:properties>
|
||||||
[#assign typedef = cmistype(object)]
|
[@typeCMISProps object cmistype(object) propfilter/]
|
||||||
|
</cmis:properties>
|
||||||
|
[/#macro]
|
||||||
|
|
||||||
|
[#macro typeCMISProps object typedef propfilter]
|
||||||
[#list typedef.propertyDefinitions?values as propdef]
|
[#list typedef.propertyDefinitions?values as propdef]
|
||||||
[@filter propfilter propdef.queryName][@prop object propdef/][/@filter]
|
[@filter propfilter propdef.queryName][@prop object propdef/][/@filter]
|
||||||
[/#list]
|
[/#list]
|
||||||
</cmis:properties>
|
|
||||||
[/#macro]
|
[/#macro]
|
||||||
|
|
||||||
|
|
||||||
@@ -42,7 +61,7 @@
|
|||||||
<app:edited>${xmldate(node.properties.modified)}</app:edited>
|
<app:edited>${xmldate(node.properties.modified)}</app:edited>
|
||||||
<alf:icon>${absurl(url.context)}${node.icon16}</alf:icon>
|
<alf:icon>${absurl(url.context)}${node.icon16}</alf:icon>
|
||||||
<cmisra:object>
|
<cmisra:object>
|
||||||
[@objectCMISProps node propfilter/]
|
[@nodeCMISProps node propfilter/]
|
||||||
[#if includeallowableactions][@allowableactions node/][/#if]
|
[#if includeallowableactions][@allowableactions node/][/#if]
|
||||||
[@relationships node includerelationships includeallowableactions propfilter/]
|
[@relationships node includerelationships includeallowableactions propfilter/]
|
||||||
[#if includeacl][@aclreport node/][/#if]
|
[#if includeacl][@aclreport node/][/#if]
|
||||||
@@ -95,7 +114,7 @@
|
|||||||
<app:edited>${xmldate(node.properties.modified)}</app:edited>
|
<app:edited>${xmldate(node.properties.modified)}</app:edited>
|
||||||
<alf:icon>${absurl(url.context)}${node.icon16}</alf:icon>
|
<alf:icon>${absurl(url.context)}${node.icon16}</alf:icon>
|
||||||
<cmisra:object>
|
<cmisra:object>
|
||||||
[@objectCMISProps node propfilter/]
|
[@nodeCMISProps node propfilter/]
|
||||||
[#if includeallowableactions][@allowableactions node/][/#if]
|
[#if includeallowableactions][@allowableactions node/][/#if]
|
||||||
[@relationships node includerelationships includeallowableactions propfilter/]
|
[@relationships node includerelationships includeallowableactions propfilter/]
|
||||||
[#if includeacl][@aclreport node/][/#if]
|
[#if includeacl][@aclreport node/][/#if]
|
||||||
|
@@ -89,76 +89,30 @@ function updateNode(node, entry, exclude, validator)
|
|||||||
|
|
||||||
var updated = false;
|
var updated = false;
|
||||||
var object = entry.getExtension(atom.names.cmisra_object);
|
var object = entry.getExtension(atom.names.cmisra_object);
|
||||||
var props = (object == null) ? null : object.properties;
|
|
||||||
var vals = new Object();
|
var vals = new Object();
|
||||||
|
|
||||||
// calculate list of properties to update
|
|
||||||
// TODO: consider array form of properties.names
|
|
||||||
var updateProps = (props == null) ? new Array() : props.ids.toArray().filter(function(element, index, array) {return true;});
|
|
||||||
updateProps.push(PROP_NAME); // mapped to entry.title
|
|
||||||
var exclude = (exclude == null) ? new Array() : exclude;
|
var exclude = (exclude == null) ? new Array() : exclude;
|
||||||
exclude.push(PROP_BASE_TYPE_ID);
|
exclude.push(PROP_BASE_TYPE_ID);
|
||||||
updateProps = updateProps.filter(includeProperty, exclude);
|
|
||||||
|
|
||||||
// build values to update
|
|
||||||
if (updateProps.length > 0)
|
|
||||||
{
|
|
||||||
var typeDef = cmis.queryType(node);
|
var typeDef = cmis.queryType(node);
|
||||||
var propDefs = typeDef.propertyDefinitions;
|
|
||||||
for each (propName in updateProps)
|
|
||||||
{
|
|
||||||
// is this a valid property?
|
|
||||||
var propDef = propDefs[propName];
|
|
||||||
if (propDef == null)
|
|
||||||
{
|
|
||||||
status.code = 400;
|
|
||||||
status.message = "Property " + propName + " is not a known property for type " + typeDef.typeId;
|
|
||||||
status.redirect = true;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate property update
|
// Apply the provided properties of the node type
|
||||||
var valid = validator(propDef);
|
unpackProperties(node, typeDef, object == null ? null : object.properties, exclude, validator, vals);
|
||||||
if (valid == null)
|
|
||||||
{
|
|
||||||
// error, abort update
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (valid == false)
|
|
||||||
{
|
|
||||||
// ignore property
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// extract value
|
|
||||||
var val = null;
|
|
||||||
var prop = (props == null) ? null : props.find(propName);
|
|
||||||
if (prop != null && !prop.isNull())
|
|
||||||
{
|
|
||||||
if (prop.isMultiValued())
|
|
||||||
{
|
|
||||||
if (propDef.updatability === CMISCardinalityEnum.MULTI_VALUED)
|
|
||||||
{
|
|
||||||
status.code = 500;
|
|
||||||
status.message = "Property " + propName + " is single valued."
|
|
||||||
status.redirect = true;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
val = prop.nativeValues;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
val = prop.nativeValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: special case name: entry.title overrides cmis:name
|
// NOTE: special case name: entry.title overrides cmis:name
|
||||||
if (propName === PROP_NAME)
|
var propDef = typeDef.propertyDefinitions[PROP_NAME];
|
||||||
{
|
vals[propDef.propertyAccessor.mappedProperty.toString()] = entry.title;
|
||||||
val = entry.title;
|
|
||||||
}
|
|
||||||
|
|
||||||
vals[propDef.propertyAccessor.mappedProperty.toString()] = val;
|
// Handle Alfresco aspects extension
|
||||||
|
if (object != null)
|
||||||
|
{
|
||||||
|
var extension = object.properties.getExtension(atom.names.alf_setAspects);
|
||||||
|
|
||||||
|
if (extension != null)
|
||||||
|
{
|
||||||
|
// Add and remove aspects
|
||||||
|
cmis.setAspects(node, extension.aspectsToAdd, extension.aspectsToRemove);
|
||||||
|
|
||||||
|
// Apply the provided properties of the aspects
|
||||||
|
unpackProperties(node, null, extension.properties, exclude, validator, vals);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,7 +189,81 @@ function updateNode(node, entry, exclude, validator)
|
|||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function unpackProperties(node, typeDef, props, exclude, validator, vals)
|
||||||
|
{
|
||||||
|
// calculate list of properties to update
|
||||||
|
// TODO: consider array form of properties.names
|
||||||
|
var updateProps = (props == null) ? new Array() : props.ids.toArray().filter(function(element, index, array) {return true;});
|
||||||
|
updateProps = updateProps.filter(includeProperty, exclude);
|
||||||
|
|
||||||
|
// build values to update
|
||||||
|
if (updateProps.length > 0)
|
||||||
|
{
|
||||||
|
for each (propName in updateProps)
|
||||||
|
{
|
||||||
|
// is this a valid property?
|
||||||
|
var propDef = typeDef == null ? cmis.queryProperty(propName) : typeDef.propertyDefinitions[propName];
|
||||||
|
if (propDef == null)
|
||||||
|
{
|
||||||
|
status.code = 400;
|
||||||
|
if (typeDef == null)
|
||||||
|
{
|
||||||
|
status.message = "Property " + propName + " is not a known property";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status.message = "Property " + propName + " is not a known property for type " + typeDef.typeId;
|
||||||
|
}
|
||||||
|
status.redirect = true;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate property update
|
||||||
|
var valid = validator(propDef);
|
||||||
|
if (valid == null)
|
||||||
|
{
|
||||||
|
// error, abort update
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (valid == false)
|
||||||
|
{
|
||||||
|
// ignore property
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract value
|
||||||
|
var val = null;
|
||||||
|
var prop = (props == null) ? null : props.find(propName);
|
||||||
|
if (prop != null && !prop.isNull())
|
||||||
|
{
|
||||||
|
if (prop.isMultiValued())
|
||||||
|
{
|
||||||
|
if (propDef.updatability === CMISCardinalityEnum.MULTI_VALUED)
|
||||||
|
{
|
||||||
|
status.code = 500;
|
||||||
|
status.message = "Property " + propName + " is single valued."
|
||||||
|
status.redirect = true;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
val = prop.nativeValues;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val = prop.nativeValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: special case name: entry.title overrides cmis:name
|
||||||
|
if (propName === PROP_NAME)
|
||||||
|
{
|
||||||
|
val = entry.title;
|
||||||
|
}
|
||||||
|
|
||||||
|
vals[propDef.propertyAccessor.mappedProperty.toString()] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// Create Alfresco Association from Atom Entry
|
// Create Alfresco Association from Atom Entry
|
||||||
//
|
//
|
||||||
|
@@ -174,6 +174,11 @@
|
|||||||
<constructor-arg><ref bean="webscripts.repo.imageresolver"/></constructor-arg>
|
<constructor-arg><ref bean="webscripts.repo.imageresolver"/></constructor-arg>
|
||||||
</bean>
|
</bean>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry key="cmisaspects">
|
||||||
|
<bean class="org.alfresco.repo.cmis.rest.CMISAspectsMethod">
|
||||||
|
<constructor-arg><ref bean="CMISService"/></constructor-arg>
|
||||||
|
</bean>
|
||||||
|
</entry>
|
||||||
</map>
|
</map>
|
||||||
</property>
|
</property>
|
||||||
<property name="registryFactory">
|
<property name="registryFactory">
|
||||||
@@ -241,11 +246,12 @@
|
|||||||
<prop key="cmisra_object">{http://docs.oasis-open.org/ns/cmis/restatom/200908/}object</prop>
|
<prop key="cmisra_object">{http://docs.oasis-open.org/ns/cmis/restatom/200908/}object</prop>
|
||||||
<prop key="cmisra_content">{http://docs.oasis-open.org/ns/cmis/restatom/200908/}content</prop>
|
<prop key="cmisra_content">{http://docs.oasis-open.org/ns/cmis/restatom/200908/}content</prop>
|
||||||
<prop key="cmisra_repositoryInfo">{http://docs.oasis-open.org/ns/cmis/restatom/200908/}repositoryInfo</prop>
|
<prop key="cmisra_repositoryInfo">{http://docs.oasis-open.org/ns/cmis/restatom/200908/}repositoryInfo</prop>
|
||||||
|
<prop key="alf_setAspects">{http://www.alfresco.org}setAspects</prop>
|
||||||
</props>
|
</props>
|
||||||
</property>
|
</property>
|
||||||
<property name="extensionFactories">
|
<property name="extensionFactories">
|
||||||
<list>
|
<list>
|
||||||
<bean class="org.apache.chemistry.abdera.ext.CMISExtensionFactory"/>
|
<bean class="org.alfresco.repo.cmis.rest.AlfrescoCMISExtensionFactory"/>
|
||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
99
source/generated/org/alfresco/repo/cmis/ws/GetAspects.java
Normal file
99
source/generated/org/alfresco/repo/cmis/ws/GetAspects.java
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
|
||||||
|
package org.alfresco.repo.cmis.ws;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
import javax.xml.bind.annotation.XmlType;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Java class for anonymous complex type.
|
||||||
|
*
|
||||||
|
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* <complexType>
|
||||||
|
* <complexContent>
|
||||||
|
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||||
|
* <sequence>
|
||||||
|
* <element name="appliedAspects" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
|
||||||
|
* <element name="properties" type="{http://docs.oasis-open.org/ns/cmis/core/200908/}cmisPropertiesType" minOccurs="0"/>
|
||||||
|
* </sequence>
|
||||||
|
* </restriction>
|
||||||
|
* </complexContent>
|
||||||
|
* </complexType>
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
|
@XmlType(name = "", propOrder = {
|
||||||
|
"appliedAspects",
|
||||||
|
"properties"
|
||||||
|
})
|
||||||
|
@XmlRootElement(name = "getAspects", namespace = "http://www.alfresco.org")
|
||||||
|
public class GetAspects {
|
||||||
|
|
||||||
|
@XmlElement(namespace = "http://www.alfresco.org")
|
||||||
|
protected List<String> appliedAspects;
|
||||||
|
@XmlElement(namespace = "http://www.alfresco.org")
|
||||||
|
protected CmisPropertiesType properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the appliedAspects property.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This accessor method returns a reference to the live list,
|
||||||
|
* not a snapshot. Therefore any modification you make to the
|
||||||
|
* returned list will be present inside the JAXB object.
|
||||||
|
* This is why there is not a <CODE>set</CODE> method for the appliedAspects property.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* For example, to add a new item, do as follows:
|
||||||
|
* <pre>
|
||||||
|
* getAppliedAspects().add(newItem);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Objects of the following type(s) are allowed in the list
|
||||||
|
* {@link String }
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public List<String> getAppliedAspects() {
|
||||||
|
if (appliedAspects == null) {
|
||||||
|
appliedAspects = new ArrayList<String>();
|
||||||
|
}
|
||||||
|
return this.appliedAspects;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the properties property.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* possible object is
|
||||||
|
* {@link CmisPropertiesType }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public CmisPropertiesType getProperties() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of the properties property.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* allowed object is
|
||||||
|
* {@link CmisPropertiesType }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setProperties(CmisPropertiesType value) {
|
||||||
|
this.properties = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
132
source/generated/org/alfresco/repo/cmis/ws/SetAspects.java
Normal file
132
source/generated/org/alfresco/repo/cmis/ws/SetAspects.java
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
|
||||||
|
package org.alfresco.repo.cmis.ws;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
import javax.xml.bind.annotation.XmlType;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Java class for anonymous complex type.
|
||||||
|
*
|
||||||
|
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* <complexType>
|
||||||
|
* <complexContent>
|
||||||
|
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||||
|
* <sequence>
|
||||||
|
* <element name="aspectsToAdd" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
|
||||||
|
* <element name="aspectsToRemove" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
|
||||||
|
* <element name="properties" type="{http://docs.oasis-open.org/ns/cmis/core/200908/}cmisPropertiesType" minOccurs="0"/>
|
||||||
|
* </sequence>
|
||||||
|
* </restriction>
|
||||||
|
* </complexContent>
|
||||||
|
* </complexType>
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
|
@XmlType(name = "", propOrder = {
|
||||||
|
"aspectsToAdd",
|
||||||
|
"aspectsToRemove",
|
||||||
|
"properties"
|
||||||
|
})
|
||||||
|
@XmlRootElement(name = "setAspects", namespace = "http://www.alfresco.org")
|
||||||
|
public class SetAspects {
|
||||||
|
|
||||||
|
@XmlElement(namespace = "http://www.alfresco.org")
|
||||||
|
protected List<String> aspectsToAdd;
|
||||||
|
@XmlElement(namespace = "http://www.alfresco.org")
|
||||||
|
protected List<String> aspectsToRemove;
|
||||||
|
@XmlElement(namespace = "http://www.alfresco.org")
|
||||||
|
protected CmisPropertiesType properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the aspectsToAdd property.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This accessor method returns a reference to the live list,
|
||||||
|
* not a snapshot. Therefore any modification you make to the
|
||||||
|
* returned list will be present inside the JAXB object.
|
||||||
|
* This is why there is not a <CODE>set</CODE> method for the aspectsToAdd property.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* For example, to add a new item, do as follows:
|
||||||
|
* <pre>
|
||||||
|
* getAspectsToAdd().add(newItem);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Objects of the following type(s) are allowed in the list
|
||||||
|
* {@link String }
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public List<String> getAspectsToAdd() {
|
||||||
|
if (aspectsToAdd == null) {
|
||||||
|
aspectsToAdd = new ArrayList<String>();
|
||||||
|
}
|
||||||
|
return this.aspectsToAdd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the aspectsToRemove property.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This accessor method returns a reference to the live list,
|
||||||
|
* not a snapshot. Therefore any modification you make to the
|
||||||
|
* returned list will be present inside the JAXB object.
|
||||||
|
* This is why there is not a <CODE>set</CODE> method for the aspectsToRemove property.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* For example, to add a new item, do as follows:
|
||||||
|
* <pre>
|
||||||
|
* getAspectsToRemove().add(newItem);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Objects of the following type(s) are allowed in the list
|
||||||
|
* {@link String }
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public List<String> getAspectsToRemove() {
|
||||||
|
if (aspectsToRemove == null) {
|
||||||
|
aspectsToRemove = new ArrayList<String>();
|
||||||
|
}
|
||||||
|
return this.aspectsToRemove;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the properties property.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* possible object is
|
||||||
|
* {@link CmisPropertiesType }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public CmisPropertiesType getProperties() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of the properties property.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* allowed object is
|
||||||
|
* {@link CmisPropertiesType }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setProperties(CmisPropertiesType value) {
|
||||||
|
this.properties = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.alfresco.repo.cmis.rest;
|
||||||
|
|
||||||
|
import org.apache.chemistry.abdera.ext.CMISExtensionFactory;
|
||||||
|
import org.apache.chemistry.abdera.ext.CMISProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A CMIS extension factory that is also aware of Alfresco extensions.
|
||||||
|
*
|
||||||
|
* @author dward
|
||||||
|
*/
|
||||||
|
public class AlfrescoCMISExtensionFactory extends CMISExtensionFactory
|
||||||
|
{
|
||||||
|
public AlfrescoCMISExtensionFactory()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
addImpl(SetAspectsExtension.QNAME, SetAspectsExtension.class);
|
||||||
|
addImpl(SetAspectsExtension.PROPERTIES, CMISProperties.class);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.cmis.rest;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.cmis.CMISServices;
|
||||||
|
import org.alfresco.cmis.CMISTypeDefinition;
|
||||||
|
import org.alfresco.repo.template.TemplateNode;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
|
||||||
|
import freemarker.ext.beans.BeanModel;
|
||||||
|
import freemarker.template.TemplateMethodModelEx;
|
||||||
|
import freemarker.template.TemplateModelException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom FreeMarker Template language method.
|
||||||
|
* <p>
|
||||||
|
* Gets the type definitions of a TemplateNode's aspects
|
||||||
|
* <p>
|
||||||
|
* Usage: cmisaspects(TemplateNode node)
|
||||||
|
*
|
||||||
|
* @author dward
|
||||||
|
*/
|
||||||
|
public class CMISAspectsMethod implements TemplateMethodModelEx
|
||||||
|
{
|
||||||
|
private CMISServices cmisService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct
|
||||||
|
*/
|
||||||
|
public CMISAspectsMethod(CMISServices cmisService)
|
||||||
|
{
|
||||||
|
this.cmisService = cmisService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Object exec(List args) throws TemplateModelException
|
||||||
|
{
|
||||||
|
NodeRef nodeRef = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
// extract node ref
|
||||||
|
Object arg = args.get(i++);
|
||||||
|
if (arg instanceof BeanModel)
|
||||||
|
{
|
||||||
|
Object wrapped = ((BeanModel) arg).getWrappedObject();
|
||||||
|
if (wrapped != null)
|
||||||
|
{
|
||||||
|
if (wrapped instanceof TemplateNode)
|
||||||
|
{
|
||||||
|
nodeRef = ((TemplateNode) wrapped).getNodeRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IndexOutOfBoundsException e)
|
||||||
|
{
|
||||||
|
// Ignore optional arguments
|
||||||
|
}
|
||||||
|
|
||||||
|
// query aspects
|
||||||
|
if (nodeRef != null)
|
||||||
|
{
|
||||||
|
return cmisService.getAspects(nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.<CMISTypeDefinition> emptySet();
|
||||||
|
}
|
||||||
|
}
|
@@ -114,8 +114,8 @@ public class CMISPropertyValueMethod implements TemplateMethodModelEx
|
|||||||
Object result = null;
|
Object result = null;
|
||||||
if (wrapped != null && wrapped instanceof TemplateNode)
|
if (wrapped != null && wrapped instanceof TemplateNode)
|
||||||
{
|
{
|
||||||
// retrieve property value from node
|
// retrieve property value from node, allowing aspect properties
|
||||||
result = cmisService.getProperty(((TemplateNode) wrapped).getNodeRef(), propertyName);
|
result = cmisService.getProperty(((TemplateNode) wrapped).getNodeRef(), null, propertyName);
|
||||||
}
|
}
|
||||||
else if (wrapped != null && wrapped instanceof TemplateAssociation)
|
else if (wrapped != null && wrapped instanceof TemplateAssociation)
|
||||||
{
|
{
|
||||||
|
@@ -563,6 +563,30 @@ public class CMISScript extends BaseScopableProcessorExtension
|
|||||||
return cmisDictionaryService.findProperty(propertyName, null);
|
return cmisDictionaryService.findProperty(propertyName, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 WebScriptException
|
||||||
|
* if an argument is invalid
|
||||||
|
*/
|
||||||
|
public void setAspects(ScriptNode node, Iterable<String> aspectsToRemove, Iterable<String> aspectsToAdd)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
cmisService.setAspects(node.getNodeRef(), aspectsToRemove, aspectsToAdd);
|
||||||
|
}
|
||||||
|
catch (CMISInvalidArgumentException e)
|
||||||
|
{
|
||||||
|
throw new WebScriptException(e.getStatusCode(), e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// SQL Query
|
// SQL Query
|
||||||
//
|
//
|
||||||
|
120
source/java/org/alfresco/repo/cmis/rest/SetAspectsExtension.java
Normal file
120
source/java/org/alfresco/repo/cmis/rest/SetAspectsExtension.java
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco 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 Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.cmis.rest;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
|
import org.apache.abdera.factory.Factory;
|
||||||
|
import org.apache.abdera.model.Element;
|
||||||
|
import org.apache.abdera.model.ExtensibleElementWrapper;
|
||||||
|
import org.apache.chemistry.abdera.ext.CMISConstants;
|
||||||
|
import org.apache.chemistry.abdera.ext.CMISProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alfresco CMIS extension for controlling aspects and their properties.
|
||||||
|
*
|
||||||
|
* @author dward
|
||||||
|
*/
|
||||||
|
public class SetAspectsExtension extends ExtensibleElementWrapper
|
||||||
|
{
|
||||||
|
/** The Alfresco extension namespace. */
|
||||||
|
private static final String NAMESPACE = "http://www.alfresco.org";
|
||||||
|
|
||||||
|
/** The name of this element. */
|
||||||
|
public static final QName QNAME = new QName(NAMESPACE, "setAspects");
|
||||||
|
|
||||||
|
/** The name of the element containing the aspect properties. */
|
||||||
|
public static final QName PROPERTIES = new QName(NAMESPACE, "properties");
|
||||||
|
|
||||||
|
/** The name of the element containing the aspects to add. */
|
||||||
|
private static final QName ASPECTS_TO_ADD = new QName(NAMESPACE, "aspectsToAdd");
|
||||||
|
|
||||||
|
/** The name of the element containing the aspects to remove. */
|
||||||
|
private static final QName ASPECTS_TO_REMOVE = new QName(NAMESPACE, "aspectsToRemove");
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Constructor.
|
||||||
|
*
|
||||||
|
* @param internal
|
||||||
|
* the internal element
|
||||||
|
*/
|
||||||
|
public SetAspectsExtension(Element internal)
|
||||||
|
{
|
||||||
|
super(internal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Constructor.
|
||||||
|
*
|
||||||
|
* @param factory
|
||||||
|
* the factory
|
||||||
|
*/
|
||||||
|
public SetAspectsExtension(Factory factory)
|
||||||
|
{
|
||||||
|
super(factory, CMISConstants.OBJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the aspects to add.
|
||||||
|
*
|
||||||
|
* @return the aspects to add
|
||||||
|
*/
|
||||||
|
public Set<String> getAspectsToAdd()
|
||||||
|
{
|
||||||
|
Set<String> aspects = new TreeSet<String>();
|
||||||
|
for (Element aspect = getFirstChild(ASPECTS_TO_ADD); aspect != null; aspect = aspect
|
||||||
|
.getNextSibling(ASPECTS_TO_ADD))
|
||||||
|
{
|
||||||
|
aspects.add(aspect.getText());
|
||||||
|
|
||||||
|
}
|
||||||
|
return aspects;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the aspects to remove.
|
||||||
|
*
|
||||||
|
* @return the aspects to remove
|
||||||
|
*/
|
||||||
|
public Set<String> getAspectsToRemove()
|
||||||
|
{
|
||||||
|
Set<String> aspects = new TreeSet<String>();
|
||||||
|
for (Element aspect = getFirstChild(ASPECTS_TO_REMOVE); aspect != null; aspect = aspect
|
||||||
|
.getNextSibling(ASPECTS_TO_REMOVE))
|
||||||
|
{
|
||||||
|
aspects.add(aspect.getText());
|
||||||
|
|
||||||
|
}
|
||||||
|
return aspects;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all aspect properties
|
||||||
|
*
|
||||||
|
* @return aspect properties
|
||||||
|
*/
|
||||||
|
public CMISProperties getProperties()
|
||||||
|
{
|
||||||
|
return (CMISProperties) getFirstChild(PROPERTIES);
|
||||||
|
}
|
||||||
|
}
|
@@ -45,7 +45,6 @@ import org.alfresco.repo.cmis.ws.utils.ExceptionUtil;
|
|||||||
import org.alfresco.repo.web.util.paging.Cursor;
|
import org.alfresco.repo.web.util.paging.Cursor;
|
||||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
|
||||||
import org.alfresco.service.cmr.model.FileExistsException;
|
import org.alfresco.service.cmr.model.FileExistsException;
|
||||||
import org.alfresco.service.cmr.model.FileInfo;
|
import org.alfresco.service.cmr.model.FileInfo;
|
||||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||||
@@ -213,14 +212,16 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
|
|||||||
Map<String, Object> propertiesMap = propertiesUtil.getPropertiesMap(properties);
|
Map<String, Object> propertiesMap = propertiesUtil.getPropertiesMap(properties);
|
||||||
String typeId = extractAndAssertTypeId(propertiesMap);
|
String typeId = extractAndAssertTypeId(propertiesMap);
|
||||||
CMISTypeDefinition type = cmisService.getTypeDefinition(typeId);
|
CMISTypeDefinition type = cmisService.getTypeDefinition(typeId);
|
||||||
TypeDefinition nativeType = dictionaryService.getType(nodeService.getType(folderNodeRef));
|
|
||||||
if (type == null || type.getTypeId() == null || type.getTypeId().getScope() != CMISScope.FOLDER)
|
if (type == null || type.getTypeId() == null || type.getTypeId().getScope() != CMISScope.FOLDER)
|
||||||
{
|
{
|
||||||
throw ExceptionUtil.createCmisException("The typeID is not an Object-Type whose baseType is 'Folder': " + typeId, EnumServiceException.CONSTRAINT);
|
throw ExceptionUtil.createCmisException("The typeID is not an Object-Type whose baseType is 'Folder': " + typeId, EnumServiceException.CONSTRAINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
String name = propertiesUtil.getCmisPropertyValue(properties, CMISDictionaryModel.PROP_NAME, null);
|
String name = propertiesUtil.getCmisPropertyValue(properties, CMISDictionaryModel.PROP_NAME, null);
|
||||||
propertiesUtil.checkProperty(nativeType, type, CMISDictionaryModel.PROP_NAME, name, false);
|
if (null == name)
|
||||||
|
{
|
||||||
|
throw ExceptionUtil.createCmisException("Name property not found", EnumServiceException.INVALID_ARGUMENT);
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -819,8 +820,6 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
|
|||||||
{
|
{
|
||||||
throw ExceptionUtil.createCmisException("Name property not found", EnumServiceException.INVALID_ARGUMENT);
|
throw ExceptionUtil.createCmisException("Name property not found", EnumServiceException.INVALID_ARGUMENT);
|
||||||
}
|
}
|
||||||
propertiesUtil.checkProperty(null, typeDef, CMISDictionaryModel.PROP_NAME, result, (EnumVersioningState.CHECKEDOUT == versioningState));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -25,6 +25,7 @@ import java.util.Collection;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.xml.datatype.DatatypeConfigurationException;
|
import javax.xml.datatype.DatatypeConfigurationException;
|
||||||
@@ -37,9 +38,9 @@ import org.alfresco.cmis.CMISDictionaryService;
|
|||||||
import org.alfresco.cmis.CMISInvalidArgumentException;
|
import org.alfresco.cmis.CMISInvalidArgumentException;
|
||||||
import org.alfresco.cmis.CMISPropertyDefinition;
|
import org.alfresco.cmis.CMISPropertyDefinition;
|
||||||
import org.alfresco.cmis.CMISScope;
|
import org.alfresco.cmis.CMISScope;
|
||||||
|
import org.alfresco.cmis.CMISServiceException;
|
||||||
import org.alfresco.cmis.CMISServices;
|
import org.alfresco.cmis.CMISServices;
|
||||||
import org.alfresco.cmis.CMISTypeDefinition;
|
import org.alfresco.cmis.CMISTypeDefinition;
|
||||||
import org.alfresco.cmis.CMISUpdatabilityEnum;
|
|
||||||
import org.alfresco.repo.cmis.PropertyFilter;
|
import org.alfresco.repo.cmis.PropertyFilter;
|
||||||
import org.alfresco.repo.cmis.ws.CmisException;
|
import org.alfresco.repo.cmis.ws.CmisException;
|
||||||
import org.alfresco.repo.cmis.ws.CmisPropertiesType;
|
import org.alfresco.repo.cmis.ws.CmisPropertiesType;
|
||||||
@@ -53,13 +54,13 @@ import org.alfresco.repo.cmis.ws.CmisPropertyInteger;
|
|||||||
import org.alfresco.repo.cmis.ws.CmisPropertyString;
|
import org.alfresco.repo.cmis.ws.CmisPropertyString;
|
||||||
import org.alfresco.repo.cmis.ws.CmisPropertyUri;
|
import org.alfresco.repo.cmis.ws.CmisPropertyUri;
|
||||||
import org.alfresco.repo.cmis.ws.EnumServiceException;
|
import org.alfresco.repo.cmis.ws.EnumServiceException;
|
||||||
|
import org.alfresco.repo.cmis.ws.GetAspects;
|
||||||
|
import org.alfresco.repo.cmis.ws.SetAspects;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
|
||||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeService;
|
|
||||||
import org.alfresco.service.cmr.version.Version;
|
import org.alfresco.service.cmr.version.Version;
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
@@ -89,7 +90,6 @@ public class PropertyUtil
|
|||||||
|
|
||||||
private static final String BASE_TYPE_PROPERTY_NAME = "BaseType";
|
private static final String BASE_TYPE_PROPERTY_NAME = "BaseType";
|
||||||
|
|
||||||
private NodeService nodeService;
|
|
||||||
private DictionaryService dictionaryService;
|
private DictionaryService dictionaryService;
|
||||||
private NamespaceService namespaceService;
|
private NamespaceService namespaceService;
|
||||||
private CMISServices cmisService;
|
private CMISServices cmisService;
|
||||||
@@ -99,11 +99,6 @@ public class PropertyUtil
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNodeService(NodeService nodeService)
|
|
||||||
{
|
|
||||||
this.nodeService = nodeService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDictionaryService(DictionaryService dictionaryService)
|
public void setDictionaryService(DictionaryService dictionaryService)
|
||||||
{
|
{
|
||||||
this.dictionaryService = dictionaryService;
|
this.dictionaryService = dictionaryService;
|
||||||
@@ -348,59 +343,71 @@ public class PropertyUtil
|
|||||||
/**
|
/**
|
||||||
* Sets and checks all properties' fields for specified node
|
* Sets and checks all properties' fields for specified node
|
||||||
*
|
*
|
||||||
* @param nodeRef - <b>NodeRef</b> for node for those properties must be setted
|
* @param nodeRef
|
||||||
* @param properties - <b>CmisPropertiesType</b> instance that contains all the necessary properties' fields
|
* - <b>NodeRef</b> for node for those properties must be setted
|
||||||
* @param ignoringPropertiesFilter - <b>PropertyFilter</b> instance. This filter determines which properties should be ignored and not setted without exception. If this
|
* @param properties
|
||||||
* parameter is <b>null</b> all properties will be processed in common flow
|
* - <b>CmisPropertiesType</b> instance that contains all the necessary properties' fields
|
||||||
|
* @param ignoringPropertiesFilter
|
||||||
|
* - <b>PropertyFilter</b> instance. This filter determines which properties should be ignored and not
|
||||||
|
* setted without exception. If this parameter is <b>null</b> all properties will be processed in common
|
||||||
|
* flow
|
||||||
*/
|
*/
|
||||||
public void setProperties(NodeRef nodeRef, CmisPropertiesType properties, PropertyFilter ignoringPropertiesFilter) throws CmisException
|
public void setProperties(NodeRef nodeRef, CmisPropertiesType properties, PropertyFilter ignoringPropertiesFilter)
|
||||||
|
throws CmisException
|
||||||
{
|
{
|
||||||
// TODO: WARINING!!! This is WRONG behavior!!! Each CMIS object type and each property MUST be described in appropriate to CMIS manner
|
if (nodeRef == null || properties == null)
|
||||||
if ((null == nodeRef) || (null == properties) || (null == properties.getProperty()))
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String typeId = getProperty(nodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, null);
|
try
|
||||||
boolean checkedOut = getProperty(nodeRef, CMISDictionaryModel.PROP_IS_VERSION_SERIES_CHECKED_OUT, false);
|
|
||||||
CMISTypeDefinition cmisObjectType = cmisDictionaryService.findType(typeId);
|
|
||||||
|
|
||||||
TypeDefinition nativeObjectType = dictionaryService.getType(nodeService.getType(nodeRef));
|
|
||||||
|
|
||||||
if ((null == cmisObjectType) && (null == nativeObjectType))
|
|
||||||
{
|
{
|
||||||
throw ExceptionUtil.createCmisException(("Can't find type definition for current object with \"" + typeId + "\" type Id"), EnumServiceException.INVALID_ARGUMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (CmisProperty property : properties.getProperty())
|
for (CmisProperty property : properties.getProperty())
|
||||||
{
|
{
|
||||||
String propertyName = getPropertyName(property);
|
String propertyName = getPropertyName(property);
|
||||||
if ((null == propertyName) || ((null != ignoringPropertiesFilter) && ignoringPropertiesFilter.allow(propertyName)))
|
if ((null == propertyName)
|
||||||
|
|| ((null != ignoringPropertiesFilter) && ignoringPropertiesFilter.allow(propertyName)))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Object value = getValue(property);
|
||||||
|
cmisService.setProperty(nodeRef, propertyName, (Serializable) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process Alfresco aspect-setting extension
|
||||||
|
for (Object extensionObj : properties.getAny())
|
||||||
|
{
|
||||||
|
if (!(extensionObj instanceof SetAspects))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SetAspects setAspects = (SetAspects) extensionObj;
|
||||||
|
cmisService.setAspects(nodeRef, setAspects.getAspectsToRemove(), setAspects.getAspectsToAdd());
|
||||||
|
CmisPropertiesType extensionProperties = setAspects.getProperties();
|
||||||
|
if (extensionProperties == null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (CmisProperty property : extensionProperties.getProperty())
|
||||||
|
{
|
||||||
|
String propertyName = getPropertyName(property);
|
||||||
|
if ((null == propertyName)
|
||||||
|
|| ((null != ignoringPropertiesFilter) && ignoringPropertiesFilter.allow(propertyName)))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
Object value = getValue(property);
|
Object value = getValue(property);
|
||||||
QName alfrescoPropertyName = null;
|
|
||||||
switch (checkProperty(nativeObjectType, cmisObjectType, propertyName, value, checkedOut))
|
// This time, call setProperty without constraining the owning type
|
||||||
{
|
cmisService.setProperty(nodeRef, null, propertyName, (Serializable) value);
|
||||||
case PROPERTY_CHECKED:
|
|
||||||
{
|
|
||||||
alfrescoPropertyName = cmisDictionaryService.findProperty(propertyName, cmisObjectType).getPropertyAccessor().getMappedProperty();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PROPERTY_NATIVE:
|
|
||||||
{
|
|
||||||
alfrescoPropertyName = createQName(propertyName);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PROPERTY_NOT_UPDATABLE:
|
|
||||||
{
|
|
||||||
throw ExceptionUtil.createCmisException(("\"" + propertyName + "\" property is not updatable by repository for specified Object id"),
|
|
||||||
EnumServiceException.CONSTRAINT);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nodeService.setProperty(nodeRef, alfrescoPropertyName, (Serializable) value);
|
}
|
||||||
|
catch (CMISServiceException e)
|
||||||
|
{
|
||||||
|
throw ExceptionUtil.createCmisException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,82 +439,6 @@ public class PropertyUtil
|
|||||||
return qname;
|
return qname;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks any CMIS property on constraints conforming
|
|
||||||
*
|
|
||||||
* @param type - <b>CMISTypeDefinition</b> instance. This value must not be <b>null</b>
|
|
||||||
* @param propertyName - <b>String</b> instance that represents name of the property
|
|
||||||
* @param value - instance of a <b>Serializable</b> object that represents value of the property
|
|
||||||
* @return <b>true</b> if property was checked and <b>false</b> if property can't be checked
|
|
||||||
* @throws <b>CmisException</b> if some constraint is not satisfied
|
|
||||||
*/
|
|
||||||
public PropertyCheckingStateEnum checkProperty(TypeDefinition nativeObjectType, CMISTypeDefinition cmisObjectType, String propertyName, Object value, boolean checkedOut)
|
|
||||||
throws CmisException
|
|
||||||
{
|
|
||||||
CMISPropertyDefinition propertyDefinition = cmisDictionaryService.findProperty(propertyName, cmisObjectType);
|
|
||||||
|
|
||||||
if (null == propertyDefinition)
|
|
||||||
{
|
|
||||||
// TODO: WARINING!!! This is WRONG behavior!!! Each CMIS object type and each property MUST be described in appropriate CMIS manner
|
|
||||||
QName qualifiedName = createQName(propertyName);
|
|
||||||
Map<QName, PropertyDefinition> properties = (null != nativeObjectType) ? (nativeObjectType.getProperties()) : (null);
|
|
||||||
if ((null == qualifiedName) || (null == properties) || properties.containsKey(qualifiedName))
|
|
||||||
{
|
|
||||||
return PropertyCheckingStateEnum.PROPERTY_NOT_UPDATABLE;
|
|
||||||
}
|
|
||||||
return PropertyCheckingStateEnum.PROPERTY_NATIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// [FIXED BUG] condition and first calculating value were swapped
|
|
||||||
boolean updatable = ((CMISUpdatabilityEnum.READ_AND_WRITE_WHEN_CHECKED_OUT == propertyDefinition.getUpdatability()) ? (checkedOut)
|
|
||||||
: (CMISUpdatabilityEnum.READ_AND_WRITE == propertyDefinition.getUpdatability()));
|
|
||||||
|
|
||||||
if (!updatable)
|
|
||||||
{
|
|
||||||
return PropertyCheckingStateEnum.PROPERTY_NOT_UPDATABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (propertyDefinition.isRequired() && (null == value))
|
|
||||||
{
|
|
||||||
throw ExceptionUtil.createCmisException((propertyName + " property required"), EnumServiceException.CONSTRAINT);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (propertyDefinition.getDataType())
|
|
||||||
{
|
|
||||||
case STRING:
|
|
||||||
{
|
|
||||||
checkStringProperty(propertyDefinition, propertyName, (String) value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case INTEGER:
|
|
||||||
case DECIMAL:
|
|
||||||
{
|
|
||||||
checkNumberProperty(propertyDefinition, propertyName, (Number) value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return PropertyCheckingStateEnum.PROPERTY_CHECKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum PropertyCheckingStateEnum
|
|
||||||
{
|
|
||||||
PROPERTY_CHECKED, PROPERTY_NATIVE, PROPERTY_NOT_UPDATABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkNumberProperty(CMISPropertyDefinition propertyDefinition, String propertyName, Number value)
|
|
||||||
{
|
|
||||||
// TODO: if max and min value properties will be added to CMISPropertyDefinition
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkStringProperty(CMISPropertyDefinition propertyDefinition, String propertyName, String value) throws CmisException
|
|
||||||
{
|
|
||||||
if (value != null && (propertyDefinition.getMaximumLength() > 0) && (value.length() > propertyDefinition.getMaximumLength()))
|
|
||||||
{
|
|
||||||
throw ExceptionUtil.createCmisException((propertyName + " property value is too long"), EnumServiceException.CONSTRAINT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get CMIS properties for object
|
* Get CMIS properties for object
|
||||||
*
|
*
|
||||||
@@ -517,23 +448,36 @@ public class PropertyUtil
|
|||||||
*/
|
*/
|
||||||
public CmisPropertiesType getProperties(Object object, PropertyFilter filter) throws CmisException
|
public CmisPropertiesType getProperties(Object object, PropertyFilter filter) throws CmisException
|
||||||
{
|
{
|
||||||
|
if (object instanceof Version)
|
||||||
|
{
|
||||||
|
object = ((Version) object).getFrozenStateNodeRef();
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
CmisPropertiesType result = new CmisPropertiesType();
|
||||||
Map<String, Serializable> properties;
|
Map<String, Serializable> properties;
|
||||||
if (object instanceof NodeRef)
|
if (object instanceof NodeRef)
|
||||||
{
|
{
|
||||||
properties = cmisService.getProperties((NodeRef) object);
|
properties = cmisService.getProperties((NodeRef) object);
|
||||||
}
|
|
||||||
else if (object instanceof Version)
|
// Handle fetching of aspects and their properties with Alfresco extension
|
||||||
|
GetAspects extension = new GetAspects();
|
||||||
|
result.getAny().add(extension);
|
||||||
|
List<String> aspects = extension.getAppliedAspects();
|
||||||
|
Map<String, Serializable> aspectProperties = new HashMap<String, Serializable>(97);
|
||||||
|
for (CMISTypeDefinition typeDef : cmisService.getAspects((NodeRef)object))
|
||||||
{
|
{
|
||||||
properties = cmisService.getProperties(((Version) object).getFrozenStateNodeRef());
|
aspects.add(typeDef.getTypeId().getId());
|
||||||
|
aspectProperties.putAll(cmisService.getProperties((NodeRef)object, typeDef));
|
||||||
|
}
|
||||||
|
CmisPropertiesType aspectResult = new CmisPropertiesType();
|
||||||
|
convertToCmisProperties(aspectProperties, filter, aspectResult);
|
||||||
|
extension.setProperties(aspectResult);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
properties = createBaseRelationshipProperties((AssociationRef) object);
|
properties = createBaseRelationshipProperties((AssociationRef) object);
|
||||||
}
|
}
|
||||||
|
|
||||||
CmisPropertiesType result = new CmisPropertiesType();
|
|
||||||
convertToCmisProperties(properties, filter, result);
|
convertToCmisProperties(properties, filter, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
9
source/wsdl/Alfresco-CMISWS-Service.wsdl
Normal file
9
source/wsdl/Alfresco-CMISWS-Service.wsdl
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<definitions xmlns:alf="http://www.alfresco.org" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
|
||||||
|
xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:ns="http://schemas.xmlsoap.org/soap/encoding/" targetNamespace="http://www.alfresco.org"
|
||||||
|
name="AlfrescoCMISWebServices">
|
||||||
|
|
||||||
|
<import namespace="http://docs.oasis-open.org/ns/cmis/ws/200908/" location="CMISWS-Service.wsdl" />
|
||||||
|
<import namespace="http://www.alfresco.org" location="Alfresco-Core.xsd" />
|
||||||
|
|
||||||
|
</definitions>
|
28
source/wsdl/Alfresco-Core.xsd
Normal file
28
source/wsdl/Alfresco-Core.xsd
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.alfresco.org"
|
||||||
|
xmlns:atom="http://www.w3.org/2005/Atom" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
|
||||||
|
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc" jaxb:version="2.1"
|
||||||
|
xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200908/" version="1.0">
|
||||||
|
|
||||||
|
<xs:import schemaLocation="CMIS-Core.xsd" namespace="http://docs.oasis-open.org/ns/cmis/core/200908/" />
|
||||||
|
|
||||||
|
<xs:element name="setAspects">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element minOccurs="0" maxOccurs="unbounded" name="aspectsToAdd" type="xs:string" />
|
||||||
|
<xs:element minOccurs="0" maxOccurs="unbounded" name="aspectsToRemove" type="xs:string" />
|
||||||
|
<xs:element name="properties" type="cmis:cmisPropertiesType" minOccurs="0" />
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:element name="getAspects">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element minOccurs="0" maxOccurs="unbounded" name="appliedAspects" type="xs:string" />
|
||||||
|
<xs:element name="properties" type="cmis:cmisPropertiesType" minOccurs="0" />
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
</xs:schema>
|
Reference in New Issue
Block a user