From a650515ea88d395564794935c5f8a4c4e7035f6f Mon Sep 17 00:00:00 2001 From: Kevin Roast Date: Tue, 17 Apr 2007 14:52:04 +0000 Subject: [PATCH] Added create/remove association JavaScript API and improvements to the createNode() JavaScript API git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5504 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../java/org/alfresco/repo/jscript/Node.java | 198 +++++++++++++----- .../alfresco/repo/template/TemplateNode.java | 76 ++----- 2 files changed, 159 insertions(+), 115 deletions(-) diff --git a/source/java/org/alfresco/repo/jscript/Node.java b/source/java/org/alfresco/repo/jscript/Node.java index 13deb28c83..cc5f23d28c 100644 --- a/source/java/org/alfresco/repo/jscript/Node.java +++ b/source/java/org/alfresco/repo/jscript/Node.java @@ -68,6 +68,7 @@ import org.alfresco.service.cmr.version.VersionType; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.RegexQNamePattern; +import org.alfresco.util.GUID; import org.alfresco.util.ParameterCheck; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -404,7 +405,7 @@ public class Node implements Serializable, Scopeable } /** - * Return the associations for this Node. As a Map of assoc name to an Array of Nodes. + * Return the target associations from this Node. As a Map of assoc name to an Array of Nodes. * The Map returned implements the Scriptable interface to allow access to the assoc arrays via JavaScript * associative array access. This means associations of this node can be access thus: * node.assocs["translations"][0] @@ -988,7 +989,7 @@ public class Node implements Serializable, Scopeable // Create and Modify API /** - * Persist the properties of this Node. + * Persist the modified properties of this Node. */ public void save() { @@ -1046,16 +1047,11 @@ public class Node implements Serializable, Scopeable */ public Node createFile(String name) { - Node node = null; + ParameterCheck.mandatoryString("Node Name", name); - if (name != null && name.length() != 0) - { - FileInfo fileInfo = this.services.getFileFolderService().create(this.nodeRef, name, - ContentModel.TYPE_CONTENT); - node = newInstance(fileInfo.getNodeRef(), this.services, this.scope); - } - - return node; + FileInfo fileInfo = this.services.getFileFolderService().create(this.nodeRef, name, + ContentModel.TYPE_CONTENT); + return newInstance(fileInfo.getNodeRef(), this.services, this.scope); } /** @@ -1067,41 +1063,122 @@ public class Node implements Serializable, Scopeable */ public Node createFolder(String name) { - Node node = null; + ParameterCheck.mandatoryString("Node Name", name); - if (name != null && name.length() != 0) - { - FileInfo fileInfo = this.services.getFileFolderService().create(this.nodeRef, name, - ContentModel.TYPE_FOLDER); - node = newInstance(fileInfo.getNodeRef(), this.services, this.scope); - } - - return node; + FileInfo fileInfo = this.services.getFileFolderService().create(this.nodeRef, name, + ContentModel.TYPE_FOLDER); + return newInstance(fileInfo.getNodeRef(), this.services, this.scope); } /** * Create a new Node of the specified type as a child of this node. * - * @param name Name of the node to create - * @param type QName type (can either be fully qualified or short form such as 'cm:content') + * @param name Name of the node to create (can be null for a node without a 'cm:name' property) + * @param type QName type (fully qualified or short form such as 'cm:content') * * @return Newly created Node or null if failed to create. */ public Node createNode(String name, String type) { - Node node = null; + return createNode(name, type, null, ContentModel.ASSOC_CONTAINS.toString()); + } + + /** + * Create a new Node of the specified type as a child of this node. + * + * @param name Name of the node to create (can be null for a node without a 'cm:name' property) + * @param type QName type (fully qualified or short form such as 'cm:content') + * @param assocName QName of the child association (fully qualified or short form e.g. 'cm:contains') + * + * @return Newly created Node or null if failed to create. + */ + public Node createNode(String name, String type, String assocName) + { + return createNode(name, type, null, assocName); + } + + /** + * Create a new Node of the specified type as a child of this node. + * + * @param name Name of the node to create (can be null for a node without a 'cm:name' property) + * @param type QName type (fully qualified or short form such as 'cm:content') + * @param properties Associative array of the default properties for the node. + * + * @return Newly created Node or null if failed to create. + */ + public Node createNode(String name, String type, Object properties) + { + return createNode(name, type, properties, ContentModel.ASSOC_CONTAINS.toString()); + } + + /** + * Create a new Node of the specified type as a child of this node. + * + * @param name Name of the node to create (can be null for a node without a 'cm:name' property) + * @param type QName type (fully qualified or short form such as 'cm:content') + * @param properties Associative array of the default properties for the node. + * @param assocName QName of the child association (fully qualified or short form e.g. 'cm:contains') + * + * @return Newly created Node or null if failed to create. + */ + public Node createNode(String name, String type, Object properties, String assocName) + { + ParameterCheck.mandatoryString("Node Type", type); + ParameterCheck.mandatoryString("Association Name", assocName); - if (name != null && name.length() != 0 && type != null && type.length() != 0) + Map props = null; + + if (properties instanceof ScriptableObject) { - Map props = new HashMap(1); - props.put(ContentModel.PROP_NAME, name); - ChildAssociationRef childAssocRef = this.nodeService.createNode(this.nodeRef, ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.ALFRESCO_URI, QName.createValidLocalName(name)), - createQName(type), props); - node = newInstance(childAssocRef.getChildRef(), this.services, this.scope); + props = new HashMap(4, 1.0f); + extractScriptableProperties((ScriptableObject)properties, props); } - return node; + if (name != null) + { + if (props == null) props = new HashMap(1, 1.0f); + props.put(ContentModel.PROP_NAME, name); + } + else + { + // set name for the assoc local name + name = GUID.generate(); + } + + ChildAssociationRef childAssocRef = this.nodeService.createNode( + this.nodeRef, createQName(assocName), + QName.createQName(NamespaceService.ALFRESCO_URI, QName.createValidLocalName(name)), + createQName(type), props); + + return newInstance(childAssocRef.getChildRef(), this.services, this.scope); + } + + /** + * Create an association between this node and the specified target node. + * + * @param target Destination node for the association + * @param assocType Association type qname (short form or fully qualified) + */ + public void createAssociation(Node target, String assocType) + { + ParameterCheck.mandatory("Target", target); + ParameterCheck.mandatoryString("Association Type Name", assocType); + + this.nodeService.createAssociation(this.nodeRef, target.nodeRef, createQName(assocType)); + } + + /** + * Remove an association between this node and the specified target node. + * + * @param target Destination node on the end of the association + * @param assocType Association type qname (short form or fully qualified) + */ + public void removeAssociation(Node target, String assocType) + { + ParameterCheck.mandatory("Target", target); + ParameterCheck.mandatoryString("Association Type Name", assocType); + + this.nodeService.removeAssociation(this.nodeRef, target.nodeRef, createQName(assocType)); } /** @@ -1211,26 +1288,8 @@ public class Node implements Serializable, Scopeable Map aspectProps = null; if (props instanceof ScriptableObject) { - ScriptableObject properties = (ScriptableObject) props; - - // we need to get all the keys to the properties provided - // and convert them to a Map of QName to Serializable objects - Object[] propIds = properties.getIds(); - aspectProps = new HashMap(propIds.length); - for (int i = 0; i < propIds.length; i++) - { - // work on each key in turn - Object propId = propIds[i]; - - // we are only interested in keys that are formed of Strings i.e. QName.toString() - if (propId instanceof String) - { - // get the value out for the specified key - make sure it is Serializable - Object value = properties.get((String) propId, properties); - value = getValueConverter().convertValueForRepo((Serializable) value); - aspectProps.put(createQName((String) propId), (Serializable) value); - } - } + aspectProps = new HashMap(4, 1.0f); + extractScriptableProperties((ScriptableObject)props, aspectProps); } QName aspectQName = createQName(type); this.nodeService.addAspect(this.nodeRef, aspectQName, aspectProps); @@ -1240,6 +1299,37 @@ public class Node implements Serializable, Scopeable return true; } + + /** + * Extract a map of properties from a scriptable object (generally an associative array) + * + * @param scriptable The scriptable object to extract name/value pairs from. + * @param map The map to add the converted name/value pairs to. + */ + private void extractScriptableProperties(ScriptableObject scriptable, Map map) + { + // we need to get all the keys to the properties provided + // and convert them to a Map of QName to Serializable objects + Object[] propIds = scriptable.getIds(); + for (int i = 0; i < propIds.length; i++) + { + // work on each key in turn + Object propId = propIds[i]; + + // we are only interested in keys that are formed of Strings i.e. QName.toString() + if (propId instanceof String) + { + // get the value out for the specified key - it must be Serializable + String key = (String)propId; + Object value = scriptable.get(key, scriptable); + if (value instanceof Serializable) + { + value = getValueConverter().convertValueForRepo((Serializable)value); + map.put(createQName(key), (Serializable)value); + } + } + } + } /** * Remove aspect from the node. @@ -1566,7 +1656,7 @@ public class Node implements Serializable, Scopeable public String processTemplate(Node template, Object args) { ParameterCheck.mandatory("Template Node", template); - return processTemplate(template.getContent(), null, (ScriptableObject) args); + return processTemplate(template.getContent(), null, (ScriptableObject)args); } /** @@ -1594,7 +1684,7 @@ public class Node implements Serializable, Scopeable public String processTemplate(String template, Object args) { ParameterCheck.mandatoryString("Template", template); - return processTemplate(template, null, (ScriptableObject) args); + return processTemplate(template, null, (ScriptableObject)args); } private String processTemplate(String template, NodeRef templateRef, ScriptableObject args) @@ -1636,7 +1726,7 @@ public class Node implements Serializable, Scopeable { // get the value out for the specified key - make sure it is Serializable Object value = args.get((String) propId, args); - value = getValueConverter().convertValueForRepo((Serializable) value); + value = getValueConverter().convertValueForRepo((Serializable)value); if (value != null) { templateArgs.put((String) propId, value.toString()); diff --git a/source/java/org/alfresco/repo/template/TemplateNode.java b/source/java/org/alfresco/repo/template/TemplateNode.java index 989ec04fa4..383633b14c 100644 --- a/source/java/org/alfresco/repo/template/TemplateNode.java +++ b/source/java/org/alfresco/repo/template/TemplateNode.java @@ -72,12 +72,6 @@ public class TemplateNode extends BasePermissionsNode private static Log logger = LogFactory.getLog(TemplateNode.class); - /** The target associations from this node */ - private Map> targetAssocs = null; - - /** The child associations from this node */ - private Map> childAssocs = null; - /** All associations from this node */ private Map> assocs = null; @@ -227,68 +221,28 @@ public class TemplateNode extends BasePermissionsNode // Repository Node API /** - * @return The child associations for this Node. As a Map of assoc name to a List of TemplateNodes. - */ - public Map> getChildAssocs() - { - if (this.childAssocs == null) - { - List refs = this.services.getNodeService().getChildAssocs(this.nodeRef); - this.childAssocs = new QNameMap>(this.services.getNamespaceService()); - for (ChildAssociationRef ref : refs) - { - String qname = ref.getTypeQName().toString(); - List nodes = this.childAssocs.get(qname); - if (nodes == null) - { - // first access for the list for this qname - nodes = new ArrayList(4); - this.childAssocs.put(ref.getTypeQName().toString(), nodes); - } - nodes.add( new TemplateNode(ref.getChildRef(), this.services, this.imageResolver) ); - } - } - - return this.childAssocs; - } - - /** - * @return The target associations for this Node. As a Map of assoc name to a List of TemplateNodes. - */ - public Map> getTargetAssocs() - { - if (this.targetAssocs == null) - { - List refs = this.services.getNodeService().getTargetAssocs(this.nodeRef, RegexQNamePattern.MATCH_ALL); - this.targetAssocs = new QNameMap>(this.services.getNamespaceService()); - for (AssociationRef ref : refs) - { - String qname = ref.getTypeQName().toString(); - List nodes = this.targetAssocs.get(qname); - if (nodes == null) - { - // first access for the list for this qname - nodes = new ArrayList(4); - this.targetAssocs.put(ref.getTypeQName().toString(), nodes); - } - nodes.add( new TemplateNode(ref.getTargetRef(), this.services, this.imageResolver) ); - } - } - - return this.targetAssocs; - } - - /** - * @return All associations for this Node. As a Map of assoc name to a List of TemplateNodes. + * @return Target associations for this Node. As a Map of assoc name to a List of TemplateNodes. */ public Map> getAssocs() { if (this.assocs == null) { + List refs = this.services.getNodeService().getTargetAssocs(this.nodeRef, RegexQNamePattern.MATCH_ALL); this.assocs = new QNameMap>(this.services.getNamespaceService()); - this.assocs.putAll(getTargetAssocs()); - this.assocs.putAll(getChildAssocs()); + for (AssociationRef ref : refs) + { + String qname = ref.getTypeQName().toString(); + List nodes = this.assocs.get(qname); + if (nodes == null) + { + // first access for the list for this qname + nodes = new ArrayList(4); + this.assocs.put(ref.getTypeQName().toString(), nodes); + } + nodes.add( new TemplateNode(ref.getTargetRef(), this.services, this.imageResolver) ); + } } + return this.assocs; }