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:
David Caruana
2009-05-27 22:11:31 +00:00
parent 0e56f7f40c
commit 47da70f4df
23 changed files with 622 additions and 77 deletions

View File

@@ -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);
}
}
}

View File

@@ -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();
}
/**
@@ -242,6 +245,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
*

View File

@@ -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);
}
}
}

View File

@@ -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
//

View File

@@ -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");
@@ -315,5 +318,91 @@ public class CMISCustomTypeTest extends BaseCMISWebScriptTest
assertEquals(false, result2multiValues.get(1));
}
}
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());
}
}

View File

@@ -4,8 +4,8 @@
<summary>${NAME} (summary)</summary>
<content type="text/html">${CONTENT}</content>
<cmis:object>
<cmis:properties>
<cmis:propertyString cmis:name="ObjectTypeId"><cmis:value>document</cmis:value></cmis:propertyString>
</cmis:properties>
<cmis:properties>
<cmis:propertyString cmis:name="ObjectTypeId"><cmis:value>document</cmis:value></cmis:propertyString>
</cmis:properties>
</cmis:object>
</entry>

View File

@@ -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>

View File

@@ -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
//

View File

@@ -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>