Author: bcarothers
Date: 2009-06-14 18:58:57 -0400 (Sun, 14 Jun 2009)
New Revision: 1050
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/federation/ForkRequestProcessor.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/BatchRequestBuilder.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CopyBranchRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RequestBuilder.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaTckTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatingRequestProcessor.java
Log:
DNA-453 Implement Workspace.copy(String, String, String)
Applied patch that modifies the copy operation in Graph and Graph.Batch to support the
"fromWorkspace" construct, allowing users to specify that the source node is in
a workspace other than the current workspace. The patch also moves the
JcrWorkspace.copy(String, String) code into JcrWorkspace.copy(String, String, String) and
generalizes it to support source nodes in workspaces other than the workspace represented
by the JcrWorkspace.
The patch modifies JcrWorkspace.copy(String, String) to call JcrWorkspace.copy(String,
String, String) with the name of the current workspace as the source workspace. This
allows for the corner cases of the JcrWorkspace.copy(String, String, String) to be tested
by the JR TCK tests. Added an additional test to DnaTckTest to test copying from
workspace to another. For some reason the JR TCK tests don't actually do this.
Finally, the patch adds the concept of UuidConflictBehavior to the copy operation and
CopyBranchRequest. This feature is not yet implemented in the request processors, but is
needed in order to implement the JcrWorkspace.clone(...) and update(String) methods as
copies from one workspace to another.
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java 2009-06-13 15:56:00 UTC
(rev 1049)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java 2009-06-14 22:58:57 UTC
(rev 1050)
@@ -78,6 +78,7 @@
import org.jboss.dna.graph.request.Request;
import org.jboss.dna.graph.request.RequestBuilder;
import org.jboss.dna.graph.request.UnsupportedRequestException;
+import org.jboss.dna.graph.request.UuidConflictBehavior;
import org.jboss.dna.graph.request.VerifyWorkspaceRequest;
import org.jboss.dna.graph.request.CloneWorkspaceRequest.CloneConflictBehavior;
import org.jboss.dna.graph.request.CreateWorkspaceRequest.CreateConflictBehavior;
@@ -564,17 +565,19 @@
public Copy<Graph> copy( Location from ) {
return new CopyAction<Graph>(this, from) {
@Override
- protected Graph submit( Locations from,
+ protected Graph submit( String fromWorkspaceName,
+ Locations from,
Location into,
Name childName ) {
- String workspaceName = getCurrentWorkspaceName();
+ String workspaceName = fromWorkspaceName != null ? fromWorkspaceName :
getCurrentWorkspaceName();
do {
requests.copyBranch(from.getLocation(),
workspaceName,
into,
- workspaceName,
+ getCurrentWorkspaceName(),
childName,
- NodeConflictBehavior.APPEND);
+ NodeConflictBehavior.APPEND,
+ UuidConflictBehavior.ALWAYS_CREATE_NEW_UUID);
} while ((from = from.next()) != null);
return and();
}
@@ -1734,15 +1737,13 @@
}
public List<Location> under( Location at ) {
- return requests.readBlockOfChildren(at,
getCurrentWorkspaceName(), startingIndex, blockSize)
- .getChildren();
+ return requests.readBlockOfChildren(at,
getCurrentWorkspaceName(), startingIndex, blockSize).getChildren();
}
};
}
public List<Location> startingAfter( final Location
previousSibling ) {
- return requests.readNextBlockOfChildren(previousSibling,
getCurrentWorkspaceName(), blockSize)
- .getChildren();
+ return requests.readNextBlockOfChildren(previousSibling,
getCurrentWorkspaceName(), blockSize).getChildren();
}
public List<Location> startingAfter( String
pathOfPreviousSibling ) {
@@ -2368,12 +2369,19 @@
assertNotExecuted();
return new CopyAction<BatchConjunction>(this.nextRequests, from) {
@Override
- protected BatchConjunction submit( Locations from,
+ protected BatchConjunction submit( String fromWorkspaceName,
+ Locations from,
Location into,
Name copyName ) {
- String workspaceName = getCurrentWorkspaceName();
+ String workspaceName = fromWorkspaceName != null ? fromWorkspaceName
: getCurrentWorkspaceName();
do {
- requestQueue.copyBranch(from.getLocation(), workspaceName, into,
workspaceName, copyName);
+ requestQueue.copyBranch(from.getLocation(),
+ workspaceName,
+ into,
+ workspaceName,
+ copyName,
+ null,
+
UuidConflictBehavior.ALWAYS_CREATE_NEW_UUID);
} while ((from = from.next()) != null);
return and();
}
@@ -3993,10 +4001,36 @@
* @param <Next> The interface that is to be returned when this request is
completed
* @author Randall Hauch
*/
- public interface Copy<Next> extends To<Next>, Into<Next>,
And<Copy<Next>> {
+ public interface Copy<Next>
+ extends WithUuids<FromWorkspace<CopyTarget<Next>>>,
FromWorkspace<CopyTarget<Next>>, CopyTarget<Next>,
And<Copy<Next>> {
}
+ public interface CopyTarget<Next> extends To<Next>, Into<Next> {
+ }
+
/**
+ * The interface for specifying that a node should come from a workspace other than
the current workspace.
+ *
+ * @param <Next> The interface that is to be returned when this request is
completed
+ */
+ public interface FromWorkspace<Next> {
+ Next fromWorkspace( String workspaceName );
+ }
+
+ /**
+ * The interface for specifying how UUID conflicts should be handled.
+ *
+ * @param <Next> The interface that is to be returned when this request is
completed
+ */
+ public interface WithUuids<Next> {
+ Next removingMatchingUuids();
+
+ Next failingIfUuidsMatch();
+
+ Next unlessMatchingUuidExists();
+ }
+
+ /**
* The interface for defining additional properties on a new node.
*
* @param <Next> The interface that is to be returned when this create request
is completed
@@ -5473,10 +5507,7 @@
}
public SubgraphNode getNode( Name relativePath ) {
- Path path = getGraph().getContext()
- .getValueFactories()
- .getPathFactory()
- .create(getLocation().getPath(), relativePath);
+ Path path =
getGraph().getContext().getValueFactories().getPathFactory().create(getLocation().getPath(),
relativePath);
path = path.getNormalizedPath();
return getNode(path);
}
@@ -5762,12 +5793,16 @@
@NotThreadSafe
protected abstract class CopyAction<T> extends AbstractAction<T>
implements Copy<T> {
- private final Locations from;
+ protected Locations from;
+ protected String fromWorkspaceName;
+ protected UuidConflictBehavior uuidConflictBehavior;
/*package*/CopyAction( T afterConjunction,
Location from ) {
super(afterConjunction);
this.from = new Locations(from);
+ this.fromWorkspaceName = Graph.this.getCurrentWorkspaceName();
+ this.uuidConflictBehavior = UuidConflictBehavior.ALWAYS_CREATE_NEW_UUID;
}
public Copy<T> and( Location from ) {
@@ -5809,38 +5844,61 @@
/**
* Submit any requests to move the targets into the supplied parent location
*
+ * @param fromWorkspaceName the name of the workspace containing the {@code from}
locations
* @param from the locations that are being copied
* @param into the parent location
* @param nameForCopy the name that should be used for the copy, or null if the
name should be the same as the original
* @return this object, for method chaining
*/
- protected abstract T submit( Locations from,
- Location into,
- Name nameForCopy );
+ protected abstract T submit( String fromWorkspaceName,
+ Locations from,
+ Location into,
+ Name nameForCopy );
+ public FromWorkspace<CopyTarget<T>> failingIfUuidsMatch() {
+ this.uuidConflictBehavior = UuidConflictBehavior.THROW_EXCEPTION;
+ return this;
+ }
+
+ public FromWorkspace<CopyTarget<T>> removingMatchingUuids() {
+ this.uuidConflictBehavior = UuidConflictBehavior.REPLACE_EXISTING_NODE;
+ return this;
+ }
+
+ public FromWorkspace<CopyTarget<T>> unlessMatchingUuidExists() {
+ this.uuidConflictBehavior = UuidConflictBehavior.DO_NOT_COPY;
+ return this;
+ }
+
+ public CopyTarget<T> fromWorkspace( String workspaceName ) {
+ this.fromWorkspaceName = workspaceName;
+
+ return this;
+ }
+
public T into( Location into ) {
- return submit(from, into, null);
+ return submit(this.fromWorkspaceName, this.from, into, null);
}
public T into( Path into ) {
- return submit(from, Location.create(into), null);
+ return submit(this.fromWorkspaceName, this.from, Location.create(into),
null);
}
public T into( UUID into ) {
- return submit(from, Location.create(into), null);
+ return submit(this.fromWorkspaceName, this.from, Location.create(into),
null);
}
public T into( Property firstIdProperty,
Property... additionalIdProperties ) {
- return submit(from, Location.create(firstIdProperty, additionalIdProperties),
null);
+ return submit(this.fromWorkspaceName, this.from,
Location.create(firstIdProperty, additionalIdProperties), null);
}
public T into( Property into ) {
- return submit(from, Location.create(into), null);
+ return submit(this.fromWorkspaceName, this.from, Location.create(into),
null);
}
public T into( String into ) {
- return submit(from, Location.create(createPath(into)), null);
+ return submit(this.fromWorkspaceName, this.from,
Location.create(createPath(into)), null);
}
public T to( Location desiredLocation ) {
@@ -5852,7 +5910,7 @@
throw new
IllegalArgumentException(GraphI18n.unableToCopyToTheRoot.text(this.from,
desiredLocation));
}
Path parent = desiredPath.getParent();
- return submit(from, Location.create(parent),
desiredPath.getLastSegment().getName());
+ return submit(this.fromWorkspaceName, this.from, Location.create(parent),
desiredPath.getLastSegment().getName());
}
public T to( Path desiredPath ) {
@@ -5860,7 +5918,7 @@
throw new
IllegalArgumentException(GraphI18n.unableToCopyToTheRoot.text(this.from, desiredPath));
}
Path parent = desiredPath.getParent();
- return submit(from, Location.create(parent),
desiredPath.getLastSegment().getName());
+ return submit(this.fromWorkspaceName, this.from, Location.create(parent),
desiredPath.getLastSegment().getName());
}
public T to( String desiredPath ) {
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/federation/ForkRequestProcessor.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/federation/ForkRequestProcessor.java 2009-06-13
15:56:00 UTC (rev 1049)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/federation/ForkRequestProcessor.java 2009-06-14
22:58:57 UTC (rev 1050)
@@ -1262,7 +1262,8 @@
// Create the pushed-down request ...
CopyBranchRequest pushDown = new CopyBranchRequest(fromProxy.location(),
fromProxy.workspaceName(), intoProxy.location(),
intoProxy.workspaceName(),
request.desiredName(),
- request.conflictBehavior());
+
request.nodeConflictBehavior(),
+
request.uuidConflictBehavior());
// Create the federated request ...
FederatedRequest federatedRequest = new FederatedRequest(request);
federatedRequest.add(pushDown, sameLocation, false, fromProxy.projection(),
intoProxy.projection());
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/BatchRequestBuilder.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/BatchRequestBuilder.java 2009-06-13
15:56:00 UTC (rev 1049)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/BatchRequestBuilder.java 2009-06-14
22:58:57 UTC (rev 1050)
@@ -572,7 +572,8 @@
String intoWorkspace,
Name nameForCopy ) {
return add(new CopyBranchRequest(from, fromWorkspace, into, intoWorkspace,
nameForCopy,
- CopyBranchRequest.DEFAULT_CONFLICT_BEHAVIOR));
+
CopyBranchRequest.DEFAULT_NODE_CONFLICT_BEHAVIOR,
+ UuidConflictBehavior.ALWAYS_CREATE_NEW_UUID));
}
/**
@@ -585,7 +586,10 @@
* @param nameForCopy the desired name for the node that results from the copy, or
null if the name of the original should be
* used
* @param conflictBehavior the expected behavior if an equivalently-named child
already exists at the <code>into</code>
- * location, or null if the default conflict behavior should be used
+ * location, or null if the default node conflict behavior should be used
+ * @param uuidConflictBehavior the expected behavior if a node with the same UUID as
any of the nodes in the branch under the
+ * {@code from} location in the {@code fromWorkspace} workspace already exists
in the workspace, or null if the default
+ * UUID conflict behavior should be used
* @return this builder for method chaining; never null
* @throws IllegalArgumentException if either of the locations or workspace names are
null
*/
@@ -594,9 +598,12 @@
Location into,
String intoWorkspace,
Name nameForCopy,
- NodeConflictBehavior conflictBehavior ) {
- if (conflictBehavior == null) conflictBehavior =
CopyBranchRequest.DEFAULT_CONFLICT_BEHAVIOR;
- return add(new CopyBranchRequest(from, fromWorkspace, into, intoWorkspace,
nameForCopy, conflictBehavior));
+ NodeConflictBehavior conflictBehavior,
+ UuidConflictBehavior uuidConflictBehavior) {
+ if (conflictBehavior == null) conflictBehavior =
CopyBranchRequest.DEFAULT_NODE_CONFLICT_BEHAVIOR;
+ if (uuidConflictBehavior == null) uuidConflictBehavior =
CopyBranchRequest.DEFAULT_UUID_CONFLICT_BEHAVIOR;
+ return add(new CopyBranchRequest(from, fromWorkspace, into, intoWorkspace,
nameForCopy, conflictBehavior,
+ uuidConflictBehavior));
}
/**
@@ -628,7 +635,8 @@
Location into,
String workspaceName,
Name newNameForNode ) {
- return add(new MoveBranchRequest(from, into, null, workspaceName, newNameForNode,
MoveBranchRequest.DEFAULT_CONFLICT_BEHAVIOR));
+ return add(new MoveBranchRequest(from, into, null, workspaceName,
newNameForNode,
+ MoveBranchRequest.DEFAULT_CONFLICT_BEHAVIOR));
}
/**
@@ -647,7 +655,8 @@
Location before,
String workspaceName,
Name newNameForNode ) {
- return add(new MoveBranchRequest(from, into, before, workspaceName,
newNameForNode, MoveBranchRequest.DEFAULT_CONFLICT_BEHAVIOR));
+ return add(new MoveBranchRequest(from, into, before, workspaceName,
newNameForNode,
+ MoveBranchRequest.DEFAULT_CONFLICT_BEHAVIOR));
}
/**
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CopyBranchRequest.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CopyBranchRequest.java 2009-06-13
15:56:00 UTC (rev 1049)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CopyBranchRequest.java 2009-06-14
22:58:57 UTC (rev 1050)
@@ -41,14 +41,16 @@
private static final long serialVersionUID = 1L;
- public static final NodeConflictBehavior DEFAULT_CONFLICT_BEHAVIOR =
NodeConflictBehavior.APPEND;
+ public static final NodeConflictBehavior DEFAULT_NODE_CONFLICT_BEHAVIOR =
NodeConflictBehavior.APPEND;
+ public static final UuidConflictBehavior DEFAULT_UUID_CONFLICT_BEHAVIOR =
UuidConflictBehavior.ALWAYS_CREATE_NEW_UUID;
private final Location from;
private final Location into;
private final String fromWorkspace;
private final String intoWorkspace;
private final Name desiredNameForCopy;
- private final NodeConflictBehavior conflictBehavior;
+ private final NodeConflictBehavior nodeConflictBehavior;
+ private final UuidConflictBehavior uuidConflictBehavior;
private Location actualFromLocation;
private Location actualIntoLocation;
@@ -66,7 +68,7 @@
String fromWorkspace,
Location into,
String intoWorkspace ) {
- this(from, fromWorkspace, into, intoWorkspace, null, DEFAULT_CONFLICT_BEHAVIOR);
+ this(from, fromWorkspace, into, intoWorkspace, null,
DEFAULT_NODE_CONFLICT_BEHAVIOR, DEFAULT_UUID_CONFLICT_BEHAVIOR);
}
/**
@@ -85,7 +87,7 @@
Location into,
String intoWorkspace,
Name nameForCopy ) {
- this(from, fromWorkspace, into, intoWorkspace, nameForCopy,
DEFAULT_CONFLICT_BEHAVIOR);
+ this(from, fromWorkspace, into, intoWorkspace, nameForCopy,
DEFAULT_NODE_CONFLICT_BEHAVIOR, DEFAULT_UUID_CONFLICT_BEHAVIOR);
}
/**
@@ -97,8 +99,10 @@
* @param intoWorkspace the name of the workspace where the
<code>into</code> node is to be copied
* @param nameForCopy the desired name for the node that results from the copy, or
null if the name of the original should be
* used
- * @param conflictBehavior the expected behavior if an equivalently-named child
already exists at the <code>into</code>
+ * @param nodeConflictBehavior the expected behavior if an equivalently-named child
already exists at the <code>into</code>
* location
+ * @param uuidConflictBehavior the expected behavior if a node with the same UUID as
any of the nodes in the branch under the
+ * {@code from} location in the {@code fromWorkspace} workspace already exists
in the workspace
* @throws IllegalArgumentException if any of the parameters are null
*/
public CopyBranchRequest( Location from,
@@ -106,18 +110,21 @@
Location into,
String intoWorkspace,
Name nameForCopy,
- NodeConflictBehavior conflictBehavior ) {
+ NodeConflictBehavior nodeConflictBehavior,
+ UuidConflictBehavior uuidConflictBehavior ) {
CheckArg.isNotNull(from, "from");
CheckArg.isNotNull(into, "into");
CheckArg.isNotNull(fromWorkspace, "fromWorkspace");
CheckArg.isNotNull(intoWorkspace, "intoWorkspace");
- CheckArg.isNotNull(conflictBehavior, "conflictBehavior");
+ CheckArg.isNotNull(nodeConflictBehavior, "nodeConflictBehavior");
+ CheckArg.isNotNull(uuidConflictBehavior, "uuidConflictBehavior");
this.from = from;
this.into = into;
this.fromWorkspace = fromWorkspace;
this.intoWorkspace = intoWorkspace;
this.desiredNameForCopy = nameForCopy;
- this.conflictBehavior = conflictBehavior;
+ this.nodeConflictBehavior = nodeConflictBehavior;
+ this.uuidConflictBehavior = uuidConflictBehavior;
}
/**
@@ -191,11 +198,20 @@
*
* @return the behavior specification
*/
- public NodeConflictBehavior conflictBehavior() {
- return conflictBehavior;
+ public NodeConflictBehavior nodeConflictBehavior() {
+ return nodeConflictBehavior;
}
/**
+ * Get the expected behavior when one of the nodes in the branch has the same UUID as
an existing node in the workspace.
+ *
+ * @return the behavior specification
+ */
+ public UuidConflictBehavior uuidConflictBehavior() {
+ return uuidConflictBehavior;
+ }
+
+ /**
* Sets the actual and complete location of the node being renamed and its new
location. This method must be called when
* processing the request, and the actual location must have a {@link
Location#getPath() path}.
*
@@ -313,7 +329,7 @@
CopyBranchRequest that = (CopyBranchRequest)obj;
if (!this.from().equals(that.from())) return false;
if (!this.into().equals(that.into())) return false;
- if (!this.conflictBehavior().equals(that.conflictBehavior())) return false;
+ if (!this.nodeConflictBehavior().equals(that.nodeConflictBehavior())) return
false;
if (!this.fromWorkspace.equals(that.fromWorkspace)) return false;
if (!this.intoWorkspace.equals(that.intoWorkspace)) return false;
return true;
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RequestBuilder.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RequestBuilder.java 2009-06-13
15:56:00 UTC (rev 1049)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RequestBuilder.java 2009-06-14
22:58:57 UTC (rev 1050)
@@ -432,6 +432,8 @@
* used
* @param conflictBehavior the expected behavior if an equivalently-named child
already exists at the <code>into</code>
* location, or null if the default conflict behavior should be used
+ * @param uuidConflictBehavior the expected behavior if a node with the same UUID as
any of the nodes in the branch under the
+ * {@code from} location in the {@code fromWorkspace} workspace already exists
in the workspace
* @return the request; never null
* @throws IllegalArgumentException if either of the locations or workspace names are
null
*/
@@ -440,9 +442,11 @@
Location into,
String intoWorkspace,
Name nameForCopy,
- NodeConflictBehavior conflictBehavior ) {
- if (conflictBehavior == null) conflictBehavior =
CopyBranchRequest.DEFAULT_CONFLICT_BEHAVIOR;
- return process(new CopyBranchRequest(from, fromWorkspace, into, intoWorkspace,
nameForCopy, conflictBehavior));
+ NodeConflictBehavior conflictBehavior,
+ UuidConflictBehavior uuidConflictBehavior) {
+ if (conflictBehavior == null) conflictBehavior =
CopyBranchRequest.DEFAULT_NODE_CONFLICT_BEHAVIOR;
+ return process(new CopyBranchRequest(from, fromWorkspace, into, intoWorkspace,
nameForCopy, conflictBehavior,
+ uuidConflictBehavior));
}
/**
@@ -474,9 +478,10 @@
Location into,
String workspaceName,
Name newNameForNode ) {
- return process(new MoveBranchRequest(from, into, null, workspaceName,
newNameForNode, MoveBranchRequest.DEFAULT_CONFLICT_BEHAVIOR));
+ return process(new MoveBranchRequest(from, into, null, workspaceName,
newNameForNode,
+
MoveBranchRequest.DEFAULT_CONFLICT_BEHAVIOR));
}
-
+
/**
* Create a request to move a branch from one location into another before the given
child node of the new location.
*
@@ -490,11 +495,13 @@
*/
public MoveBranchRequest moveBranch( Location from,
Location into,
- Location before,
+ Location before,
String workspaceName,
Name newNameForNode ) {
- return process(new MoveBranchRequest(from, into, before, workspaceName,
newNameForNode, MoveBranchRequest.DEFAULT_CONFLICT_BEHAVIOR));
- }
+ return process(new MoveBranchRequest(from, into, before, workspaceName,
newNameForNode,
+
MoveBranchRequest.DEFAULT_CONFLICT_BEHAVIOR));
+ }
+
/**
* Create a request to move a branch from one location into another.
*
Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java 2009-06-13 15:56:00
UTC (rev 1049)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java 2009-06-14 22:58:57
UTC (rev 1050)
@@ -72,6 +72,7 @@
import org.jboss.dna.graph.request.Request;
import org.jboss.dna.graph.request.SetPropertyRequest;
import org.jboss.dna.graph.request.UpdatePropertiesRequest;
+import org.jboss.dna.graph.request.UuidConflictBehavior;
import org.jboss.dna.graph.request.VerifyNodeExistsRequest;
import org.jboss.dna.graph.request.VerifyWorkspaceRequest;
import org.jboss.dna.graph.request.CloneWorkspaceRequest.CloneConflictBehavior;
@@ -184,13 +185,28 @@
protected void assertNextRequestIsCopy( Location from,
Location to ) {
+ assertNextRequestIsCopy(this.graph.getCurrentWorkspaceName(), from, to);
+ }
+
+ protected void assertNextRequestIsCopy( String fromWorkspace,
+ Location from,
+ Location to ) {
+ assertNextRequestIsCopy(fromWorkspace, from, to,
UuidConflictBehavior.ALWAYS_CREATE_NEW_UUID);
+ }
+
+ protected void assertNextRequestIsCopy( String fromWorkspace,
+ Location from,
+ Location to,
+ UuidConflictBehavior uuidConflictBehavior) {
Request request = executedRequests.poll();
assertThat(request, is(instanceOf(CopyBranchRequest.class)));
CopyBranchRequest copy = (CopyBranchRequest)request;
+ assertThat(copy.fromWorkspace(), is(fromWorkspace));
assertThat(copy.from(), is(from));
assertThat(copy.into(), is(to));
+ assertThat(copy.uuidConflictBehavior(), is(uuidConflictBehavior));
}
-
+
protected void assertNextRequestIsDelete( Location at ) {
Request request = executedRequests.poll();
assertThat(request, is(instanceOf(DeleteBranchRequest.class)));
@@ -377,6 +393,24 @@
}
@Test
+ public void shouldCopyNodeFromOtherWorkspace() {
+ graph.copy(validPath).fromWorkspace("other").into(validIdProperty1,
validIdProperty2);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsCopy("other", Location.create(validPath),
Location.create(validIdProperty1, validIdProperty2));
+ assertNoMoreRequests();
+
+ graph.copy(validPathString).into(validIdProperty1, validIdProperty2);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsCopy(Location.create(validPath),
Location.create(validIdProperty1, validIdProperty2));
+ assertNoMoreRequests();
+
+ graph.copy(validUuid).into(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsCopy(Location.create(validUuid), Location.create(validPath));
+ assertNoMoreRequests();
+ }
+
+ @Test
public void shouldDeleteNode() {
graph.delete(validPath);
assertThat(numberOfExecutions, is(1));
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java 2009-06-13 15:56:00
UTC (rev 1049)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java 2009-06-14 22:58:57
UTC (rev 1050)
@@ -28,6 +28,7 @@
import java.security.AccessControlException;
import java.util.Map;
import java.util.Set;
+import java.util.UUID;
import javax.jcr.AccessDeniedException;
import javax.jcr.InvalidSerializedDataException;
import javax.jcr.ItemExistsException;
@@ -53,6 +54,7 @@
import org.jboss.dna.graph.connector.RepositorySource;
import org.jboss.dna.graph.connector.RepositorySourceException;
import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NameFactory;
import org.jboss.dna.graph.property.Path;
import org.jboss.dna.graph.property.PathFactory;
import org.jboss.dna.graph.property.Property;
@@ -270,9 +272,25 @@
String destAbsPath )
throws ConstraintViolationException, VersionException, AccessDeniedException,
PathNotFoundException, ItemExistsException,
LockException, RepositoryException {
- CheckArg.isNotEmpty(srcAbsPath, "srcAbsPath");
- CheckArg.isNotEmpty(destAbsPath, "destAbsPath");
+ this.copy(this.name, srcAbsPath, destAbsPath);
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public void copy( String srcWorkspace,
+ String srcAbsPath,
+ String destAbsPath )
+ throws ConstraintViolationException, VersionException, AccessDeniedException,
PathNotFoundException, ItemExistsException,
+ LockException, RepositoryException {
+ CheckArg.isNotNull(srcWorkspace, "source workspace name");
+ CheckArg.isNotNull(srcAbsPath, "source path");
+ CheckArg.isNotNull(destAbsPath, "destination path");
+
+ if (!graph.getWorkspaces().contains(srcWorkspace)) {
+ throw new
NoSuchWorkspaceException(JcrI18n.workspaceNameIsInvalid.text(graph.getSourceName(),
this.name));
+ }
+
// Create the paths ...
PathFactory factory = context.getValueFactories().getPathFactory();
Path srcPath = null;
@@ -294,8 +312,7 @@
}
try {
- // this.session.checkPermission(srcAbsPath.substring(0,
srcAbsPath.lastIndexOf('/')), "remove");
- this.session.checkPermission(destAbsPath, "add_node");
+ this.session.checkPermission(destPath.getParent(), "add_node");
}
catch (AccessControlException ace) {
throw new AccessDeniedException(ace);
@@ -305,7 +322,6 @@
* Make sure that the node has a definition at the new location
*/
SessionCache cache = this.session.cache();
- NodeInfo nodeInfo = cache.findNodeInfo(null, srcPath);
NodeInfo cacheParent = cache.findNodeInfo(null, destPath.getParent());
// Skip the cache and load the latest parent info directly from the graph
@@ -314,30 +330,22 @@
String parentPath =
destPath.getParent().getString(this.context.getNamespaceRegistry());
// This will check for a definition and throw a ConstraintViolationException or
ItemExistsException if none is found
- this.session.cache().findBestNodeDefinition(parent, parentPath, newNodeName,
nodeInfo.getPrimaryTypeName());
+ graph.useWorkspace(srcWorkspace);
+ Property primaryTypeProp =
graph.getNodeAt(srcPath).getProperty(JcrLexicon.PRIMARY_TYPE);
+ Property uuidProp = graph.getNodeAt(srcPath).getProperty(DnaLexicon.UUID);
+ graph.useWorkspace(this.name);
+
+ assert primaryTypeProp != null : "Cannot have a node in a JCR repository
with no jcr:primaryType property";
+ assert uuidProp != null : "Cannot have a node in a JCR repository with no
UUID";
+ NameFactory nameFactory = this.context.getValueFactories().getNameFactory();
+ this.session.cache().findBestNodeDefinition(parent, parentPath, newNodeName,
nameFactory.create(primaryTypeProp.getFirstValue()));
+
// Perform the copy operation, but use the "to" form (not the
"into", which takes the parent) ...
- graph.copy(srcPath).to(destPath);
- cache.compensateForWorkspaceChildChange(cacheParent.getUuid(), null,
nodeInfo.getUuid(), newNodeName);
-
- }
-
- /**
- * {@inheritDoc}
- */
- public void copy( String srcWorkspace,
- String srcAbsPath,
- String destAbsPath ) throws NoSuchWorkspaceException {
- CheckArg.isNotNull(srcWorkspace, "source workspace");
- CheckArg.isNotNull(srcAbsPath, "source path");
- CheckArg.isNotNull(destAbsPath, "destination path");
+ graph.copy(srcPath).fromWorkspace(srcWorkspace).to(destPath);
- if (!graph.getWorkspaces().contains(srcWorkspace)) {
- throw new
NoSuchWorkspaceException(JcrI18n.workspaceNameIsInvalid.text(graph.getSourceName(),
this.name));
- }
-
-
- throw new UnsupportedOperationException();
+ // Load the node that we just copied
+ cache.compensateForWorkspaceChildChange(cacheParent.getUuid(), null,
UUID.fromString(uuidProp.getFirstValue().toString()), newNodeName);
}
/**
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaTckTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaTckTest.java 2009-06-13 15:56:00 UTC
(rev 1049)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaTckTest.java 2009-06-14 22:58:57 UTC
(rev 1050)
@@ -9,7 +9,6 @@
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import org.apache.jackrabbit.test.AbstractJCRTest;
-import org.junit.Test;
/**
* Additional DNA tests that check for JCR compliance.
@@ -141,7 +140,6 @@
* Tests that read-write sessions can read nodes by loading all of the children of
the root node
* @throws Exception
*/
- @Test
public void testShouldAllowReadWriteSessionToRead() throws Exception {
session = helper.getReadWriteSession();
testRead(session);
@@ -151,7 +149,6 @@
* Tests that read-write sessions can add nodes, remove nodes, set nodes, and set
properties.
* @throws Exception
*/
- @Test
public void testShouldAllowReadWriteSessionToWrite() throws Exception {
session = helper.getReadWriteSession();
testWrite(session);
@@ -162,7 +159,6 @@
* workspace. This test makes sure both work.
* @throws Exception
*/
- @Test
public void testShouldMapRolesToWorkspacesWhenSpecified() throws Exception {
Credentials creds = new SimpleCredentials("defaultonly",
"defaultonly".toCharArray());
session = helper.getRepository().login(creds);
@@ -183,4 +179,24 @@
session.logout();
}
+
+ public void testShouldCopyFromAnotherWorkspace() throws Exception {
+ session = helper.getSuperuserSession("otherWorkspace");
+ String nodetype1 = this.getProperty("nodetype");
+ Node node1 = session.getRootNode().addNode(nodeName1, nodetype1);
+ node1.addNode(nodeName2, nodetype1);
+ session.save();
+ session.logout();
+
+ superuser.getRootNode().addNode(nodeName4, nodetype1);
+ superuser.save();
+
+ superuser.getWorkspace().copy("otherWorkspace", "/" +
nodeName1, "/" + nodeName4 + "/" + nodeName1);
+
+ Node node4 = superuser.getRootNode().getNode(nodeName4);
+ Node node4node1 = node4.getNode(nodeName1);
+ Node node4node1node2 = node4node1.getNode(nodeName2);
+
+ assertNotNull(node4node1node2);
+ }
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java 2009-06-13
15:56:00 UTC (rev 1049)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java 2009-06-14
22:58:57 UTC (rev 1050)
@@ -98,6 +98,7 @@
Graph graph = Graph.create(source, context);
graph.create("/a").and().create("/a/b").and().create("/a/b/c").and().create("/b");
graph.set("booleanProperty").on("/a/b").to(true);
+
graph.set("jcr:primaryType").on("/a/b").to("nt:unstructured");
graph.set("stringProperty").on("/a/b/c").to("value");
// Make sure the path to the namespaces exists ...
Modified:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatingRequestProcessor.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatingRequestProcessor.java 2009-06-13
15:56:00 UTC (rev 1049)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatingRequestProcessor.java 2009-06-14
22:58:57 UTC (rev 1050)
@@ -367,7 +367,8 @@
Location intoLocation = Location.create(intoProjection.pathInSource);
String workspaceName = fromProjection.projection.getWorkspaceName();
CopyBranchRequest sourceRequest = new CopyBranchRequest(fromLocation,
workspaceName, intoLocation, workspaceName,
- request.desiredName(),
request.conflictBehavior());
+ request.desiredName(),
request.nodeConflictBehavior(),
+
request.uuidConflictBehavior());
execute(sourceRequest, fromProjection.projection);
// Copy/transform the results ...