. Rhino JavaScript integration checkpoint:

- APIs to allow creation of Nodes of any valid type (e.g. not just files and folders)
  - APIs for Copy, Move and Delete of nodes.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2754 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Kevin Roast
2006-05-04 10:51:03 +00:00
parent 8274d21c4d
commit 5b81614707

View File

@@ -40,12 +40,17 @@ import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.TemplateImageResolver; import org.alfresco.service.cmr.repository.TemplateImageResolver;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.service.namespace.RegexQNamePattern;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.mozilla.javascript.NativeArray;
import org.mozilla.javascript.ScriptableObject;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
@@ -85,6 +90,7 @@ public final class Node implements Serializable
private ScriptableQNameMap<String, Serializable> properties; private ScriptableQNameMap<String, Serializable> properties;
private boolean propsRetrieved = false; private boolean propsRetrieved = false;
private ServiceRegistry services = null; private ServiceRegistry services = null;
private NodeService nodeService = null;
private Boolean isDocument = null; private Boolean isDocument = null;
private Boolean isContainer = null; private Boolean isContainer = null;
private String displayPath = null; private String displayPath = null;
@@ -95,6 +101,9 @@ public final class Node implements Serializable
private ChildAssociationRef primaryParentAssoc = null; private ChildAssociationRef primaryParentAssoc = null;
// ------------------------------------------------------------------------------
// Construction
/** /**
* Constructor * Constructor
* *
@@ -117,9 +126,14 @@ public final class Node implements Serializable
this.nodeRef = nodeRef; this.nodeRef = nodeRef;
this.id = nodeRef.getId(); this.id = nodeRef.getId();
this.services = services; this.services = services;
this.nodeService = services.getNodeService();
this.imageResolver = resolver; this.imageResolver = resolver;
} }
// ------------------------------------------------------------------------------
// Node Wrapper API
/** /**
* @return The GUID for the node * @return The GUID for the node
*/ */
@@ -153,7 +167,7 @@ public final class Node implements Serializable
{ {
if (this.type == null) if (this.type == null)
{ {
this.type = this.services.getNodeService().getType(this.nodeRef); this.type = this.nodeService.getType(this.nodeRef);
} }
return type; return type;
@@ -177,7 +191,7 @@ public final class Node implements Serializable
// if we didn't find it as a property get the name from the association name // if we didn't find it as a property get the name from the association name
if (this.name == null) if (this.name == null)
{ {
ChildAssociationRef parentRef = this.services.getNodeService().getPrimaryParent(this.nodeRef); ChildAssociationRef parentRef = this.nodeService.getPrimaryParent(this.nodeRef);
if (parentRef != null && parentRef.getQName() != null) if (parentRef != null && parentRef.getQName() != null)
{ {
this.name = parentRef.getQName().getLocalName(); this.name = parentRef.getQName().getLocalName();
@@ -222,7 +236,7 @@ public final class Node implements Serializable
{ {
if (this.children == null) if (this.children == null)
{ {
List<ChildAssociationRef> childRefs = this.services.getNodeService().getChildAssocs(this.nodeRef); List<ChildAssociationRef> childRefs = this.nodeService.getChildAssocs(this.nodeRef);
this.children = new Node[childRefs.size()]; this.children = new Node[childRefs.size()];
for (int i=0; i<childRefs.size(); i++) for (int i=0; i<childRefs.size(); i++)
{ {
@@ -301,7 +315,7 @@ public final class Node implements Serializable
// this Map implements the Scriptable interface for native JS syntax property access // this Map implements the Scriptable interface for native JS syntax property access
this.assocs = new ScriptableQNameMap<String, Node[]>(this.services.getNamespaceService()); this.assocs = new ScriptableQNameMap<String, Node[]>(this.services.getNamespaceService());
List<AssociationRef> refs = this.services.getNodeService().getTargetAssocs(this.nodeRef, RegexQNamePattern.MATCH_ALL); List<AssociationRef> refs = this.nodeService.getTargetAssocs(this.nodeRef, RegexQNamePattern.MATCH_ALL);
for (AssociationRef ref : refs) for (AssociationRef ref : refs)
{ {
String qname = ref.getTypeQName().toString(); String qname = ref.getTypeQName().toString();
@@ -347,7 +361,7 @@ public final class Node implements Serializable
// this Map implements the Scriptable interface for native JS syntax property access // this Map implements the Scriptable interface for native JS syntax property access
this.properties = new ScriptableQNameMap<String, Serializable>(this.services.getNamespaceService()); this.properties = new ScriptableQNameMap<String, Serializable>(this.services.getNamespaceService());
Map<QName, Serializable> props = this.services.getNodeService().getProperties(this.nodeRef); Map<QName, Serializable> props = this.nodeService.getProperties(this.nodeRef);
for (QName qname : props.keySet()) for (QName qname : props.keySet())
{ {
Serializable propValue = props.get(qname); Serializable propValue = props.get(qname);
@@ -423,7 +437,7 @@ public final class Node implements Serializable
{ {
if (this.aspects == null) if (this.aspects == null)
{ {
this.aspects = this.services.getNodeService().getAspects(this.nodeRef); this.aspects = this.nodeService.getAspects(this.nodeRef);
} }
return this.aspects; return this.aspects;
@@ -443,7 +457,7 @@ public final class Node implements Serializable
{ {
if (this.aspects == null) if (this.aspects == null)
{ {
this.aspects = this.services.getNodeService().getAspects(this.nodeRef); this.aspects = this.nodeService.getAspects(this.nodeRef);
} }
if (aspect.startsWith(NAMESPACE_BEGIN)) if (aspect.startsWith(NAMESPACE_BEGIN))
@@ -474,7 +488,7 @@ public final class Node implements Serializable
{ {
try try
{ {
displayPath = this.services.getNodeService().getPath(this.nodeRef).toDisplayPath(this.services.getNodeService()); displayPath = this.nodeService.getPath(this.nodeRef).toDisplayPath(this.nodeService);
} }
catch (AccessDeniedException err) catch (AccessDeniedException err)
{ {
@@ -583,7 +597,7 @@ public final class Node implements Serializable
{ {
if (parent == null) if (parent == null)
{ {
NodeRef parentRef = this.services.getNodeService().getPrimaryParent(nodeRef).getParentRef(); NodeRef parentRef = this.nodeService.getPrimaryParent(nodeRef).getParentRef();
// handle root node (no parent!) // handle root node (no parent!)
if (parentRef != null) if (parentRef != null)
{ {
@@ -607,7 +621,7 @@ public final class Node implements Serializable
{ {
if (primaryParentAssoc == null) if (primaryParentAssoc == null)
{ {
primaryParentAssoc = this.services.getNodeService().getPrimaryParent(nodeRef); primaryParentAssoc = this.nodeService.getPrimaryParent(nodeRef);
} }
return primaryParentAssoc; return primaryParentAssoc;
} }
@@ -749,6 +763,10 @@ public final class Node implements Serializable
return this.imageResolver; return this.imageResolver;
} }
// ------------------------------------------------------------------------------
// Create and Modify API
/** /**
* Persist the properties of this Node. * Persist the properties of this Node.
*/ */
@@ -771,11 +789,11 @@ public final class Node implements Serializable
} }
props.put(QName.createQName(key), value); props.put(QName.createQName(key), value);
} }
this.services.getNodeService().setProperties(this.nodeRef, props); this.nodeService.setProperties(this.nodeRef, props);
} }
/** /**
* Create a new File node as a child of this node. * Create a new File (cm:content) node as a child of this node.
* <p> * <p>
* Once created the file should have content set using the <code>content</code> property. * Once created the file should have content set using the <code>content</code> property.
* *
@@ -783,15 +801,18 @@ public final class Node implements Serializable
* *
* @return Newly created Node or null if failed to create. * @return Newly created Node or null if failed to create.
*/ */
// TODO: create with type? create with content?
public Node createFile(String name) public Node createFile(String name)
{ {
Node node = null; Node node = null;
try try
{ {
FileInfo fileInfo = this.services.getFileFolderService().create( if (name != null && name.length() != 0)
this.nodeRef, name, ContentModel.TYPE_CONTENT); {
node = new Node(fileInfo.getNodeRef(), this.services, this.imageResolver); FileInfo fileInfo = this.services.getFileFolderService().create(
this.nodeRef, name, ContentModel.TYPE_CONTENT);
node = new Node(fileInfo.getNodeRef(), this.services, this.imageResolver);
}
} }
catch (FileExistsException fileErr) catch (FileExistsException fileErr)
{ {
@@ -807,18 +828,24 @@ public final class Node implements Serializable
} }
/** /**
* Create a new folder node * Create a new folder (cm:folder) node as a child of this node.
* @param name *
* @return * @param name Name of the folder to create
*
* @return Newly created Node or null if failed to create.
*/ */
public Node createFolder(String name) public Node createFolder(String name)
{ {
Node node = null; Node node = null;
try try
{ {
FileInfo fileInfo = this.services.getFileFolderService().create( if (name != null && name.length() != 0)
this.nodeRef, name, ContentModel.TYPE_FOLDER); {
node = new Node(fileInfo.getNodeRef(), this.services, this.imageResolver); FileInfo fileInfo = this.services.getFileFolderService().create(
this.nodeRef, name, ContentModel.TYPE_FOLDER);
node = new Node(fileInfo.getNodeRef(), this.services, this.imageResolver);
}
} }
catch (FileExistsException fileErr) catch (FileExistsException fileErr)
{ {
@@ -833,12 +860,144 @@ public final class Node implements Serializable
return node; return node;
} }
/**
* 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')
*
* @return Newly created Node or null if failed to create.
*/
public Node createNode(String name, String type)
{
Node node = null;
try
{
if (name != null && name.length() != 0 &&
type != null && type.length() != 0)
{
Map<QName, Serializable> props = new HashMap<QName, Serializable>(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)),
QName.createQName(type),
props);
node = new Node(childAssocRef.getChildRef(), this.services, this.imageResolver);
}
}
catch (AccessDeniedException accessErr)
{
// default of null will be returned
}
return node;
}
/**
* Delete this node. Any references to this Node or its NodeRef should be discarded!
*/
public boolean delete()
{
boolean success = false;
try
{
this.nodeService.deleteNode(this.nodeRef);
success = true;
}
catch (AccessDeniedException accessErr)
{
// default of false will be returned
}
catch (InvalidNodeRefException refErr)
{
// default of false will be returned
}
return success;
}
/**
* Copy this Node to a new parent destination.
*
* @param destination Node
*
* @return The newly copied Node instance or null if failed to copy.
*/
public Node copy(Node destination)
{
Node copy = null;
try
{
if (destination != null)
{
NodeRef copyRef = this.services.getCopyService().copy(
this.nodeRef,
destination.getNodeRef(),
ContentModel.ASSOC_CONTAINS,
getPrimaryParentAssoc().getQName(),
false);
copy = new Node(copyRef, this.services, this.imageResolver);
}
}
catch (AccessDeniedException accessErr)
{
// default of null will be returned
}
catch (InvalidNodeRefException nodeErr)
{
// default of null will be returned
}
return copy;
}
/**
* Move this Node to a new parent destination.
*
* @param destination Node
*
* @return true on successful move, false on failure to move.
*/
public boolean move(Node destination)
{
boolean success = false;
try
{
if (destination != null)
{
this.primaryParentAssoc = this.nodeService.moveNode(
this.nodeRef,
destination.getNodeRef(),
ContentModel.ASSOC_CONTAINS,
getPrimaryParentAssoc().getQName());
this.parent = null; // has been changed - so reset it
success = true;
}
}
catch (AccessDeniedException accessErr)
{
// default of false will be returned
}
catch (InvalidNodeRefException refErr)
{
// default of false will be returned
}
return success;
}
/** /**
* Override Object.toString() to provide useful debug output * Override Object.toString() to provide useful debug output
*/ */
public String toString() public String toString()
{ {
if (this.services.getNodeService().exists(nodeRef)) if (this.nodeService.exists(nodeRef))
{ {
return "Node Type: " + getType() + return "Node Type: " + getType() +
"\nNode Properties: " + this.getProperties().toString() + "\nNode Properties: " + this.getProperties().toString() +
@@ -850,6 +1009,10 @@ public final class Node implements Serializable
} }
} }
// ------------------------------------------------------------------------------
// Private Helpers
/** /**
* Return a list or a single Node from executing an xpath against the parent Node. * Return a list or a single Node from executing an xpath against the parent Node.
* *
@@ -874,7 +1037,7 @@ public final class Node implements Serializable
} }
else else
{ {
contextRef = this.services.getNodeService().getRootNode(nodeRef.getStoreRef()); contextRef = this.nodeService.getRootNode(nodeRef.getStoreRef());
} }
List<NodeRef> nodes = this.services.getSearchService().selectNodes( List<NodeRef> nodes = this.services.getSearchService().selectNodes(
contextRef, contextRef,
@@ -908,6 +1071,9 @@ public final class Node implements Serializable
} }
// ------------------------------------------------------------------------------
// Inner Classes
/** /**
* Inner class wrapping and providing access to a ContentData property * Inner class wrapping and providing access to a ContentData property
*/ */