Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/CrNode.java =================================================================== diff -u -r6e5832d17263bc6c6f7683733e91e22f97eab569 -r3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/CrNode.java (.../CrNode.java) (revision 6e5832d17263bc6c6f7683733e91e22f97eab569) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/CrNode.java (.../CrNode.java) (revision 3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52) @@ -69,30 +69,40 @@ /** versions of this node. persistent field */ private Set crNodeVersions; - /** full constructor */ - public CrNode(String path, String type, Date createdDateTime, Long nextVersionId, org.lamsfoundation.lams.contentrepository.CrWorkspace crWorkspace, org.lamsfoundation.lams.contentrepository.CrNodeVersion parentNodeVersion, Set crNodeVersions) { - this.path = path; - this.type = type; + /** default constructor - used by Hibernate */ + public CrNode() { + } + + /** Create the CrNode and its initial CrNodeVersion. + */ + public CrNode(String relPath, String nodeTypeName, Date createdDateTime, CrWorkspace workspace, + CrNodeVersion parentNodeVersion, String versionDescription) { + + this.path = relPath; + this.type = nodeTypeName; this.createdDateTime = createdDateTime; - this.nextVersionId = nextVersionId; - this.crWorkspace = crWorkspace; + + // start the next version id at 1, which is used straight away by incrementNextVersionId() + this.nextVersionId = new Long(1); + + this.crWorkspace = workspace; this.parentNodeVersion = parentNodeVersion; - this.crNodeVersions = crNodeVersions; - } + this.addCrNodeVersion(new CrNodeVersion(this, createdDateTime, incrementNextVersionId(), versionDescription)); + } - /** default constructor */ - public CrNode() { - } + /** full constructor */ +/* public CrNode(String path, String type, Date createdDateTime, Long nextVersionId, org.lamsfoundation.lams.contentrepository.CrWorkspace crWorkspace, org.lamsfoundation.lams.contentrepository.CrNodeVersion parentNodeVersion, Set crNodeVersions) { + } */ /** minimal constructor */ - public CrNode(String type, Long nextVersionId, org.lamsfoundation.lams.contentrepository.CrWorkspace crWorkspace, org.lamsfoundation.lams.contentrepository.CrNodeVersion parentNodeVersion, Set crNodeVersions) { +/* public CrNode(String type, Long nextVersionId, org.lamsfoundation.lams.contentrepository.CrWorkspace crWorkspace, org.lamsfoundation.lams.contentrepository.CrNodeVersion parentNodeVersion, Set crNodeVersions) { this.type = type; this.nextVersionId = nextVersionId; this.crWorkspace = crWorkspace; this.parentNodeVersion = parentNodeVersion; this.crNodeVersions = crNodeVersions; } - +*/ /** * @hibernate.id * generator-class="identity" @@ -289,6 +299,7 @@ } /* ********* Manually added methods ****/ + /** Get the next version id for this node and then * increment it. All other ids come out of the database * but for the version we need the next id within a @@ -335,7 +346,8 @@ return nodeTypeName != null && nodeTypeName.equals(getType()); } - /** Get a particular version of this node + /** Get a particular version of this node. If versionId is null, then + * gets the latest version. */ public CrNodeVersion getNodeVersion(Long versionId) { Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/CrNodeVersion.java =================================================================== diff -u -r36a3488f8517a3143da11d93f287c782f7e758bd -r3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/CrNodeVersion.java (.../CrNodeVersion.java) (revision 36a3488f8517a3143da11d93f287c782f7e758bd) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/CrNodeVersion.java (.../CrNodeVersion.java) (revision 3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52) @@ -60,26 +60,37 @@ /** persistent field */ private Set crNodeVersionProperties; - /** full constructor */ - public CrNodeVersion(Long versionId, Date createdDateTime, org.lamsfoundation.lams.contentrepository.CrNode node, Set crNodeVersionProperties) { + /* full constructor */ +/* public CrNodeVersion(Long versionId, Date createdDateTime, org.lamsfoundation.lams.contentrepository.CrNode node, Set crNodeVersionProperties) { this.versionId = versionId; this.createdDateTime = createdDateTime; this.node = node; this.crNodeVersionProperties = crNodeVersionProperties; //this.childNodes = childNodes; - } + } */ - /** default constructor */ + /** default constructor - used by Hibernate */ public CrNodeVersion() { } - /** minimal constructor */ - public CrNodeVersion(Long versionId, org.lamsfoundation.lams.contentrepository.CrNode node,Set crNodeVersionProperties) { + /** Normal constructor + */ + public CrNodeVersion (CrNode node, Date createdDate, Long versionId, String versionDescription) { + this.createdDateTime = createdDate; + this.node = node; + this.versionId = versionId; + setVersionDescription(versionDescription); + } + + + + /* minimal constructor */ + /*public CrNodeVersion(Long versionId, org.lamsfoundation.lams.contentrepository.CrNode node,Set crNodeVersionProperties) { this.versionId = versionId; this.node = node; this.crNodeVersionProperties = crNodeVersionProperties; //this.childNodes = childNodes; - } + } */ /** * @hibernate.id Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/IVersionedNode.java =================================================================== diff -u -rd69fd0c0b6e3af330bb1ddbf3099022feca3f092 -r3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/IVersionedNode.java (.../IVersionedNode.java) (revision d69fd0c0b6e3af330bb1ddbf3099022feca3f092) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/IVersionedNode.java (.../IVersionedNode.java) (revision 3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52) @@ -177,7 +177,14 @@ */ public Long getVersion(); - /** Get the date/time of when this node was created. + /** + * Get the version description. + * + * @return The version description + */ + public String getVersionDescription(); + + /** Get the date/time of when this node was created. * @return date/time stamp of creation */ public Date getCreatedDateTime(); Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/applicationContext.xml =================================================================== diff -u -r643f195ff0e9d4ca74456bc9dbf835b15c7f513d -r3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/applicationContext.xml (.../applicationContext.xml) (revision 643f195ff0e9d4ca74456bc9dbf835b15c7f513d) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/applicationContext.xml (.../applicationContext.xml) (revision 3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52) @@ -86,21 +86,26 @@ - + + + + + + Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/client/IToolContentHandler.java =================================================================== diff -u -r16f8b72963d9569f0e67f5de8bf64d9aa6e4660a -r3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/client/IToolContentHandler.java (.../IToolContentHandler.java) (revision 16f8b72963d9569f0e67f5de8bf64d9aa6e4660a) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/client/IToolContentHandler.java (.../IToolContentHandler.java) (revision 3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52) @@ -105,6 +105,16 @@ public abstract void deleteFile(Long uuid) throws InvalidParameterException, RepositoryCheckedException; + /** + * Copy an entry in the content repository. + * + * @param uuid id of the file node. Mandatory + * @throws ItemNotFoundException Node to copy cannot be found + * @throws RepositoryCheckedException Some other error occured. + */ + public abstract NodeKey copyFile(Long uuid) + throws ItemNotFoundException, RepositoryCheckedException; + /** Get a file node. * @param uuid id of the file node. Mandatory * @throws FileException An error occured writing the input stream to disk. Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/client/ToolContentHandler.java =================================================================== diff -u -rd59d0d4fc282b7ee296ff4efe17b3db5eabd952e -r3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/client/ToolContentHandler.java (.../ToolContentHandler.java) (revision d59d0d4fc282b7ee296ff4efe17b3db5eabd952e) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/client/ToolContentHandler.java (.../ToolContentHandler.java) (revision 3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52) @@ -225,6 +225,35 @@ return nodeKey; } + /** + * Copy an entry in the content repository. + * + * @param uuid id of the file node. Mandatory + * @throws ItemNotFoundException Node to copy cannot be found + * @throws RepositoryCheckedException Some other error occured. + */ + public NodeKey copyFile(Long uuid) throws ItemNotFoundException, RepositoryCheckedException { + NodeKey nodeKey = null; + try { + try { + nodeKey = getRepositoryService().copyNodeVersion(getTicket(false), uuid, null); + } catch (AccessDeniedException e) { + log.warn("Unable to access repository to add copy node "+uuid + +"AccessDeniedException: "+e.getMessage()+" Retrying login."); + nodeKey = getRepositoryService().copyNodeVersion(getTicket(true), uuid, null); + } + } catch (ItemNotFoundException e) { + log.warn("Unable to to copy node "+uuid + +" as the node cannot be found. Repository Exception: "+e.getMessage()+" Retry not possible."); + throw e; + } catch (RepositoryCheckedException e) { + log.warn("Unable to to copy node "+uuid + +"Repository Exception: "+e.getMessage()+" Retry not possible."); + throw e; + } + return nodeKey; + } + /** * Delete a file node. If the node does not exist, then nothing happens (ie ItemNotFoundException is NOT thrown). * @param uuid id of the file node. Mandatory Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/dao/IWorkspaceDAO.java =================================================================== diff -u -r6e5832d17263bc6c6f7683733e91e22f97eab569 -r3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/dao/IWorkspaceDAO.java (.../IWorkspaceDAO.java) (revision 6e5832d17263bc6c6f7683733e91e22f97eab569) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/dao/IWorkspaceDAO.java (.../IWorkspaceDAO.java) (revision 3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52) @@ -35,6 +35,9 @@ */ public interface IWorkspaceDAO extends IBaseDAO { + /** String used to define node factory in Spring context */ + public static final String WORKSPACE_DAO_ID = "workspaceDAO"; + /** Get a workspace. * * @param workspaceName Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/package.html =================================================================== diff -u -rc624fa1214cb17e6966fc6593f13080404b0df0f -r3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/package.html (.../package.html) (revision c624fa1214cb17e6966fc6593f13080404b0df0f) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/package.html (.../package.html) (revision 3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52) @@ -183,7 +183,7 @@ } -

Using the ticket, the tool can now add, retrieve and delete nodes. Deleting a package +

Using the ticket, the tool can now add, retrieve, delete and copy nodes. Deleting a package node deletes all the files in the package. Warning: deleting removes the node completely - from both the database and the file system.

@@ -207,11 +207,22 @@
 	IVersionedNode node = repositoryService.getFileItem(repositoryTicket, 
 							nodeKey2.getUuid(), nodeKey2.getVersion());
 	
+	Copy the initial version of the file node. CopyNodeVersion copies the specified version or last version (if not specified), duplicates the actual files.
+	NodeKey nodeKey3 = repositoryService.copyNodeVersion(repositoryTicket, 
+							nodeKey1.getUuId(),
+							nodeKey1.getVersion());
+
+	Copy the latest version of the file node. 
+	NodeKey nodeKey3 = repositoryService.copyNodeVersion(repositoryTicket, 
+							nodeKey1.getUuId(),
+							null);
+
 	Delete the second version of the file:
 	String[] problemFiles = repositoryService.deleteVersion(repositoryTicket,nodeKey2.getUuid(), nodeKey2.getVersion());
 
 	Delete all versions of the file:
 	String[] problemFiles = repositoryService.deleteNode(repositoryTicket, nodeKey2.getUuid());
+	
 

Similar methods exist for packages of files. See IRepositoryService for all the available calls.

@@ -264,16 +275,6 @@
  • JBOSS location Edit build.properties (in the root of the project) to set the JBOSS directory. This is required for the deploy and copyfiles ANT tasks.
  • -
  • JUNIT Testing Edit the TEXT_FILEPATH, TEXT_FILENAME, BINARY_FILEPATH -BINARY_FILENAME, PACKAGE_DIR_PATH, PACKAGE_TEST_FILE in -org.lamsfoundation.lams.contentrepository.BaseTestCase ( in the test hierarchy). -These must point to files on your PC. The TEXT* variables should point to a text file, -the BINARY* to a binary file (e.g. jpeg, zip file). The allows you to check that manually -that neither text nor binary files are corrupted. The PACKAGE_DIR_PATH should be -a directory containing an index.html file and a series of other files (e.g. images -to go with the index.html file). The PACKAGE_TEST_FILE should be the relative -path to a file within the directory. -
  • Building the Repository

    Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/INodeFactory.java =================================================================== diff -u --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/INodeFactory.java (revision 0) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/INodeFactory.java (revision 3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52) @@ -0,0 +1,126 @@ +package org.lamsfoundation.lams.contentrepository.service; + +import java.io.InputStream; + +import org.lamsfoundation.lams.contentrepository.CrNode; +import org.lamsfoundation.lams.contentrepository.CrWorkspace; +import org.lamsfoundation.lams.contentrepository.FileException; +import org.lamsfoundation.lams.contentrepository.InvalidParameterException; +import org.lamsfoundation.lams.contentrepository.ItemNotFoundException; +import org.lamsfoundation.lams.contentrepository.RepositoryRuntimeException; +import org.lamsfoundation.lams.contentrepository.ValueFormatException; +import org.lamsfoundation.lams.contentrepository.dao.INodeDAO; + +public interface INodeFactory { + + /** String used to define node factory in Spring context */ + public static final String NODE_FACTORY_ID = "nodeFactory"; + + /** + * Create a new file node (which is assumed to be a newly created Spring + * bean) with relPath and node type. + * + * @param relPath The path of the new Node that is to be created, + * the last item of this path will be the name of the new Node. + * @throws org.lamsfoundation.lams.contentrepository.InvalidParameterException if the file parameters are invalid + * @throws RepositoryRuntimeException if an internal error occurs. + */ + public abstract SimpleVersionedNode createFileNode(CrWorkspace workspace, + SimpleVersionedNode parentNode, String relPath, + InputStream istream, String filename, String mimeType, + String versionDescription) + throws org.lamsfoundation.lams.contentrepository.InvalidParameterException; + + /** + * Create a new package node (which is assumed to be a newly created Spring + * bean) with the default file and node type. Package node cannot have a parent node. + * + * @param initialPath The path of the default content. + * @throws org.lamsfoundation.lams.contentrepository.InvalidParameterException if the file parameters are invalid + * @throws RepositoryRuntimeException if an internal error occurs. + */ + public abstract SimpleVersionedNode createPackageNode( + CrWorkspace workspace, String initialPath, String versionDescription) + throws org.lamsfoundation.lams.contentrepository.InvalidParameterException; + + /** + * Create a new data node (which is assumed to be a newly created Spring + * bean). This node may have a parent node. + * + * @throws org.lamsfoundation.lams.contentrepository.InvalidParameterException if the file parameters are invalid + * @throws RepositoryRuntimeException if an internal error occurs. + */ + public abstract SimpleVersionedNode createDataNode(CrWorkspace workspace, + SimpleVersionedNode parentNode, String versionDescription) + throws org.lamsfoundation.lams.contentrepository.InvalidParameterException; + + /** + * Build a SimpleVersionedNode, given a CrNode from the database. If versionId == null + * then gets the latest version. + * + * @see org.lamsfoundation.lams.contentrepository.IVersionedNode#getNode(String relPath) + */ + public abstract SimpleVersionedNode getNode(CrNode databaseNode, + Long versionId); + + /** + * Build a SimpleVersionedNode, reading the data from the database. + * Creates the CrNode and CrNodeVersion objects. + * Equivalent of createFileNode/createPackageNode for existing nodes + * Checks that the workspace found in the database is the expected workspace. + * + * If this node object is returned to a web app, then the + * crNode and crNodeVersion objects will be disconnected + * from the session, as the session will have been ended + * with the Spring transaction. + * + * If versionId is null, then gets the latest version + */ + public abstract SimpleVersionedNode getNode(Long workspaceId, Long uuid, Long versionId) throws ItemNotFoundException; + + /** + * Build a SimpleVersionedNode, reading the data from the database. + * Creates a new (empty) version ready for updating. + * Equivalent of createFileNode/createPackageNode for existing nodes + * Checks that the workspace found in the database is the expected workspace. + *

    + * If this node object is returned to a web app, then the + * crNode and crNodeVersion objects will be disconnected + * from the session, as the session will have been ended + * with the Spring transaction. + * @throws ItemNotFoundException + * + * @throws RepositoryRuntimeException if an internal error occurs. + * @see org.lamsfoundation.lams.contentrepository.IVersionedNode#createNewVersion(java.lang.String, java.lang.String) + */ + public abstract SimpleVersionedNode getNodeNewVersion(Long workspaceId, Long uuid, Long versionId, String versionDescription) throws ItemNotFoundException; + + + /** Copy the supplied node/version to a new node. Does not copy the history + * of the node. Copies any child nodes of the current version. All files are duplicated. + * + * This method only works as we know that we have two levels of nodes - the + * childNodes can't have their own childNodes. If this is no longer the case, + * this method and SimpleVersionedNode.save() will need to be changed. + * @throws FileException will occur if there is a problem reading a file from the repository + * @throws InvalidParameterException will only occur if there is an internal bug as it will only happen if the + * file, filename or mimetype properties are invalid. + * @throws ValueFormatException will only occur if there is an internal bug as it will only happen if the filename or mimetype properties are not strings. + */ + public abstract SimpleVersionedNode copy(SimpleVersionedNode originalNode) + throws FileException, ValueFormatException, + InvalidParameterException; + + /** + * @return Returns the nodeDAO. + */ + public abstract INodeDAO getNodeDAO(); + + /** + * @param nodeDAO The nodeDAO to set. + */ + public abstract void setNodeDAO(INodeDAO nodeDAO); + + + +} \ No newline at end of file Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/IRepositoryService.java =================================================================== diff -u -rc624fa1214cb17e6966fc6593f13080404b0df0f -r3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/IRepositoryService.java (.../IRepositoryService.java) (revision c624fa1214cb17e6966fc6593f13080404b0df0f) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/IRepositoryService.java (.../IRepositoryService.java) (revision 3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52) @@ -230,6 +230,25 @@ public void setProperty(ITicket ticket, Long uuid, Long versionId, String name, Object value, int type) throws AccessDeniedException, ItemNotFoundException, ValidationException ; + /** Copy node, copying the specified/latest version of the existing node + * to version 1 of the new node. + *

    + * Copies a node (identified by uuid/version). The file(s) attached to the + * supplied version are duplicated and become version 1 of the new node. Therefore + * any "history" of the original node is lost. If the version is not supplied, + * then it uses the latest version of the node as the basis for the new node. + *

    + * This method works for both file nodes and package nodes. + * + * @param ticket ticket issued on login. Identifies tool and workspace - mandatory + * @param uuid id of the file/package - mandatory + * @param version desired version - if null gets latest version + * @return nodeKey (uuid and version) + * @throws AccessDeniedException if the ticket is invalid + * @throws ItemNotFoundException if the node cannot be found + */ + public NodeKey copyNodeVersion(ITicket ticket, Long uuid, Long versionId) throws AccessDeniedException, ItemNotFoundException; + /** * Get an item from the repository based on the UUID. This * may be either a file or package node. Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/NodeFactory.java =================================================================== diff -u --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/NodeFactory.java (revision 0) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/NodeFactory.java (revision 3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52) @@ -0,0 +1,263 @@ +package org.lamsfoundation.lams.contentrepository.service; + +import java.io.InputStream; +import java.util.Date; +import java.util.Iterator; +import java.util.Set; + +import org.apache.log4j.Logger; +import org.lamsfoundation.lams.contentrepository.CrNode; +import org.lamsfoundation.lams.contentrepository.CrNodeVersion; +import org.lamsfoundation.lams.contentrepository.CrNodeVersionProperty; +import org.lamsfoundation.lams.contentrepository.CrWorkspace; +import org.lamsfoundation.lams.contentrepository.FileException; +import org.lamsfoundation.lams.contentrepository.IValue; +import org.lamsfoundation.lams.contentrepository.InvalidParameterException; +import org.lamsfoundation.lams.contentrepository.ItemNotFoundException; +import org.lamsfoundation.lams.contentrepository.NodeType; +import org.lamsfoundation.lams.contentrepository.PropertyName; +import org.lamsfoundation.lams.contentrepository.RepositoryRuntimeException; +import org.lamsfoundation.lams.contentrepository.ValueFormatException; +import org.lamsfoundation.lams.contentrepository.dao.INodeDAO; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; + +/** Singleton spring bean that creates new SimpleVersionedNodes. Would + * be nice if it was a Spring factory. Must be created by Spring, so that + * it gets the Spring bean factory, which allows it to create Node objects + * via Spring. + * + * @author Fiona Malikoff + * + */ +public class NodeFactory implements INodeFactory, BeanFactoryAware { + + protected Logger log = Logger.getLogger(NodeFactory.class); + + private BeanFactory beanFactory = null; + private INodeDAO nodeDAO = null; + + public NodeFactory() { + super(); + } + + /* (non-Javadoc) + * @see org.lamsfoundation.lams.contentrepository.service.INodeFactory#createFileNode(org.lamsfoundation.lams.contentrepository.CrWorkspace, org.lamsfoundation.lams.contentrepository.service.SimpleVersionedNode, java.lang.String, java.io.InputStream, java.lang.String, java.lang.String, java.lang.String) + */ + public SimpleVersionedNode createFileNode(CrWorkspace workspace, SimpleVersionedNode parentNode, + String relPath, InputStream istream, String filename, String mimeType, String versionDescription) + throws org.lamsfoundation.lams.contentrepository.InvalidParameterException { + + SimpleVersionedNode initialNodeVersion = createBasicNode(NodeType.FILENODE, + workspace, parentNode, relPath, versionDescription); + initialNodeVersion.setFile(istream, filename, mimeType); + + return initialNodeVersion; + } + + /* (non-Javadoc) + * @see org.lamsfoundation.lams.contentrepository.service.INodeFactory#createPackageNode(org.lamsfoundation.lams.contentrepository.CrWorkspace, java.lang.String, java.lang.String) + */ + public SimpleVersionedNode createPackageNode(CrWorkspace workspace, + String initialPath, String versionDescription) + throws org.lamsfoundation.lams.contentrepository.InvalidParameterException { + + SimpleVersionedNode initialNodeVersion = createBasicNode(NodeType.PACKAGENODE, + workspace, null, null, versionDescription); + initialNodeVersion.setProperty(PropertyName.INITIALPATH, initialPath); + + return initialNodeVersion; + } + + /* (non-Javadoc) + * @see org.lamsfoundation.lams.contentrepository.service.INodeFactory#createDataNode(org.lamsfoundation.lams.contentrepository.CrWorkspace, org.lamsfoundation.lams.contentrepository.service.SimpleVersionedNode, java.lang.String) + */ + public SimpleVersionedNode createDataNode(CrWorkspace workspace, SimpleVersionedNode parentNode, + String versionDescription) + throws org.lamsfoundation.lams.contentrepository.InvalidParameterException { + + SimpleVersionedNode initialNodeVersion = createBasicNode(NodeType.DATANODE, + workspace, parentNode, null, versionDescription); + + return initialNodeVersion; + } + + /** Create the core part of a node */ + private SimpleVersionedNode createBasicNode(String nodeType, CrWorkspace workspace, SimpleVersionedNode parentNode, + String relPath, String versionDescription) { + + SimpleVersionedNode initialNodeVersion = (SimpleVersionedNode) beanFactory.getBean("node", SimpleVersionedNode.class); + + Date createdDate = new Date(System.currentTimeMillis()); + CrNodeVersion parentNodeVersion = parentNode != null ? parentNode.getNodeVersion() : null; + CrNode node = new CrNode(relPath, nodeType, createdDate, workspace, parentNodeVersion, versionDescription); + CrNodeVersion nodeVersion = node.getNodeVersion(null); + + initialNodeVersion.setNode(node); + initialNodeVersion.setNodeVersion(nodeVersion); + + if ( parentNode != null ) { + parentNode.addChildNode(initialNodeVersion); + } + + return initialNodeVersion; + } + /* (non-Javadoc) + * @see org.lamsfoundation.lams.contentrepository.service.INodeFactory#getNode(org.lamsfoundation.lams.contentrepository.CrNode, java.lang.Long) + */ + public SimpleVersionedNode getNode(CrNode databaseNode, Long versionId) { + SimpleVersionedNode newNode = (SimpleVersionedNode) beanFactory.getBean("node", SimpleVersionedNode.class); + newNode.setNode(databaseNode); + newNode.setNodeVersion(databaseNode.getNodeVersion(versionId)); + return newNode; + } + + /* (non-Javadoc) + * @see org.lamsfoundation.lams.contentrepository.service.INodeFactory#getNode(java.lang.Long, java.lang.Long, java.lang.Long) + */ + public SimpleVersionedNode getNode(Long workspaceId, Long uuid, Long versionId) throws ItemNotFoundException { + + if ( uuid == null ) { + throw new ItemNotFoundException("UUID is null, unable to find node."); + } + + if ( workspaceId == null ) { + throw new ItemNotFoundException("Workspace Id is null, unable to find node."); + } + + CrNode node = null; + + node = (CrNode) nodeDAO.find(CrNode.class, uuid); + if ( node == null ) { + + throw new ItemNotFoundException("Node "+uuid+" not found."); + + } else if ( ! workspaceId.equals(node.getCrWorkspace().getWorkspaceId()) ) { + + log.error("Security warning. User of workspace "+workspaceId + +" is trying to access node "+uuid+" which is in workspace " + +node.getCrWorkspace().getWorkspaceId() + +" Request for node will be rejected."); + throw new ItemNotFoundException("Node "+uuid+" does not exist in workspace "+workspaceId); + } + + return getNode(node,versionId); + } + + /* (non-Javadoc) + * @see org.lamsfoundation.lams.contentrepository.service.INodeFactory#getNode(java.lang.Long, java.lang.Long, java.lang.Long, java.lang.String) + */ + public SimpleVersionedNode getNodeNewVersion(Long workspaceId, Long uuid, Long versionId, String versionDescription) throws ItemNotFoundException { + + SimpleVersionedNode existingNode = getNode(workspaceId, uuid, versionId); + CrNode existingCrNode = existingNode.getNode(); + + // get next version id + Long nextVersionId = existingNode.getNode().incrementNextVersionId(); + + SimpleVersionedNode newNode = (SimpleVersionedNode) beanFactory.getBean("node", SimpleVersionedNode.class); + newNode.setNode(existingCrNode); + CrNodeVersion newVersion = new CrNodeVersion(existingCrNode, new Date(System.currentTimeMillis()), nextVersionId, versionDescription); + newNode.setNodeVersion(newVersion); + existingCrNode.addCrNodeVersion(newVersion); + + return newNode; + } + + /* (non-Javadoc) + * @see org.lamsfoundation.lams.contentrepository.service.INodeFactory#copy(org.lamsfoundation.lams.contentrepository.service.SimpleVersionedNode) + */ + public SimpleVersionedNode copy( SimpleVersionedNode originalNode ) throws FileException, ValueFormatException, InvalidParameterException { + + return copy(originalNode, null); + } + + /** Private method to handle the recursive copy. The parent node is needed to set up the + * node -> parent link in the CrNode object. + * + * @param originalNode + * @param parentNode + * @return new Node + * @throws FileException + * @throws ValueFormatException + * @throws InvalidParameterException + */ + private SimpleVersionedNode copy( SimpleVersionedNode originalNode, CrNodeVersion parentNodeVersion ) throws FileException, ValueFormatException, InvalidParameterException { + + SimpleVersionedNode newNode = (SimpleVersionedNode) beanFactory.getBean("node", SimpleVersionedNode.class); + + // copy the basic CrNode/CrNodeVersion fields. Set a new timestamp and new ids + Date createdDate = new Date(System.currentTimeMillis()); + + CrNode newCrNode = new CrNode(originalNode.getPath(), originalNode.getNodeType(), createdDate, + originalNode.getNode().getCrWorkspace(), parentNodeVersion, originalNode.getVersionDescription()); + newNode.setNode(newCrNode); + + CrNodeVersion newCrNodeVersion = newCrNode.getNodeVersion(null); + newNode.setNodeVersion(newCrNodeVersion); + + // copy properties - have to clone the properties items as well + Set origProperties = originalNode.getNodeVersion().getCrNodeVersionProperties(); + if ( origProperties != null ) { + Iterator iterProp = origProperties.iterator(); + while ( iterProp.hasNext() ) { + CrNodeVersionProperty property = (CrNodeVersionProperty) iterProp.next(); + newCrNodeVersion.setProperty(property.getName(), property.getValue(), property.getType()); + } + } + + // copy any attached file. don't actually copy the file - set up + // and input stream and the file will be copied when the node is saved. + // this is likely to recopy the Filename and Mimetype properties. + if ( originalNode.isNodeType(NodeType.FILENODE) ) { + InputStream istream = originalNode.getFile(); + IValue filenameProperty = originalNode.getProperty(PropertyName.FILENAME); + IValue mimetypeProperty = originalNode.getProperty(PropertyName.MIMETYPE); + newNode.setFile(istream, + filenameProperty != null ? filenameProperty.getString() : null, + mimetypeProperty != null ? mimetypeProperty.getString() : null); + } + + // now copy the child nodes + Iterator iter = originalNode.getChildNodes().iterator(); + while ( iter.hasNext() ) { + SimpleVersionedNode childNode = (SimpleVersionedNode) iter.next(); + SimpleVersionedNode newChildNode = this.copy(childNode, newCrNodeVersion); + newNode.addChildNode(newChildNode); + } + + return newNode; + + } + + /* ********************************************************** + * Following methods are required for Spring framework to set up + * the DAO object(s). + * ********************************************************** + */ + + /* (non-Javadoc) + * @see org.lamsfoundation.lams.contentrepository.service.INodeFactory#getNodeDAO() + */ + public INodeDAO getNodeDAO() { + return nodeDAO; + } + /* (non-Javadoc) + * @see org.lamsfoundation.lams.contentrepository.service.INodeFactory#setNodeDAO(org.lamsfoundation.lams.contentrepository.dao.INodeDAO) + */ + public void setNodeDAO(INodeDAO nodeDAO) { + this.nodeDAO = nodeDAO; + } + + + /* **** Method for BeanFactoryAware interface *****************/ + /* (non-Javadoc) + * @see org.lamsfoundation.lams.contentrepository.service.INodeFactory#setBeanFactory(org.springframework.beans.factory.BeanFactory) + */ + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = beanFactory; + } + + +} Index: lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/SimpleRepository.java =================================================================== diff -u -rc7b1854c8d21405b96c097c2b9c495e87e0df51a -r3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52 --- lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/SimpleRepository.java (.../SimpleRepository.java) (revision c7b1854c8d21405b96c097c2b9c495e87e0df51a) +++ lams_contentrepository/src/java/org/lamsfoundation/lams/contentrepository/service/SimpleRepository.java (.../SimpleRepository.java) (revision 3b0119f1c5ef6fd0fb497a0219c2dd2f7cdf6d52) @@ -21,9 +21,6 @@ package org.lamsfoundation.lams.contentrepository.service; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashSet; @@ -34,7 +31,6 @@ import java.util.SortedSet; import java.util.TreeMap; -import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.lamsfoundation.lams.contentrepository.AccessDeniedException; import org.lamsfoundation.lams.contentrepository.CrCredential; @@ -50,19 +46,16 @@ import org.lamsfoundation.lams.contentrepository.ItemExistsException; import org.lamsfoundation.lams.contentrepository.ItemNotFoundException; import org.lamsfoundation.lams.contentrepository.LoginException; -import org.lamsfoundation.lams.contentrepository.NoSuchNodeTypeException; import org.lamsfoundation.lams.contentrepository.NodeKey; import org.lamsfoundation.lams.contentrepository.NodeType; import org.lamsfoundation.lams.contentrepository.PropertyName; import org.lamsfoundation.lams.contentrepository.RepositoryCheckedException; import org.lamsfoundation.lams.contentrepository.RepositoryRuntimeException; import org.lamsfoundation.lams.contentrepository.ValidationException; +import org.lamsfoundation.lams.contentrepository.ValueFormatException; import org.lamsfoundation.lams.contentrepository.WorkspaceNotFoundException; import org.lamsfoundation.lams.contentrepository.dao.ICredentialDAO; import org.lamsfoundation.lams.contentrepository.dao.IWorkspaceDAO; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; /** @@ -92,15 +85,14 @@ * * @author Fiona Malikoff */ -public class SimpleRepository implements IRepositoryAdmin, BeanFactoryAware { +public class SimpleRepository implements IRepositoryAdmin { protected Logger log = Logger.getLogger(SimpleRepository.class); private ICredentialDAO credentialDAO = null; private IWorkspaceDAO workspaceDAO = null; + private INodeFactory nodeFactory = null; - private BeanFactory beanFactory = null; - private Set ticketIdSet = new HashSet(); // set of currently known tickets. public SimpleRepository () { @@ -172,8 +164,8 @@ throws AccessDeniedException, LoginException, ItemExistsException, RepositoryCheckedException { // call workspace dao to check the login and get the workspace - if ( workspaceDAO == null || credentialDAO == null || beanFactory == null ) - throw new RepositoryRuntimeException("Workspace, Credential DAO or Bean Factory object missing. Unable to process login."); + if ( workspaceDAO == null || credentialDAO == null || nodeFactory == null ) + throw new RepositoryRuntimeException("Workspace, Credential DAO or Node Factory object missing. Unable to process login."); CrWorkspace workspace = workspaceDAO.findByName(workspaceName); if ( workspace != null ) { @@ -355,38 +347,6 @@ return ( ticket != null && ticketIdSet.contains(ticket.getTicketId()) ); } - /** Get an existing SimpleVersionedNode. Reads the node from the database. - * Does not cache the node. If versionId is null, then gets the latest version. - * @throws ItemNotFoundException*/ - private SimpleVersionedNode getNode(Long workspaceId, Long uuid, Long versionId) throws ItemNotFoundException { - SimpleVersionedNode dbNode = (SimpleVersionedNode) beanFactory.getBean("node", SimpleVersionedNode.class); - dbNode.loadData(workspaceId, uuid,versionId); - return dbNode; - } - - /** - * Create a file node. Does not save the node. - */ - private SimpleVersionedNode createFileNode(CrWorkspace workspace, InputStream istream, String filename, - String mimeType, String versionDescription, - String relPath, SimpleVersionedNode packageNode) - throws InvalidParameterException, FileException, ValidationException { - try { - - SimpleVersionedNode initialNodeVersion = (SimpleVersionedNode) beanFactory.getBean("node", - SimpleVersionedNode.class); - initialNodeVersion.initialiseNode(relPath, NodeType.FILENODE, (CrWorkspace) workspace, packageNode); - initialNodeVersion.setFile(istream, filename, mimeType); - return initialNodeVersion; - - } catch ( NoSuchNodeTypeException e) { - // if this is thrown, then it is bug - nothing external should cause it. - throw new RepositoryRuntimeException("Internal error: unable to add file. " - +e.getMessage(), e); - } - } - - /* (non-Javadoc) * @see org.lamsfoundation.lams.contentrepository.IRepository#addFileItem(org.lamsfoundation.lams.contentrepository.ITicket, java.io.InputStream, java.lang.String, java.lang.String, java.lang.String) */ @@ -397,8 +357,9 @@ try { CrWorkspace workspace = getWorkspace(ticket.getWorkspaceId()); - SimpleVersionedNode initialNodeVersion = createFileNode(workspace, istream, filename, mimeType, versionDescription, null, null); - initialNodeVersion.save(versionDescription, null); + SimpleVersionedNode initialNodeVersion = nodeFactory.createFileNode(workspace, + null, null, istream, filename, mimeType, versionDescription); + initialNodeVersion.save(); return initialNodeVersion.getNodeKey(); } catch ( ValidationException e) { // if this is thrown, then it is bug - nothing external should cause it. @@ -411,118 +372,7 @@ } } - /** - * Process files in the package. - * - * @param dirPath: the directory from which to get files. Mandatory. - * @param packageNode: node representing the package. Mandatory. - * @return nodeSet: set of child nodes for the package node - * @throws InvalidParameterException - * @throws FileException - */ - private List processPackageFilesSaveNode(CrWorkspace workspace, String dirPath, SimpleVersionedNode packageNode, String versionDescription) - throws InvalidParameterException, FileException, ValidationException { - - File directory = new File(dirPath); - if ( ! directory.exists() || ! directory.isDirectory() || ! directory.canRead() ) { - throw new FileException("Directory "+dirPath+" does not exist, is not a directory or cannot be read."); - } - // set up the path to be removed from file paths, to make a relative path. - // this is a directory but we may need to add the directory separator on the end - String removePathToMakeRelPath = directory.getAbsolutePath(); - if ( removePathToMakeRelPath.charAt(removePathToMakeRelPath.length()-1) != File.separatorChar ) - removePathToMakeRelPath += File.separatorChar; - - List nodeList = new ArrayList(); - processDirectory(workspace, removePathToMakeRelPath, directory, packageNode, versionDescription, nodeList); - return nodeList; - } - - /** - * Process Directory of files. This method is called recursively to process - * files in the initial directory and in all subdirectories of this directory. - * - * @param removePathToMakeRelPath: string to remove from a files absolute - * path to create relPath, the path relative to the package node. This is - * the absolute path to the directory that contains all the files for the package. - * This value stays the same across all recursive calls. Mandatory. - * @param dirFile: the directory from which to get files. Initially this will - * be the directory that contains the package but as recursive calls are made, - * this value will change. Mandatory. - * @param packageNode: node representing the package. Mandatory. - * @param versionDescription: version description for node. Optional. - * This value stays the same across all recursive calls. - * @param nodeSet: set of nodes to update with the new nodes. Passed in through - * the recursion for efficiency (rather than keep creating new collections). Must - * not be null. - * @throws FileException - */ - private void processDirectory(CrWorkspace workspace, String removePathToMakeRelPath, File dirFile, SimpleVersionedNode packageNode, String versionDescription, List nodeList) - throws InvalidParameterException, FileException, ValidationException { - - if ( ! dirFile.exists() || ! dirFile.isDirectory() || ! dirFile.canRead() ) { - throw new FileException("Directory "+dirFile.getAbsolutePath()+" does not exist, is not a directory or cannot be read."); - } - - File file = null; // declare outside try so available in catch - try { - - File[] files = dirFile.listFiles(); - for ( int i=0; i - * This method does not work well here as it should be on a node - * only object, not a node version object. But having a node object - * requires another interface - some methods in this class are - * really node methods, some are version methods. So live with - * this for the moment. - *

    - * If we ever pass the node back to the calling program, rather - * than working with the restricted ticket calls, then this - * method should be revisited and a new node object will be - * required - otherwise next version id could be wrong. - *

    - * Maybe put this method belongs in a factory that creates nodes... - *

    - * @throws RepositoryRuntimeException if an internal error occurs. - * @see org.lamsfoundation.lams.contentrepository.IVersionedNode#createNewVersion(java.lang.String, java.lang.String) - */ - protected void initialiseNewVersionOfNode(SimpleVersionedNode existingNode) { - - this.node = existingNode.node; - - // get next version id - Long nextVersionId = this.node.incrementNextVersionId(); - - this.node.setParentNodeVersion(existingNode.node.getParentNodeVersion()); - nodeVersion = createCrNodeVersion(node.getType(), - new Date(System.currentTimeMillis()), nextVersionId); - node.getCrNodeVersions().add(nodeVersion); - } - + public NodeKey getNodeKey() { return new NodeKey(getUUID(), getVersion()); } @@ -403,6 +289,15 @@ } /** + * @see org.lamsfoundation.lams.contentrepository.IVersionedNode#getVersionDescription() + */ + public String getVersionDescription() { + nodeObjectInitilised("Unable to get version description."); + return nodeVersion.getVersionDescription(); + } + + + /** * @see org.lamsfoundation.lams.contentrepository.IVersionedNode#getCreatedDateTime() */ public Date getCreatedDateTime() { @@ -494,34 +389,7 @@ */ - /** Create the CrNode, CrNodeVersion. - */ - private void createCrNode(String relPath, String nodeTypeName, CrWorkspace workspace, CrNodeVersion parentNode) { - - Date createdDate = new Date(System.currentTimeMillis()); - // start the next version id at 1, which is used straight away by incrementNextVersionId() - node = new CrNode(relPath, nodeTypeName, createdDate, new Long(1), workspace, parentNode, null); - nodeVersion = createCrNodeVersion(nodeTypeName, createdDate, node.incrementNextVersionId()); - node.addCrNodeVersion(nodeVersion); - } - - /** Create a version part of a node. - */ - protected CrNodeVersion createCrNodeVersion(String nodeTypeName, - Date createdDate, Long versionId) { - - nodeVersion = new CrNodeVersion(); - nodeVersion.setCreatedDateTime(createdDate); - nodeVersion.setNode(node); - nodeVersion.setVersionId(versionId); - // nvId is set automatically on save. - // ??nodeId is set automatically on save - return nodeVersion; - - } - - /** Validate that this node is in a state that may be saved. * Rules: *