diff --git a/source/java/org/alfresco/cmis/CMISPropertyAccessor.java b/source/java/org/alfresco/cmis/CMISPropertyAccessor.java index 632cc56e5f..b204d9e1ed 100644 --- a/source/java/org/alfresco/cmis/CMISPropertyAccessor.java +++ b/source/java/org/alfresco/cmis/CMISPropertyAccessor.java @@ -26,6 +26,7 @@ package org.alfresco.cmis; import java.io.Serializable; +import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.QName; @@ -51,7 +52,7 @@ public interface CMISPropertyAccessor public QName getMappedProperty(); /** - * Get the property value + * Get the property value for a node * * @param nodeRef * @return @@ -59,10 +60,18 @@ public interface CMISPropertyAccessor public Serializable getValue(NodeRef nodeRef); /** - * Set the property value + * Set the property value for a node * * @param nodeRef * @Param value */ public void setValue(NodeRef nodeRef, Serializable value); + + /** + * Get the property value for an association + * + * @param nodeRef + * @return + */ + public Serializable getValue(AssociationRef assocRef); } diff --git a/source/java/org/alfresco/cmis/CMISRelationshipDirectionEnum.java b/source/java/org/alfresco/cmis/CMISRelationshipDirectionEnum.java new file mode 100644 index 0000000000..445e6afa3a --- /dev/null +++ b/source/java/org/alfresco/cmis/CMISRelationshipDirectionEnum.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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 General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.cmis; + +/** + * CMIS Types Filter Enum + * + * @author davidc + */ +public enum CMISRelationshipDirectionEnum implements EnumLabel +{ + SOURCE("source"), + TARGET("target"), + BOTH("both"); + + + private String label; + + /** + * Construct + * + * @param label + */ + CMISRelationshipDirectionEnum(String label) + { + this.label = label; + } + + /* (non-Javadoc) + * @see org.alfresco.cmis.EnumLabel#label() + */ + public String getLabel() + { + return label; + } + + public static EnumFactory FACTORY = new EnumFactory(CMISRelationshipDirectionEnum.class, BOTH); +} \ No newline at end of file diff --git a/source/java/org/alfresco/cmis/CMISServices.java b/source/java/org/alfresco/cmis/CMISServices.java index 42d2d4d29f..5d671d65d1 100644 --- a/source/java/org/alfresco/cmis/CMISServices.java +++ b/source/java/org/alfresco/cmis/CMISServices.java @@ -27,6 +27,7 @@ package org.alfresco.cmis; import java.io.Serializable; import java.util.Map; +import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.StoreRef; @@ -86,7 +87,28 @@ public interface CMISServices public NodeRef[] getCheckedOut(String username, NodeRef folder, boolean includeDescendants); /** - * Get a single property + * Query for relationship + * + * @param relDef + * @param source + * @param target + * @return relationship + */ + public AssociationRef getRelationship(CMISTypeDefinition relDef, NodeRef source, NodeRef target); + + /** + * Query for relationships + * + * @param item node to query relationships for + * @param relDef type of relationship to query (or null, for all relationships) + * @param includeSubTypes + * @param direction limit direction of relationships to query (or null, for both directions) + * @return relationships + */ + public AssociationRef[] getRelationships(NodeRef node, CMISTypeDefinition relDef, boolean includeSubTypes, CMISRelationshipDirectionEnum direction); + + /** + * Get a single property for a node * * @param nodeRef * @param propertyName @@ -94,6 +116,15 @@ public interface CMISServices */ public Serializable getProperty(NodeRef nodeRef, String propertyName); + /** + * Get a single property for an association + * + * @param assocRef + * @param propertyName + * @return value + */ + public Serializable getProperty(AssociationRef assocRef, String propertyName); + /** * Get all properties * diff --git a/source/java/org/alfresco/cmis/CMISTypesFilterEnum.java b/source/java/org/alfresco/cmis/CMISTypesFilterEnum.java index 076d3eac74..4b54534f55 100644 --- a/source/java/org/alfresco/cmis/CMISTypesFilterEnum.java +++ b/source/java/org/alfresco/cmis/CMISTypesFilterEnum.java @@ -1,3 +1,27 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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 General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ package org.alfresco.cmis; /** diff --git a/source/java/org/alfresco/cmis/EnumFactory.java b/source/java/org/alfresco/cmis/EnumFactory.java index 8b8c99605e..1c3e2de94c 100644 --- a/source/java/org/alfresco/cmis/EnumFactory.java +++ b/source/java/org/alfresco/cmis/EnumFactory.java @@ -88,7 +88,7 @@ public class EnumFactory> * * @return default enum (or null, if no default specified) */ - public Enum defaultEnum() + public Enum getDefaultEnum() { return defaultEnum; } @@ -98,7 +98,7 @@ public class EnumFactory> * * @return label of default enum (or null, if no default specified) */ - public String defaultLabel() + public String getDefaultLabel() { return label(defaultEnum); } @@ -150,7 +150,7 @@ public class EnumFactory> */ public Enum toEnum(String label) { - Enum e = fromLabel(label); + Enum e = (label == null) ? null : fromLabel(label); if (e == null) { e = defaultEnum; diff --git a/source/java/org/alfresco/cmis/dictionary/CMISAbstractDictionaryService.java b/source/java/org/alfresco/cmis/dictionary/CMISAbstractDictionaryService.java index 578d8f31fc..68abb83adf 100644 --- a/source/java/org/alfresco/cmis/dictionary/CMISAbstractDictionaryService.java +++ b/source/java/org/alfresco/cmis/dictionary/CMISAbstractDictionaryService.java @@ -276,6 +276,10 @@ public abstract class CMISAbstractDictionaryService extends AbstractLifecycleBea else { typeDef = getRegistry().typeDefsByQName.get(clazz); + if (typeDef == null) + { + typeDef = getRegistry().assocDefsByQName.get(clazz); + } } // ensure matches one of provided matching scopes diff --git a/source/java/org/alfresco/cmis/dictionary/CMISAbstractTypeDefinition.java b/source/java/org/alfresco/cmis/dictionary/CMISAbstractTypeDefinition.java index 2f51436616..460eb5c876 100644 --- a/source/java/org/alfresco/cmis/dictionary/CMISAbstractTypeDefinition.java +++ b/source/java/org/alfresco/cmis/dictionary/CMISAbstractTypeDefinition.java @@ -450,4 +450,30 @@ public class CMISAbstractTypeDefinition implements CMISTypeDefinition, Serializa return Collections.emptyList(); } + @Override + public int hashCode() + { + return objectTypeId.hashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final CMISTypeDefinition other = (CMISTypeDefinition) obj; + if (objectTypeId == null) + { + if (other.getTypeId() != null) + return false; + } + else if (!objectTypeId.equals(other.getTypeId())) + return false; + return true; + } + } diff --git a/source/java/org/alfresco/cmis/dictionary/CMISRelationshipTypeDefinition.java b/source/java/org/alfresco/cmis/dictionary/CMISRelationshipTypeDefinition.java index d979d1ea44..5dad438eeb 100644 --- a/source/java/org/alfresco/cmis/dictionary/CMISRelationshipTypeDefinition.java +++ b/source/java/org/alfresco/cmis/dictionary/CMISRelationshipTypeDefinition.java @@ -77,13 +77,13 @@ public class CMISRelationshipTypeDefinition extends CMISAbstractTypeDefinition actionEvaluators = cmisMapping.getActionEvaluators(objectTypeId.getScope()); - creatable = false; queryable = false; controllable = false; if (assocDef == null) { // TODO: Add CMIS Association mapping?? + creatable = false; displayName = (cmisClassDef.getTitle() != null) ? cmisClassDef.getTitle() : typeId.getId(); objectTypeQueryName = typeId.getId(); QName parentQName = cmisMapping.getCmisType(cmisClassDef.getParentName()); @@ -95,6 +95,7 @@ public class CMISRelationshipTypeDefinition extends CMISAbstractTypeDefinition } else { + creatable = true; displayName = (assocDef.getTitle() != null) ? assocDef.getTitle() : typeId.getId(); objectTypeQueryName = cmisMapping.buildPrefixEncodedString(typeId.getQName(), false); parentTypeId = CMISDictionaryModel.RELATIONSHIP_TYPE_ID; diff --git a/source/java/org/alfresco/cmis/mapping/AbstractProperty.java b/source/java/org/alfresco/cmis/mapping/AbstractProperty.java index b31500d31c..10fc62330d 100644 --- a/source/java/org/alfresco/cmis/mapping/AbstractProperty.java +++ b/source/java/org/alfresco/cmis/mapping/AbstractProperty.java @@ -32,6 +32,7 @@ import org.alfresco.cmis.CMISPropertyLuceneBuilder; import org.alfresco.repo.search.impl.lucene.LuceneQueryParser; import org.alfresco.repo.search.impl.querymodel.PredicateMode; 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; import org.apache.lucene.queryParser.ParseException; @@ -146,11 +147,14 @@ public abstract class AbstractProperty implements CMISPropertyAccessor, CMISProp { throw new UnsupportedOperationException(); } - + public void setValue(NodeRef nodeRef, Serializable value) { throw new UnsupportedOperationException(); } - + public Serializable getValue(AssociationRef assocRef) + { + throw new UnsupportedOperationException(); + } } diff --git a/source/java/org/alfresco/cmis/mapping/CMISMapping.java b/source/java/org/alfresco/cmis/mapping/CMISMapping.java index e862e80f62..6b96521094 100644 --- a/source/java/org/alfresco/cmis/mapping/CMISMapping.java +++ b/source/java/org/alfresco/cmis/mapping/CMISMapping.java @@ -197,6 +197,8 @@ public class CMISMapping implements InitializingBean registerPropertyAccessor(new ContentStreamUriProperty(serviceRegistry)); registerPropertyAccessor(new ParentProperty(serviceRegistry)); registerPropertyAccessor(new FixedValueProperty(serviceRegistry, CMISDictionaryModel.PROP_ALLOWED_CHILD_OBJECT_TYPE_IDS, null)); + registerPropertyAccessor(new SourceIdProperty(serviceRegistry)); + registerPropertyAccessor(new TargetIdProperty(serviceRegistry)); // // Action Evaluator Mappings diff --git a/source/java/org/alfresco/cmis/mapping/CMISServicesImpl.java b/source/java/org/alfresco/cmis/mapping/CMISServicesImpl.java index 45b41e246b..274e26eebc 100644 --- a/source/java/org/alfresco/cmis/mapping/CMISServicesImpl.java +++ b/source/java/org/alfresco/cmis/mapping/CMISServicesImpl.java @@ -25,14 +25,20 @@ package org.alfresco.cmis.mapping; import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.alfresco.cmis.CMISDictionaryModel; import org.alfresco.cmis.CMISDictionaryService; import org.alfresco.cmis.CMISPropertyDefinition; +import org.alfresco.cmis.CMISRelationshipDirectionEnum; +import org.alfresco.cmis.CMISScope; import org.alfresco.cmis.CMISServices; import org.alfresco.cmis.CMISTypeDefinition; +import org.alfresco.cmis.CMISTypeId; import org.alfresco.cmis.CMISTypesFilterEnum; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; @@ -46,6 +52,7 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; @@ -55,6 +62,8 @@ import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.QNamePattern; +import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.util.AbstractLifecycleBean; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; @@ -450,6 +459,82 @@ public class CMISServicesImpl implements CMISServices, ApplicationContextAware, } } + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#getRelationship(org.alfresco.cmis.CMISTypeDefinition, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef) + */ + public AssociationRef getRelationship(CMISTypeDefinition relDef, NodeRef source, NodeRef target) + { + if (relDef == null) + { + relDef = cmisDictionaryService.findType(CMISDictionaryModel.RELATIONSHIP_TYPE_ID); + } + if (!relDef.getBaseType().getTypeId().equals(CMISDictionaryModel.RELATIONSHIP_TYPE_ID)) + { + throw new AlfrescoRuntimeException("Type Id " + relDef.getTypeId() + " is not a relationship type"); + } + + QName relDefQName = relDef.getTypeId().getQName(); + List assocs = nodeService.getTargetAssocs(source, new RegexQNamePattern(relDefQName.getNamespaceURI(), relDefQName.getLocalName())); + for (AssociationRef assoc : assocs) + { + if (assoc.getTargetRef().equals(target)) + { + return assoc; + } + } + return null; + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#getRelationships(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.cmis.CMISTypeId, boolean, org.alfresco.cmis.CMISRelationshipDirectionEnum) + */ + public AssociationRef[] getRelationships(NodeRef node, CMISTypeDefinition relDef, boolean includeSubTypes, CMISRelationshipDirectionEnum direction) + { + // establish relationship type to filter on + if (relDef == null) + { + relDef = cmisDictionaryService.findType(CMISDictionaryModel.RELATIONSHIP_TYPE_ID); + } + if (!relDef.getBaseType().getTypeId().equals(CMISDictionaryModel.RELATIONSHIP_TYPE_ID)) + { + throw new AlfrescoRuntimeException("Type Id " + relDef.getTypeId() + " is not a relationship type"); + } + + // retrieve associations + List assocs = new ArrayList(); + if (direction == CMISRelationshipDirectionEnum.SOURCE || direction == CMISRelationshipDirectionEnum.BOTH) + { + assocs.addAll(nodeService.getTargetAssocs(node, RegexQNamePattern.MATCH_ALL)); + } + if (direction == CMISRelationshipDirectionEnum.TARGET || direction == CMISRelationshipDirectionEnum.BOTH) + { + assocs.addAll(nodeService.getSourceAssocs(node, RegexQNamePattern.MATCH_ALL)); + } + + // filter association by type + Collection subRelDefs = (includeSubTypes ? relDef.getSubTypes(true) : null); + List filteredAssocs = new ArrayList(assocs.size()); + for (AssociationRef assoc : assocs) + { + CMISTypeDefinition assocTypeDef = cmisDictionaryService.findTypeForClass(assoc.getTypeQName(), CMISScope.RELATIONSHIP); + if (assocTypeDef == null) + { + throw new AlfrescoRuntimeException("Association Type QName " + assoc.getTypeQName() + " does not map to a CMIS Relationship Type"); + } + + if (assocTypeDef.equals(relDef) || (subRelDefs != null && subRelDefs.contains(assocTypeDef))) + { + filteredAssocs.add(assoc); + } + } + + AssociationRef[] assocArray = new AssociationRef[filteredAssocs.size()]; + filteredAssocs.toArray(assocArray); + return assocArray; + } + /* * (non-Javadoc) * @see org.alfresco.cmis.CMISServices#getProperty(org.alfresco.service.cmr.repository.NodeRef, java.lang.String) @@ -470,6 +555,26 @@ public class CMISServicesImpl implements CMISServices, ApplicationContextAware, return propDef.getPropertyAccessor().getValue(nodeRef); } + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#getProperty(org.alfresco.service.cmr.repository.AssociationRef, java.lang.String) + */ + public Serializable getProperty(AssociationRef assocRef, String propertyName) + { + QName typeQName = assocRef.getTypeQName(); + CMISTypeDefinition typeDef = cmisDictionaryService.findTypeForClass(typeQName); + if (typeDef == null) + { + throw new AlfrescoRuntimeException("Relationship Type " + typeQName + " not found in CMIS Dictionary"); + } + CMISPropertyDefinition propDef = cmisDictionaryService.findProperty(propertyName, typeDef); + if (propDef == null) + { + throw new AlfrescoRuntimeException("Property " + propertyName + " not found for relationship type " + typeDef.getTypeId() + " in CMIS Dictionary"); + } + return propDef.getPropertyAccessor().getValue(assocRef); + } + /* * (non-Javadoc) * @see org.alfresco.cmis.CMISServices#getProperties(org.alfresco.service.cmr.repository.NodeRef) diff --git a/source/java/org/alfresco/cmis/mapping/DirectProperty.java b/source/java/org/alfresco/cmis/mapping/DirectProperty.java index 8c07754ac0..4538a1bd65 100644 --- a/source/java/org/alfresco/cmis/mapping/DirectProperty.java +++ b/source/java/org/alfresco/cmis/mapping/DirectProperty.java @@ -29,6 +29,7 @@ import java.io.Serializable; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.namespace.QName; @@ -75,6 +76,15 @@ public class DirectProperty extends AbstractSimpleProperty return getServiceRegistry().getNodeService().getProperty(nodeRef, alfrescoName); } + /* + * (non-Javadoc) + * @see org.alfresco.cmis.mapping.AbstractProperty#getValue(org.alfresco.service.cmr.repository.AssociationRef) + */ + public Serializable getValue(AssociationRef assocRef) + { + return null; + } + public String getLuceneFieldName() { StringBuilder field = new StringBuilder(64); diff --git a/source/java/org/alfresco/cmis/mapping/FixedValueProperty.java b/source/java/org/alfresco/cmis/mapping/FixedValueProperty.java index 7cc3be3639..a42b03a28f 100644 --- a/source/java/org/alfresco/cmis/mapping/FixedValueProperty.java +++ b/source/java/org/alfresco/cmis/mapping/FixedValueProperty.java @@ -32,6 +32,7 @@ import java.util.regex.Pattern; import org.alfresco.repo.search.impl.lucene.LuceneQueryParser; import org.alfresco.repo.search.impl.querymodel.PredicateMode; import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.util.EqualsHelper; @@ -72,6 +73,15 @@ public class FixedValueProperty extends AbstractProperty { return value; } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.mapping.AbstractProperty#getValue(org.alfresco.service.cmr.repository.AssociationRef) + */ + public Serializable getValue(AssociationRef assocRef) + { + return value; + } /* * (non-Javadoc) diff --git a/source/java/org/alfresco/cmis/mapping/ObjectIdProperty.java b/source/java/org/alfresco/cmis/mapping/ObjectIdProperty.java index d95793be08..eefd6d9e22 100644 --- a/source/java/org/alfresco/cmis/mapping/ObjectIdProperty.java +++ b/source/java/org/alfresco/cmis/mapping/ObjectIdProperty.java @@ -35,6 +35,7 @@ import org.alfresco.repo.search.impl.lucene.LuceneQueryParser; import org.alfresco.repo.search.impl.querymodel.PredicateMode; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.apache.lucene.index.Term; @@ -64,7 +65,7 @@ public class ObjectIdProperty extends AbstractProperty /* * (non-Javadoc) - * @see org.alfresco.cmis.property.PropertyAccessor#getValue(org.alfresco.service.cmr.repository.NodeRef) + * @see org.alfresco.cmis.mapping.AbstractProperty#getValue(org.alfresco.service.cmr.repository.NodeRef) */ public Serializable getValue(NodeRef nodeRef) { @@ -84,6 +85,16 @@ public class ObjectIdProperty extends AbstractProperty return nodeRef.toString(); } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.mapping.AbstractProperty#getValue(org.alfresco.service.cmr.repository.AssociationRef) + */ + public Serializable getValue(AssociationRef assocRef) + { + // TODO: determine appropriate id for associations + return assocRef.getSourceRef().toString(); + } public String getLuceneFieldName() { diff --git a/source/java/org/alfresco/cmis/mapping/ObjectTypeIdProperty.java b/source/java/org/alfresco/cmis/mapping/ObjectTypeIdProperty.java index c6745cf7f9..42444f6229 100644 --- a/source/java/org/alfresco/cmis/mapping/ObjectTypeIdProperty.java +++ b/source/java/org/alfresco/cmis/mapping/ObjectTypeIdProperty.java @@ -30,11 +30,13 @@ import java.util.Collection; import org.alfresco.cmis.CMISDictionaryModel; import org.alfresco.cmis.CMISQueryException; +import org.alfresco.cmis.CMISScope; import org.alfresco.cmis.CMISTypeDefinition; import org.alfresco.repo.search.impl.lucene.AnalysisMode; import org.alfresco.repo.search.impl.lucene.LuceneQueryParser; import org.alfresco.repo.search.impl.querymodel.PredicateMode; import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.namespace.QName; @@ -65,7 +67,7 @@ public class ObjectTypeIdProperty extends AbstractProperty /* * (non-Javadoc) - * @see org.alfresco.cmis.property.PropertyAccessor#getValue(org.alfresco.service.cmr.repository.NodeRef) + * @see org.alfresco.cmis.mapping.AbstractProperty#getValue(org.alfresco.service.cmr.repository.NodeRef) */ public Serializable getValue(NodeRef nodeRef) { @@ -73,6 +75,15 @@ public class ObjectTypeIdProperty extends AbstractProperty return getServiceRegistry().getCMISDictionaryService().findTypeForClass(type).getTypeId().getId(); } + /* + * (non-Javadoc) + * @see org.alfresco.cmis.mapping.AbstractProperty#getValue(org.alfresco.service.cmr.repository.AssociationRef) + */ + public Serializable getValue(AssociationRef assocRef) + { + QName type = assocRef.getTypeQName(); + return getServiceRegistry().getCMISDictionaryService().findTypeForClass(type, CMISScope.RELATIONSHIP).getTypeId().getId(); + } public String getLuceneFieldName() { diff --git a/source/java/org/alfresco/cmis/mapping/SourceIdProperty.java b/source/java/org/alfresco/cmis/mapping/SourceIdProperty.java new file mode 100644 index 0000000000..cc6552ad8e --- /dev/null +++ b/source/java/org/alfresco/cmis/mapping/SourceIdProperty.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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 General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.cmis.mapping; + +import java.io.Serializable; + +import org.alfresco.cmis.CMISDictionaryModel; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.AssociationRef; + +/** + * Accessor for the Source Id (relationship) + * + * @author davidc + */ +public class SourceIdProperty extends AbstractProperty +{ + /** + * Construct + * + * @param serviceRegistry + */ + public SourceIdProperty(ServiceRegistry serviceRegistry) + { + super(serviceRegistry, CMISDictionaryModel.PROP_SOURCE_ID); + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.mapping.AbstractProperty#getValue(org.alfresco.service.cmr.repository.AssociationRef) + */ + public Serializable getValue(AssociationRef assocRef) + { + return assocRef.getSourceRef().toString(); + } +} diff --git a/source/java/org/alfresco/cmis/mapping/TargetIdProperty.java b/source/java/org/alfresco/cmis/mapping/TargetIdProperty.java new file mode 100644 index 0000000000..8c5de5df87 --- /dev/null +++ b/source/java/org/alfresco/cmis/mapping/TargetIdProperty.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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 General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.cmis.mapping; + +import java.io.Serializable; + +import org.alfresco.cmis.CMISDictionaryModel; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.AssociationRef; + +/** + * Accessor for the Target Id (relationship) + * + * @author davidc + */ +public class TargetIdProperty extends AbstractProperty +{ + /** + * Construct + * + * @param serviceRegistry + */ + public TargetIdProperty(ServiceRegistry serviceRegistry) + { + super(serviceRegistry, CMISDictionaryModel.PROP_TARGET_ID); + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.mapping.AbstractProperty#getValue(org.alfresco.service.cmr.repository.AssociationRef) + */ + public Serializable getValue(AssociationRef assocRef) + { + return assocRef.getTargetRef().toString(); + } +} diff --git a/source/java/org/alfresco/repo/jscript/Association.java b/source/java/org/alfresco/repo/jscript/Association.java index b66a643140..be71f05115 100644 --- a/source/java/org/alfresco/repo/jscript/Association.java +++ b/source/java/org/alfresco/repo/jscript/Association.java @@ -28,6 +28,7 @@ import java.io.Serializable; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.namespace.QName; import org.alfresco.util.ParameterCheck; import org.mozilla.javascript.Scriptable; @@ -85,6 +86,11 @@ public class Association implements Scopeable, Serializable return assocRef.getTypeQName().toString(); } + public QName getTypeQName() + { + return assocRef.getTypeQName(); + } + public ScriptNode getSource() { return (ScriptNode)new ValueConverter().convertValueForScript(this.services, this.scope, null, assocRef.getSourceRef()); diff --git a/source/java/org/alfresco/repo/jscript/ScriptNode.java b/source/java/org/alfresco/repo/jscript/ScriptNode.java index 96cf4a64d3..458b1ed22d 100644 --- a/source/java/org/alfresco/repo/jscript/ScriptNode.java +++ b/source/java/org/alfresco/repo/jscript/ScriptNode.java @@ -1361,13 +1361,14 @@ public class ScriptNode implements Serializable, Scopeable, NamespacePrefixResol * @param target Destination node for the association * @param assocType Association type qname (short form or fully qualified) */ - public void createAssociation(ScriptNode target, String assocType) + public Association createAssociation(ScriptNode target, String assocType) { ParameterCheck.mandatory("Target", target); ParameterCheck.mandatoryString("Association Type Name", assocType); - this.nodeService.createAssociation(this.nodeRef, target.nodeRef, createQName(assocType)); + AssociationRef assocRef = this.nodeService.createAssociation(this.nodeRef, target.nodeRef, createQName(assocType)); reset(); + return new Association(this.services, assocRef); } /** diff --git a/source/java/org/alfresco/repo/model/Repository.java b/source/java/org/alfresco/repo/model/Repository.java index 765d74dbb0..831be7a6d8 100644 --- a/source/java/org/alfresco/repo/model/Repository.java +++ b/source/java/org/alfresco/repo/model/Repository.java @@ -204,11 +204,11 @@ public class Repository implements ApplicationContextAware, ApplicationListener, { tenantAdminService.register(this); - if (companyHomeRefs == null) - { - companyHomeRefs = new ConcurrentHashMap(4); - } - + if (companyHomeRefs == null) + { + companyHomeRefs = new ConcurrentHashMap(4); + } + getCompanyHome(); } @@ -237,26 +237,26 @@ public class Repository implements ApplicationContextAware, ApplicationListener, String tenantDomain = tenantAdminService.getCurrentUserDomain(); NodeRef companyHomeRef = companyHomeRefs.get(tenantDomain); if (companyHomeRef == null) - { + { companyHomeRef = AuthenticationUtil.runAs(new RunAsWork() { - public NodeRef doWork() throws Exception - { - return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback() - { - public NodeRef execute() throws Exception - { - List refs = searchService.selectNodes(nodeService.getRootNode(companyHomeStore), companyHomePath, null, namespaceService, false); - if (refs.size() != 1) - { - throw new IllegalStateException("Invalid company home path: " + companyHomePath + " - found: " + refs.size()); - } - return refs.get(0); - } - }); - } - }, AuthenticationUtil.getSystemUserName()); - + public NodeRef doWork() throws Exception + { + return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback() + { + public NodeRef execute() throws Exception + { + List refs = searchService.selectNodes(nodeService.getRootNode(companyHomeStore), companyHomePath, null, namespaceService, false); + if (refs.size() != 1) + { + throw new IllegalStateException("Invalid company home path: " + companyHomePath + " - found: " + refs.size()); + } + return refs.get(0); + } + }); + } + }, AuthenticationUtil.getSystemUserName()); + companyHomeRefs.put(tenantDomain, companyHomeRef); } return companyHomeRef; @@ -336,51 +336,51 @@ public class Repository implements ApplicationContextAware, ApplicationListener, } else { - // construct store reference - if (reference.length < 3) - { - throw new AlfrescoRuntimeException("Reference " + Arrays.toString(reference) + " is not properly formed"); - } - StoreRef storeRef = new StoreRef(reference[0], reference[1]); - if (nodeService.exists(storeRef)) - { - if (referenceType.equals("node")) - { - // find the node the rest of the path is relative to - NodeRef relRef = new NodeRef(storeRef, reference[2]); - if (nodeService.exists(relRef)) - { - // are there any relative path elements to process? - if (reference.length == 3 || reference.length == 4) - { - // just the NodeRef can be specified - nodeRef = relRef; - } - else - { - // process optional path elements - List paths = new ArrayList(reference.length - 3); - for (int i=3; i paths = new ArrayList(reference.length - 3); + for (int i=3; i map = (Map)value; diff --git a/source/java/org/alfresco/repo/template/TemplateAssociation.java b/source/java/org/alfresco/repo/template/TemplateAssociation.java new file mode 100644 index 0000000000..fb594a68ee --- /dev/null +++ b/source/java/org/alfresco/repo/template/TemplateAssociation.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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 General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.template; + +import java.io.Serializable; + +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.TemplateImageResolver; +import org.alfresco.service.namespace.QName; + + +/** + * Object representing an association + */ +public class TemplateAssociation implements Serializable +{ + /** Serial version UUID*/ + private static final long serialVersionUID = -2903588739741433082L; + + /** Service registry **/ + private ServiceRegistry services; + + /** Association reference **/ + private AssociationRef assocRef; + + /** Image Resolver **/ + private TemplateImageResolver resolver; + + /** + * Construct + * + * @param services + * @param assocRef + */ + public TemplateAssociation(AssociationRef assocRef, ServiceRegistry services, TemplateImageResolver resolver) + { + this.assocRef = assocRef; + this.services = services; + this.resolver = resolver; + } + + public AssociationRef getAssociationRef() + { + return this.assocRef; + } + + public String getType() + { + return assocRef.getTypeQName().toString(); + } + + public QName getTypeQName() + { + return assocRef.getTypeQName(); + } + + public TemplateNode getSource() + { + return new TemplateNode(assocRef.getSourceRef(), services, resolver); + } + + public TemplateNode getTarget() + { + return new TemplateNode(assocRef.getTargetRef(), services, resolver); + } +}