mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
CMIS Relationship support in AtomPub binding
- getRelationships - getRelationship - createRelationship - unit tests for above TODO: delete relationship, includeRelationships flag git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@14461 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -10,6 +10,19 @@
|
||||
</entry>
|
||||
[/#macro]
|
||||
|
||||
[#macro objectCMISProps object propfilter]
|
||||
<cmis:properties>
|
||||
[#assign typedef = cmistype(object)]
|
||||
|
||||
[#-- TODO: Spec issue: BaseType not a property --]
|
||||
[@filter propfilter "BaseType"][@propvalue "BaseType" typedef.typeId.baseTypeId.id "STRING"/][/@filter]
|
||||
|
||||
[#list typedef.propertyDefinitions?values as propdef]
|
||||
[@filter propfilter propdef.propertyId.name][@prop propdef.propertyId.name object propdef.dataType/][/@filter]
|
||||
[/#list]
|
||||
</cmis:properties>
|
||||
[/#macro]
|
||||
|
||||
|
||||
[#-- --]
|
||||
[#-- ATOM Entry for Document --]
|
||||
@@ -30,7 +43,7 @@
|
||||
<title>${node.name}</title>
|
||||
<updated>${xmldate(node.properties.modified)}</updated>
|
||||
<cmis:object>
|
||||
[@documentCMISProps node propfilter/]
|
||||
[@objectCMISProps node propfilter/]
|
||||
[#if includeallowableactions][@allowableactions node/][/#if]
|
||||
</cmis:object>
|
||||
<cmis:terminator/>
|
||||
@@ -41,7 +54,7 @@
|
||||
|
||||
[#macro documentCMISLinks node]
|
||||
<link rel="allowableactions" href="${absurl(url.serviceContext)}/api/node/${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}/permissions"/>
|
||||
<link rel="relationships" href="${absurl(url.serviceContext)}/api/node/${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}/associations"/>
|
||||
<link rel="relationships" href="${absurl(url.serviceContext)}/api/node/${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}/rels"/>
|
||||
<link rel="parents" href="${absurl(url.serviceContext)}/api/node/${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}/parents"/>
|
||||
<link rel="allversions" href="${absurl(url.serviceContext)}/api/node/${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}/versions"/>
|
||||
[@linkstream node "stream"/]
|
||||
@@ -49,18 +62,6 @@
|
||||
<link rel="repository" href="[@serviceuri/]"/>
|
||||
[/#macro]
|
||||
|
||||
[#macro documentCMISProps node propfilter]
|
||||
<cmis:properties>
|
||||
[#-- TODO: Spec issue: BaseType not a property --]
|
||||
[@filter propfilter "BaseType"][@propvalue "BaseType" "document" "STRING"/][/@filter]
|
||||
|
||||
[#assign typedef = cmistype(node)]
|
||||
[#list typedef.propertyDefinitions?values as propdef]
|
||||
[@filter propfilter propdef.propertyId.name][@prop propdef.propertyId.name node propdef.dataType/][/@filter]
|
||||
[/#list]
|
||||
</cmis:properties>
|
||||
[/#macro]
|
||||
|
||||
|
||||
[#-- --]
|
||||
[#-- ATOM Entry for Version --]
|
||||
@@ -79,7 +80,7 @@
|
||||
<title>${node.name}</title>
|
||||
<updated>${xmldate(node.properties.modified)}</updated>
|
||||
<cmis:object>
|
||||
[@documentCMISProps node propfilter/]
|
||||
[@objectCMISProps node propfilter/]
|
||||
</cmis:object>
|
||||
<cmis:terminator/>
|
||||
<app:edited>${xmldate(node.properties.modified)}</app:edited>
|
||||
@@ -107,7 +108,7 @@
|
||||
<title>${node.name}</title>
|
||||
<updated>${xmldate(node.properties.modified)}</updated>
|
||||
<cmis:object>
|
||||
[@documentCMISProps node propfilter/]
|
||||
[@objectCMISProps node propfilter/]
|
||||
[#if includeallowableactions][@allowableactions node/][/#if]
|
||||
</cmis:object>
|
||||
<cmis:terminator/>
|
||||
@@ -136,7 +137,7 @@
|
||||
<updated>${xmldate(node.properties.modified)}</updated>
|
||||
<cmis:object>
|
||||
[#-- recurse for depth greater than 1 --]
|
||||
[@folderCMISProps node propfilter/]
|
||||
[@objectCMISProps node propfilter/]
|
||||
[#if includeallowableactions][@allowableactions node/][/#if]
|
||||
</cmis:object>
|
||||
[#if depth < maxdepth || depth == -1]
|
||||
@@ -157,7 +158,7 @@
|
||||
|
||||
[#macro folderCMISLinks node]
|
||||
<link rel="allowableactions" href="${absurl(url.serviceContext)}/api/node/${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}/permissions"/>
|
||||
<link rel="relationships" href="${absurl(url.serviceContext)}/api/node/${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}/associations"/>
|
||||
<link rel="relationships" href="${absurl(url.serviceContext)}/api/node/${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}/rels"/>
|
||||
[#if cmisproperty(node, "ParentId")?is_string]
|
||||
<link rel="parents" href="${absurl(url.serviceContext)}/api/node/${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}/parent"/>
|
||||
[/#if]
|
||||
@@ -167,16 +168,38 @@
|
||||
<link rel="repository" href="[@serviceuri/]"/>
|
||||
[/#macro]
|
||||
|
||||
[#macro folderCMISProps node propfilter]
|
||||
<cmis:properties>
|
||||
[#-- TODO: Spec issue: BaseType not a property --]
|
||||
[@filter propfilter "BaseType"][@propvalue "BaseType" "folder" "STRING"/][/@filter]
|
||||
|
||||
[#assign typedef = cmistype(node)]
|
||||
[#list typedef.propertyDefinitions?values as propdef]
|
||||
[@filter propfilter propdef.propertyId.name][@prop propdef.propertyId.name node propdef.dataType/][/@filter]
|
||||
[/#list]
|
||||
</cmis:properties>
|
||||
[#-- --]
|
||||
[#-- ATOM Entry for Relationship --]
|
||||
[#-- --]
|
||||
|
||||
[#macro assoc assoc propfilter="*" includeallowableactions=false ns=""]
|
||||
[@entry ns]
|
||||
<author><name>${xmldate(date)}</name></author> [#-- TODO: [@namedvalue "CreatedBy" assoc "STRING"/] --]
|
||||
<content>[@namedvalue "ObjectId" assoc "ID"/]</content> [#-- TODO: spec id, how to map? --]
|
||||
<id>[@namedvalue "ObjectId" assoc "ID"/]</id> [#-- TODO: id compliant --]
|
||||
<link rel="self" href="${absurl(url.serviceContext)}[@assocuri assoc/]"/>
|
||||
<link rel="edit" href="${absurl(url.serviceContext)}[@assocuri assoc/]"/>
|
||||
[@assocCMISLinks assoc=assoc/]
|
||||
<published>${xmldate(date)}</published> [#-- TODO: [@namedvalue "CreationDate" assoc "DATETIME"/] --]
|
||||
<summary>[@namedvalue "ObjectId" assoc "ID"/]</summary> [#-- TODO: spec id, how to map? --]
|
||||
<title>[@namedvalue "ObjectId" assoc "ID"/]</title> [#-- TODO: spec id, how to map? --]
|
||||
<updated>${xmldate(date)}</updated> [#-- TODO: [@namedvalue "LastModificationDate" assoc "DATETIME"/] --]
|
||||
<cmis:object>
|
||||
[@objectCMISProps assoc propfilter/]
|
||||
[#-- TODO: [#if includeallowableactions][@allowableactions node/][/#if] --]
|
||||
</cmis:object>
|
||||
<cmis:terminator/>
|
||||
<app:edited>${xmldate(date)}</app:edited> [#-- TODO: [@namedvalue "LastModificationDate" assoc "DATETIME"/] --]
|
||||
[/@entry]
|
||||
[/#macro]
|
||||
|
||||
[#macro assocCMISLinks assoc]
|
||||
[#-- TODO: <link rel="allowableactions" href="${absurl(url.serviceContext)}/api/node/${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}/permissions"/> --]
|
||||
<link rel="type" href="${absurl(url.serviceContext)}/api/type/${cmistype(assoc).typeId.id!"unknown"}"/>
|
||||
<link rel="source" href="${absurl(url.serviceContext)}[@nodeuri assoc.source/]"/>
|
||||
<link rel="target" href="${absurl(url.serviceContext)}[@nodeuri assoc.target/]"/>
|
||||
<link rel="repository" href="[@serviceuri/]"/>
|
||||
[/#macro]
|
||||
|
||||
|
||||
@@ -239,8 +262,8 @@
|
||||
[#if filter == "*" || filter?index_of(value) != -1 || filter?matches(value,'i')][#nested][/#if]
|
||||
[/#macro]
|
||||
|
||||
[#macro prop name node type]
|
||||
[#assign value=cmisproperty(node, name)/]
|
||||
[#macro prop name object type]
|
||||
[#assign value=cmisproperty(object, name)/]
|
||||
[#if value?is_string || value?is_number || value?is_boolean || value?is_date || value?is_enumerable]
|
||||
[@propvalue name value type/]
|
||||
[#elseif value.class.canonicalName?ends_with("NULL")]
|
||||
@@ -250,20 +273,20 @@
|
||||
|
||||
[#macro propvalue name value type]
|
||||
[#if type == "STRING"]
|
||||
<cmis:propertyString cmis:name="${name}">[@values value;v][@stringvalue v/][/@values]</cmis:propertyString>
|
||||
<cmis:propertyString cmis:name="${name}">[@values value;v]<cmis:value>[@stringvalue v/]</cmis:value>[/@values]</cmis:propertyString>
|
||||
[#elseif type == "INTEGER"]
|
||||
<cmis:propertyInteger cmis:name="${name}">[@values value;v][@integervalue v/][/@values]</cmis:propertyInteger>
|
||||
<cmis:propertyInteger cmis:name="${name}">[@values value;v]<cmis:value>[@integervalue v/]</cmis:value>[/@values]</cmis:propertyInteger>
|
||||
[#elseif type == "DECIMAL"]
|
||||
<cmis:propertyDecimal cmis:name="${name}">[@values value;v][@decimalvalue v/][/@values]</cmis:propertyDecimal>
|
||||
<cmis:propertyDecimal cmis:name="${name}">[@values value;v]<cmis:value>[@decimalvalue v/]</cmis:value>[/@values]</cmis:propertyDecimal>
|
||||
[#elseif type == "BOOLEAN"]
|
||||
<cmis:propertyBoolean cmis:name="${name}">[@values value;v][@booleanvalue v/][/@values]</cmis:propertyBoolean>
|
||||
<cmis:propertyBoolean cmis:name="${name}">[@values value;v]<cmis:value>[@booleanvalue v/]</cmis:value>[/@values]</cmis:propertyBoolean>
|
||||
[#elseif type == "DATETIME"]
|
||||
<cmis:propertyDateTime cmis:name="${name}">[@values value;v][@datetimevalue v/][/@values]</cmis:propertyDateTime>
|
||||
<cmis:propertyDateTime cmis:name="${name}">[@values value;v]<cmis:value>[@datetimevalue v/]</cmis:value>[/@values]</cmis:propertyDateTime>
|
||||
[#elseif type == "URI"]
|
||||
[#-- TODO: check validity of abs url prefix --]
|
||||
<cmis:propertyUri cmis:name="${name}">[@values value;v][@urivalue absurl(url.serviceContext) + v/][/@values]</cmis:propertyUri>
|
||||
<cmis:propertyUri cmis:name="${name}">[@values value;v]<cmis:value>[@urivalue absurl(url.serviceContext) + v/]</cmis:value>[/@values]</cmis:propertyUri>
|
||||
[#elseif type == "ID"]
|
||||
<cmis:propertyId cmis:name="${name}">[@values value;v][@idvalue v/][/@values]</cmis:propertyId>
|
||||
<cmis:propertyId cmis:name="${name}">[@values value;v]<cmis:value>[@idvalue v/]</cmis:value>[/@values]</cmis:propertyId>
|
||||
[#-- TODO: remaining property types --]
|
||||
[/#if]
|
||||
[/#macro]
|
||||
@@ -292,15 +315,40 @@
|
||||
[#-- CMIS Values --]
|
||||
[#-- --]
|
||||
|
||||
[#macro namedvalue name object type]
|
||||
[#assign value=cmisproperty(object, name)/]
|
||||
[#if value?is_string || value?is_number || value?is_boolean || value?is_date || value?is_enumerable][@typedvalue value type/][#elseif value.class.canonicalName?ends_with("NULL")][/#if]
|
||||
[/#macro]
|
||||
|
||||
[#macro typedvalue value type]
|
||||
[#if type == "STRING"]
|
||||
[@values value;v][@stringvalue v/][/@values]
|
||||
[#elseif type == "INTEGER"]
|
||||
[@values value;v][@integervalue v/][/@values]
|
||||
[#elseif type == "DECIMAL"]
|
||||
[@values value;v][@decimalvalue v/][/@values]
|
||||
[#elseif type == "BOOLEAN"]
|
||||
[@values value;v][@booleanvalue v/][/@values]
|
||||
[#elseif type == "DATETIME"]
|
||||
[@values value;v][@datetimevalue v/][/@values]
|
||||
[#elseif type == "URI"]
|
||||
[#-- TODO: check validity of abs url prefix --]
|
||||
[@values value;v][@urivalue absurl(url.serviceContext) + v/][/@values]
|
||||
[#elseif type == "ID"]
|
||||
[@values value;v][@idvalue v/][/@values]
|
||||
[#-- TODO: remaining property types --]
|
||||
[/#if]
|
||||
[/#macro]
|
||||
|
||||
[#macro values vals][#if vals?is_enumerable][#list vals as val][#nested val][/#list][#else][#nested vals][/#if][/#macro]
|
||||
|
||||
[#macro stringvalue value]<cmis:value>${value}</cmis:value>[/#macro]
|
||||
[#macro integervalue value]<cmis:value>${value?c}</cmis:value>[/#macro]
|
||||
[#macro decimalvalue value]<cmis:value>${value?c}</cmis:value>[/#macro]
|
||||
[#macro booleanvalue value]<cmis:value>${value?string}</cmis:value>[/#macro]
|
||||
[#macro datetimevalue value]<cmis:value>${xmldate(value)}</cmis:value>[/#macro]
|
||||
[#macro urivalue value]<cmis:value>${value}</cmis:value>[/#macro]
|
||||
[#macro idvalue value]<cmis:value>${value}</cmis:value>[/#macro]
|
||||
[#macro stringvalue value]${value}[/#macro]
|
||||
[#macro integervalue value]${value?c}[/#macro]
|
||||
[#macro decimalvalue value]${value?c}[/#macro]
|
||||
[#macro booleanvalue value]${value?string}[/#macro]
|
||||
[#macro datetimevalue value]${xmldate(value)}[/#macro]
|
||||
[#macro urivalue value]${value}[/#macro]
|
||||
[#macro idvalue value]${value}[/#macro]
|
||||
|
||||
|
||||
[#-- --]
|
||||
@@ -527,37 +575,37 @@
|
||||
[#if type == "STRING"]
|
||||
<cmis:choiceString cmis:key="${choice.name}">
|
||||
[@cmisChoices choice.children type/]
|
||||
[@stringvalue choice.value/]
|
||||
<cmis:value>[@stringvalue choice.value/]</cmis:value>
|
||||
</cmis:choiceString>
|
||||
[#elseif type == "INTEGER"]
|
||||
<cmis:choiceInteger cmis:key="${choice.name}">
|
||||
[@cmisChoices choice.children type/]
|
||||
[@stringvalue choice.value/]
|
||||
<cmis:value>[@stringvalue choice.value/]</cmis:value>
|
||||
</cmis:choiceInteger>
|
||||
[#elseif type == "DECIMAL"]
|
||||
<cmis:choiceDecimal cmis:key="${choice.name}">
|
||||
[@cmisChoices choice.children type/]
|
||||
[@stringvalue choice.value/]
|
||||
<cmis:value>[@stringvalue choice.value/]</cmis:value>
|
||||
</cmis:choiceDecimal>
|
||||
[#elseif type == "BOOLEAN"]
|
||||
<cmis:choiceBoolean cmis:key="${choice.name}">
|
||||
[@cmisChoices choice.children type/]
|
||||
[@stringvalue choice.value/]
|
||||
<cmis:value>[@stringvalue choice.value/]</cmis:value>
|
||||
</cmis:choiceBoolean>
|
||||
[#elseif type == "DATETIME"]
|
||||
<cmis:choiceDateTime cmis:key="${choice.name}">
|
||||
[@cmisChoices choice.children type/]
|
||||
[@stringvalue choice.value/]
|
||||
<cmis:value>[@stringvalue choice.value/]</cmis:value>
|
||||
</cmis:choiceDateTime>
|
||||
[#elseif type == "URI"]
|
||||
<cmis:choiceUri cmis:key="${choice.name}">
|
||||
[@cmisChoices choice.children type/]
|
||||
[@stringvalue choice.value/]
|
||||
<cmis:value>[@stringvalue choice.value/]</cmis:value>
|
||||
</cmis:choiceUri>
|
||||
[#elseif type == "ID"]
|
||||
<cmis:choiceId cmis:key="${choice.name}">
|
||||
[@cmisChoices choice.children type/]
|
||||
[@stringvalue choice.value/]
|
||||
<cmis:value>[@stringvalue choice.value/]</cmis:value>
|
||||
</cmis:choiceId>
|
||||
[#-- TODO: remaining property types --]
|
||||
[/#if]
|
||||
@@ -582,3 +630,12 @@
|
||||
|
||||
[#-- Helper to render Alfresco service document uri --]
|
||||
[#macro serviceuri]${absurl(url.serviceContext)}/api/repository[/#macro]
|
||||
|
||||
[#-- Helper to render Node Ref --]
|
||||
[#macro noderef node]${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}[/#macro]
|
||||
|
||||
[#-- Helper to render Alfresco Node uri --]
|
||||
[#macro nodeuri node]/api/node/[@noderef node/][/#macro]
|
||||
|
||||
[#-- Helper to render Alfresco Assoc uri --]
|
||||
[#macro assocuri assoc]/api/rel/[@noderef assoc.source/]/type/${cmistype(assoc).typeId.id!"undefined"}/target/[@noderef assoc.target/][/#macro]
|
||||
|
@@ -1,4 +1,3 @@
|
||||
|
||||
//
|
||||
// Create Alfresco Node from Atom Entry
|
||||
//
|
||||
@@ -199,6 +198,57 @@ function updateNode(node, entry, exclude, validator)
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Create Alfresco Association from Atom Entry
|
||||
//
|
||||
// @param source source node
|
||||
// @param entry atom entry
|
||||
// @return created association (or null, in case of error)
|
||||
//
|
||||
function createAssociation(source, entry)
|
||||
{
|
||||
var object = entry.getExtension(atom.names.cmis_object);
|
||||
var typeId = (object !== null) ? object.objectTypeId.nativeValue : null;
|
||||
|
||||
// locate relationship type definition
|
||||
// TODO: check this against spec - default to Relationship, if not specified
|
||||
var type = cmis.queryType(typeId === null ? "relationship" : typeId);
|
||||
if (type === null)
|
||||
{
|
||||
status.setCode(400, "CMIS object type " + typeId + " not understood");
|
||||
return null;
|
||||
}
|
||||
if (type.typeId.baseTypeId.id != "relationship")
|
||||
{
|
||||
status.setCode(400, "CMIS object type " + typeId + " is not a relationship type");
|
||||
return null;
|
||||
}
|
||||
if (!type.creatable)
|
||||
{
|
||||
status.setCode(400, "Relationship type " + typeId + " is not creatable");
|
||||
return null;
|
||||
}
|
||||
|
||||
// locate target
|
||||
var targetId = (object !== null) ? object.targetId.nativeValue : null;
|
||||
if (targetId === null)
|
||||
{
|
||||
status.setCode(400, "Target Id has not been specified");
|
||||
return null;
|
||||
}
|
||||
var target = search.findNode(targetId);
|
||||
if (target === null)
|
||||
{
|
||||
status.setCode(400, "Target Id " + targetId + " does not refer to known item");
|
||||
return null;
|
||||
}
|
||||
|
||||
// create association
|
||||
var assoc = source.createAssociation(target, type.typeId.QName.toString());
|
||||
return assoc;
|
||||
}
|
||||
|
||||
|
||||
// callback for validating property update for patch
|
||||
// return null => update not allowed, abort update
|
||||
// true => update allowed
|
||||
|
@@ -0,0 +1,6 @@
|
||||
//
|
||||
// Constants
|
||||
//
|
||||
|
||||
// CMIS Enums
|
||||
CMISRelationshipDirectionEnum = Packages.org.alfresco.cmis.CMISRelationshipDirectionEnum;
|
@@ -0,0 +1,11 @@
|
||||
[#ftl]
|
||||
[#import "/org/alfresco/cmis/ns.lib.atom.ftl" as nsLib/]
|
||||
[#import "/org/alfresco/cmis/atomentry.lib.atom.ftl" as entryLib/]
|
||||
[#compress]
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
[#assign namespace][@nsLib.entryNS/][/#assign]
|
||||
|
||||
[@entryLib.assoc assoc=assoc propfilter=filter includeallowableactions=includeAllowableActions ns=namespace/]
|
||||
|
||||
[/#compress]
|
@@ -0,0 +1,9 @@
|
||||
<webscript>
|
||||
<shortname>Retrieve relationship (getProperties)</shortname>
|
||||
<description>
|
||||
</description>
|
||||
<url>/api/rel/{store_type}/{store_id}/{id}/type/{rel_type}/target/{target_store_type}/{target_store_id}/{target_id}</url>
|
||||
<authentication>guest</authentication>
|
||||
<format default="atomentry">argument</format>
|
||||
<family>CMIS</family>
|
||||
</webscript>
|
@@ -0,0 +1,28 @@
|
||||
script:
|
||||
{
|
||||
// relationship type
|
||||
var relType = url.templateArgs.rel_type;
|
||||
model.relTypeDef = cmis.queryType(relType);
|
||||
if (model.relTypeDef === null)
|
||||
{
|
||||
status.setCode(400, "Relationship type " + relType + " unknown");
|
||||
break script;
|
||||
}
|
||||
if (model.relTypeDef.baseType.typeId != "relationship")
|
||||
{
|
||||
status.setCode(400, "Type + " + relType + " is not a relationship type");
|
||||
break script;
|
||||
}
|
||||
|
||||
// source and target
|
||||
var source = [url.templateArgs.store_type, url.templateArgs.store_id, url.templateArgs.id];
|
||||
var target = [url.templateArgs.target_store_type, url.templateArgs.target_store_id, url.templateArgs.target_id];
|
||||
|
||||
// locate association
|
||||
model.assoc = cmis.findRelationship(model.relTypeDef, source, target);
|
||||
if (model.assoc === null)
|
||||
{
|
||||
status.setCode(404, "Assoc " + source.join("/") + "/" + relType + "/" + target.join("/") + " not found");
|
||||
break script;
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
[#ftl]
|
||||
[#import "/org/alfresco/cmis/ns.lib.atom.ftl" as nsLib/]
|
||||
[#import "/org/alfresco/cmis/atomfeed.lib.atom.ftl" as feedLib/]
|
||||
[#import "/org/alfresco/cmis/atomentry.lib.atom.ftl" as entryLib/]
|
||||
[#import "/org/alfresco/paging.lib.atom.ftl" as pagingLib/]
|
||||
[#compress]
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<feed [@nsLib.feedNS/]>
|
||||
|
||||
[@feedLib.node node "relationships"]
|
||||
[@pagingLib.links cursor/]
|
||||
[/@feedLib.node]
|
||||
|
||||
[#list results as assoc]
|
||||
[@entryLib.assoc assoc=assoc propfilter=filter includeallowableactions=includeAllowableActions/]
|
||||
[/#list]
|
||||
|
||||
[@feedLib.hasMore cursor/]
|
||||
[@pagingLib.opensearch cursor/]
|
||||
|
||||
</feed>
|
||||
|
||||
[/#compress]
|
@@ -0,0 +1,10 @@
|
||||
<webscript>
|
||||
<shortname>Retrieve list of relationships (getRelationships)</shortname>
|
||||
<description>
|
||||
</description>
|
||||
<url>/api/node/{store_type}/{store_id}/{id}/rels?filter={filter?}&relationshipType={relationshipType?}&includeSubRelationshipTypes={includeSubRelationshipTypes?}&direction={direction?}&skipCount={skipCount?}&maxItems={maxItems?}&includeAllowableActions={includeAllowableActions?}</url>
|
||||
<url>/api/path/{store_type}/{store_id}/{id}/rels?filter={filter?}&relationshipType={relationshipType?}&includeSubRelationshipTypes={includeSubRelationshipTypes?}&direction={direction?}&skipCount={skipCount?}&maxItems={maxItems?}&includeAllowableActions={includeAllowableActions?}</url>
|
||||
<authentication>guest</authentication>
|
||||
<format default="atomfeed">argument</format>
|
||||
<family>CMIS</family>
|
||||
</webscript>
|
@@ -0,0 +1,59 @@
|
||||
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/constants.lib.js">
|
||||
|
||||
script:
|
||||
{
|
||||
// locate node
|
||||
var pathSegments = url.match.split("/");
|
||||
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
|
||||
model.node = cmis.findNode(pathSegments[2], reference);
|
||||
if (model.node === null)
|
||||
{
|
||||
status.setCode(404, "Repository " + pathSegments[2] + " " + reference.join("/") + " not found");
|
||||
break script;
|
||||
}
|
||||
|
||||
// property filter
|
||||
model.filter = args[cmis.ARG_FILTER];
|
||||
if (model.filter === null)
|
||||
{
|
||||
model.filter = "*";
|
||||
}
|
||||
|
||||
// relationship type
|
||||
var relType = args[cmis.ARG_RELATIONSHIP_TYPE];
|
||||
if (relType != null)
|
||||
{
|
||||
model.relTypeDef = cmis.queryType(relType);
|
||||
if (model.relTypeDef === null)
|
||||
{
|
||||
status.setCode(400, "Relationship type " + relType + " unknown");
|
||||
break script;
|
||||
}
|
||||
if (model.relTypeDef.baseType.typeId != "relationship")
|
||||
{
|
||||
status.setCode(400, "Type + " + relType + " is not a relationship type");
|
||||
break script;
|
||||
}
|
||||
}
|
||||
|
||||
// include sub relationship types
|
||||
model.includeSubRelationshipTypes = args[cmis.ARG_INCLUDE_SUB_RELATIONSHIP_TYPES] == "true" ? true : false;
|
||||
|
||||
// direction
|
||||
var direction = args[cmis.ARG_DIRECTION];
|
||||
if (direction !== null && !CMISRelationshipDirectionEnum.FACTORY.validLabel(direction))
|
||||
{
|
||||
status.setCode(400, "Direction " + direction + " unknown");
|
||||
break script;
|
||||
}
|
||||
model.direction = CMISRelationshipDirectionEnum.FACTORY.toEnum(direction);
|
||||
|
||||
// include allowable actions
|
||||
model.includeAllowableActions = args[cmis.ARG_INCLUDE_ALLOWABLE_ACTIONS] == "true" ? true : false;
|
||||
|
||||
// retrieve relationships
|
||||
var page = paging.createPageOrWindow(args);
|
||||
var paged = cmis.queryRelationships(model.node, model.relDefType, model.includeSubRelationshipTypes, model.direction, page);
|
||||
model.results = paged.results;
|
||||
model.cursor = paged.cursor;
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/atomentry.lib.js">
|
||||
|
||||
script:
|
||||
{
|
||||
// ensure atom entry is posted
|
||||
if (entry === null)
|
||||
{
|
||||
status.code = 400;
|
||||
status.message = "Expected atom entry";
|
||||
status.redirect = true;
|
||||
break script;
|
||||
}
|
||||
|
||||
// locate source node
|
||||
var pathSegments = url.match.split("/");
|
||||
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
|
||||
model.source = cmis.findNode(pathSegments[2], reference);
|
||||
if (model.source === null)
|
||||
{
|
||||
status.code = 404;
|
||||
status.message = "Repository " + pathSegments[2] + " " + reference.join("/") + " not found";
|
||||
status.redirect = true;
|
||||
break script;
|
||||
}
|
||||
|
||||
// create
|
||||
var assoc = createAssociation(model.source, entry);
|
||||
if (assoc == null)
|
||||
{
|
||||
break script;
|
||||
}
|
||||
|
||||
// success
|
||||
model.assoc = assoc;
|
||||
// TODO: set Content-Location
|
||||
status.code = 201;
|
||||
// TODO: complete url mapping
|
||||
status.location = url.server + url.serviceContext + "/api/rel/" + model.source.nodeRef.storeRef.protocol + "/" + model.source.nodeRef.storeRef.identifier + "/" + model.source.nodeRef.id;
|
||||
status.redirect = true;
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
[#ftl]
|
||||
[#import "/org/alfresco/cmis/ns.lib.atom.ftl" as nsLib/]
|
||||
[#import "/org/alfresco/cmis/atomentry.lib.atom.ftl" as entryLib/]
|
||||
[#compress]
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
[#assign namespace][@nsLib.entryNS/][/#assign]
|
||||
|
||||
[@entryLib.assoc assoc=assoc propfilter=filter includeallowableactions=includeAllowableActions ns=namespace/]
|
||||
|
||||
[/#compress]
|
@@ -0,0 +1,10 @@
|
||||
<webscript>
|
||||
<shortname>Create relationship (createRelationship)</shortname>
|
||||
<description>
|
||||
</description>
|
||||
<url>/api/node/{store_type}/{store_id}/{id}/rels</url>
|
||||
<url>/api/path/{store_type}/{store_id}/{id}/rels</url>
|
||||
<authentication>guest</authentication>
|
||||
<format default="atomentry">argument</format>
|
||||
<family>CMIS</family>
|
||||
</webscript>
|
@@ -27,6 +27,7 @@ package org.alfresco.repo.cmis.rest;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.cmis.CMISServices;
|
||||
import org.alfresco.repo.template.TemplateAssociation;
|
||||
import org.alfresco.repo.template.TemplateNode;
|
||||
|
||||
import freemarker.ext.beans.BeanModel;
|
||||
@@ -76,14 +77,6 @@ public final class CMISPropertyValueMethod implements TemplateMethodModelEx
|
||||
Object arg0 = args.get(0);
|
||||
if (arg0 instanceof BeanModel)
|
||||
{
|
||||
// extract node
|
||||
TemplateNode node = null;
|
||||
Object wrapped = ((BeanModel)arg0).getWrappedObject();
|
||||
if (wrapped != null && wrapped instanceof TemplateNode)
|
||||
{
|
||||
node = (TemplateNode)wrapped;
|
||||
}
|
||||
|
||||
// extract property name
|
||||
String propertyName = null;
|
||||
Object arg1 = args.get(1);
|
||||
@@ -92,8 +85,18 @@ public final class CMISPropertyValueMethod implements TemplateMethodModelEx
|
||||
propertyName = ((TemplateScalarModel)arg1).getAsString();
|
||||
}
|
||||
|
||||
// retrieve property value
|
||||
result = cmisService.getProperty(node.getNodeRef(), propertyName);
|
||||
// extract node
|
||||
Object wrapped = ((BeanModel)arg0).getWrappedObject();
|
||||
if (wrapped != null && wrapped instanceof TemplateNode)
|
||||
{
|
||||
// retrieve property value from node
|
||||
result = cmisService.getProperty(((TemplateNode)wrapped).getNodeRef(), propertyName);
|
||||
}
|
||||
else if (wrapped != null && wrapped instanceof TemplateAssociation)
|
||||
{
|
||||
// retrieve property value from node
|
||||
result = cmisService.getProperty(((TemplateAssociation)wrapped).getAssociationRef(), propertyName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -33,11 +33,13 @@ import org.alfresco.cmis.CMISPropertyDefinition;
|
||||
import org.alfresco.cmis.CMISQueryEnum;
|
||||
import org.alfresco.cmis.CMISQueryOptions;
|
||||
import org.alfresco.cmis.CMISQueryService;
|
||||
import org.alfresco.cmis.CMISRelationshipDirectionEnum;
|
||||
import org.alfresco.cmis.CMISResultSet;
|
||||
import org.alfresco.cmis.CMISServices;
|
||||
import org.alfresco.cmis.CMISTypeDefinition;
|
||||
import org.alfresco.cmis.CMISTypesFilterEnum;
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.jscript.Association;
|
||||
import org.alfresco.repo.jscript.BaseScopableProcessorExtension;
|
||||
import org.alfresco.repo.jscript.ScriptNode;
|
||||
import org.alfresco.repo.model.Repository;
|
||||
@@ -46,6 +48,7 @@ import org.alfresco.repo.web.util.paging.Page;
|
||||
import org.alfresco.repo.web.util.paging.PagedResults;
|
||||
import org.alfresco.repo.web.util.paging.Paging;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
@@ -73,7 +76,7 @@ public class CMISScript extends BaseScopableProcessorExtension
|
||||
public static final String ARG_INCLUDE_ALLOWABLE_ACTIONS = "includeAllowableActions";
|
||||
public static final String ARG_INCLUDE_PROPERTY_DEFINITIONS = "includePropertyDefinitions";
|
||||
public static final String ARG_INCLUDE_RELATIONSHIPS = "includeRelationships";
|
||||
public static final String ARG_INCLUDE_SUB_RELATIONSHIP_TYPES = "includeSubrelationshipTypes";
|
||||
public static final String ARG_INCLUDE_SUB_RELATIONSHIP_TYPES = "includeSubRelationshipTypes";
|
||||
public static final String ARG_LENGTH = "length";
|
||||
public static final String ARG_MAJOR = "major";
|
||||
public static final String ARG_MAJOR_VERSION = "majorVersion";
|
||||
@@ -197,7 +200,7 @@ public class CMISScript extends BaseScopableProcessorExtension
|
||||
*/
|
||||
public String getDefaultTypesFilter()
|
||||
{
|
||||
return CMISTypesFilterEnum.FACTORY.defaultLabel();
|
||||
return CMISTypesFilterEnum.FACTORY.getDefaultLabel();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -243,6 +246,25 @@ public class CMISScript extends BaseScopableProcessorExtension
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an Association
|
||||
*
|
||||
* @param sourceType
|
||||
* @param source
|
||||
* @param relDef
|
||||
* @param targetType
|
||||
* @param target
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Association findRelationship(CMISTypeDefinition relDef, String[] sourceRef, String[] targetRef)
|
||||
{
|
||||
NodeRef source = new NodeRef(sourceRef[0], sourceRef[1], sourceRef[2]);
|
||||
NodeRef target = new NodeRef(targetRef[0], targetRef[1], targetRef[2]);
|
||||
AssociationRef assocRef = cmisService.getRelationship(relDef, source, target);
|
||||
return (assocRef == null) ? null : new Association(services, assocRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query for node children
|
||||
*
|
||||
@@ -267,6 +289,31 @@ public class CMISScript extends BaseScopableProcessorExtension
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query for node relationships
|
||||
*
|
||||
* @param node
|
||||
* @param relDef
|
||||
* @param includeSubTypes
|
||||
* @param direction
|
||||
* @param page
|
||||
* @return
|
||||
*/
|
||||
public PagedResults queryRelationships(ScriptNode node, CMISTypeDefinition relDef, boolean includeSubTypes, CMISRelationshipDirectionEnum direction, Page page)
|
||||
{
|
||||
AssociationRef[] relationships = cmisService.getRelationships(node.getNodeRef(), relDef, includeSubTypes, direction);
|
||||
|
||||
Cursor cursor = paging.createCursor(relationships.length, page);
|
||||
Association[] assocs = new Association[cursor.getRowCount()];
|
||||
for (int i = cursor.getStartRow(); i <= cursor.getEndRow(); i++)
|
||||
{
|
||||
assocs[i - cursor.getStartRow()] = new Association(services, relationships[i], getScope());
|
||||
}
|
||||
|
||||
PagedResults results = paging.createPagedResults(assocs, cursor);
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query for items checked-out to user
|
||||
*
|
||||
|
@@ -27,7 +27,10 @@ package org.alfresco.repo.cmis.rest;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.cmis.CMISDictionaryService;
|
||||
import org.alfresco.cmis.CMISScope;
|
||||
import org.alfresco.cmis.CMISTypeDefinition;
|
||||
import org.alfresco.cmis.mapping.CMISMapping;
|
||||
import org.alfresco.repo.template.TemplateAssociation;
|
||||
import org.alfresco.repo.template.TemplateNode;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
@@ -47,8 +50,10 @@ import freemarker.template.TemplateModelException;
|
||||
*/
|
||||
public class CMISTypeDefinitionMethod implements TemplateMethodModelEx
|
||||
{
|
||||
private static CMISScope[] EMPTY_SCOPES = new CMISScope[] {};
|
||||
private CMISDictionaryService dictionaryService;
|
||||
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*/
|
||||
@@ -71,6 +76,7 @@ public class CMISTypeDefinitionMethod implements TemplateMethodModelEx
|
||||
if (arg0 instanceof BeanModel)
|
||||
{
|
||||
// extract node type qname
|
||||
CMISScope[] matchingScopes = EMPTY_SCOPES;
|
||||
QName nodeType = null;
|
||||
Object wrapped = ((BeanModel)arg0).getWrappedObject();
|
||||
if (wrapped != null)
|
||||
@@ -79,6 +85,11 @@ public class CMISTypeDefinitionMethod implements TemplateMethodModelEx
|
||||
{
|
||||
nodeType = ((TemplateNode)wrapped).getType();
|
||||
}
|
||||
else if (wrapped instanceof TemplateAssociation)
|
||||
{
|
||||
nodeType = ((TemplateAssociation)wrapped).getTypeQName();
|
||||
matchingScopes = new CMISScope[] { CMISScope.RELATIONSHIP };
|
||||
}
|
||||
else if (wrapped instanceof QName)
|
||||
{
|
||||
nodeType = (QName)wrapped;
|
||||
@@ -88,7 +99,7 @@ public class CMISTypeDefinitionMethod implements TemplateMethodModelEx
|
||||
// convert to CMIS type
|
||||
if (nodeType != null)
|
||||
{
|
||||
result = dictionaryService.findTypeForClass(nodeType);
|
||||
result = dictionaryService.findTypeForClass(nodeType, matchingScopes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -501,6 +501,31 @@ public class BaseCMISWebScriptTest extends BaseWebScriptTest
|
||||
return entry;
|
||||
}
|
||||
|
||||
protected Entry createRelationship(IRI parent, String type, String targetId)
|
||||
throws Exception
|
||||
{
|
||||
return createRelationship(parent, type, targetId, "/org/alfresco/repo/cmis/rest/test/createrelationship.atomentry.xml");
|
||||
}
|
||||
|
||||
protected Entry createRelationship(IRI parent, String type, String targetId, String atomEntryFile)
|
||||
throws Exception
|
||||
{
|
||||
String createFile = loadString(atomEntryFile);
|
||||
createFile = createFile.replace("${RELTYPE}", type);
|
||||
createFile = createFile.replace("${TARGETID}", targetId);
|
||||
Response res = sendRequest(new PostRequest(parent.toString(), createFile, Format.ATOMENTRY.mimetype()), 201, getAtomValidator());
|
||||
assertNotNull(res);
|
||||
String xml = res.getContentAsString();
|
||||
Entry entry = abdera.parseEntry(new StringReader(xml), null);
|
||||
assertNotNull(entry);
|
||||
CMISObject object = entry.getExtension(CMISConstants.OBJECT);
|
||||
assertEquals("relationship", object.getBaseType().getStringValue());
|
||||
assertEquals(targetId, object.getTargetId().getStringValue());
|
||||
String testFileHREF = (String)res.getHeader("Location");
|
||||
assertNotNull(testFileHREF);
|
||||
return entry;
|
||||
}
|
||||
|
||||
//
|
||||
// General Test Helpers
|
||||
//
|
||||
|
@@ -25,12 +25,15 @@
|
||||
package org.alfresco.repo.cmis.rest.test;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.abdera.ext.cmis.CMISConstants;
|
||||
import org.alfresco.abdera.ext.cmis.CMISObject;
|
||||
import org.alfresco.abdera.ext.cmis.CMISProperties;
|
||||
import org.alfresco.abdera.ext.cmis.CMISProperty;
|
||||
import org.alfresco.repo.cmis.rest.CMISScript;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.alfresco.web.scripts.Format;
|
||||
import org.alfresco.web.scripts.TestWebScriptServer.DeleteRequest;
|
||||
@@ -105,11 +108,11 @@ public class CMISCustomTypeTest extends BaseCMISWebScriptTest
|
||||
Feed children = getFeed(childrenLink.getHref());
|
||||
assertNotNull(children);
|
||||
int entriesBefore = children.getEntries().size();
|
||||
Entry folder = createDocument(children.getSelfLink().getHref(), "testCreateCustomDocument", "/org/alfresco/repo/cmis/rest/test/createcustomdocument.atomentry.xml");
|
||||
Entry document = createDocument(children.getSelfLink().getHref(), "testCreateCustomDocument", "/org/alfresco/repo/cmis/rest/test/createcustomdocument.atomentry.xml");
|
||||
Feed feedFolderAfter = getFeed(childrenLink.getHref());
|
||||
int entriesAfter = feedFolderAfter.getEntries().size();
|
||||
assertEquals(entriesBefore +1, entriesAfter);
|
||||
Entry entry = feedFolderAfter.getEntry(folder.getId().toString());
|
||||
Entry entry = feedFolderAfter.getEntry(document.getId().toString());
|
||||
CMISObject object = entry.getExtension(CMISConstants.OBJECT);
|
||||
assertEquals("D/cmiscustom_document", object.getObjectTypeId().getStringValue());
|
||||
CMISProperty customProp = object.getProperties().find("cmiscustom_docprop_string");
|
||||
@@ -316,4 +319,90 @@ public class CMISCustomTypeTest extends BaseCMISWebScriptTest
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreateRelationship()
|
||||
throws Exception
|
||||
{
|
||||
Entry testFolder = createTestFolder("testCreateCustomRelationship");
|
||||
Link childrenLink = testFolder.getLink(CMISConstants.REL_CHILDREN);
|
||||
assertNotNull(childrenLink);
|
||||
Feed children = getFeed(childrenLink.getHref());
|
||||
assertNotNull(children);
|
||||
Entry source = createDocument(children.getSelfLink().getHref(), "testSource", "/org/alfresco/repo/cmis/rest/test/createcustomdocument.atomentry.xml");
|
||||
assertNotNull(source);
|
||||
Entry target = createDocument(children.getSelfLink().getHref(), "testTarget", "/org/alfresco/repo/cmis/rest/test/createcustomdocument.atomentry.xml");
|
||||
assertNotNull(target);
|
||||
|
||||
// retrieve relationships feed on source
|
||||
Link relsLink = source.getLink(CMISConstants.REL_RELATIONSHIPS);
|
||||
assertNotNull(relsLink);
|
||||
Feed relsBefore = getFeed(relsLink.getHref());
|
||||
assertNotNull(relsBefore);
|
||||
assertEquals(0, relsBefore.getEntries().size());
|
||||
|
||||
// create relationship between source and target documents
|
||||
CMISObject targetObject = target.getExtension(CMISConstants.OBJECT);
|
||||
assertNotNull(targetObject);
|
||||
String targetId = targetObject.getObjectId().getStringValue();
|
||||
assertNotNull(targetId);
|
||||
Entry rel = createRelationship(relsLink.getHref(), "R/cmiscustom_assoc", targetId);
|
||||
assertNotNull(rel);
|
||||
|
||||
// check created relationship
|
||||
CMISObject sourceObject = source.getExtension(CMISConstants.OBJECT);
|
||||
assertNotNull(sourceObject);
|
||||
String sourceId = sourceObject.getObjectId().getStringValue();
|
||||
assertNotNull(sourceId);
|
||||
CMISObject relObject = rel.getExtension(CMISConstants.OBJECT);
|
||||
assertNotNull(relObject);
|
||||
assertEquals("R/cmiscustom_assoc", relObject.getObjectTypeId().getStringValue());
|
||||
assertEquals(sourceId, relObject.getSourceId().getStringValue());
|
||||
assertEquals(targetId, relObject.getTargetId().getStringValue());
|
||||
assertEquals(source.getSelfLink().getHref(), rel.getLink(CMISConstants.REL_SOURCE).getHref());
|
||||
assertEquals(target.getSelfLink().getHref(), rel.getLink(CMISConstants.REL_TARGET).getHref());
|
||||
|
||||
// check relationships for created item
|
||||
Map<String, String> args = new HashMap<String, String>();
|
||||
args.put(CMISScript.ARG_INCLUDE_SUB_RELATIONSHIP_TYPES, "true");
|
||||
Feed relsAfter = getFeed(relsLink.getHref(), args);
|
||||
assertNotNull(relsAfter);
|
||||
assertEquals(1, relsAfter.getEntries().size());
|
||||
}
|
||||
|
||||
public void testGetRelationship()
|
||||
throws Exception
|
||||
{
|
||||
Entry testFolder = createTestFolder("testGetCustomRelationship");
|
||||
Link childrenLink = testFolder.getLink(CMISConstants.REL_CHILDREN);
|
||||
assertNotNull(childrenLink);
|
||||
Feed children = getFeed(childrenLink.getHref());
|
||||
assertNotNull(children);
|
||||
Entry source = createDocument(children.getSelfLink().getHref(), "testSource", "/org/alfresco/repo/cmis/rest/test/createcustomdocument.atomentry.xml");
|
||||
assertNotNull(source);
|
||||
Entry target = createDocument(children.getSelfLink().getHref(), "testTarget", "/org/alfresco/repo/cmis/rest/test/createcustomdocument.atomentry.xml");
|
||||
assertNotNull(target);
|
||||
|
||||
// retrieve relationships feed on source
|
||||
Link relsLink = source.getLink(CMISConstants.REL_RELATIONSHIPS);
|
||||
assertNotNull(relsLink);
|
||||
|
||||
// create relationship between source and target documents
|
||||
CMISObject targetObject = target.getExtension(CMISConstants.OBJECT);
|
||||
assertNotNull(targetObject);
|
||||
String targetId = targetObject.getObjectId().getStringValue();
|
||||
assertNotNull(targetId);
|
||||
Entry rel = createRelationship(relsLink.getHref(), "R/cmiscustom_assoc", targetId);
|
||||
assertNotNull(rel);
|
||||
|
||||
// get created relationship
|
||||
Entry relEntry = getEntry(rel.getSelfLink().getHref());
|
||||
CMISObject relEntryObject = rel.getExtension(CMISConstants.OBJECT);
|
||||
CMISObject relObject = rel.getExtension(CMISConstants.OBJECT);
|
||||
assertNotNull(relObject);
|
||||
assertEquals(relObject.getObjectTypeId().getStringValue(), relEntryObject.getObjectTypeId().getStringValue());
|
||||
assertEquals(relObject.getSourceId().getStringValue(), relEntryObject.getSourceId().getStringValue());
|
||||
assertEquals(relObject.getTargetId().getStringValue(), relEntryObject.getTargetId().getStringValue());
|
||||
assertEquals(source.getSelfLink().getHref(), relEntry.getLink(CMISConstants.REL_SOURCE).getHref());
|
||||
assertEquals(target.getSelfLink().getHref(), relEntry.getLink(CMISConstants.REL_TARGET).getHref());
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200901">
|
||||
<cmis:object>
|
||||
<cmis:properties>
|
||||
<cmis:propertyString cmis:name="ObjectTypeId"><cmis:value>${RELTYPE}</cmis:value></cmis:propertyString>
|
||||
<cmis:propertyId cmis:name="TargetId"><cmis:value>${TARGETID}</cmis:value></cmis:propertyId>
|
||||
</cmis:properties>
|
||||
</cmis:object>
|
||||
</entry>
|
@@ -208,6 +208,13 @@ public class CMISSchemaTest extends TestCase
|
||||
assertValidXML(xml, cmisValidator.getCMISAtomValidator());
|
||||
}
|
||||
|
||||
public void testAtomEntry()
|
||||
throws Exception
|
||||
{
|
||||
String xml = getXML("example_atomentry.xml");
|
||||
assertValidXML(xml, cmisValidator.getCMISAtomValidator());
|
||||
}
|
||||
|
||||
//
|
||||
// Missing from v0.61
|
||||
//
|
||||
|
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<ns3:entry xmlns:ns1="http://docs.oasis-open.org/ns/cmis/core/200901" xmlns:ns2="http://docs.oasis-open.org/ns/cmis/messaging/200901" xmlns:ns3="http://www.w3.org/2005/Atom" xmlns:ns4="http://www.w3.org/2007/app">
|
||||
<ns3:author>
|
||||
<ns3:name>Al Brown</ns3:name>
|
||||
<ns3:uri>http://www.ibm.com/</ns3:uri>
|
||||
<ns3:email>albertcbrown@us.ibm.com</ns3:email>
|
||||
</ns3:author>
|
||||
<ns3:content src="http://cmisexample.oasis-open.org/rep1/70cfe57f-5d59-4293-9cbc-842107117d65"/>
|
||||
<ns3:id>urn:uuid:70cfe57f-5d59-4293-9cbc-842107117d65</ns3:id>
|
||||
<ns3:link rel="self" href="http://cmisexample.oasis-open.org/rep1/70cfe57f-5d59-4293-9cbc-842107117d65"/>
|
||||
<ns3:link rel="edit" href="http://cmisexample.oasis-open.org/rep1/70cfe57f-5d59-4293-9cbc-842107117d65"/>
|
||||
<ns3:link type="application/cmis+xml;type=allowableActions" rel="allowableactions" href="http://cmisexample.oasis-open.org/rep1/70cfe57f-5d59-4293-9cbc-842107117d65/allowableactions"/>
|
||||
<ns3:link type="application/atom+xml;type=entry" rel="type" href="http://cmisexample.oasis-open.org/rep1/70cfe57f-5d59-4293-9cbc-842107117d65/type"/>
|
||||
<ns3:link rel="edit-media" href="http://cmisexample.oasis-open.org/rep1/70cfe57f-5d59-4293-9cbc-842107117d65/edit-media"/>
|
||||
<ns3:link rel="alternate" href="http://cmisexample.oasis-open.org/rep1/70cfe57f-5d59-4293-9cbc-842107117d65/alternate"/>
|
||||
<ns3:link type="application/atom+xml;type=feed" rel="parents" href="http://cmisexample.oasis-open.org/rep1/70cfe57f-5d59-4293-9cbc-842107117d65/parents"/>
|
||||
<ns3:link type="application/atom+xml;type=feed" rel="allversions" href="http://cmisexample.oasis-open.org/rep1/70cfe57f-5d59-4293-9cbc-842107117d65/allversions"/>
|
||||
<ns3:link type="application/atom+xml;type=entry" rel="latestversion" href="http://cmisexample.oasis-open.org/rep1/70cfe57f-5d59-4293-9cbc-842107117d65/latestversions"/>
|
||||
<ns3:link length="4123" type="text/plain" rel="stream" href="http://cmisexample.oasis-open.org/rep1/70cfe57f-5d59-4293-9cbc-842107117d65media"/>
|
||||
<ns3:link type="application/atom+xml;type=feed" rel="relationships" href="http://cmisexample.oasis-open.org/rep1/70cfe57f-5d59-4293-9cbc-842107117d65/relationships"/>
|
||||
<ns3:published>2009-04-17T13:50:58.656-07:00</ns3:published>
|
||||
<ns3:summary type="html">HTML summary of Entry 70cfe57f-5d59-4293-9cbc-842107117d65</ns3:summary>
|
||||
<ns3:title type="text">CMIS Example Document</ns3:title>
|
||||
<ns3:updated>2009-04-17T13:50:58.656-07:00</ns3:updated>
|
||||
<ns1:terminator xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
|
||||
</ns3:entry>
|
@@ -42,6 +42,19 @@
|
||||
<multiple>true</multiple>
|
||||
</property>
|
||||
</properties>
|
||||
<associations>
|
||||
<association name="cmiscustom:assoc">
|
||||
<source>
|
||||
<mandatory>false</mandatory>
|
||||
<many>false</many>
|
||||
</source>
|
||||
<target>
|
||||
<class>cm:content</class>
|
||||
<mandatory>false</mandatory>
|
||||
<many>true</many>
|
||||
</target>
|
||||
</association>
|
||||
</associations>
|
||||
</type>
|
||||
</types>
|
||||
|
||||
|
Reference in New Issue
Block a user