OCM-54 do copy in session state only and persist on save
git-svn-id: https://svn.apache.org/repos/asf/jackrabbit/commons/ocm/trunk@1357259 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/jackrabbit/ocm/manager/ObjectContentManager.java b/src/main/java/org/apache/jackrabbit/ocm/manager/ObjectContentManager.java
index 8fe6aa6..31fe86c 100644
--- a/src/main/java/org/apache/jackrabbit/ocm/manager/ObjectContentManager.java
+++ b/src/main/java/org/apache/jackrabbit/ocm/manager/ObjectContentManager.java
@@ -508,14 +508,21 @@
throws ObjectContentManagerException;
/**
- * Copy an object
+ * Copy an object from <code>scrPath</code> to <code>destPath</code>. When there does not exist a node yet at
+ * <code>destPath</code> a new node will be created there if the parent {@link javax.jcr.Node} exists already. If
+ * the parent does not exist, an {@link ObjectContentManagerException} will be thrown
+ *
+ * If there already exists a node at <code>destPath</code>, we
+ * try to add the {@link javax.jcr.Node} from <code>srcPath</code>. If not possible, an {@link ObjectContentManagerException}
+ * will be thrown.
*
* @param srcPath
* path of the object to copy
* @param destPath
* destination path
*
- * @throws ObjectContentManagerException
+ * @throws ObjectContentManagerException when the copy did not succeed for example because there exists no {@link javax.jcr.Node} at
+ * <code>srcPath</code> the parent of <code>destPath</code> does not exist or there already exists an (incompatible) node at <code>destPath</code>
*/
public void copy(String srcPath, String destPath)
throws ObjectContentManagerException;
diff --git a/src/main/java/org/apache/jackrabbit/ocm/manager/impl/ObjectContentManagerImpl.java b/src/main/java/org/apache/jackrabbit/ocm/manager/impl/ObjectContentManagerImpl.java
index 7b5b7a2..4642614 100644
--- a/src/main/java/org/apache/jackrabbit/ocm/manager/impl/ObjectContentManagerImpl.java
+++ b/src/main/java/org/apache/jackrabbit/ocm/manager/impl/ObjectContentManagerImpl.java
@@ -29,13 +29,16 @@
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.UnsupportedRepositoryOperationException;
-import javax.jcr.Workspace;
import javax.jcr.lock.LockException;
import javax.jcr.lock.LockManager;
import javax.jcr.nodetype.NoSuchNodeTypeException;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.PropertyDefinition;
import javax.jcr.query.InvalidQueryException;
import javax.jcr.query.QueryResult;
import javax.jcr.version.VersionHistory;
@@ -60,7 +63,6 @@
import org.apache.jackrabbit.ocm.mapper.Mapper;
import org.apache.jackrabbit.ocm.mapper.impl.digester.DigesterMapperImpl;
import org.apache.jackrabbit.ocm.mapper.model.ClassDescriptor;
-import org.apache.jackrabbit.ocm.query.Filter;
import org.apache.jackrabbit.ocm.query.Query;
import org.apache.jackrabbit.ocm.query.QueryManager;
import org.apache.jackrabbit.ocm.query.impl.QueryManagerImpl;
@@ -1028,10 +1030,33 @@
}
}
- public void copy(String srcPath, String destPath) {
- Workspace workspace = session.getWorkspace();
+ public void copy(String srcPath, String destPath) throws ObjectContentManagerException {
try {
- workspace.copy(srcPath, destPath);
+ if(StringUtils.isBlank(srcPath) || StringUtils.isBlank(destPath) || !srcPath.startsWith("/") || !destPath.startsWith("/")) {
+ throw new ObjectContentManagerException("scrPath " + srcPath + " or destPath " + destPath + " is not valid");
+ }
+ // no check for existence needed, as handled by exceptions
+ Node srcNode = session.getNode(srcPath);
+ Node destNode;
+ if (session.nodeExists(destPath)) {
+ destNode = session.getNode(destPath);
+ } else {
+ // if parentDestNode cannot be found, just a PathNotFoundException is thrown
+ while (destPath.endsWith("/")) {
+ destPath = destPath.substring(0, destPath.length()-1);
+ }
+ int indexOfLastSlash = destPath.lastIndexOf("/");
+ String parentDestPath = destPath.substring(0, indexOfLastSlash);
+ String destNodeName = destPath.substring(indexOfLastSlash + 1);
+ Node parentDestNode;
+ if (StringUtils.isBlank(parentDestPath)) {
+ parentDestNode = session.getRootNode();
+ } else {
+ parentDestNode = session.getNode(parentDestPath);
+ }
+ destNode = parentDestNode.addNode(destNodeName, srcNode.getPrimaryNodeType().getName());
+ }
+ copy(srcNode, destNode);
} catch (javax.jcr.nodetype.ConstraintViolationException cve) {
throw new ObjectContentManagerException("Cannot copy the object from " + srcPath + " to " + destPath + "."
+ "Violation of a nodetype or attempt to copy under property detected ", cve);
@@ -1044,7 +1069,7 @@
throw new ObjectContentManagerException("Cannot copy the object from " + srcPath + " to " + destPath + "." + " Session does not have access permissions", ade);
} catch (javax.jcr.PathNotFoundException pnf) {
- throw new ObjectContentManagerException("Cannot copy the object from " + srcPath + " to " + destPath + "." + "Node at source or destination does not exist ", pnf);
+ throw new ObjectContentManagerException("Cannot copy the object from " + srcPath + " to " + destPath + "." + "Node at source or parent of destination does not exist ", pnf);
} catch (javax.jcr.ItemExistsException ie) {
throw new ObjectContentManagerException("Cannot copy the object from " + srcPath + " to " + destPath + "." + "It might already exist at destination path.", ie);
@@ -1065,4 +1090,43 @@
return session.getWorkspace().getVersionManager();
}
+ /**
+ * Helper for copying scrNode (including properties & descendants) to destNode
+ *
+ * @param srcNode
+ * @param destNode
+ * @throws RepositoryException
+ */
+ private void copy(Node srcNode, Node destNode) throws RepositoryException {
+
+ NodeType[] mixinNodeTypes = srcNode.getMixinNodeTypes();
+ for (int i = 0; i < mixinNodeTypes.length; i++) {
+ destNode.addMixin(mixinNodeTypes[i].getName());
+ }
+
+ for (PropertyIterator iter = srcNode.getProperties(); iter.hasNext(); ) {
+ Property property = iter.nextProperty();
+ PropertyDefinition definition = property.getDefinition();
+ if (!definition.isProtected()) {
+ if (definition.isMultiple()) {
+ destNode.setProperty(property.getName(), property.getValues(), property.getType());
+ } else {
+ destNode.setProperty(property.getName(), property.getValue());
+ }
+ }
+ }
+
+ for (NodeIterator iter = srcNode.getNodes(); iter.hasNext(); ) {
+ Node node = iter.nextNode();
+ Node child;
+ // check if the subnode is autocreated
+ if (!node.getDefinition().isAutoCreated() && destNode.hasNode(node.getName())) {
+ child = destNode.getNode(node.getName());
+ } else {
+ child = destNode.addNode(node.getName(), node.getPrimaryNodeType().getName());
+ }
+ copy(node, child);
+ }
+ }
+
}
diff --git a/src/test/java/org/apache/jackrabbit/ocm/manager/basic/AnnotationCopyMoveTest.java b/src/test/java/org/apache/jackrabbit/ocm/manager/basic/AnnotationCopyMoveTest.java
index fe5ff6d..d9fc649 100644
--- a/src/test/java/org/apache/jackrabbit/ocm/manager/basic/AnnotationCopyMoveTest.java
+++ b/src/test/java/org/apache/jackrabbit/ocm/manager/basic/AnnotationCopyMoveTest.java
@@ -97,7 +97,7 @@
// Copy the object
// --------------------------------------------------------------------------------
ocm.copy("/test", "/test2");
-
+ ocm.save();
// --------------------------------------------------------------------------------
// Get the object
// --------------------------------------------------------------------------------
diff --git a/src/test/java/org/apache/jackrabbit/ocm/manager/basic/DigesterCopyMoveTest.java b/src/test/java/org/apache/jackrabbit/ocm/manager/basic/DigesterCopyMoveTest.java
index 233546f..2943db0 100644
--- a/src/test/java/org/apache/jackrabbit/ocm/manager/basic/DigesterCopyMoveTest.java
+++ b/src/test/java/org/apache/jackrabbit/ocm/manager/basic/DigesterCopyMoveTest.java
@@ -98,7 +98,7 @@
// Copy the object
// --------------------------------------------------------------------------------
ocm.copy("/test", "/test2");
-
+ ocm.save();
// --------------------------------------------------------------------------------
// Get the object
// --------------------------------------------------------------------------------