DNA SVN: r809 - in trunk: dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory and 13 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-04-07 17:23:28 -0400 (Tue, 07 Apr 2009)
New Revision: 809
Added:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/BatchRequestBuilder.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RemovePropertyRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RequestBuilder.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/SetPropertyRequest.java
Removed:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RemovePropertiesRequest.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/RemovePropertiesRequestTest.java
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphImporter.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRequestProcessor.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CloneWorkspaceRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/DeleteBranchRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/DestroyWorkspaceRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/UpdatePropertiesRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/package-info.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/LoggingRequestProcessor.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/RequestProcessor.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/AbstractConnectorTest.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/UpdatePropertiesRequestTest.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemRequestProcessor.java
trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheRequestProcessor.java
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Serializer.java
trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorReadingTest.java
trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/util/SerializerTest.java
trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryRequestProcessor.java
Log:
DNA-341 Graph API behavior when removing all property values doesn't reflect that of JCR
Applied patch that changes the connector API. Specifically the semantics and a few method signatures of UpdatePropertiesRequest class were changed to no longer assume that an empty property should be removed; rather, the names of properties that are to be removed are tracked explicitly, and the number of values in a property no longer has any relationship to whether the property is to be removed. All connectors were changed to apply these new semantics.
A number of other changes to the connector API were made. New SetPropertyRequest and RemovePropertyRequest requests types were added as being more efficient when a single property is being set or removed. These are optional requests, meaning that the RequestProcessor has default implementations for the corresponding "process" methods that convert the reqeusts to UpdatedPropertiesRequest. Thus, a connector doesn't have to implement these, but it may be more efficient for it to do so. The RemovedPropertiesRequest was also removed, since it didn't offer any benefit over UpdatePropertiesRequest (and since it is simpler to only have one). All connectors were updated to reflect these semantics.
Also, the Graph batch implementation was improved to optimize adjacent calls to set/remove properties on the same node. In other words, if a batch is used to set a property on node A and then is immediately used to set another property on the same node, the batch will combine the two requests. However, this optimization does not apply if any other operations are performed between the set/remove property operations.
Finally, a minor error was found and corrected in how the connector unit tests reported the (trivial) metrics for creating nodes. The total times (line 2) were correct, but the average and the times for additional nodes (line 3) were all incorrect.
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-04-06 15:55:23 UTC (rev 808)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -43,6 +43,7 @@
import java.util.UUID;
import net.jcip.annotations.Immutable;
import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.common.collection.EmptyIterator;
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.graph.cache.CachePolicy;
import org.jboss.dna.graph.connector.RepositoryConnection;
@@ -60,27 +61,22 @@
import org.jboss.dna.graph.property.Reference;
import org.jboss.dna.graph.property.ValueFormatException;
import org.jboss.dna.graph.property.Path.Segment;
+import org.jboss.dna.graph.request.BatchRequestBuilder;
import org.jboss.dna.graph.request.CloneWorkspaceRequest;
import org.jboss.dna.graph.request.CompositeRequest;
-import org.jboss.dna.graph.request.CopyBranchRequest;
import org.jboss.dna.graph.request.CreateNodeRequest;
import org.jboss.dna.graph.request.CreateWorkspaceRequest;
-import org.jboss.dna.graph.request.DeleteBranchRequest;
-import org.jboss.dna.graph.request.GetWorkspacesRequest;
import org.jboss.dna.graph.request.InvalidRequestException;
import org.jboss.dna.graph.request.InvalidWorkspaceException;
-import org.jboss.dna.graph.request.MoveBranchRequest;
import org.jboss.dna.graph.request.ReadAllChildrenRequest;
import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
import org.jboss.dna.graph.request.ReadBlockOfChildrenRequest;
import org.jboss.dna.graph.request.ReadBranchRequest;
-import org.jboss.dna.graph.request.ReadNextBlockOfChildrenRequest;
import org.jboss.dna.graph.request.ReadNodeRequest;
import org.jboss.dna.graph.request.ReadPropertyRequest;
-import org.jboss.dna.graph.request.RemovePropertiesRequest;
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.UpdatePropertiesRequest;
import org.jboss.dna.graph.request.VerifyWorkspaceRequest;
import org.jboss.dna.graph.request.CloneWorkspaceRequest.CloneConflictBehavior;
import org.jboss.dna.graph.request.CreateWorkspaceRequest.CreateConflictBehavior;
@@ -97,6 +93,13 @@
@NotThreadSafe
public class Graph {
+ protected static final Iterator<Property> EMPTY_PROPERTIES = new EmptyIterator<Property>();
+ protected static final Iterable<Property> NO_PROPERTIES = new Iterable<Property>() {
+ public final Iterator<Property> iterator() {
+ return EMPTY_PROPERTIES;
+ }
+ };
+
/**
* Create a graph instance that uses the supplied repository and {@link ExecutionContext context}.
*
@@ -157,8 +160,8 @@
private final String sourceName;
private final RepositoryConnectionFactory connectionFactory;
private final ExecutionContext context;
- private final RequestQueue requestQueue;
- private final Conjunction<Graph> nextGraph;
+ protected final RequestBuilder requests;
+ protected final Conjunction<Graph> nextGraph;
private Workspace currentWorkspace;
protected Graph( String sourceName,
@@ -175,7 +178,13 @@
return Graph.this;
}
};
- this.requestQueue = new GraphRequestQueue();
+ this.requests = new RequestBuilder() {
+ @Override
+ protected <T extends Request> T process( T request ) {
+ Graph.this.execute(request);
+ return request;
+ }
+ };
}
/**
@@ -207,16 +216,12 @@
return context;
}
- /*package*/RequestQueue queue() {
- return this.requestQueue;
- }
-
/**
* Obtain a connection to the source, execute the supplied request, and check the request for {@link Request#getError()
* errors}. If an error is found, then it is thrown (or wrapped by a {@link RepositorySourceException} if the error is not a
* {@link RuntimeException}.
* <p>
- * This method is called by one of the {@link RequestQueue} implementations.
+ * This method is called automatically when the {@link #requests request builder} creates each request.
* </p>
*
* @param request the request to be executed (may be a {@link CompositeRequest}.
@@ -314,9 +319,7 @@
* @return the set of workspace names; never null
*/
public Set<String> getWorkspaces() {
- GetWorkspacesRequest request = new GetWorkspacesRequest();
- this.requestQueue.submit(request);
- return request.getAvailableWorkspaceNames();
+ return requests.getWorkspaces().getAvailableWorkspaceNames();
}
/**
@@ -329,8 +332,7 @@
* workspace name but the source does not have a default workspace
*/
public Workspace useWorkspace( String workspaceName ) {
- VerifyWorkspaceRequest request = new VerifyWorkspaceRequest(workspaceName);
- requestQueue.submit(request); // will throw error if there is one ...
+ VerifyWorkspaceRequest request = requests.verifyWorkspace(workspaceName);
return setWorkspace(request.getActualWorkspaceName(), request.getActualLocationOfRoot());
}
@@ -349,8 +351,7 @@
* @see org.jboss.dna.graph.Graph.NameWorkspace#named(java.lang.String)
*/
public Workspace named( String workspaceName ) {
- CreateWorkspaceRequest request = new CreateWorkspaceRequest(workspaceName, CreateConflictBehavior.DO_NOT_CREATE);
- queue().submit(request); // will throw error if there is one ...
+ CreateWorkspaceRequest request = requests.createWorkspace(workspaceName, CreateConflictBehavior.DO_NOT_CREATE);
return setWorkspace(request.getActualWorkspaceName(), request.getActualLocationOfRoot());
}
@@ -360,9 +361,8 @@
* @see org.jboss.dna.graph.Graph.CreateWorkspace#namedSomethingLike(java.lang.String)
*/
public Workspace namedSomethingLike( String workspaceName ) {
- CreateWorkspaceRequest request = new CreateWorkspaceRequest(workspaceName,
- CreateConflictBehavior.CREATE_WITH_ADJUSTED_NAME);
- queue().submit(request); // will throw error if there is one ...
+ CreateWorkspaceRequest request = requests.createWorkspace(workspaceName,
+ CreateConflictBehavior.CREATE_WITH_ADJUSTED_NAME);
return setWorkspace(request.getActualWorkspaceName(), request.getActualLocationOfRoot());
}
@@ -379,11 +379,10 @@
* @see org.jboss.dna.graph.Graph.NameWorkspace#named(java.lang.String)
*/
public Workspace named( String nameOfWorkspaceToCreate ) {
- CloneWorkspaceRequest request = new CloneWorkspaceRequest(nameOfWorkspaceToClone,
- nameOfWorkspaceToCreate,
- CreateConflictBehavior.DO_NOT_CREATE,
- CloneConflictBehavior.DO_NOT_CLONE);
- queue().submit(request); // will throw error if there is one ...
+ CloneWorkspaceRequest request = requests.cloneWorkspace(nameOfWorkspaceToClone,
+ nameOfWorkspaceToCreate,
+ CreateConflictBehavior.DO_NOT_CREATE,
+ CloneConflictBehavior.DO_NOT_CLONE);
return setWorkspace(request.getActualWorkspaceName(), request.getActualLocationOfRoot());
}
@@ -393,12 +392,10 @@
* @see org.jboss.dna.graph.Graph.NameWorkspace#namedSomethingLike(java.lang.String)
*/
public Workspace namedSomethingLike( String nameOfWorkspaceToCreate ) {
- CloneWorkspaceRequest request = new CloneWorkspaceRequest(
- nameOfWorkspaceToClone,
- nameOfWorkspaceToCreate,
- CreateConflictBehavior.CREATE_WITH_ADJUSTED_NAME,
- CloneConflictBehavior.DO_NOT_CLONE);
- queue().submit(request); // will throw error if there is one ...
+ CloneWorkspaceRequest request = requests.cloneWorkspace(nameOfWorkspaceToClone,
+ nameOfWorkspaceToCreate,
+ CreateConflictBehavior.CREATE_WITH_ADJUSTED_NAME,
+ CloneConflictBehavior.DO_NOT_CLONE);
return setWorkspace(request.getActualWorkspaceName(), request.getActualLocationOfRoot());
}
};
@@ -419,7 +416,7 @@
* be moved
*/
public Move<Conjunction<Graph>> move( Node from ) {
- return new MoveAction<Conjunction<Graph>>(this.nextGraph, this.requestQueue, from.getLocation());
+ return move(from.getLocation());
}
/**
@@ -435,7 +432,17 @@
* be moved
*/
public Move<Conjunction<Graph>> move( Location from ) {
- return new MoveAction<Conjunction<Graph>>(this.nextGraph, this.requestQueue, from);
+ return new MoveAction<Conjunction<Graph>>(this.nextGraph, from) {
+ @Override
+ protected Conjunction<Graph> submit( Locations from,
+ Location into ) {
+ String workspaceName = getCurrentWorkspaceName();
+ do {
+ requests.moveBranch(from.getLocation(), into, workspaceName);
+ } while ((from = from.next()) != null);
+ return and();
+ }
+ };
}
/**
@@ -451,7 +458,7 @@
* be moved
*/
public Move<Conjunction<Graph>> move( String fromPath ) {
- return new MoveAction<Conjunction<Graph>>(this.nextGraph, this.requestQueue, Location.create(createPath(fromPath)));
+ return move(Location.create(createPath(fromPath)));
}
/**
@@ -467,7 +474,7 @@
* be moved
*/
public Move<Conjunction<Graph>> move( Path from ) {
- return new MoveAction<Conjunction<Graph>>(this.nextGraph, this.requestQueue, Location.create(from));
+ return move(Location.create(from));
}
/**
@@ -483,7 +490,7 @@
* be moved
*/
public Move<Conjunction<Graph>> move( UUID from ) {
- return new MoveAction<Conjunction<Graph>>(this.nextGraph, this.requestQueue, Location.create(from));
+ return move(Location.create(from));
}
/**
@@ -500,7 +507,7 @@
* be moved
*/
public Move<Conjunction<Graph>> move( Property idProperty ) {
- return new MoveAction<Conjunction<Graph>>(this.nextGraph, this.requestQueue, Location.create(idProperty));
+ return move(Location.create(idProperty));
}
/**
@@ -519,8 +526,7 @@
*/
public Move<Conjunction<Graph>> move( Property firstIdProperty,
Property... additionalIdProperties ) {
- return new MoveAction<Conjunction<Graph>>(this.nextGraph, this.requestQueue, Location.create(firstIdProperty,
- additionalIdProperties));
+ return move(Location.create(firstIdProperty, additionalIdProperties));
}
/**
@@ -536,7 +542,7 @@
* be copied
*/
public Copy<Graph> copy( Node from ) {
- return new CopyAction<Graph>(this, this.requestQueue, from.getLocation());
+ return copy(from.getLocation());
}
/**
@@ -552,7 +558,23 @@
* be copied
*/
public Copy<Graph> copy( Location from ) {
- return new CopyAction<Graph>(this, this.requestQueue, from);
+ return new CopyAction<Graph>(this, from) {
+ @Override
+ protected Graph submit( Locations from,
+ Location into,
+ Name childName ) {
+ String workspaceName = getCurrentWorkspaceName();
+ do {
+ requests.copyBranch(from.getLocation(),
+ workspaceName,
+ into,
+ workspaceName,
+ childName,
+ NodeConflictBehavior.APPEND);
+ } while ((from = from.next()) != null);
+ return and();
+ }
+ };
}
/**
@@ -568,7 +590,7 @@
* be copied
*/
public Copy<Graph> copy( String fromPath ) {
- return new CopyAction<Graph>(this, this.requestQueue, Location.create(createPath(fromPath)));
+ return copy(Location.create(createPath(fromPath)));
}
/**
@@ -584,7 +606,7 @@
* be copied
*/
public Copy<Graph> copy( Path from ) {
- return new CopyAction<Graph>(this, this.requestQueue, Location.create(from));
+ return copy(Location.create(from));
}
/**
@@ -600,7 +622,7 @@
* be copied
*/
public Copy<Graph> copy( UUID from ) {
- return new CopyAction<Graph>(this, this.requestQueue, Location.create(from));
+ return copy(Location.create(from));
}
/**
@@ -617,7 +639,7 @@
* be copied
*/
public Copy<Graph> copy( Property idProperty ) {
- return new CopyAction<Graph>(this, this.requestQueue, Location.create(idProperty));
+ return copy(Location.create(idProperty));
}
/**
@@ -636,7 +658,7 @@
*/
public Copy<Graph> copy( Property firstIdProperty,
Property... additionalIdProperties ) {
- return new CopyAction<Graph>(this, this.requestQueue, Location.create(firstIdProperty, additionalIdProperties));
+ return copy(Location.create(firstIdProperty, additionalIdProperties));
}
/**
@@ -646,7 +668,7 @@
* @return an object that may be used to start another request
*/
public Conjunction<Graph> delete( Node at ) {
- this.requestQueue.submit(new DeleteBranchRequest(at.getLocation(), getCurrentWorkspaceName()));
+ requests.deleteBranch(at.getLocation(), getCurrentWorkspaceName());
return nextGraph;
}
@@ -657,7 +679,7 @@
* @return an object that may be used to start another request
*/
public Conjunction<Graph> delete( Location at ) {
- this.requestQueue.submit(new DeleteBranchRequest(at, getCurrentWorkspaceName()));
+ requests.deleteBranch(at, getCurrentWorkspaceName());
return nextGraph;
}
@@ -668,8 +690,7 @@
* @return an object that may be used to start another request
*/
public Conjunction<Graph> delete( String atPath ) {
- this.requestQueue.submit(new DeleteBranchRequest(Location.create(createPath(atPath)), getCurrentWorkspaceName()));
- return nextGraph;
+ return delete(Location.create(createPath(atPath)));
}
/**
@@ -679,8 +700,7 @@
* @return an object that may be used to start another request
*/
public Conjunction<Graph> delete( Path at ) {
- this.requestQueue.submit(new DeleteBranchRequest(Location.create(at), getCurrentWorkspaceName()));
- return nextGraph;
+ return delete(Location.create(at));
}
/**
@@ -690,8 +710,7 @@
* @return an object that may be used to start another request
*/
public Conjunction<Graph> delete( UUID at ) {
- this.requestQueue.submit(new DeleteBranchRequest(Location.create(at), getCurrentWorkspaceName()));
- return nextGraph;
+ return delete(Location.create(at));
}
/**
@@ -702,8 +721,7 @@
* @return an object that may be used to start another request
*/
public Conjunction<Graph> delete( Property idProperty ) {
- this.requestQueue.submit(new DeleteBranchRequest(Location.create(idProperty), getCurrentWorkspaceName()));
- return nextGraph;
+ return delete(Location.create(idProperty));
}
/**
@@ -716,9 +734,7 @@
*/
public Conjunction<Graph> delete( Property firstIdProperty,
Property... additionalIdProperties ) {
- this.requestQueue.submit(new DeleteBranchRequest(Location.create(firstIdProperty, additionalIdProperties),
- getCurrentWorkspaceName()));
- return nextGraph;
+ return delete(Location.create(firstIdProperty, additionalIdProperties));
}
/**
@@ -758,7 +774,7 @@
private final List<Property> properties = new LinkedList<Property>();
public CreateAt<Graph> and( UUID uuid ) {
- PropertyFactory factory = queue().getGraph().getContext().getPropertyFactory();
+ PropertyFactory factory = getContext().getPropertyFactory();
properties.add(factory.create(DnaLexicon.UUID, uuid));
return this;
}
@@ -777,7 +793,7 @@
public CreateAt<Graph> and( String name,
Object... values ) {
- ExecutionContext context = queue().getGraph().getContext();
+ ExecutionContext context = getContext();
PropertyFactory factory = context.getPropertyFactory();
NameFactory nameFactory = context.getValueFactories().getNameFactory();
properties.add(factory.create(nameFactory.create(name), values));
@@ -786,7 +802,7 @@
public CreateAt<Graph> and( Name name,
Object... values ) {
- ExecutionContext context = queue().getGraph().getContext();
+ ExecutionContext context = getContext();
PropertyFactory factory = context.getPropertyFactory();
properties.add(factory.create(name, values));
return this;
@@ -830,20 +846,18 @@
public Location getLocation() {
Location parentLoc = Location.create(parent);
- CreateNodeRequest request = new CreateNodeRequest(parentLoc, workspaceName, childName, this.properties);
- queue().submit(request); // immediate
+ CreateNodeRequest request = requests.createNode(parentLoc, workspaceName, childName, this.properties.iterator());
return request.getActualLocationOfNode();
}
public Node getNode() {
Location parentLoc = Location.create(parent);
- CreateNodeRequest request = new CreateNodeRequest(parentLoc, workspaceName, childName, this.properties);
- queue().submit(request); // immediate
+ CreateNodeRequest request = requests.createNode(parentLoc, workspaceName, childName, this.properties.iterator());
return getNodeAt(request.getActualLocationOfNode());
}
public Graph and() {
- queue().submit(new CreateNodeRequest(Location.create(parent), workspaceName, childName, this.properties));
+ requests.createNode(Location.create(parent), workspaceName, childName, this.properties.iterator());
return Graph.this;
}
};
@@ -864,7 +878,7 @@
Path at = createPath(atPath);
Path parent = at.getParent();
Name child = at.getLastSegment().getName();
- this.requestQueue.submit(new CreateNodeRequest(Location.create(parent), getCurrentWorkspaceName(), child));
+ requests.createNode(Location.create(parent), getCurrentWorkspaceName(), child, EMPTY_PROPERTIES);
return nextGraph;
}
@@ -882,7 +896,7 @@
public Conjunction<Graph> create( final Path at ) {
Path parent = at.getParent();
Name child = at.getLastSegment().getName();
- this.requestQueue.submit(new CreateNodeRequest(Location.create(parent), getCurrentWorkspaceName(), child));
+ requests.createNode(Location.create(parent), getCurrentWorkspaceName(), child, EMPTY_PROPERTIES);
return nextGraph;
}
@@ -903,7 +917,7 @@
Path at = createPath(atPath);
Path parent = at.getParent();
Name child = at.getLastSegment().getName();
- this.requestQueue.submit(new CreateNodeRequest(Location.create(parent), getCurrentWorkspaceName(), child, properties));
+ requests.createNode(Location.create(parent), getCurrentWorkspaceName(), child, properties);
return nextGraph;
}
@@ -924,7 +938,7 @@
CheckArg.isNotNull(at, "at");
Path parent = at.getParent();
Name child = at.getLastSegment().getName();
- this.requestQueue.submit(new CreateNodeRequest(Location.create(parent), getCurrentWorkspaceName(), child, properties));
+ requests.createNode(Location.create(parent), getCurrentWorkspaceName(), child, properties);
return nextGraph;
}
@@ -945,7 +959,7 @@
CheckArg.isNotNull(at, "at");
Path parent = at.getParent();
Name child = at.getLastSegment().getName();
- this.requestQueue.submit(new CreateNodeRequest(Location.create(parent), getCurrentWorkspaceName(), child, properties));
+ requests.createNode(Location.create(parent), getCurrentWorkspaceName(), child, properties.iterator());
return nextGraph;
}
@@ -964,27 +978,24 @@
final NameFactory nameFactory = getContext().getValueFactories().getNameFactory();
CheckArg.isNotNull(parent, "parent");
return new CreateNode<Conjunction<Graph>>() {
- @SuppressWarnings( "synthetic-access" )
public Conjunction<Graph> node( String name,
Property... properties ) {
Name child = nameFactory.create(name);
- requestQueue.submit(new CreateNodeRequest(parent, getCurrentWorkspaceName(), child, properties));
+ requests.createNode(parent, getCurrentWorkspaceName(), child, properties);
return nextGraph;
}
- @SuppressWarnings( "synthetic-access" )
public Conjunction<Graph> node( String name,
Iterator<Property> properties ) {
Name child = nameFactory.create(name);
- requestQueue.submit(new CreateNodeRequest(parent, getCurrentWorkspaceName(), child, properties));
+ requests.createNode(parent, getCurrentWorkspaceName(), child, properties);
return nextGraph;
}
- @SuppressWarnings( "synthetic-access" )
public Conjunction<Graph> node( String name,
Iterable<Property> properties ) {
Name child = nameFactory.create(name);
- requestQueue.submit(new CreateNodeRequest(parent, getCurrentWorkspaceName(), child, properties));
+ requests.createNode(parent, getCurrentWorkspaceName(), child, properties.iterator());
return nextGraph;
}
};
@@ -998,10 +1009,8 @@
*/
public On<Conjunction<Graph>> set( final Property... properties ) {
return new On<Conjunction<Graph>>() {
- @SuppressWarnings( "synthetic-access" )
public Conjunction<Graph> on( Location location ) {
- UpdatePropertiesRequest request = new UpdatePropertiesRequest(location, getCurrentWorkspaceName(), properties);
- queue().submit(request);
+ requests.setProperties(location, getCurrentWorkspaceName(), properties);
return nextGraph;
}
@@ -1053,7 +1062,6 @@
*/
public SetValues<Conjunction<Graph>> set( final Name propertyName ) {
return new SetValues<Conjunction<Graph>>() {
- @SuppressWarnings( "synthetic-access" )
public SetValuesTo<Conjunction<Graph>> on( final Location location ) {
return new SetValuesTo<Conjunction<Graph>>() {
public Conjunction<Graph> to( Node value ) {
@@ -1063,17 +1071,13 @@
public Conjunction<Graph> to( Location value ) {
Reference ref = (Reference)convertReferenceValue(value);
Property property = getContext().getPropertyFactory().create(propertyName, ref);
- UpdatePropertiesRequest request = new UpdatePropertiesRequest(location, getCurrentWorkspaceName(),
- property);
- queue().submit(request);
+ requests.setProperty(location, getCurrentWorkspaceName(), property);
return nextGraph;
}
protected Conjunction<Graph> toValue( Object value ) {
Property property = getContext().getPropertyFactory().create(propertyName, value);
- UpdatePropertiesRequest request = new UpdatePropertiesRequest(location, getCurrentWorkspaceName(),
- property);
- queue().submit(request);
+ requests.setProperty(location, getCurrentWorkspaceName(), property);
return nextGraph;
}
@@ -1160,9 +1164,7 @@
public Conjunction<Graph> to( Object value ) {
value = convertReferenceValue(value);
Property property = getContext().getPropertyFactory().create(propertyName, value);
- UpdatePropertiesRequest request = new UpdatePropertiesRequest(location, getCurrentWorkspaceName(),
- property);
- queue().submit(request);
+ requests.setProperty(location, getCurrentWorkspaceName(), property);
return nextGraph;
}
@@ -1173,9 +1175,7 @@
otherValues[i] = convertReferenceValue(otherValues[i]);
}
Property property = getContext().getPropertyFactory().create(propertyName, firstValue, otherValues);
- UpdatePropertiesRequest request = new UpdatePropertiesRequest(location, getCurrentWorkspaceName(),
- property);
- queue().submit(request);
+ requests.setProperty(location, getCurrentWorkspaceName(), property);
return nextGraph;
}
@@ -1186,9 +1186,7 @@
valueList.add(value);
}
Property property = getContext().getPropertyFactory().create(propertyName, valueList);
- UpdatePropertiesRequest request = new UpdatePropertiesRequest(location, getCurrentWorkspaceName(),
- property);
- queue().submit(request);
+ requests.setProperty(location, getCurrentWorkspaceName(), property);
return nextGraph;
}
@@ -1199,9 +1197,7 @@
valueList.add(value);
}
Property property = getContext().getPropertyFactory().create(propertyName, valueList);
- UpdatePropertiesRequest request = new UpdatePropertiesRequest(location, getCurrentWorkspaceName(),
- property);
- queue().submit(request);
+ requests.setProperty(location, getCurrentWorkspaceName(), property);
return nextGraph;
}
};
@@ -1368,10 +1364,8 @@
*/
public On<Conjunction<Graph>> remove( final Name... propertyNames ) {
return new On<Conjunction<Graph>>() {
- @SuppressWarnings( "synthetic-access" )
public Conjunction<Graph> on( Location location ) {
- RemovePropertiesRequest request = new RemovePropertiesRequest(location, getCurrentWorkspaceName(), propertyNames);
- queue().submit(request);
+ requests.removeProperties(location, getCurrentWorkspaceName(), propertyNames);
return nextGraph;
}
@@ -1408,17 +1402,16 @@
* @param propertyNames the names of the properties to be removed
* @return the remove request object that should be used to specify the node from which the properties are to be removed.
*/
- public On<Conjunction<Graph>> remove( String... propertyNames ) {
+ public On<Conjunction<Graph>> remove( final String... propertyNames ) {
NameFactory nameFactory = getContext().getValueFactories().getNameFactory();
- final List<Name> names = new LinkedList<Name>();
- for (String propertyName : propertyNames) {
- names.add(nameFactory.create(propertyName));
+ int number = propertyNames.length;
+ final Name[] names = new Name[number];
+ for (int i = 0; i != number; ++i) {
+ names[i] = nameFactory.create(propertyNames[i]);
}
return new On<Conjunction<Graph>>() {
- @SuppressWarnings( "synthetic-access" )
public Conjunction<Graph> on( Location location ) {
- RemovePropertiesRequest request = new RemovePropertiesRequest(location, getCurrentWorkspaceName(), names);
- queue().submit(request);
+ requests.removeProperties(location, getCurrentWorkspaceName(), names);
return nextGraph;
}
@@ -1458,9 +1451,7 @@
public On<Collection<Property>> getProperties() {
return new On<Collection<Property>>() {
public Collection<Property> on( Location location ) {
- ReadAllPropertiesRequest request = new ReadAllPropertiesRequest(location, getCurrentWorkspaceName());
- queue().submit(request);
- return request.getProperties();
+ return requests.readAllProperties(location, getCurrentWorkspaceName()).getProperties();
}
public Collection<Property> on( String path ) {
@@ -1500,9 +1491,7 @@
public On<Map<Name, Property>> getPropertiesByName() {
return new On<Map<Name, Property>>() {
public Map<Name, Property> on( Location location ) {
- ReadAllPropertiesRequest request = new ReadAllPropertiesRequest(location, getCurrentWorkspaceName());
- queue().submit(request);
- return request.getPropertiesByName();
+ return requests.readAllProperties(location, getCurrentWorkspaceName()).getPropertiesByName();
}
public Map<Name, Property> on( String path ) {
@@ -1567,9 +1556,7 @@
}
public List<Location> of( Location at ) {
- ReadAllChildrenRequest request = new ReadAllChildrenRequest(at, getCurrentWorkspaceName());
- queue().submit(request);
- return request.getChildren();
+ return requests.readAllChildren(at, getCurrentWorkspaceName()).getChildren();
}
public BlockOfChildren<List<Location>> inBlockOf( final int blockSize ) {
@@ -1598,21 +1585,15 @@
}
public List<Location> under( Location at ) {
- ReadBlockOfChildrenRequest request = new ReadBlockOfChildrenRequest(at,
- getCurrentWorkspaceName(),
- startingIndex, blockSize);
- queue().submit(request);
- return request.getChildren();
+ return requests.readBlockOfChildren(at, getCurrentWorkspaceName(), startingIndex, blockSize)
+ .getChildren();
}
};
}
public List<Location> startingAfter( final Location previousSibling ) {
- ReadNextBlockOfChildrenRequest request = new ReadNextBlockOfChildrenRequest(previousSibling,
- getCurrentWorkspaceName(),
- blockSize);
- queue().submit(request);
- return request.getChildren();
+ return requests.readNextBlockOfChildren(previousSibling, getCurrentWorkspaceName(), blockSize)
+ .getChildren();
}
public List<Location> startingAfter( String pathOfPreviousSibling ) {
@@ -1688,9 +1669,7 @@
}
public Property on( Location at ) {
- ReadPropertyRequest request = new ReadPropertyRequest(at, getCurrentWorkspaceName(), name);
- queue().submit(request);
- return request.getProperty();
+ return requests.readProperty(at, getCurrentWorkspaceName(), name).getProperty();
}
};
}
@@ -1712,9 +1691,7 @@
* @return the node that is read from the repository
*/
public Node getNodeAt( Location location ) {
- ReadNodeRequest request = new ReadNodeRequest(location, getCurrentWorkspaceName());
- this.requestQueue.submit(request);
- return new GraphNode(request);
+ return new GraphNode(requests.readNode(location, getCurrentWorkspaceName()));
}
/**
@@ -1794,9 +1771,7 @@
public At<Subgraph> getSubgraphOfDepth( final int depth ) {
return new At<Subgraph>() {
public Subgraph at( Location location ) {
- ReadBranchRequest request = new ReadBranchRequest(location, getCurrentWorkspaceName(), depth);
- queue().submit(request);
- return new SubgraphResults(request);
+ return new SubgraphResults(requests.readBranch(location, getCurrentWorkspaceName(), depth));
}
public Subgraph at( String path ) {
@@ -1868,7 +1843,6 @@
return into(Location.create(uuid));
}
- @SuppressWarnings( "synthetic-access" )
public Conjunction<Graph> into( Location at ) throws IOException, SAXException {
GraphImporter importer = new GraphImporter(Graph.this);
importer.importXml(uri, at, skipRootElement).execute(); // 'importXml' creates and uses a new batch
@@ -1925,7 +1899,7 @@
* @see Results
*/
public Batch batch() {
- return new Batch(new LinkedList<Request>());
+ return new Batch(null);
}
/**
@@ -1934,14 +1908,14 @@
* {@link #getSourceName() repository source}. The {@link Results results} are not available until the {@link Batch#execute()}
* method is invoked.
*
- * @param queue the queue where all batched requests should be placed
+ * @param builder the request builder that should be used; may not be null
* @return the batch object used to build and accumulate multiple requests and to submit them all for processing at once.
* @see Batch#execute()
* @see Results
*/
- public Batch batch( LinkedList<Request> queue ) {
- CheckArg.isNotNull(queue, "queue");
- return new Batch(queue);
+ public Batch batch( BatchRequestBuilder builder ) {
+ CheckArg.isNotNull(builder, "builder");
+ return new Batch(builder);
}
/**
@@ -1953,13 +1927,13 @@
*/
@Immutable
public final class Batch implements Executable<Node> {
- protected final CompositingRequestQueue requestQueue;
+ protected final BatchRequestBuilder requestQueue;
protected final BatchConjunction nextRequests;
protected final String workspaceName;
protected boolean executed = false;
- /*package*/Batch( LinkedList<Request> queue ) {
- this.requestQueue = new CompositingRequestQueue(queue);
+ /*package*/Batch( BatchRequestBuilder builder ) {
+ this.requestQueue = builder != null ? builder : new BatchRequestBuilder();
this.workspaceName = Graph.this.getCurrentWorkspaceName();
this.nextRequests = new BatchConjunction() {
public Batch and() {
@@ -1967,8 +1941,7 @@
}
public Results execute() {
- executed = true;
- return Batch.this.requestQueue.execute();
+ return Batch.this.execute();
}
};
}
@@ -1988,7 +1961,7 @@
* @return true if there are some requests in this batch that need to be executed, or false execution is not required
*/
public boolean isExecuteRequired() {
- return !executed || requestQueue.size() != 0;
+ return !executed || requestQueue.hasRequests();
}
/**
@@ -2028,8 +2001,7 @@
* to be moved
*/
public Move<BatchConjunction> move( Node from ) {
- assertNotExecuted();
- return new MoveAction<BatchConjunction>(this.nextRequests, this.requestQueue, from.getLocation());
+ return move(from.getLocation());
}
/**
@@ -2044,9 +2016,19 @@
* @return the object that can be used to specify addition nodes to be moved or the location of the node where the node is
* to be moved
*/
- public Move<BatchConjunction> move( Location from ) {
+ public final Move<BatchConjunction> move( Location from ) {
assertNotExecuted();
- return new MoveAction<BatchConjunction>(this.nextRequests, this.requestQueue, from);
+ return new MoveAction<BatchConjunction>(this.nextRequests, from) {
+ @Override
+ protected BatchConjunction submit( Locations from,
+ Location into ) {
+ String workspaceName = getCurrentWorkspaceName();
+ do {
+ requestQueue.moveBranch(from.getLocation(), into, workspaceName);
+ } while ((from = from.next()) != null);
+ return and();
+ }
+ };
}
/**
@@ -2062,8 +2044,7 @@
* to be moved
*/
public Move<BatchConjunction> move( String fromPath ) {
- assertNotExecuted();
- return new MoveAction<BatchConjunction>(this.nextRequests, this.requestQueue, Location.create(createPath(fromPath)));
+ return move(Location.create(createPath(fromPath)));
}
/**
@@ -2079,8 +2060,7 @@
* to be moved
*/
public Move<BatchConjunction> move( Path from ) {
- assertNotExecuted();
- return new MoveAction<BatchConjunction>(this.nextRequests, this.requestQueue, Location.create(from));
+ return move(Location.create(from));
}
/**
@@ -2096,8 +2076,7 @@
* to be moved
*/
public Move<BatchConjunction> move( UUID from ) {
- assertNotExecuted();
- return new MoveAction<BatchConjunction>(this.nextRequests, this.requestQueue, Location.create(from));
+ return move(Location.create(from));
}
/**
@@ -2114,8 +2093,7 @@
* to be moved
*/
public Move<BatchConjunction> move( Property idProperty ) {
- assertNotExecuted();
- return new MoveAction<BatchConjunction>(this.nextRequests, this.requestQueue, Location.create(idProperty));
+ return move(Location.create(idProperty));
}
/**
@@ -2134,9 +2112,7 @@
*/
public Move<BatchConjunction> move( Property firstIdProperty,
Property... additionalIdProperties ) {
- assertNotExecuted();
- return new MoveAction<BatchConjunction>(this.nextRequests, this.requestQueue, Location.create(firstIdProperty,
- additionalIdProperties));
+ return move(Location.create(firstIdProperty, additionalIdProperties));
}
/**
@@ -2153,8 +2129,7 @@
* to be moved
*/
public Move<BatchConjunction> move( Iterable<Property> idProperties ) {
- assertNotExecuted();
- return new MoveAction<BatchConjunction>(this.nextRequests, this.requestQueue, Location.create(idProperties));
+ return move(Location.create(idProperties));
}
/**
@@ -2170,8 +2145,7 @@
* is to be copied
*/
public Copy<BatchConjunction> copy( Node from ) {
- assertNotExecuted();
- return new CopyAction<BatchConjunction>(nextRequests, this.requestQueue, from.getLocation());
+ return copy(from.getLocation());
}
/**
@@ -2188,7 +2162,18 @@
*/
public Copy<BatchConjunction> copy( Location from ) {
assertNotExecuted();
- return new CopyAction<BatchConjunction>(nextRequests, this.requestQueue, from);
+ return new CopyAction<BatchConjunction>(this.nextRequests, from) {
+ @Override
+ protected BatchConjunction submit( Locations from,
+ Location into,
+ Name copyName ) {
+ String workspaceName = getCurrentWorkspaceName();
+ do {
+ requestQueue.copyBranch(from.getLocation(), workspaceName, into, workspaceName, copyName);
+ } while ((from = from.next()) != null);
+ return and();
+ }
+ };
}
/**
@@ -2204,8 +2189,7 @@
* is to be copied
*/
public Copy<BatchConjunction> copy( String fromPath ) {
- assertNotExecuted();
- return new CopyAction<BatchConjunction>(nextRequests, this.requestQueue, Location.create(createPath(fromPath)));
+ return copy(Location.create(createPath(fromPath)));
}
/**
@@ -2221,8 +2205,7 @@
* is to be copied
*/
public Copy<BatchConjunction> copy( Path from ) {
- assertNotExecuted();
- return new CopyAction<BatchConjunction>(nextRequests, this.requestQueue, Location.create(from));
+ return copy(Location.create(from));
}
/**
@@ -2238,8 +2221,7 @@
* is to be copied
*/
public Copy<BatchConjunction> copy( UUID from ) {
- assertNotExecuted();
- return new CopyAction<BatchConjunction>(nextRequests, this.requestQueue, Location.create(from));
+ return copy(Location.create(from));
}
/**
@@ -2256,8 +2238,7 @@
* is to be copied
*/
public Copy<BatchConjunction> copy( Property idProperty ) {
- assertNotExecuted();
- return new CopyAction<BatchConjunction>(nextRequests, this.requestQueue, Location.create(idProperty));
+ return copy(Location.create(idProperty));
}
/**
@@ -2276,9 +2257,7 @@
*/
public Copy<BatchConjunction> copy( Property firstIdProperty,
Property... additionalIdProperties ) {
- assertNotExecuted();
- return new CopyAction<BatchConjunction>(nextRequests, this.requestQueue, Location.create(firstIdProperty,
- additionalIdProperties));
+ return copy(Location.create(firstIdProperty, additionalIdProperties));
}
/**
@@ -2295,8 +2274,7 @@
* is to be copied
*/
public Copy<BatchConjunction> copy( Iterable<Property> idProperties ) {
- assertNotExecuted();
- return new CopyAction<BatchConjunction>(nextRequests, this.requestQueue, Location.create(idProperties));
+ return copy(Location.create(idProperties));
}
/**
@@ -2310,9 +2288,7 @@
* @return an object that may be used to start another request
*/
public BatchConjunction delete( Node at ) {
- assertNotExecuted();
- this.requestQueue.submit(new DeleteBranchRequest(at.getLocation(), getCurrentWorkspaceName()));
- return nextRequests;
+ return delete(at.getLocation());
}
/**
@@ -2327,7 +2303,7 @@
*/
public BatchConjunction delete( Location at ) {
assertNotExecuted();
- this.requestQueue.submit(new DeleteBranchRequest(at, getCurrentWorkspaceName()));
+ this.requestQueue.deleteBranch(at, getCurrentWorkspaceName());
return nextRequests;
}
@@ -2342,9 +2318,7 @@
* @return an object that may be used to start another request
*/
public BatchConjunction delete( String atPath ) {
- assertNotExecuted();
- this.requestQueue.submit(new DeleteBranchRequest(Location.create(createPath(atPath)), getCurrentWorkspaceName()));
- return nextRequests;
+ return delete(Location.create(createPath(atPath)));
}
/**
@@ -2358,9 +2332,7 @@
* @return an object that may be used to start another request
*/
public BatchConjunction delete( Path at ) {
- assertNotExecuted();
- this.requestQueue.submit(new DeleteBranchRequest(Location.create(at), getCurrentWorkspaceName()));
- return nextRequests;
+ return delete(Location.create(at));
}
/**
@@ -2374,9 +2346,7 @@
* @return an object that may be used to start another request
*/
public BatchConjunction delete( UUID at ) {
- assertNotExecuted();
- this.requestQueue.submit(new DeleteBranchRequest(Location.create(at), getCurrentWorkspaceName()));
- return nextRequests;
+ return delete(Location.create(at));
}
/**
@@ -2390,9 +2360,7 @@
* @return an object that may be used to start another request
*/
public BatchConjunction delete( Property idProperty ) {
- assertNotExecuted();
- this.requestQueue.submit(new DeleteBranchRequest(Location.create(idProperty), getCurrentWorkspaceName()));
- return nextRequests;
+ return delete(Location.create(idProperty));
}
/**
@@ -2409,10 +2377,7 @@
*/
public BatchConjunction delete( Property firstIdProperty,
Property... additionalIdProperties ) {
- assertNotExecuted();
- this.requestQueue.submit(new DeleteBranchRequest(Location.create(firstIdProperty, additionalIdProperties),
- getCurrentWorkspaceName()));
- return nextRequests;
+ return delete(Location.create(firstIdProperty, additionalIdProperties));
}
/**
@@ -2427,9 +2392,7 @@
* @return an object that may be used to start another request
*/
public BatchConjunction delete( Iterable<Property> idProperties ) {
- assertNotExecuted();
- this.requestQueue.submit(new DeleteBranchRequest(Location.create(idProperties), getCurrentWorkspaceName()));
- return nextRequests;
+ return delete(Location.create(idProperties));
}
/**
@@ -2444,11 +2407,7 @@
* node where the node is to be created
*/
public Create<Batch> create( String atPath ) {
- assertNotExecuted();
- Path at = createPath(atPath);
- Path parent = at.getParent();
- Name name = at.getLastSegment().getName();
- return new CreateAction<Batch>(this, requestQueue, Location.create(parent), getCurrentWorkspaceName(), name);
+ return create(createPath(atPath));
}
/**
@@ -2465,11 +2424,7 @@
*/
public Create<Batch> create( String atPath,
Property property ) {
- assertNotExecuted();
- Path at = createPath(atPath);
- Path parent = at.getParent();
- Name name = at.getLastSegment().getName();
- return new CreateAction<Batch>(this, requestQueue, Location.create(parent), getCurrentWorkspaceName(), name).with(property);
+ return create(createPath(atPath)).with(property);
}
/**
@@ -2488,12 +2443,7 @@
public Create<Batch> create( String atPath,
Property firstProperty,
Property... additionalProperties ) {
- assertNotExecuted();
- Path at = createPath(atPath);
- Path parent = at.getParent();
- Name name = at.getLastSegment().getName();
- return new CreateAction<Batch>(this, requestQueue, Location.create(parent), getCurrentWorkspaceName(), name).with(firstProperty,
- additionalProperties);
+ return create(createPath(atPath)).with(firstProperty, additionalProperties);
}
/**
@@ -2507,14 +2457,38 @@
* @return the object that can be used to specify addition properties for the new node to be copied or the location of the
* node where the node is to be created
*/
- public Create<Batch> create( Path at ) {
+ public final Create<Batch> create( Path at ) {
assertNotExecuted();
CheckArg.isNotNull(at, "at");
Path parent = at.getParent();
Name name = at.getLastSegment().getName();
- return new CreateAction<Batch>(this, requestQueue, Location.create(parent), getCurrentWorkspaceName(), name);
+ return create(Location.create(parent), name);
}
+ protected final CreateAction<Batch> create( Location parent,
+ Name child ) {
+ return new CreateAction<Batch>(this, parent, getCurrentWorkspaceName(), child) {
+ @Override
+ protected Batch submit( Location parent,
+ String workspaceName,
+ Name childName,
+ Collection<Property> properties ) {
+ requestQueue.createNode(parent, workspaceName, childName, properties.iterator());
+ return Batch.this;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.Graph.Executable#execute()
+ */
+ public Results execute() {
+ and();
+ return Batch.this.execute();
+ }
+ };
+ }
+
/**
* Begin the request to create a node located at the supplied path.
* <p>
@@ -2529,12 +2503,7 @@
*/
public Create<Batch> create( Path at,
Iterable<Property> properties ) {
- assertNotExecuted();
- CheckArg.isNotNull(at, "at");
- Path parent = at.getParent();
- Name name = at.getLastSegment().getName();
- CreateAction<Batch> action = new CreateAction<Batch>(this, requestQueue, Location.create(parent),
- getCurrentWorkspaceName(), name);
+ Create<Batch> action = create(at);
for (Property property : properties) {
action.and(property);
}
@@ -2555,11 +2524,7 @@
*/
public Create<Batch> create( Path at,
Property property ) {
- assertNotExecuted();
- CheckArg.isNotNull(at, "at");
- Path parent = at.getParent();
- Name name = at.getLastSegment().getName();
- return new CreateAction<Batch>(this, requestQueue, Location.create(parent), getCurrentWorkspaceName(), name).with(property);
+ return create(at).with(property);
}
/**
@@ -2578,12 +2543,7 @@
public Create<Batch> create( Path at,
Property firstProperty,
Property... additionalProperties ) {
- assertNotExecuted();
- CheckArg.isNotNull(at, "at");
- Path parent = at.getParent();
- Name name = at.getLastSegment().getName();
- return new CreateAction<Batch>(this, requestQueue, Location.create(parent), getCurrentWorkspaceName(), name).with(firstProperty,
- additionalProperties);
+ return create(at).with(firstProperty, additionalProperties);
}
/**
@@ -2595,7 +2555,14 @@
*/
public CreateNodeNamed<Batch> createUnder( Location parent ) {
CheckArg.isNotNull(parent, "parent");
- return new CreateNodeNamedAction<Batch>(this, requestQueue, parent, getCurrentWorkspaceName());
+ return new CreateNodeNamedAction<Batch>(this, parent) {
+ @Override
+ protected CreateAction<Batch> createWith( Batch batch,
+ Location parent,
+ Name childName ) {
+ return Batch.this.create(parent, childName);
+ }
+ };
}
/**
@@ -2607,8 +2574,7 @@
public On<BatchConjunction> set( final Property... properties ) {
return new On<BatchConjunction>() {
public BatchConjunction on( Location location ) {
- UpdatePropertiesRequest request = new UpdatePropertiesRequest(location, getCurrentWorkspaceName(), properties);
- requestQueue.submit(request);
+ requestQueue.setProperties(location, getCurrentWorkspaceName(), properties);
return nextRequests;
}
@@ -2669,17 +2635,13 @@
public BatchConjunction to( Location value ) {
Reference ref = (Reference)convertReferenceValue(value);
Property property = getContext().getPropertyFactory().create(propertyName, ref);
- UpdatePropertiesRequest request = new UpdatePropertiesRequest(location, getCurrentWorkspaceName(),
- property);
- requestQueue.submit(request);
+ requestQueue.setProperty(location, getCurrentWorkspaceName(), property);
return nextRequests;
}
protected BatchConjunction toValue( Object value ) {
Property property = getContext().getPropertyFactory().create(propertyName, value);
- UpdatePropertiesRequest request = new UpdatePropertiesRequest(location, getCurrentWorkspaceName(),
- property);
- requestQueue.submit(request);
+ requestQueue.setProperty(location, getCurrentWorkspaceName(), property);
return nextRequests;
}
@@ -2766,9 +2728,7 @@
public BatchConjunction to( Object value ) {
value = convertReferenceValue(value);
Property property = getContext().getPropertyFactory().create(propertyName, value);
- UpdatePropertiesRequest request = new UpdatePropertiesRequest(location, getCurrentWorkspaceName(),
- property);
- requestQueue.submit(request);
+ requestQueue.setProperty(location, getCurrentWorkspaceName(), property);
return nextRequests;
}
@@ -2779,9 +2739,7 @@
otherValues[i] = convertReferenceValue(otherValues[i]);
}
Property property = getContext().getPropertyFactory().create(propertyName, firstValue, otherValues);
- UpdatePropertiesRequest request = new UpdatePropertiesRequest(location, getCurrentWorkspaceName(),
- property);
- requestQueue.submit(request);
+ requestQueue.setProperty(location, getCurrentWorkspaceName(), property);
return nextRequests;
}
@@ -2792,9 +2750,7 @@
valueList.add(value);
}
Property property = getContext().getPropertyFactory().create(propertyName, valueList);
- UpdatePropertiesRequest request = new UpdatePropertiesRequest(location, getCurrentWorkspaceName(),
- property);
- requestQueue.submit(request);
+ requestQueue.setProperty(location, getCurrentWorkspaceName(), property);
return nextRequests;
}
@@ -2805,9 +2761,7 @@
valueList.add(value);
}
Property property = getContext().getPropertyFactory().create(propertyName, valueList);
- UpdatePropertiesRequest request = new UpdatePropertiesRequest(location, getCurrentWorkspaceName(),
- property);
- requestQueue.submit(request);
+ requestQueue.setProperty(location, getCurrentWorkspaceName(), property);
return nextRequests;
}
@@ -2976,9 +2930,7 @@
public On<BatchConjunction> remove( final Name... propertyNames ) {
return new On<BatchConjunction>() {
public BatchConjunction on( Location location ) {
- RemovePropertiesRequest request = new RemovePropertiesRequest(location, getCurrentWorkspaceName(),
- propertyNames);
- requestQueue.submit(request);
+ requestQueue.removeProperties(location, getCurrentWorkspaceName(), propertyNames);
return nextRequests;
}
@@ -3017,14 +2969,14 @@
*/
public On<BatchConjunction> remove( String... propertyNames ) {
NameFactory nameFactory = getContext().getValueFactories().getNameFactory();
- final List<Name> names = new LinkedList<Name>();
- for (String propertyName : propertyNames) {
- names.add(nameFactory.create(propertyName));
+ int number = propertyNames.length;
+ final Name[] names = new Name[number];
+ for (int i = 0; i != number; ++i) {
+ names[i] = nameFactory.create(propertyNames[i]);
}
return new On<BatchConjunction>() {
public BatchConjunction on( Location location ) {
- RemovePropertiesRequest request = new RemovePropertiesRequest(location, getCurrentWorkspaceName(), names);
- requestQueue.submit(request);
+ requestQueue.removeProperties(location, getCurrentWorkspaceName(), names);
return nextRequests;
}
@@ -3081,8 +3033,7 @@
*/
public BatchConjunction read( Location location ) {
assertNotExecuted();
- ReadNodeRequest request = new ReadNodeRequest(location, getCurrentWorkspaceName());
- requestQueue.submit(request);
+ requestQueue.readNode(location, getCurrentWorkspaceName());
return nextRequests;
}
@@ -3216,8 +3167,7 @@
}
public BatchConjunction on( Location at ) {
- ReadPropertyRequest request = new ReadPropertyRequest(at, getCurrentWorkspaceName(), name);
- requestQueue.submit(request);
+ requestQueue.readProperty(at, getCurrentWorkspaceName(), name);
return Batch.this.nextRequests;
}
};
@@ -3237,8 +3187,7 @@
assertNotExecuted();
return new On<BatchConjunction>() {
public BatchConjunction on( Location location ) {
- ReadAllPropertiesRequest request = new ReadAllPropertiesRequest(location, getCurrentWorkspaceName());
- requestQueue.submit(request);
+ requestQueue.readAllProperties(location, getCurrentWorkspaceName());
return Batch.this.nextRequests;
}
@@ -3308,8 +3257,7 @@
}
public BatchConjunction of( Location at ) {
- ReadAllChildrenRequest request = new ReadAllChildrenRequest(at, getCurrentWorkspaceName());
- requestQueue.submit(request);
+ requestQueue.readAllChildren(at, getCurrentWorkspaceName());
return Batch.this.nextRequests;
}
};
@@ -3330,8 +3278,7 @@
assertNotExecuted();
return new At<BatchConjunction>() {
public BatchConjunction at( Location location ) {
- ReadBranchRequest request = new ReadBranchRequest(location, getCurrentWorkspaceName(), depth);
- requestQueue.submit(request);
+ requestQueue.readBranch(location, getCurrentWorkspaceName());
return Batch.this.nextRequests;
}
@@ -3368,7 +3315,17 @@
* @see org.jboss.dna.graph.Graph.Executable#execute()
*/
public Results execute() {
- return this.requestQueue.execute();
+ executed = true;
+ Request request = requestQueue.pop();
+ if (request == null) {
+ return new BatchResults();
+ }
+ Graph.this.execute(request);
+ if (request instanceof CompositeRequest) {
+ CompositeRequest composite = (CompositeRequest)request;
+ return new BatchResults(composite.getRequests());
+ }
+ return new BatchResults(request);
}
}
@@ -4700,116 +4657,6 @@
}
// ----------------------------------------------------------------------------------------------------------------
- // RequestQueue and the different implementations
- // ----------------------------------------------------------------------------------------------------------------
-
- /**
- * A queue to which each each {@link AbstractAction} can submit its {@link Request} objects, either in single or multiple.
- * This interface abstracts away from the {@link AbstractAction} what it is to do with its {@link Request} objects, allowing
- * the same <code>AbstractAction</code> classes to be used by the {@link Graph} and {@link Graph.Batch} components.
- *
- * @author Randall Hauch
- */
- protected interface RequestQueue extends Executable<Node> {
- Graph getGraph();
-
- void submit( Request request );
-
- void submit( List<Request> requests );
-
- }
-
- /**
- * A RequestQueue that is used by the Graph instance to immediately execute the submitted requests.
- *
- * @author Randall Hauch
- */
- @NotThreadSafe
- protected class GraphRequestQueue implements RequestQueue {
- public Graph getGraph() {
- return Graph.this;
- }
-
- public void submit( Request request ) {
- // Execute the request immediately ...
- Graph.this.execute(request);
- }
-
- public void submit( List<Request> requests ) {
- Request request = CompositeRequest.with(requests);
- // Execute the request immediately ...
- Graph.this.execute(request);
- }
-
- public Results execute() {
- throw new UnsupportedOperationException();
- }
- }
-
- /**
- * A RequestQueue that is used by the {@link Graph.Batch} component to enqueue {@link Request}s until they are to be submitted
- * to the repository connections.
- *
- * @author Randall Hauch
- */
- @NotThreadSafe
- /*package*/class CompositingRequestQueue implements RequestQueue {
- private final LinkedList<Request> requests;
-
- CompositingRequestQueue( LinkedList<Request> queue ) {
- assert queue != null;
- this.requests = queue;
- }
-
- public Graph getGraph() {
- return Graph.this;
- }
-
- public List<Request> getRequests() {
- return this.requests;
- }
-
- /**
- * Determine the number of requests that are currently in the queue.
- *
- * @return the number of currently-enqueued requests
- */
- public int size() {
- return requests.size();
- }
-
- public void submit( Request request ) {
- if (!requests.isEmpty() && request instanceof UpdatePropertiesRequest) {
- // If the previous request was also an update, then maybe they can be merged ...
- Request previous = requests.getLast();
- if (previous instanceof UpdatePropertiesRequest) {
- // They can be merged if the have the same location ...
- UpdatePropertiesRequest next = (UpdatePropertiesRequest)request;
- UpdatePropertiesRequest prev = (UpdatePropertiesRequest)previous;
- if (next.on().equals(prev.on())) {
- requests.removeLast();
- requests.add(prev.mergeWith(next));
- }
- }
- }
- this.requests.add(request);
- }
-
- public void submit( List<Request> requests ) {
- this.requests.addAll(requests);
- }
-
- public Results execute() {
- if (!requests.isEmpty()) {
- // Execute the requests ...
- Request request = CompositeRequest.with(requests);
- Graph.this.execute(request);
- }
- return new BatchResults(requests);
- }
- }
-
- // ----------------------------------------------------------------------------------------------------------------
// Node Implementation
// ----------------------------------------------------------------------------------------------------------------
@Immutable
@@ -4920,6 +4767,39 @@
}
}
+ /*package*/BatchResults( Request request ) {
+ if (request instanceof ReadAllPropertiesRequest) {
+ ReadAllPropertiesRequest read = (ReadAllPropertiesRequest)request;
+ getOrCreateNode(read.getActualLocationOfNode()).setProperties(read.getPropertiesByName());
+ } else if (request instanceof ReadPropertyRequest) {
+ ReadPropertyRequest read = (ReadPropertyRequest)request;
+ getOrCreateNode(read.getActualLocationOfNode()).addProperty(read.getProperty());
+ } else if (request instanceof ReadNodeRequest) {
+ ReadNodeRequest read = (ReadNodeRequest)request;
+ BatchResultsNode node = getOrCreateNode(read.getActualLocationOfNode());
+ node.setProperties(read.getPropertiesByName());
+ node.setChildren(read.getChildren());
+ } else if (request instanceof ReadBlockOfChildrenRequest) {
+ throw new IllegalStateException();
+ } else if (request instanceof ReadAllChildrenRequest) {
+ ReadAllChildrenRequest read = (ReadAllChildrenRequest)request;
+ getOrCreateNode(read.getActualLocationOfNode()).setChildren(read.getChildren());
+ } else if (request instanceof ReadBranchRequest) {
+ ReadBranchRequest read = (ReadBranchRequest)request;
+ for (Location location : read) {
+ BatchResultsNode node = getOrCreateNode(location);
+ node.setProperties(read.getPropertiesFor(location));
+ node.setChildren(read.getChildren(location));
+ }
+ }
+ for (Map.Entry<Path, BatchResultsNode> entry : nodes.entrySet()) {
+ entry.getValue().freeze();
+ }
+ }
+
+ /*package*/BatchResults() {
+ }
+
private BatchResultsNode getOrCreateNode( Location location ) {
BatchResultsNode node = nodes.get(location);
if (node == null) {
@@ -5290,20 +5170,13 @@
// Action Implementations
// ----------------------------------------------------------------------------------------------------------------
@Immutable
- protected static abstract class AbstractAction<T> implements Conjunction<T>, Executable<Node> {
- private final RequestQueue queue;
+ protected abstract class AbstractAction<T> implements Conjunction<T> {
private final T afterConjunction;
- /*package*/AbstractAction( T afterConjunction,
- RequestQueue queue ) {
- this.queue = queue;
+ /*package*/AbstractAction( T afterConjunction ) {
this.afterConjunction = afterConjunction;
}
- /*package*/RequestQueue queue() {
- return this.queue;
- }
-
/*package*/T afterConjunction() {
return this.afterConjunction;
}
@@ -5313,22 +5186,17 @@
}
/*package*/Path createPath( String path ) {
- return queue.getGraph().getContext().getValueFactories().getPathFactory().create(path);
+ return Graph.this.getContext().getValueFactories().getPathFactory().create(path);
}
-
- public Results execute() {
- return queue.execute();
- }
}
@NotThreadSafe
- protected class MoveAction<T> extends AbstractAction<T> implements Move<T> {
+ protected abstract class MoveAction<T> extends AbstractAction<T> implements Move<T> {
private final Locations from;
/*package*/MoveAction( T afterConjunction,
- RequestQueue queue,
Location from ) {
- super(afterConjunction, queue);
+ super(afterConjunction);
this.from = new Locations(from);
}
@@ -5371,65 +5239,46 @@
/**
* Submit any requests to move the targets into the supplied parent location
*
+ * @param from the location(s) that are being moved; never null
* @param into the parent location
* @return this object, for method chaining
*/
- private T submit( Location into ) {
- String workspaceName = getCurrentWorkspaceName();
- if (this.from.hasNext()) {
- List<Request> requests = new LinkedList<Request>();
- Locations locations = this.from;
- while (locations.hasNext()) {
- Location location = locations.getLocation();
- requests.add(new MoveBranchRequest(location, into, workspaceName));
- locations = locations.next();
- }
- queue().submit(requests);
- } else {
- queue().submit(new MoveBranchRequest(this.from.getLocation(), into, workspaceName));
- }
- return and();
- }
+ protected abstract T submit( Locations from,
+ Location into );
public T into( Location into ) {
- return submit(into);
+ return submit(from, into);
}
public T into( Path into ) {
- return submit(Location.create(into));
+ return submit(from, Location.create(into));
}
public T into( UUID into ) {
- return submit(Location.create(into));
+ return submit(from, Location.create(into));
}
public T into( Property firstIdProperty,
Property... additionalIdProperties ) {
- return submit(Location.create(firstIdProperty, additionalIdProperties));
+ return submit(from, Location.create(firstIdProperty, additionalIdProperties));
}
public T into( Property into ) {
- return submit(Location.create(into));
+ return submit(from, Location.create(into));
}
public T into( String into ) {
- return submit(Location.create(createPath(into)));
+ return submit(from, Location.create(createPath(into)));
}
-
- @Override
- public Results execute() {
- return queue().execute();
- }
}
@NotThreadSafe
- protected class CopyAction<T> extends AbstractAction<T> implements Copy<T> {
+ protected abstract class CopyAction<T> extends AbstractAction<T> implements Copy<T> {
private final Locations from;
/*package*/CopyAction( T afterConjunction,
- RequestQueue queue,
Location from ) {
- super(afterConjunction, queue);
+ super(afterConjunction);
this.from = new Locations(from);
}
@@ -5472,51 +5321,38 @@
/**
* Submit any requests to move the targets into the supplied parent location
*
+ * @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
*/
- private T submit( Location into,
- Name nameForCopy ) {
- String workspaceName = getCurrentWorkspaceName();
- if (this.from.hasNext()) {
- List<Request> requests = new LinkedList<Request>();
- Locations locations = this.from;
- while (locations.hasNext()) {
- Location location = locations.getLocation();
- requests.add(new CopyBranchRequest(location, workspaceName, into, workspaceName, nameForCopy));
- locations = locations.next();
- }
- queue().submit(requests);
- } else {
- queue().submit(new CopyBranchRequest(this.from.getLocation(), workspaceName, into, workspaceName, nameForCopy));
- }
- return and();
- }
+ protected abstract T submit( Locations from,
+ Location into,
+ Name nameForCopy );
public T into( Location into ) {
- return submit(into, null);
+ return submit(from, into, null);
}
public T into( Path into ) {
- return submit(Location.create(into), null);
+ return submit(from, Location.create(into), null);
}
public T into( UUID into ) {
- return submit(Location.create(into), null);
+ return submit(from, Location.create(into), null);
}
public T into( Property firstIdProperty,
Property... additionalIdProperties ) {
- return submit(Location.create(firstIdProperty, additionalIdProperties), null);
+ return submit(from, Location.create(firstIdProperty, additionalIdProperties), null);
}
public T into( Property into ) {
- return submit(Location.create(into), null);
+ return submit(from, Location.create(into), null);
}
public T into( String into ) {
- return submit(Location.create(createPath(into)), null);
+ return submit(from, Location.create(createPath(into)), null);
}
public T to( Location desiredLocation ) {
@@ -5528,7 +5364,7 @@
throw new IllegalArgumentException(GraphI18n.unableToCopyToTheRoot.text(this.from, desiredLocation));
}
Path parent = desiredPath.getParent();
- return submit(Location.create(parent), desiredPath.getLastSegment().getName());
+ return submit(from, Location.create(parent), desiredPath.getLastSegment().getName());
}
public T to( Path desiredPath ) {
@@ -5536,77 +5372,72 @@
throw new IllegalArgumentException(GraphI18n.unableToCopyToTheRoot.text(this.from, desiredPath));
}
Path parent = desiredPath.getParent();
- return submit(Location.create(parent), desiredPath.getLastSegment().getName());
+ return submit(from, Location.create(parent), desiredPath.getLastSegment().getName());
}
public T to( String desiredPath ) {
return to(createPath(desiredPath));
}
-
- @Override
- public Results execute() {
- return queue().execute();
- }
}
@NotThreadSafe
- protected static class CreateAction<T> extends AbstractAction<T> implements Create<T> {
+ protected abstract class CreateAction<T> extends AbstractAction<T> implements Create<T> {
private final String workspaceName;
private final Location parent;
private final Name childName;
- private final List<Property> properties = new LinkedList<Property>();
+ private final Map<Name, Property> properties = new HashMap<Name, Property>();
+ private boolean submitted = false;
/*package*/CreateAction( T afterConjunction,
- RequestQueue queue,
Location parent,
String workspaceName,
Name childName ) {
- super(afterConjunction, queue);
+ super(afterConjunction);
this.parent = parent;
this.workspaceName = workspaceName;
this.childName = childName;
}
public Create<T> and( UUID uuid ) {
- PropertyFactory factory = queue().getGraph().getContext().getPropertyFactory();
- properties.add(factory.create(DnaLexicon.UUID, uuid));
+ PropertyFactory factory = getContext().getPropertyFactory();
+ properties.put(DnaLexicon.UUID, factory.create(DnaLexicon.UUID, uuid));
return this;
}
public Create<T> and( Property property ) {
- properties.add(property);
+ properties.put(property.getName(), property);
return this;
}
public Create<T> and( Iterable<Property> properties ) {
for (Property property : properties) {
- this.properties.add(property);
+ this.properties.put(property.getName(), property);
}
return this;
}
public Create<T> and( String name,
Object... values ) {
- ExecutionContext context = queue().getGraph().getContext();
+ ExecutionContext context = getContext();
PropertyFactory factory = context.getPropertyFactory();
NameFactory nameFactory = context.getValueFactories().getNameFactory();
- properties.add(factory.create(nameFactory.create(name), values));
+ Name propertyName = nameFactory.create(name);
+ properties.put(propertyName, factory.create(propertyName, values));
return this;
}
public Create<T> and( Name name,
Object... values ) {
- ExecutionContext context = queue().getGraph().getContext();
- PropertyFactory factory = context.getPropertyFactory();
- properties.add(factory.create(name, values));
+ PropertyFactory factory = getContext().getPropertyFactory();
+ properties.put(name, factory.create(name, values));
return this;
}
public Create<T> and( Property property,
Property... additionalProperties ) {
- properties.add(property);
+ properties.put(property.getName(), property);
for (Property additionalProperty : additionalProperties) {
- properties.add(additionalProperty);
+ properties.put(additionalProperty.getName(), additionalProperty);
}
return this;
}
@@ -5638,43 +5469,44 @@
return and(name, values);
}
+ protected abstract T submit( Location parent,
+ String workspaceName,
+ Name childName,
+ Collection<Property> properties );
+
@Override
public T and() {
- this.queue().submit(new CreateNodeRequest(parent, workspaceName, childName, this.properties));
+ if (!submitted) {
+ submit(parent, workspaceName, childName, this.properties.values());
+ submitted = true;
+ }
return super.and();
}
-
- @Override
- public Results execute() {
- this.queue().submit(new CreateNodeRequest(parent, workspaceName, childName, this.properties));
- return queue().execute();
- }
}
@NotThreadSafe
- protected static class CreateNodeNamedAction<T> extends AbstractAction<T> implements CreateNodeNamed<T> {
+ protected abstract class CreateNodeNamedAction<T> extends AbstractAction<T> implements CreateNodeNamed<T> {
private final Location parent;
- private final String workspaceName;
- /*package*/CreateNodeNamedAction( T afterConjunction,
- RequestQueue queue,
- Location parent,
- String workspaceName ) {
- super(afterConjunction, queue);
+ protected CreateNodeNamedAction( T afterConjunction,
+ Location parent ) {
+ super(afterConjunction);
this.parent = parent;
- this.workspaceName = workspaceName;
}
public CreateAction<T> nodeNamed( String name ) {
- ExecutionContext context = queue().getGraph().getContext();
- NameFactory factory = context.getValueFactories().getNameFactory();
+ NameFactory factory = getContext().getValueFactories().getNameFactory();
Name nameObj = factory.create(name);
- return new CreateAction<T>(afterConjunction(), queue(), parent, workspaceName, nameObj);
+ return createWith(afterConjunction(), parent, nameObj);
}
public CreateAction<T> nodeNamed( Name name ) {
- return new CreateAction<T>(afterConjunction(), queue(), parent, workspaceName, name);
+ return createWith(afterConjunction(), parent, name);
}
+
+ protected abstract CreateAction<T> createWith( T afterConjunction,
+ Location parent,
+ Name nodeName );
}
@Immutable
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphImporter.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphImporter.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphImporter.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -254,7 +254,7 @@
if (firstProperty == null) {
batch.create(path).and();
} else {
- batch.create(path, firstProperty, additionalProperties);
+ batch.create(path, firstProperty, additionalProperties).and();
}
}
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRequestProcessor.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRequestProcessor.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRequestProcessor.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -208,12 +208,13 @@
InMemoryNode node = getTargetNode(workspace, request, request.on());
if (node == null) return;
// Now set (or remove) the properties to the supplied node ...
- for (Property property : request.properties()) {
- Name propName = property.getName();
- if (property.size() == 0) {
- node.getProperties().remove(propName);
+ for (Map.Entry<Name, Property> propertyEntry : request.properties().entrySet()) {
+ Property property = propertyEntry.getValue();
+ if (property == null) {
+ node.getProperties().remove(propertyEntry.getKey());
continue;
}
+ Name propName = property.getName();
if (!propName.equals(DnaLexicon.UUID)) {
node.getProperties().put(propName, property);
}
Added: 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 (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/BatchRequestBuilder.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -0,0 +1,671 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * Unless otherwise indicated, all code in JBoss DNA is licensed
+ * to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.NodeConflictBehavior;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.request.CloneWorkspaceRequest.CloneConflictBehavior;
+import org.jboss.dna.graph.request.CreateWorkspaceRequest.CreateConflictBehavior;
+
+/**
+ * A component that can be used to build up a list of requests. This implementation does perform some simple optimizations, such
+ * as combining adjacent compatible requests.
+ * <p>
+ * This builder can be used to add multiple requests. When the enqueued requests are to be processed, calling {@link #pop()} will
+ * remove and return the enqueued requests (as a {@link CompositeRequest} if there is more than one enqueued request).
+ * </p>
+ */
+public class BatchRequestBuilder {
+
+ private LinkedList<Request> requests;
+ private NodeChange pendingRequest;
+
+ public BatchRequestBuilder() {
+ this.requests = new LinkedList<Request>();
+ }
+
+ public BatchRequestBuilder( LinkedList<Request> requests ) {
+ this.requests = requests != null ? requests : new LinkedList<Request>();
+ }
+
+ /**
+ * Determine whether this builder has built any requests.
+ *
+ * @return true if there are requests (i.e., {@link #pop()} will return a non-null request), or false if there are no requests
+ */
+ public boolean hasRequests() {
+ return pendingRequest != null || !requests.isEmpty();
+ }
+
+ /**
+ * Finish any pending request
+ */
+ public void finishPendingRequest() {
+ if (pendingRequest != null) {
+ // There's a pending request, we need to build it ...
+ add(pendingRequest.toRequest());
+ }
+ }
+
+ /**
+ * Remove and return any requests that have been built by this builder since the last call to this method. This method will
+ * return null if no requests have been built. If only one request was built, then it will be returned. If multiple requests
+ * have been built, then this method will return a {@link CompositeRequest} containing them.
+ *
+ * @return the request (or {@link CompositeRequest}) representing those requests that this builder has created since the last
+ * call to this method, or null if there are no requests to return
+ */
+ public Request pop() {
+ int number = requests.size();
+ if (pendingRequest != null) {
+ // There's a pending request, we need to build it ...
+ Request newRequest = pendingRequest.toRequest();
+ if (number == 0) {
+ // There's no other request ...
+ return newRequest;
+ }
+ // We have at least one other request, so add the pending request ...
+ add(newRequest);
+ ++number;
+ } else {
+ // There is no pending request ...
+ if (number == 0) {
+ // And no enqueued request ...
+ return null;
+ }
+ if (number == 1) {
+ // There's only one request, so return just the one ...
+ Request result = requests.getFirst();
+ requests.clear();
+ return result;
+ }
+ }
+ assert number >= 2;
+ // Build a composite request (reusing the existing list), and then replace the list
+ Request result = CompositeRequest.with(requests);
+ requests = new LinkedList<Request>();
+ return result;
+ }
+
+ protected final BatchRequestBuilder add( Request request ) {
+ addPending();
+ requests.add(request);
+ return this;
+ }
+
+ protected final BatchRequestBuilder addPending() {
+ if (pendingRequest != null) {
+ requests.add(pendingRequest.toRequest());
+ pendingRequest = null;
+ }
+ return this;
+ }
+
+ /**
+ * Add a request to obtain the information about the available workspaces.
+ *
+ * @return this builder for method chaining; never null
+ */
+ public BatchRequestBuilder getWorkspaces() {
+ return add(new GetWorkspacesRequest());
+ }
+
+ /**
+ * Add a request to verify the existance of the named workspace.
+ *
+ * @param workspaceName the desired name of the workspace, or null if the source's default workspace should be used
+ * @return this builder for method chaining; never null
+ */
+ public BatchRequestBuilder verifyWorkspace( String workspaceName ) {
+ return add(new VerifyWorkspaceRequest(workspaceName));
+ }
+
+ /**
+ * Add a request to create a new workspace, and specify the behavior should a workspace already exists with a name that
+ * matches the desired name for the new workspace.
+ *
+ * @param desiredNameOfNewWorkspace the desired name of the new workspace
+ * @param createConflictBehavior the behavior if a workspace already exists with the same name, or null if the default
+ * behavior should be used
+ * @return this builder for method chaining; never null
+ */
+ public BatchRequestBuilder createWorkspace( String desiredNameOfNewWorkspace,
+ CreateConflictBehavior createConflictBehavior ) {
+ return add(new CreateWorkspaceRequest(desiredNameOfNewWorkspace, createConflictBehavior));
+ }
+
+ /**
+ * Add a request to clone an existing workspace to create a new workspace, and specify the behavior should a workspace already
+ * exists with a name that matches the desired name for the new workspace.
+ *
+ * @param nameOfWorkspaceToBeCloned the name of the existing workspace that is to be cloned
+ * @param desiredNameOfTargetWorkspace the desired name of the target workspace
+ * @param createConflictBehavior the behavior if a workspace already exists with the same name
+ * @param cloneConflictBehavior the behavior if the workspace to be cloned does not exist
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the either workspace name is null
+ */
+ public BatchRequestBuilder cloneWorkspace( String nameOfWorkspaceToBeCloned,
+ String desiredNameOfTargetWorkspace,
+ CreateConflictBehavior createConflictBehavior,
+ CloneConflictBehavior cloneConflictBehavior ) {
+ return add(new CloneWorkspaceRequest(nameOfWorkspaceToBeCloned, desiredNameOfTargetWorkspace, createConflictBehavior,
+ cloneConflictBehavior));
+ }
+
+ /**
+ * Add a request to destroy an existing workspace.
+ *
+ * @param workspaceName the name of the workspace that is to be destroyed
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the workspace name is null
+ */
+ public BatchRequestBuilder destroyWorkspace( String workspaceName ) {
+ return add(new DestroyWorkspaceRequest(workspaceName));
+ }
+
+ /**
+ * Add a request to verify the existance and location of a node at the supplied location.
+ *
+ * @param at the location of the node to be verified
+ * @param workspaceName the name of the workspace containing the node
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the location or workspace name is null
+ */
+ public BatchRequestBuilder verifyNodeExists( Location at,
+ String workspaceName ) {
+ return add(new VerifyNodeExistsRequest(at, workspaceName));
+ }
+
+ /**
+ * Add a request to read the properties and number of children of a node at the supplied location.
+ *
+ * @param at the location of the node to be read
+ * @param workspaceName the name of the workspace containing the node
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the location or workspace name is null
+ */
+ public BatchRequestBuilder readNode( Location at,
+ String workspaceName ) {
+ return add(new ReadNodeRequest(at, workspaceName));
+ }
+
+ /**
+ * Add a request to read the children of a node at the supplied location in the designated workspace.
+ *
+ * @param of the location of the node whose children are to be read
+ * @param workspaceName the name of the workspace
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the location or workspace name is null
+ */
+ public BatchRequestBuilder readAllChildren( Location of,
+ String workspaceName ) {
+ return add(new ReadAllChildrenRequest(of, workspaceName));
+ }
+
+ /**
+ * Add a request to read the properties and number of children of a node at the supplied location.
+ *
+ * @param of the location of the node whose children are to be read
+ * @param workspaceName the name of the workspace
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the location or workspace name is null
+ */
+ public BatchRequestBuilder readAllProperties( Location of,
+ String workspaceName ) {
+ return add(new ReadAllPropertiesRequest(of, workspaceName));
+ }
+
+ /**
+ * Add a request to read the properties and number of children of a node at the supplied location.
+ *
+ * @param of the location of the node whose children are to be read
+ * @param workspaceName the name of the workspace
+ * @param propertyName the name of the property to read
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the location or workspace name is null
+ */
+ public BatchRequestBuilder readProperty( Location of,
+ String workspaceName,
+ Name propertyName ) {
+ return add(new ReadPropertyRequest(of, workspaceName, propertyName));
+ }
+
+ /**
+ * Add a request to read the branch at the supplied location, to a maximum depth of 2.
+ *
+ * @param at the location of the branch
+ * @param workspaceName the name of the workspace containing the branch
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the location or workspace name is null or if the maximum depth is not positive
+ */
+ public BatchRequestBuilder readBranch( Location at,
+ String workspaceName ) {
+ return add(new ReadBranchRequest(at, workspaceName));
+ }
+
+ /**
+ * Add a request to read the branch (of given depth) at the supplied location.
+ *
+ * @param at the location of the branch
+ * @param workspaceName the name of the workspace containing the branch
+ * @param maxDepth the maximum depth to read
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the location or workspace name is null or if the maximum depth is not positive
+ */
+ public BatchRequestBuilder readBranch( Location at,
+ String workspaceName,
+ int maxDepth ) {
+ return add(new ReadBranchRequest(at, workspaceName, maxDepth));
+ }
+
+ /**
+ * Add a request to read a block of the children of a node at the supplied location. The block is defined by the starting
+ * index of the first child and the number of children to include. Note that this index is <i>not</i> the
+ * {@link Path.Segment#getIndex() same-name-sibiling index}, but rather is the index of the child as if the children were in
+ * an array.
+ *
+ * @param of the location of the node whose children are to be read
+ * @param workspaceName the name of the workspace containing the parent
+ * @param startingIndex the zero-based index of the first child to be included in the block
+ * @param count the maximum number of children that should be included in the block
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the location or workspace name is null, if <code>startingIndex</code> is negative, or
+ * if <code>count</count> is less than 1.
+ */
+ public BatchRequestBuilder readBlockOfChildren( Location of,
+ String workspaceName,
+ int startingIndex,
+ int count ) {
+ return add(new ReadBlockOfChildrenRequest(of, workspaceName, startingIndex, count));
+ }
+
+ /**
+ * Add a request to read those children of a node that are immediately after a supplied sibling node.
+ *
+ * @param startingAfter the location of the previous sibling that was the last child of the previous block of children read
+ * @param workspaceName the name of the workspace containing the node
+ * @param count the maximum number of children that should be included in the block
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the workspace name or <code>startingAfter</code> location is null, or if
+ * <code>count</count> is less than 1.
+ */
+ public BatchRequestBuilder readNextBlockOfChildren( Location startingAfter,
+ String workspaceName,
+ int count ) {
+ return add(new ReadNextBlockOfChildrenRequest(startingAfter, workspaceName, count));
+ }
+
+ /**
+ * Add a request to create a node with the given properties under the supplied location.
+ *
+ * @param parentLocation the location of the existing parent node, under which the new child should be created
+ * @param workspaceName the name of the workspace containing the parent
+ * @param childName the name of the new child to create under the existing parent
+ * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
+ * properties} for the new node
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the location, workspace name, or child name is null
+ */
+ public BatchRequestBuilder createNode( Location parentLocation,
+ String workspaceName,
+ Name childName,
+ Iterator<Property> properties ) {
+ return add(new CreateNodeRequest(parentLocation, workspaceName, childName, CreateNodeRequest.DEFAULT_CONFLICT_BEHAVIOR,
+ properties));
+ }
+
+ /**
+ * Add a request to create a node with the given properties under the supplied location.
+ *
+ * @param parentLocation the location of the existing parent node, under which the new child should be created
+ * @param workspaceName the name of the workspace containing the parent
+ * @param childName the name of the new child to create under the existing parent
+ * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
+ * properties} for the new node
+ * @param conflictBehavior the expected behavior if an equivalently-named child already exists under the <code>into</code>
+ * location
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the location, workspace name, or child name is null
+ */
+ public BatchRequestBuilder createNode( Location parentLocation,
+ String workspaceName,
+ Name childName,
+ Iterator<Property> properties,
+ NodeConflictBehavior conflictBehavior ) {
+ if (conflictBehavior == null) conflictBehavior = CreateNodeRequest.DEFAULT_CONFLICT_BEHAVIOR;
+ return add(new CreateNodeRequest(parentLocation, workspaceName, childName, conflictBehavior, properties));
+ }
+
+ /**
+ * Add a request to create a node with the given properties under the supplied location.
+ *
+ * @param parentLocation the location of the existing parent node, under which the new child should be created
+ * @param workspaceName the name of the workspace containing the parent
+ * @param childName the name of the new child to create under the existing parent
+ * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
+ * properties} for the new node
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the location, workspace name, or child name is null
+ */
+ public BatchRequestBuilder createNode( Location parentLocation,
+ String workspaceName,
+ Name childName,
+ Property[] properties ) {
+ return add(new CreateNodeRequest(parentLocation, workspaceName, childName, CreateNodeRequest.DEFAULT_CONFLICT_BEHAVIOR,
+ properties));
+ }
+
+ /**
+ * Add a request to create a node with the given properties under the supplied location.
+ *
+ * @param parentLocation the location of the existing parent node, under which the new child should be created
+ * @param workspaceName the name of the workspace containing the parent
+ * @param childName the name of the new child to create under the existing parent
+ * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
+ * properties} for the new node
+ * @param conflictBehavior the expected behavior if an equivalently-named child already exists under the <code>into</code>
+ * location
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the location, workspace name, or child name is null
+ */
+ public BatchRequestBuilder createNode( Location parentLocation,
+ String workspaceName,
+ Name childName,
+ Property[] properties,
+ NodeConflictBehavior conflictBehavior ) {
+ if (conflictBehavior == null) conflictBehavior = CreateNodeRequest.DEFAULT_CONFLICT_BEHAVIOR;
+ return add(new CreateNodeRequest(parentLocation, workspaceName, childName, conflictBehavior, properties));
+ }
+
+ /**
+ * Add a request to update the property on the node at the supplied location. This request will create the property if it does
+ * not yet exist.
+ *
+ * @param on the location of the node to be read
+ * @param workspaceName the name of the workspace containing the node
+ * @param property the new property on the node
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the location or workspace name is null or if there are no properties to update
+ */
+ public BatchRequestBuilder setProperty( Location on,
+ String workspaceName,
+ Property property ) {
+ // If there's a pending request ...
+ if (pendingRequest != null) {
+ // Compare the supplied location with that of the pending request
+ if (pendingRequest.location.equals(on)) {
+ // They are the same location, so we can add the properties to the pending request ...
+ pendingRequest.pendingProperties.put(property.getName(), property);
+ return this;
+ }
+ // Not the exact same location, so push the existing pending request ...
+ addPending();
+ }
+
+ // Record this operation as a pending change ...
+ pendingRequest = new NodeChange(on, workspaceName);
+ pendingRequest.pendingProperties.put(property.getName(), property);
+ return this;
+ }
+
+ /**
+ * Add a request to update the properties on the node at the supplied location.
+ *
+ * @param on the location of the node to be read
+ * @param workspaceName the name of the workspace containing the node
+ * @param properties the new properties on the node
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the location or workspace name is null or if there are no properties to update
+ */
+ public BatchRequestBuilder setProperties( Location on,
+ String workspaceName,
+ Property... properties ) {
+ // If there's a pending request ...
+ if (pendingRequest != null) {
+ // Compare the supplied location with that of the pending request
+ if (pendingRequest.location.equals(on)) {
+ // They are the same location, so we can add the properties to the pending request ...
+ for (Property property : properties) {
+ pendingRequest.pendingProperties.put(property.getName(), property);
+ }
+ return this;
+ }
+ // Not the exact same location, so push the existing pending request ...
+ addPending();
+ }
+
+ // Record this operation as a pending change ...
+ pendingRequest = new NodeChange(on, workspaceName);
+ for (Property property : properties) {
+ pendingRequest.pendingProperties.put(property.getName(), property);
+ }
+ return this;
+ }
+
+ /**
+ * Add a request to remove the property with the supplied name from the given node. Supplying a name for a property that does
+ * not exist will not cause an error.
+ *
+ * @param on the location of the node to be read
+ * @param workspaceName the name of the workspace containing the node
+ * @param propertyName the name of the property that is to be removed
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the location or workspace name is null or if there are no properties to remove
+ */
+ public BatchRequestBuilder removeProperty( Location on,
+ String workspaceName,
+ Name propertyName ) {
+ // If there's a pending request ...
+ if (pendingRequest != null) {
+ // Compare the supplied location with that of the pending request
+ if (pendingRequest.location.equals(on)) {
+ // They are the same location, so we can add the properties to the pending request ...
+ pendingRequest.pendingProperties.put(propertyName, null);
+ return this;
+ }
+ // Not the exact same location, so push the existing pending request ...
+ addPending();
+ }
+
+ // Record this operation as a pending change ...
+ pendingRequest = new NodeChange(on, workspaceName);
+ pendingRequest.pendingProperties.put(propertyName, null);
+ return this;
+ }
+
+ /**
+ * Add a request to remove from the node the properties with the supplied names. Supplying a name for a property that does not
+ * exist will not cause an error.
+ *
+ * @param on the location of the node to be read
+ * @param workspaceName the name of the workspace containing the node
+ * @param propertyNames the names of the properties that are to be removed
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the location or workspace name is null or if there are no properties to remove
+ */
+ public BatchRequestBuilder removeProperties( Location on,
+ String workspaceName,
+ Name... propertyNames ) {
+ // If there's a pending request ...
+ if (pendingRequest != null) {
+ // Compare the supplied location with that of the pending request
+ if (pendingRequest.location.equals(on)) {
+ // They are the same location, so we can add the properties to the pending request ...
+ for (Name propertyName : propertyNames) {
+ pendingRequest.pendingProperties.put(propertyName, null);
+ }
+ return this;
+ }
+ // Not the exact same location, so push the existing pending request ...
+ addPending();
+ }
+
+ // Record this operation as a pending change ...
+ pendingRequest = new NodeChange(on, workspaceName);
+ for (Name propertyName : propertyNames) {
+ pendingRequest.pendingProperties.put(propertyName, null);
+ }
+ return this;
+ }
+
+ /**
+ * Add a request to rename the node at the supplied location.
+ *
+ * @param at the location of the node to be read
+ * @param workspaceName the name of the workspace containing the node
+ * @param newName the new name for the node
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the location or workspace name is null
+ */
+ public BatchRequestBuilder renameNode( Location at,
+ String workspaceName,
+ Name newName ) {
+ return add(new RenameNodeRequest(at, workspaceName, newName));
+ }
+
+ /**
+ * Add a request to copy a branch to another.
+ *
+ * @param from the location of the top node in the existing branch that is to be copied
+ * @param fromWorkspace the name of the workspace where the <code>from</code> node exists
+ * @param into the location of the existing node into which the copy should be placed
+ * @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
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if either of the locations or workspace names are null
+ */
+ public BatchRequestBuilder copyBranch( Location from,
+ String fromWorkspace,
+ Location into,
+ String intoWorkspace,
+ Name nameForCopy ) {
+ return add(new CopyBranchRequest(from, fromWorkspace, into, intoWorkspace, nameForCopy,
+ CopyBranchRequest.DEFAULT_CONFLICT_BEHAVIOR));
+ }
+
+ /**
+ * Add a request to copy a branch to another.
+ *
+ * @param from the location of the top node in the existing branch that is to be copied
+ * @param fromWorkspace the name of the workspace where the <code>from</code> node exists
+ * @param into the location of the existing node into which the copy should be placed
+ * @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>
+ * location, or null if the default 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
+ */
+ public BatchRequestBuilder copyBranch( Location from,
+ String fromWorkspace,
+ 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));
+ }
+
+ /**
+ * Create a request to move a branch from one location into another.
+ *
+ * @param from the location of the top node in the existing branch that is to be moved
+ * @param into the location of the existing node into which the branch should be moved
+ * @param workspaceName the name of the workspace
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if any of the parameters are null
+ */
+ public BatchRequestBuilder moveBranch( Location from,
+ Location into,
+ String workspaceName ) {
+ return add(new MoveBranchRequest(from, into, workspaceName, MoveBranchRequest.DEFAULT_CONFLICT_BEHAVIOR));
+ }
+
+ /**
+ * Create a request to move a branch from one location into another.
+ *
+ * @param from the location of the top node in the existing branch that is to be moved
+ * @param into the location of the existing node into which the branch should be moved
+ * @param workspaceName the name of the workspace
+ * @param conflictBehavior the expected behavior if an equivalently-named child already exists at the <code>into</code>
+ * location
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if any of the parameters are null
+ */
+ public BatchRequestBuilder moveBranch( Location from,
+ Location into,
+ String workspaceName,
+ NodeConflictBehavior conflictBehavior ) {
+ if (conflictBehavior == null) conflictBehavior = MoveBranchRequest.DEFAULT_CONFLICT_BEHAVIOR;
+ return add(new MoveBranchRequest(from, into, workspaceName, conflictBehavior));
+ }
+
+ /**
+ * Add a request to delete a branch.
+ *
+ * @param at the location of the top node in the existing branch that is to be deleted
+ * @param workspaceName the name of the workspace containing the parent
+ * @return this builder for method chaining; never null
+ * @throws IllegalArgumentException if the location or workspace name is null
+ */
+ public BatchRequestBuilder deleteBranch( Location at,
+ String workspaceName ) {
+ return add(new DeleteBranchRequest(at, workspaceName));
+ }
+
+ protected class NodeChange {
+ protected final Location location;
+ protected final String workspaceName;
+ protected final Map<Name, Property> pendingProperties = new HashMap<Name, Property>();
+
+ protected NodeChange( Location location,
+ String workspaceName ) {
+ this.location = location;
+ this.workspaceName = workspaceName;
+ }
+
+ protected Request toRequest() {
+ if (pendingProperties.size() == 1) {
+ Map.Entry<Name, Property> entry = pendingProperties.entrySet().iterator().next();
+ Property property = entry.getValue();
+ if (property == null) {
+ return new RemovePropertyRequest(location, workspaceName, entry.getKey());
+ }
+ return new SetPropertyRequest(location, workspaceName, property);
+ }
+ return new UpdatePropertiesRequest(location, workspaceName, pendingProperties);
+ }
+ }
+
+}
Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/BatchRequestBuilder.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CloneWorkspaceRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CloneWorkspaceRequest.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CloneWorkspaceRequest.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -73,6 +73,7 @@
* @param desiredNameOfTargetWorkspace the desired name of the target workspace
* @param createConflictBehavior the behavior if a workspace already exists with the same name
* @param cloneConflictBehavior the behavior if the workspace to be cloned does not exist
+ * @throws IllegalArgumentException if the either workspace name is null
*/
public CloneWorkspaceRequest( String nameOfWorkspaceToBeCloned,
String desiredNameOfTargetWorkspace,
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/DeleteBranchRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/DeleteBranchRequest.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/DeleteBranchRequest.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -46,7 +46,7 @@
*
* @param at the location of the top node in the existing branch that is to be deleted
* @param workspaceName the name of the workspace containing the parent
- * @throws IllegalArgumentException if the location is null
+ * @throws IllegalArgumentException if the location or workspace name is null
*/
public DeleteBranchRequest( Location at,
String workspaceName ) {
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/DestroyWorkspaceRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/DestroyWorkspaceRequest.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/DestroyWorkspaceRequest.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -38,6 +38,7 @@
* Create a request to destroy an existing workspace.
*
* @param workspaceName the name of the workspace that is to be destroyed
+ * @throws IllegalArgumentException if the workspace name is null
*/
public DestroyWorkspaceRequest( String workspaceName ) {
CheckArg.isNotNull(workspaceName, "workspaceName");
Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RemovePropertiesRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RemovePropertiesRequest.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RemovePropertiesRequest.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -1,248 +0,0 @@
-/*
- * JBoss DNA (http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
- * is licensed to you under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * JBoss DNA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.request;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.GraphI18n;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.Path;
-
-/**
- * Instruction to remove properties from the node at the specified location.
- *
- * @author Randall Hauch
- */
-public class RemovePropertiesRequest extends Request implements Iterable<Name>, ChangeRequest {
-
- private static final long serialVersionUID = 1L;
-
- private final Location from;
- private final String workspaceName;
- private final Set<Name> propertyNames;
- private Location actualLocation;
-
- /**
- * Create a request to remove the properties with the given names from the node at the supplied location.
- *
- * @param from the location of the node to be read
- * @param workspaceName the name of the workspace containing the node
- * @param propertyNames the names of the properties to be removed from the node
- * @throws IllegalArgumentException if the location is null or if there are no properties to remove
- */
- public RemovePropertiesRequest( Location from,
- String workspaceName,
- Name... propertyNames ) {
- CheckArg.isNotNull(from, "from");
- CheckArg.isNotEmpty(propertyNames, "propertyNames");
- CheckArg.isNotNull(workspaceName, "workspaceName");
- this.workspaceName = workspaceName;
- this.from = from;
- Set<Name> names = new HashSet<Name>();
- for (Name name : propertyNames) {
- if (name != null) names.add(name);
- }
- this.propertyNames = Collections.unmodifiableSet(names);
- }
-
- /**
- * Create a request to remove the properties with the given names from the node at the supplied location.
- *
- * @param from the location of the node to be read
- * @param workspaceName the name of the workspace containing the node
- * @param propertyNames the names of the properties to be removed from the node
- * @throws IllegalArgumentException if the location is null or if there are no properties to remove
- */
- public RemovePropertiesRequest( Location from,
- String workspaceName,
- Iterable<Name> propertyNames ) {
- CheckArg.isNotNull(from, "from");
- CheckArg.isNotNull(propertyNames, "propertyNames");
- CheckArg.isNotNull(workspaceName, "workspaceName");
- this.workspaceName = workspaceName;
- this.from = from;
- Set<Name> names = new HashSet<Name>();
- for (Name name : propertyNames) {
- if (name != null) names.add(name);
- }
- this.propertyNames = Collections.unmodifiableSet(names);
- CheckArg.isNotEmpty(this.propertyNames, "propertyNames");
- }
-
- /**
- * Create a request to remove the properties with the given names from the node at the supplied location.
- *
- * @param from the location of the node to be read
- * @param workspaceName the name of the workspace containing the node
- * @param propertyNames the names of the properties to be removed from the node
- * @throws IllegalArgumentException if the location is null or if there are no properties to remove
- */
- public RemovePropertiesRequest( Location from,
- String workspaceName,
- Iterator<Name> propertyNames ) {
- CheckArg.isNotNull(from, "from");
- CheckArg.isNotNull(propertyNames, "propertyNames");
- CheckArg.isNotNull(workspaceName, "workspaceName");
- this.workspaceName = workspaceName;
- this.from = from;
- Set<Name> names = new HashSet<Name>();
- while (propertyNames.hasNext()) {
- Name name = propertyNames.next();
- if (name != null) names.add(name);
- }
- this.propertyNames = Collections.unmodifiableSet(names);
- CheckArg.isNotEmpty(this.propertyNames, "propertyNames");
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.graph.request.Request#isReadOnly()
- */
- @Override
- public boolean isReadOnly() {
- return false;
- }
-
- /**
- * Get the location defining the node from which the properties are to be removed.
- *
- * @return the location of the node; never null
- */
- public Location from() {
- return from;
- }
-
- /**
- * Get the name of the workspace in which the node exists.
- *
- * @return the name of the workspace; never null
- */
- public String inWorkspace() {
- return workspaceName;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Iterable#iterator()
- */
- public Iterator<Name> iterator() {
- return this.propertyNames.iterator();
- }
-
- /**
- * Get the names of the properties that are to be removed from the node.
- *
- * @return the collection of property names; never null and never empty
- */
- public Collection<Name> propertyNames() {
- return propertyNames;
- }
-
- /**
- * Sets the actual and complete location of the node whose properties were removed. This method must be called when processing
- * the request, and the actual location must have a {@link Location#getPath() path}.
- *
- * @param actual the actual location of the node being changed, or null if the {@link #from() current location} should be used
- * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
- * location} as the {@link #from() current location}, or if the actual location does not have a path.
- */
- public void setActualLocationOfNode( Location actual ) {
- if (!from.isSame(actual)) { // not same if actual is null
- throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, from));
- }
- assert actual != null;
- if (!actual.hasPath()) {
- throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
- }
- this.actualLocation = actual;
- }
-
- /**
- * Get the actual location of the node whose properties were removed.
- *
- * @return the actual location, or null if the actual location was not set
- */
- public Location getActualLocationOfNode() {
- return actualLocation;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.graph.request.ChangeRequest#changes(java.lang.String, org.jboss.dna.graph.property.Path)
- */
- public boolean changes( String workspace,
- Path path ) {
- return this.workspaceName.equals(workspace) && from.hasPath() && from.getPath().isAtOrBelow(path);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.graph.request.ChangeRequest#changedLocation()
- */
- public Location changedLocation() {
- return from;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals( Object obj ) {
- if (obj == this) return true;
- if (this.getClass().isInstance(obj)) {
- RemovePropertiesRequest that = (RemovePropertiesRequest)obj;
- if (!this.from().equals(that.from())) return false;
- if (!this.propertyNames().equals(that.propertyNames())) return false;
- if (!this.inWorkspace().equals(that.inWorkspace())) return false;
- return true;
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- if (propertyNames.size() == 1) {
- return "remove from " + from() + " in the \"" + workspaceName + "\" workspace the property named "
- + propertyNames.iterator().next();
- }
- return "remove from " + from() + " in the \"" + workspaceName + "\" workspace the properties named " + propertyNames();
- }
-
-}
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RemovePropertyRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RemovePropertyRequest.java (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RemovePropertyRequest.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -0,0 +1,177 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+
+/**
+ * Instruction to remove the property with the supplied name from the node at the given location. This request has no net effect
+ * if the node does not contain a property with the supplied name.
+ *
+ * @author Randall Hauch
+ */
+public class RemovePropertyRequest extends Request implements ChangeRequest {
+
+ private static final long serialVersionUID = 1L;
+
+ private final Location from;
+ private final String workspaceName;
+ private final Name propertyName;
+ private Location actualLocation;
+
+ /**
+ * Create a request to remove a named property from the node at the supplied location.
+ *
+ * @param from the location of the node to be read
+ * @param workspaceName the name of the workspace containing the node
+ * @param propertyName the name of the property to be removed
+ * @throws IllegalArgumentException if the location, workspace name, or property name is null
+ */
+ public RemovePropertyRequest( Location from,
+ String workspaceName,
+ Name propertyName ) {
+ CheckArg.isNotNull(from, "from");
+ CheckArg.isNotNull(propertyName, "propertyName");
+ CheckArg.isNotNull(workspaceName, "workspaceName");
+ this.workspaceName = workspaceName;
+ this.from = from;
+ this.propertyName = propertyName;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.request.Request#isReadOnly()
+ */
+ @Override
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ /**
+ * Get the location defining the node from which the property is to be removed.
+ *
+ * @return the location of the node; never null
+ */
+ public Location from() {
+ return from;
+ }
+
+ /**
+ * Get the name of the workspace in which the node exists.
+ *
+ * @return the name of the workspace; never null
+ */
+ public String inWorkspace() {
+ return workspaceName;
+ }
+
+ /**
+ * Get the name of the property that is being removed.
+ *
+ * @return the property name; never null
+ */
+ public Name propertyName() {
+ return propertyName;
+ }
+
+ /**
+ * Sets the actual and complete location of the node being updated. This method must be called when processing the request,
+ * and the actual location must have a {@link Location#getPath() path}.
+ *
+ * @param actual the actual location of the node being updated, or null if the {@link #from() current location} should be used
+ * @throws IllegalArgumentException if the actual location does represent the {@link Location#isSame(Location) same location}
+ * as the {@link #from() current location}, or if the actual location does not have a path.
+ */
+ public void setActualLocationOfNode( Location actual ) {
+ if (!from.isSame(actual)) { // not same if actual is null
+ throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, from));
+ }
+ assert actual != null;
+ if (!actual.hasPath()) {
+ throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
+ }
+ this.actualLocation = actual;
+ }
+
+ /**
+ * Get the actual location of the node that was updated.
+ *
+ * @return the actual location, or null if the actual location was not set
+ */
+ public Location getActualLocationOfNode() {
+ return actualLocation;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.request.ChangeRequest#changes(java.lang.String, org.jboss.dna.graph.property.Path)
+ */
+ public boolean changes( String workspace,
+ Path path ) {
+ return this.workspaceName.equals(workspace) && from.hasPath() && from.getPath().isAtOrBelow(path);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (this.getClass().isInstance(obj)) {
+ RemovePropertyRequest that = (RemovePropertyRequest)obj;
+ if (!this.from().equals(that.from())) return false;
+ if (!this.propertyName().equals(that.propertyName())) return false;
+ if (!this.inWorkspace().equals(that.inWorkspace())) return false;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.request.ChangeRequest#changedLocation()
+ */
+ public Location changedLocation() {
+ return from;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "remove property " + propertyName() + " from " + from() + " in the \"" + workspaceName + "\" workspace";
+ }
+}
Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RemovePropertyRequest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: 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 (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RequestBuilder.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -0,0 +1,494 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * Unless otherwise indicated, all code in JBoss DNA is licensed
+ * to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.NodeConflictBehavior;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.request.CloneWorkspaceRequest.CloneConflictBehavior;
+import org.jboss.dna.graph.request.CreateWorkspaceRequest.CreateConflictBehavior;
+
+/**
+ * A component that can be used to build requests while allowing different strategies for how requests are handled. Subclasses can
+ * simply override the {@link #process(Request)} method to define what happens with each request.
+ */
+public abstract class RequestBuilder {
+
+ /**
+ * Create a new builder.
+ */
+ protected RequestBuilder() {
+ }
+
+ protected abstract <T extends Request> T process( T request );
+
+ /**
+ * Add a request to obtain the information about the available workspaces.
+ *
+ * @return the request; never null
+ */
+ public GetWorkspacesRequest getWorkspaces() {
+ GetWorkspacesRequest request = new GetWorkspacesRequest();
+ process(request);
+ return request;
+ }
+
+ /**
+ * Add a request to verify the existance of the named workspace.
+ *
+ * @param workspaceName the desired name of the workspace, or null if the source's default workspace should be used
+ * @return the request; never null
+ */
+ public VerifyWorkspaceRequest verifyWorkspace( String workspaceName ) {
+ return process(new VerifyWorkspaceRequest(workspaceName));
+ }
+
+ /**
+ * Add a request to create a new workspace, and specify the behavior should a workspace already exists with a name that
+ * matches the desired name for the new workspace.
+ *
+ * @param desiredNameOfNewWorkspace the desired name of the new workspace
+ * @param createConflictBehavior the behavior if a workspace already exists with the same name, or null if the default
+ * behavior should be used
+ * @return the request; never null
+ */
+ public CreateWorkspaceRequest createWorkspace( String desiredNameOfNewWorkspace,
+ CreateConflictBehavior createConflictBehavior ) {
+ return process(new CreateWorkspaceRequest(desiredNameOfNewWorkspace, createConflictBehavior));
+ }
+
+ /**
+ * Add a request to clone an existing workspace to create a new workspace, and specify the behavior should a workspace already
+ * exists with a name that matches the desired name for the new workspace.
+ *
+ * @param nameOfWorkspaceToBeCloned the name of the existing workspace that is to be cloned
+ * @param desiredNameOfTargetWorkspace the desired name of the target workspace
+ * @param createConflictBehavior the behavior if a workspace already exists with the same name
+ * @param cloneConflictBehavior the behavior if the workspace to be cloned does not exist
+ * @return the request; never null
+ * @throws IllegalArgumentException if the either workspace name is null
+ */
+ public CloneWorkspaceRequest cloneWorkspace( String nameOfWorkspaceToBeCloned,
+ String desiredNameOfTargetWorkspace,
+ CreateConflictBehavior createConflictBehavior,
+ CloneConflictBehavior cloneConflictBehavior ) {
+ return process(new CloneWorkspaceRequest(nameOfWorkspaceToBeCloned, desiredNameOfTargetWorkspace, createConflictBehavior,
+ cloneConflictBehavior));
+ }
+
+ /**
+ * Add a request to destroy an existing workspace.
+ *
+ * @param workspaceName the name of the workspace that is to be destroyed
+ * @return the request; never null
+ * @throws IllegalArgumentException if the workspace name is null
+ */
+ public DestroyWorkspaceRequest destroyWorkspace( String workspaceName ) {
+ return process(new DestroyWorkspaceRequest(workspaceName));
+ }
+
+ /**
+ * Add a request to verify the existance and location of a node at the supplied location.
+ *
+ * @param at the location of the node to be verified
+ * @param workspaceName the name of the workspace containing the node
+ * @return the request; never null
+ * @throws IllegalArgumentException if the location or workspace name is null
+ */
+ public VerifyNodeExistsRequest verifyNodeExists( Location at,
+ String workspaceName ) {
+ return process(new VerifyNodeExistsRequest(at, workspaceName));
+ }
+
+ /**
+ * Add a request to read the properties and number of children of a node at the supplied location.
+ *
+ * @param at the location of the node to be read
+ * @param workspaceName the name of the workspace containing the node
+ * @return the request; never null
+ * @throws IllegalArgumentException if the location or workspace name is null
+ */
+ public ReadNodeRequest readNode( Location at,
+ String workspaceName ) {
+ return process(new ReadNodeRequest(at, workspaceName));
+ }
+
+ /**
+ * Add a request to read the children of a node at the supplied location in the designated workspace.
+ *
+ * @param of the location of the node whose children are to be read
+ * @param workspaceName the name of the workspace
+ * @return the request; never null
+ * @throws IllegalArgumentException if the location or workspace name is null
+ */
+ public ReadAllChildrenRequest readAllChildren( Location of,
+ String workspaceName ) {
+ return process(new ReadAllChildrenRequest(of, workspaceName));
+ }
+
+ /**
+ * Add a request to read the properties and number of children of a node at the supplied location.
+ *
+ * @param of the location of the node whose children are to be read
+ * @param workspaceName the name of the workspace
+ * @return the request; never null
+ * @throws IllegalArgumentException if the location or workspace name is null
+ */
+ public ReadAllPropertiesRequest readAllProperties( Location of,
+ String workspaceName ) {
+ return process(new ReadAllPropertiesRequest(of, workspaceName));
+ }
+
+ /**
+ * Add a request to read the properties and number of children of a node at the supplied location.
+ *
+ * @param of the location of the node whose children are to be read
+ * @param workspaceName the name of the workspace
+ * @param propertyName the name of the property to read
+ * @return the request; never null
+ * @throws IllegalArgumentException if the location or workspace name is null
+ */
+ public ReadPropertyRequest readProperty( Location of,
+ String workspaceName,
+ Name propertyName ) {
+ return process(new ReadPropertyRequest(of, workspaceName, propertyName));
+ }
+
+ /**
+ * Add a request to read the branch at the supplied location, to a maximum depth of 2.
+ *
+ * @param at the location of the branch
+ * @param workspaceName the name of the workspace containing the branch
+ * @return the request; never null
+ * @throws IllegalArgumentException if the location or workspace name is null or if the maximum depth is not positive
+ */
+ public ReadBranchRequest readBranch( Location at,
+ String workspaceName ) {
+ return process(new ReadBranchRequest(at, workspaceName));
+ }
+
+ /**
+ * Add a request to read the branch (of given depth) at the supplied location.
+ *
+ * @param at the location of the branch
+ * @param workspaceName the name of the workspace containing the branch
+ * @param maxDepth the maximum depth to read
+ * @return the request; never null
+ * @throws IllegalArgumentException if the location or workspace name is null or if the maximum depth is not positive
+ */
+ public ReadBranchRequest readBranch( Location at,
+ String workspaceName,
+ int maxDepth ) {
+ return process(new ReadBranchRequest(at, workspaceName, maxDepth));
+ }
+
+ /**
+ * Add a request to read a block of the children of a node at the supplied location. The block is defined by the starting
+ * index of the first child and the number of children to include. Note that this index is <i>not</i> the
+ * {@link Path.Segment#getIndex() same-name-sibiling index}, but rather is the index of the child as if the children were in
+ * an array.
+ *
+ * @param of the location of the node whose children are to be read
+ * @param workspaceName the name of the workspace containing the parent
+ * @param startingIndex the zero-based index of the first child to be included in the block
+ * @param count the maximum number of children that should be included in the block
+ * @return the request; never null
+ * @throws IllegalArgumentException if the location or workspace name is null, if <code>startingIndex</code> is negative, or
+ * if <code>count</count> is less than 1.
+ */
+ public ReadBlockOfChildrenRequest readBlockOfChildren( Location of,
+ String workspaceName,
+ int startingIndex,
+ int count ) {
+ return process(new ReadBlockOfChildrenRequest(of, workspaceName, startingIndex, count));
+ }
+
+ /**
+ * Add a request to read those children of a node that are immediately after a supplied sibling node.
+ *
+ * @param startingAfter the location of the previous sibling that was the last child of the previous block of children read
+ * @param workspaceName the name of the workspace containing the node
+ * @param count the maximum number of children that should be included in the block
+ * @return the request; never null
+ * @throws IllegalArgumentException if the workspace name or <code>startingAfter</code> location is null, or if
+ * <code>count</count> is less than 1.
+ */
+ public ReadNextBlockOfChildrenRequest readNextBlockOfChildren( Location startingAfter,
+ String workspaceName,
+ int count ) {
+ return process(new ReadNextBlockOfChildrenRequest(startingAfter, workspaceName, count));
+ }
+
+ /**
+ * Add a request to create a node with the given properties under the supplied location.
+ *
+ * @param parentLocation the location of the existing parent node, under which the new child should be created
+ * @param workspaceName the name of the workspace containing the parent
+ * @param childName the name of the new child to create under the existing parent
+ * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
+ * properties} for the new node
+ * @return the request; never null
+ * @throws IllegalArgumentException if the location, workspace name, or child name is null
+ */
+ public CreateNodeRequest createNode( Location parentLocation,
+ String workspaceName,
+ Name childName,
+ Iterator<Property> properties ) {
+ return process(new CreateNodeRequest(parentLocation, workspaceName, childName,
+ CreateNodeRequest.DEFAULT_CONFLICT_BEHAVIOR, properties));
+ }
+
+ /**
+ * Add a request to create a node with the given properties under the supplied location.
+ *
+ * @param parentLocation the location of the existing parent node, under which the new child should be created
+ * @param workspaceName the name of the workspace containing the parent
+ * @param childName the name of the new child to create under the existing parent
+ * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
+ * properties} for the new node
+ * @param conflictBehavior the expected behavior if an equivalently-named child already exists under the <code>into</code>
+ * location
+ * @return the request; never null
+ * @throws IllegalArgumentException if the location, workspace name, or child name is null
+ */
+ public CreateNodeRequest createNode( Location parentLocation,
+ String workspaceName,
+ Name childName,
+ Iterator<Property> properties,
+ NodeConflictBehavior conflictBehavior ) {
+ if (conflictBehavior == null) conflictBehavior = CreateNodeRequest.DEFAULT_CONFLICT_BEHAVIOR;
+ return process(new CreateNodeRequest(parentLocation, workspaceName, childName, conflictBehavior, properties));
+ }
+
+ /**
+ * Add a request to create a node with the given properties under the supplied location.
+ *
+ * @param parentLocation the location of the existing parent node, under which the new child should be created
+ * @param workspaceName the name of the workspace containing the parent
+ * @param childName the name of the new child to create under the existing parent
+ * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
+ * properties} for the new node
+ * @return the request; never null
+ * @throws IllegalArgumentException if the location, workspace name, or child name is null
+ */
+ public CreateNodeRequest createNode( Location parentLocation,
+ String workspaceName,
+ Name childName,
+ Property[] properties ) {
+ return process(new CreateNodeRequest(parentLocation, workspaceName, childName,
+ CreateNodeRequest.DEFAULT_CONFLICT_BEHAVIOR, properties));
+ }
+
+ /**
+ * Add a request to create a node with the given properties under the supplied location.
+ *
+ * @param parentLocation the location of the existing parent node, under which the new child should be created
+ * @param workspaceName the name of the workspace containing the parent
+ * @param childName the name of the new child to create under the existing parent
+ * @param properties the properties of the new node, which should include any {@link Location#getIdProperties() identification
+ * properties} for the new node
+ * @param conflictBehavior the expected behavior if an equivalently-named child already exists under the <code>into</code>
+ * location
+ * @return the request; never null
+ * @throws IllegalArgumentException if the location, workspace name, or child name is null
+ */
+ public CreateNodeRequest createNode( Location parentLocation,
+ String workspaceName,
+ Name childName,
+ Property[] properties,
+ NodeConflictBehavior conflictBehavior ) {
+ if (conflictBehavior == null) conflictBehavior = CreateNodeRequest.DEFAULT_CONFLICT_BEHAVIOR;
+ return process(new CreateNodeRequest(parentLocation, workspaceName, childName, conflictBehavior, properties));
+ }
+
+ /**
+ * Add a request to update the property on the node at the supplied location. This request will create the property if it does
+ * not yet exist.
+ *
+ * @param on the location of the node to be read
+ * @param workspaceName the name of the workspace containing the node
+ * @param property the new property on the node
+ * @return the request; never null
+ * @throws IllegalArgumentException if the location or workspace name is null or if there are no properties to update
+ */
+ public SetPropertyRequest setProperty( Location on,
+ String workspaceName,
+ Property property ) {
+ return process(new SetPropertyRequest(on, workspaceName, property));
+ }
+
+ /**
+ * Add a request to update the properties on the node at the supplied location.
+ *
+ * @param on the location of the node to be read
+ * @param workspaceName the name of the workspace containing the node
+ * @param properties the new properties on the node
+ * @return the {@link SetPropertyRequest} or {@link UpdatePropertiesRequest} request, depending upon the number of properties
+ * being set; never null
+ * @throws IllegalArgumentException if the location or workspace name is null or if there are no properties to update
+ */
+ public Request setProperties( Location on,
+ String workspaceName,
+ Property... properties ) {
+ if (properties.length == 1) {
+ return process(new SetPropertyRequest(on, workspaceName, properties[0]));
+ }
+ Map<Name, Property> propertyMap = new HashMap<Name, Property>();
+ for (Property property : properties) {
+ propertyMap.put(property.getName(), property);
+ }
+ return process(new UpdatePropertiesRequest(on, workspaceName, propertyMap));
+ }
+
+ /**
+ * Add a request to remove the property with the supplied name from the given node. Supplying a name for a property that does
+ * not exist will not cause an error.
+ *
+ * @param on the location of the node to be read
+ * @param workspaceName the name of the workspace containing the node
+ * @param propertyName the name of the property that is to be removed
+ * @return the request; never null
+ * @throws IllegalArgumentException if the location or workspace name is null or if there are no properties to remove
+ */
+ public RemovePropertyRequest removeProperty( Location on,
+ String workspaceName,
+ Name propertyName ) {
+ return process(new RemovePropertyRequest(on, workspaceName, propertyName));
+ }
+
+ /**
+ * Add a request to remove from the node the properties with the supplied names. Supplying a name for a property that does not
+ * exist will not cause an error.
+ *
+ * @param on the location of the node to be read
+ * @param workspaceName the name of the workspace containing the node
+ * @param propertyNames the names of the properties that are to be removed
+ * @return the {@link RemovePropertyRequest} or {@link UpdatePropertiesRequest} request, depending upon the number of
+ * properties being removed; never null
+ * @throws IllegalArgumentException if the location or workspace name is null or if there are no properties to remove
+ */
+ public Request removeProperties( Location on,
+ String workspaceName,
+ Name... propertyNames ) {
+ if (propertyNames.length == 1) {
+ return process(new RemovePropertyRequest(on, workspaceName, propertyNames[0]));
+ }
+ Map<Name, Property> properties = new HashMap<Name, Property>();
+ for (Name propertyName : propertyNames) {
+ properties.put(propertyName, null);
+ }
+ return process(new UpdatePropertiesRequest(on, workspaceName, properties));
+ }
+
+ /**
+ * Add a request to rename the node at the supplied location.
+ *
+ * @param at the location of the node to be read
+ * @param workspaceName the name of the workspace containing the node
+ * @param newName the new name for the node
+ * @return the request; never null
+ * @throws IllegalArgumentException if the location or workspace name is null
+ */
+ public RenameNodeRequest renameNode( Location at,
+ String workspaceName,
+ Name newName ) {
+ return process(new RenameNodeRequest(at, workspaceName, newName));
+ }
+
+ /**
+ * Add a request to copy a branch to another.
+ *
+ * @param from the location of the top node in the existing branch that is to be copied
+ * @param fromWorkspace the name of the workspace where the <code>from</code> node exists
+ * @param into the location of the existing node into which the copy should be placed
+ * @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>
+ * location, or null if the default conflict behavior should be used
+ * @return the request; never null
+ * @throws IllegalArgumentException if either of the locations or workspace names are null
+ */
+ public CopyBranchRequest copyBranch( Location from,
+ String fromWorkspace,
+ 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));
+ }
+
+ /**
+ * Create a request to move a branch from one location into another.
+ *
+ * @param from the location of the top node in the existing branch that is to be moved
+ * @param into the location of the existing node into which the branch should be moved
+ * @param workspaceName the name of the workspace
+ * @return the request; never null
+ * @throws IllegalArgumentException if any of the parameters are null
+ */
+ public MoveBranchRequest moveBranch( Location from,
+ Location into,
+ String workspaceName ) {
+ return process(new MoveBranchRequest(from, into, workspaceName, MoveBranchRequest.DEFAULT_CONFLICT_BEHAVIOR));
+ }
+
+ /**
+ * Create a request to move a branch from one location into another.
+ *
+ * @param from the location of the top node in the existing branch that is to be moved
+ * @param into the location of the existing node into which the branch should be moved
+ * @param workspaceName the name of the workspace
+ * @param conflictBehavior the expected behavior if an equivalently-named child already exists at the <code>into</code>
+ * location
+ * @return the request; never null
+ * @throws IllegalArgumentException if any of the parameters are null
+ */
+ public MoveBranchRequest moveBranch( Location from,
+ Location into,
+ String workspaceName,
+ NodeConflictBehavior conflictBehavior ) {
+ if (conflictBehavior == null) conflictBehavior = MoveBranchRequest.DEFAULT_CONFLICT_BEHAVIOR;
+ return process(new MoveBranchRequest(from, into, workspaceName, conflictBehavior));
+ }
+
+ /**
+ * Add a request to delete a branch.
+ *
+ * @param at the location of the top node in the existing branch that is to be deleted
+ * @param workspaceName the name of the workspace containing the parent
+ * @return the request; never null
+ * @throws IllegalArgumentException if the location or workspace name is null
+ */
+ public DeleteBranchRequest deleteBranch( Location at,
+ String workspaceName ) {
+ return process(new DeleteBranchRequest(at, workspaceName));
+ }
+}
Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/RequestBuilder.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/SetPropertyRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/SetPropertyRequest.java (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/SetPropertyRequest.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -0,0 +1,178 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph.request;
+
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+
+/**
+ * Instruction to set a particular property on the node at the specified location. This request <i>never</i> removes the node,
+ * even if the property is empty.
+ *
+ * @author Randall Hauch
+ */
+public class SetPropertyRequest extends Request implements ChangeRequest {
+
+ private static final long serialVersionUID = 1L;
+
+ private final Location on;
+ private final String workspaceName;
+ private final Property property;
+ private Location actualLocation;
+
+ /**
+ * Create a request to set the property on the node at the supplied location.
+ *
+ * @param on the location of the node to be read
+ * @param workspaceName the name of the workspace containing the node
+ * @param property the new property on the node
+ * @throws IllegalArgumentException if the location, workspace name, or property is null
+ */
+ public SetPropertyRequest( Location on,
+ String workspaceName,
+ Property property ) {
+ CheckArg.isNotNull(on, "on");
+ CheckArg.isNotNull(property, "property");
+ CheckArg.isNotNull(workspaceName, "workspaceName");
+ this.workspaceName = workspaceName;
+ this.on = on;
+ this.property = property;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.request.Request#isReadOnly()
+ */
+ @Override
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ /**
+ * Get the location defining the node that is to be updated.
+ *
+ * @return the location of the node; never null
+ */
+ public Location on() {
+ return on;
+ }
+
+ /**
+ * Get the name of the workspace in which the node exists.
+ *
+ * @return the name of the workspace; never null
+ */
+ public String inWorkspace() {
+ return workspaceName;
+ }
+
+ /**
+ * Get the property that is being set.
+ *
+ * @return the new property; never null
+ */
+ public Property property() {
+ return property;
+ }
+
+ /**
+ * Sets the actual and complete location of the node being updated. This method must be called when processing the request,
+ * and the actual location must have a {@link Location#getPath() path}.
+ *
+ * @param actual the actual location of the node being updated, or null if the {@link #on() current location} should be used
+ * @throws IllegalArgumentException if the actual location does represent the {@link Location#isSame(Location) same location}
+ * as the {@link #on() current location}, or if the actual location does not have a path.
+ */
+ public void setActualLocationOfNode( Location actual ) {
+ if (!on.isSame(actual)) { // not same if actual is null
+ throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, on));
+ }
+ assert actual != null;
+ if (!actual.hasPath()) {
+ throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
+ }
+ this.actualLocation = actual;
+ }
+
+ /**
+ * Get the actual location of the node that was updated.
+ *
+ * @return the actual location, or null if the actual location was not set
+ */
+ public Location getActualLocationOfNode() {
+ return actualLocation;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.request.ChangeRequest#changes(java.lang.String, org.jboss.dna.graph.property.Path)
+ */
+ public boolean changes( String workspace,
+ Path path ) {
+ return this.workspaceName.equals(workspace) && on.hasPath() && on.getPath().isAtOrBelow(path);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (this.getClass().isInstance(obj)) {
+ SetPropertyRequest that = (SetPropertyRequest)obj;
+ if (!this.on().equals(that.on())) return false;
+ if (!this.property().equals(that.property())) return false;
+ if (!this.inWorkspace().equals(that.inWorkspace())) return false;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.request.ChangeRequest#changedLocation()
+ */
+ public Location changedLocation() {
+ return on;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "set property " + property().getName() + " on " + on() + " in the \"" + workspaceName + "\" workspace to "
+ + property().getValuesAsArray();
+ }
+}
Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/SetPropertyRequest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/UpdatePropertiesRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/UpdatePropertiesRequest.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/UpdatePropertiesRequest.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -23,14 +23,8 @@
*/
package org.jboss.dna.graph.request;
-import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
+import java.util.Map;
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.graph.GraphI18n;
import org.jboss.dna.graph.Location;
@@ -39,17 +33,32 @@
import org.jboss.dna.graph.property.Property;
/**
- * Instruction to update the properties on the node at the specified location. Any property with no values will be removed.
+ * Instruction to update the properties on the node at the specified location.
+ * <p>
+ * This request is capable of specifying that certain properties are to have new values and that other properties are to be
+ * removed. The request has a single map of properties keyed by their name. If a property is to be set with new values, the map
+ * will contain an entry with the property keyed by its name. However, if a property is to be removed, the entry will contain the
+ * property name for the key but will have a null entry value.
+ * </p>
+ * <p>
+ * The use of the map also ensures that a single property appears only once in the request (it either has new values or it is to
+ * be removed).
+ * </p>
+ * <p>
+ * Note that the number of values in a property (e.g., {@link Property#size()}, {@link Property#isEmpty()},
+ * {@link Property#isSingle()}, and {@link Property#isMultiple()}) has no influence on whether the property should be removed. It
+ * is possible for a property to have no values.
+ * </p>
*
* @author Randall Hauch
*/
-public class UpdatePropertiesRequest extends Request implements Iterable<Property>, ChangeRequest {
+public class UpdatePropertiesRequest extends Request implements ChangeRequest {
private static final long serialVersionUID = 1L;
private final Location on;
private final String workspaceName;
- private final List<Property> properties;
+ private final Map<Name, Property> properties;
private Location actualLocation;
/**
@@ -57,90 +66,21 @@
*
* @param on the location of the node to be read
* @param workspaceName the name of the workspace containing the node
- * @param properties the new properties on the node
+ * @param properties the map of properties (keyed by their name), which is reused without copying
* @throws IllegalArgumentException if the location or workspace name is null or if there are no properties to update
*/
public UpdatePropertiesRequest( Location on,
String workspaceName,
- Property... properties ) {
+ Map<Name, Property> properties ) {
CheckArg.isNotNull(on, "on");
CheckArg.isNotEmpty(properties, "properties");
CheckArg.isNotNull(workspaceName, "workspaceName");
this.workspaceName = workspaceName;
this.on = on;
- this.properties = Collections.unmodifiableList(Arrays.asList(properties));
+ this.properties = Collections.unmodifiableMap(properties);
}
/**
- * Create a request to update the properties on the node at the supplied location.
- *
- * @param on the location of the node to be read
- * @param workspaceName the name of the workspace containing the node
- * @param properties the new properties on the node
- * @throws IllegalArgumentException if the location or workspace name is null or if there are no properties to update
- */
- public UpdatePropertiesRequest( Location on,
- String workspaceName,
- Iterable<Property> properties ) {
- CheckArg.isNotNull(on, "on");
- CheckArg.isNotNull(properties, "properties");
- CheckArg.isNotNull(workspaceName, "workspaceName");
- this.workspaceName = workspaceName;
- this.on = on;
- List<Property> props = new LinkedList<Property>();
- for (Property property : properties) {
- if (property != null) props.add(property);
- }
- this.properties = Collections.unmodifiableList(props);
- CheckArg.isNotEmpty(this.properties, "properties");
- }
-
- /**
- * Create a request to update the properties on the node at the supplied location.
- *
- * @param on the location of the node to be read
- * @param workspaceName the name of the workspace containing the node
- * @param properties the new properties on the node
- * @throws IllegalArgumentException if the location or workspace name is null or if there are no properties to update
- */
- public UpdatePropertiesRequest( Location on,
- String workspaceName,
- Iterator<Property> properties ) {
- CheckArg.isNotNull(on, "on");
- CheckArg.isNotNull(properties, "properties");
- CheckArg.isNotNull(workspaceName, "workspaceName");
- this.workspaceName = workspaceName;
- this.on = on;
- List<Property> props = new LinkedList<Property>();
- while (properties.hasNext()) {
- Property property = properties.next();
- if (property != null) props.add(property);
- }
- this.properties = Collections.unmodifiableList(props);
- CheckArg.isNotEmpty(this.properties, "properties");
- }
-
- /**
- * Create a request to update the properties on the node at the supplied location.
- *
- * @param on the location of the node to be read
- * @param workspaceName the name of the workspace containing the node
- * @param properties the new properties on the node
- * @throws IllegalArgumentException if the location or workspace name is null or if there are no properties to update
- */
- private UpdatePropertiesRequest( Location on,
- String workspaceName,
- List<Property> properties ) {
- CheckArg.isNotNull(on, "on");
- CheckArg.isNotNull(properties, "properties");
- CheckArg.isNotNull(workspaceName, "workspaceName");
- this.workspaceName = workspaceName;
- this.on = on;
- this.properties = properties;
- CheckArg.isNotEmpty(this.properties, "properties");
- }
-
- /**
* {@inheritDoc}
*
* @see org.jboss.dna.graph.request.Request#isReadOnly()
@@ -169,20 +109,12 @@
}
/**
- * {@inheritDoc}
+ * Get the map of properties for the node, keyed by property name. Any property to be removed will have a map entry with a
+ * null value.
*
- * @see java.lang.Iterable#iterator()
+ * @return the properties being updated; never null and never empty
*/
- public Iterator<Property> iterator() {
- return this.properties.iterator();
- }
-
- /**
- * Get the properties for the node.
- *
- * @return the collection of properties; never null and never empty
- */
- public Collection<Property> properties() {
+ public Map<Name, Property> properties() {
return properties;
}
@@ -261,39 +193,4 @@
return "update properties on " + on() + " in the \"" + workspaceName + "\" workspace to " + properties();
}
- /**
- * Merge these updates with those in the supplied request, with the supplied changes overwriting any similar changes on this
- * node.
- *
- * @param other the other updates that are to be merged with these
- * @return the merged request
- */
- public UpdatePropertiesRequest mergeWith( UpdatePropertiesRequest other ) {
- if (other == null) return this;
- if (other.properties().size() == 1) {
- Property newProp = other.properties.get(0);
- List<Property> newProps = new LinkedList<Property>();
- for (Property prop : this.properties) {
- if (!prop.getName().equals(newProp.getName())) {
- newProps.add(prop);
- }
- }
- newProps.add(newProp);
- return new UpdatePropertiesRequest(on, workspaceName, Collections.unmodifiableList(newProps));
- }
- Set<Name> otherNames = new HashSet<Name>();
- for (Property prop : other.properties()) {
- otherNames.add(prop.getName());
- }
- List<Property> newProps = new LinkedList<Property>();
- for (Property prop : this.properties) {
- if (!otherNames.contains(prop.getName())) {
- newProps.add(prop);
- }
- }
- newProps.addAll(other.properties);
- return new UpdatePropertiesRequest(on, workspaceName, Collections.unmodifiableList(newProps));
-
- }
-
}
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/package-info.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/package-info.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/package-info.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -148,8 +148,10 @@
* <li>{@link UpdatePropertiesRequest} - A request to update one or more properties on a node. Any property
* with no values will be removed, while properties with one or more values will be set (replace any existing property
* with the same name, if they exist). </li>
- * <li>{@link RemovePropertiesRequest} - A request to remove one or more properties on a node. No error is reported
+ * <li>{@link RemovePropertyRequest} - A request to remove one property from a node. No error is reported
* if the node does not contain a property that is to be removed.</li>
+ * <li>{@link SetPropertyRequest} - A request to set one property on a node. No error is reported
+ * if the node does not already have the property, since the property is just created.</li>
* <li>{@link DeleteBranchRequest} - A request to delete a node and all nodes located below it.</li>
* <li>{@link CompositeRequest} - A request that acts as a container for multiple other requests (of various kinds),
* allowing you to batch together multiple for processing. Use the one of the {@link CompositeRequest#with(Request...) CompositeRequest.with(...)}
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/LoggingRequestProcessor.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/LoggingRequestProcessor.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/LoggingRequestProcessor.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -42,10 +42,12 @@
import org.jboss.dna.graph.request.ReadNextBlockOfChildrenRequest;
import org.jboss.dna.graph.request.ReadNodeRequest;
import org.jboss.dna.graph.request.ReadPropertyRequest;
-import org.jboss.dna.graph.request.RemovePropertiesRequest;
+import org.jboss.dna.graph.request.RemovePropertyRequest;
import org.jboss.dna.graph.request.RenameNodeRequest;
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.VerifyNodeExistsRequest;
import org.jboss.dna.graph.request.VerifyWorkspaceRequest;
/**
@@ -185,6 +187,18 @@
/**
* {@inheritDoc}
*
+ * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.VerifyNodeExistsRequest)
+ */
+ @Override
+ public void process( VerifyNodeExistsRequest request ) {
+ logger.log(level, GraphI18n.executingRequest, request);
+ delegate.process(request);
+ logger.log(level, GraphI18n.executedRequest, request);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllChildrenRequest)
*/
@Override
@@ -293,10 +307,10 @@
/**
* {@inheritDoc}
*
- * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.RemovePropertiesRequest)
+ * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.SetPropertyRequest)
*/
@Override
- public void process( RemovePropertiesRequest request ) {
+ public void process( SetPropertyRequest request ) {
logger.log(level, GraphI18n.executingRequest, request);
delegate.process(request);
logger.log(level, GraphI18n.executedRequest, request);
@@ -305,6 +319,18 @@
/**
* {@inheritDoc}
*
+ * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.RemovePropertyRequest)
+ */
+ @Override
+ public void process( RemovePropertyRequest request ) {
+ logger.log(level, GraphI18n.executingRequest, request);
+ delegate.process(request);
+ logger.log(level, GraphI18n.executedRequest, request);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.RenameNodeRequest)
*/
@Override
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/RequestProcessor.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/RequestProcessor.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/RequestProcessor.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -23,10 +23,10 @@
*/
package org.jboss.dna.graph.request.processor;
-import java.util.ArrayList;
-import java.util.Collection;
+import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.Queue;
import net.jcip.annotations.Immutable;
import org.jboss.dna.common.util.CheckArg;
@@ -40,7 +40,6 @@
import org.jboss.dna.graph.property.Path;
import org.jboss.dna.graph.property.Property;
import org.jboss.dna.graph.property.ReferentialIntegrityException;
-import org.jboss.dna.graph.property.basic.BasicEmptyProperty;
import org.jboss.dna.graph.request.CacheableRequest;
import org.jboss.dna.graph.request.CloneWorkspaceRequest;
import org.jboss.dna.graph.request.CompositeRequest;
@@ -59,9 +58,10 @@
import org.jboss.dna.graph.request.ReadNextBlockOfChildrenRequest;
import org.jboss.dna.graph.request.ReadNodeRequest;
import org.jboss.dna.graph.request.ReadPropertyRequest;
-import org.jboss.dna.graph.request.RemovePropertiesRequest;
+import org.jboss.dna.graph.request.RemovePropertyRequest;
import org.jboss.dna.graph.request.RenameNodeRequest;
import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.SetPropertyRequest;
import org.jboss.dna.graph.request.UnsupportedRequestException;
import org.jboss.dna.graph.request.UpdatePropertiesRequest;
import org.jboss.dna.graph.request.VerifyNodeExistsRequest;
@@ -190,8 +190,10 @@
process((ReadAllPropertiesRequest)request);
} else if (request instanceof ReadPropertyRequest) {
process((ReadPropertyRequest)request);
- } else if (request instanceof RemovePropertiesRequest) {
- process((RemovePropertiesRequest)request);
+ } else if (request instanceof RemovePropertyRequest) {
+ process((RemovePropertyRequest)request);
+ } else if (request instanceof SetPropertyRequest) {
+ process((SetPropertyRequest)request);
} else if (request instanceof RenameNodeRequest) {
process((RenameNodeRequest)request);
} else if (request instanceof UpdatePropertiesRequest) {
@@ -608,23 +610,18 @@
}
/**
- * Process a request to remove the specified properties from a node.
+ * Process a request to remove the specified property from a node.
* <p>
* This method does nothing if the request is null. Unless overridden, this method converts this request into a
* {@link UpdatePropertiesRequest}.
* </p>
*
- * @param request the request to remove the properties with certain names
+ * @param request the request to remove the property
*/
- public void process( RemovePropertiesRequest request ) {
+ public void process( RemovePropertyRequest request ) {
if (request == null) return;
- Collection<Name> names = request.propertyNames();
- if (names.isEmpty()) return;
- List<Property> emptyProperties = new ArrayList<Property>(names.size());
- for (Name propertyName : names) {
- emptyProperties.add(new BasicEmptyProperty(propertyName));
- }
- UpdatePropertiesRequest update = new UpdatePropertiesRequest(request.from(), request.inWorkspace(), emptyProperties);
+ Map<Name, Property> properties = Collections.singletonMap(request.propertyName(), null);
+ UpdatePropertiesRequest update = new UpdatePropertiesRequest(request.from(), request.inWorkspace(), properties);
process(update);
if (update.hasError()) {
request.setError(update.getError());
@@ -634,6 +631,29 @@
}
/**
+ * Process a request to set the specified property on a node.
+ * <p>
+ * This method does nothing if the request is null. Unless overridden, this method converts this request into a
+ * {@link UpdatePropertiesRequest}.
+ * </p>
+ *
+ * @param request the request to set the property
+ */
+ public void process( SetPropertyRequest request ) {
+ if (request == null) return;
+ Property property = request.property();
+ Map<Name, Property> properties = Collections.singletonMap(property.getName(), property);
+ UpdatePropertiesRequest update = new UpdatePropertiesRequest(request.on(), request.inWorkspace(), properties);
+ process(update);
+ if (update.hasError()) {
+ request.setError(update.getError());
+ } else {
+ // Set the actual location ...
+ request.setActualLocationOfNode(update.getActualLocationOfNode());
+ }
+ }
+
+ /**
* Process a request to remove the specified properties from a node.
* <p>
* This method does nothing if the request is null.
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-04-06 15:55:23 UTC (rev 808)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -70,6 +70,7 @@
import org.jboss.dna.graph.request.ReadNodeRequest;
import org.jboss.dna.graph.request.ReadPropertyRequest;
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.VerifyNodeExistsRequest;
import org.jboss.dna.graph.request.VerifyWorkspaceRequest;
@@ -319,9 +320,18 @@
assertThat(request, is(instanceOf(UpdatePropertiesRequest.class)));
UpdatePropertiesRequest read = (UpdatePropertiesRequest)request;
assertThat(read.on(), is(on));
- assertThat(read.properties(), hasItems(properties));
+ assertThat(read.properties().values(), hasItems(properties));
}
+ protected void assertNextRequestSetProperty( Location on,
+ Property property ) {
+ Request request = executedRequests.poll();
+ assertThat(request, is(instanceOf(SetPropertyRequest.class)));
+ SetPropertyRequest read = (SetPropertyRequest)request;
+ assertThat(read.on(), is(on));
+ assertThat(read.property(), is(property));
+ }
+
// ----------------------------------------------------------------------------------------------------------------
// Immediate requests
// ----------------------------------------------------------------------------------------------------------------
@@ -623,53 +633,80 @@
}
@Test
- public void shouldSetPropertiesWithEitherOnOrToMethodsCalledFirst() {
+ public void shouldSetPropertyWithEitherOnOrToMethodsCalledFirst() {
graph.set("propName").on(validPath).to(3.0f);
- assertNextRequestUpdateProperties(Location.create(validPath), createProperty("propName", 3.0f));
+ assertNextRequestSetProperty(Location.create(validPath), createProperty("propName", 3.0f));
graph.set("propName").to(3.0f).on(validPath);
- assertNextRequestUpdateProperties(Location.create(validPath), createProperty("propName", 3.0f));
+ assertNextRequestSetProperty(Location.create(validPath), createProperty("propName", 3.0f));
}
@Test
public void shouldSetPropertyValueToPrimitiveTypes() {
graph.set("propName").on(validPath).to(3.0F);
- assertNextRequestUpdateProperties(Location.create(validPath), createProperty("propName", new Float(3.0f)));
+ assertNextRequestSetProperty(Location.create(validPath), createProperty("propName", new Float(3.0f)));
graph.set("propName").on(validPath).to(1.0D);
- assertNextRequestUpdateProperties(Location.create(validPath), createProperty("propName", new Double(1.0)));
+ assertNextRequestSetProperty(Location.create(validPath), createProperty("propName", new Double(1.0)));
graph.set("propName").on(validPath).to(false);
- assertNextRequestUpdateProperties(Location.create(validPath), createProperty("propName", Boolean.FALSE));
+ assertNextRequestSetProperty(Location.create(validPath), createProperty("propName", Boolean.FALSE));
graph.set("propName").on(validPath).to(3);
- assertNextRequestUpdateProperties(Location.create(validPath), createProperty("propName", new Integer(3)));
+ assertNextRequestSetProperty(Location.create(validPath), createProperty("propName", new Integer(3)));
graph.set("propName").on(validPath).to(5L);
- assertNextRequestUpdateProperties(Location.create(validPath), createProperty("propName", new Long(5)));
+ assertNextRequestSetProperty(Location.create(validPath), createProperty("propName", new Long(5)));
graph.set("propName").on(validPath).to(validPath);
- assertNextRequestUpdateProperties(Location.create(validPath), createProperty("propName", validPath));
+ assertNextRequestSetProperty(Location.create(validPath), createProperty("propName", validPath));
graph.set("propName").on(validPath).to(validPath.getLastSegment().getName());
- assertNextRequestUpdateProperties(Location.create(validPath), createProperty("propName", validPath.getLastSegment()
- .getName()));
+ assertNextRequestSetProperty(Location.create(validPath), createProperty("propName", validPath.getLastSegment().getName()));
Date now = new Date();
graph.set("propName").on(validPath).to(now);
- assertNextRequestUpdateProperties(Location.create(validPath), createProperty("propName", now));
+ assertNextRequestSetProperty(Location.create(validPath), createProperty("propName", now));
DateTime dtNow = context.getValueFactories().getDateFactory().create(now);
graph.set("propName").on(validPath).to(dtNow);
- assertNextRequestUpdateProperties(Location.create(validPath), createProperty("propName", dtNow));
+ assertNextRequestSetProperty(Location.create(validPath), createProperty("propName", dtNow));
Calendar calNow = Calendar.getInstance();
calNow.setTime(now);
graph.set("propName").on(validPath).to(calNow);
- assertNextRequestUpdateProperties(Location.create(validPath), createProperty("propName", dtNow));
+ assertNextRequestSetProperty(Location.create(validPath), createProperty("propName", dtNow));
+ }
+ @Test
+ public void shouldSetMultiplePropertiesAtOnce() {
+ Property p1 = createProperty("propName1", new Float(3.0f));
+ Property p2 = createProperty("propName2", new Double(1.0));
+ Property p3 = createProperty("propName3", "String value");
+ graph.batch().set(p1, p2, p3).on(validPath).execute();
+ assertNextRequestUpdateProperties(Location.create(validPath), p1, p2, p3);
}
@Test
+ public void shouldCombineAdjacentSetPropertyCalls() {
+ Property p1 = createProperty("propName1", new Float(3.0f));
+ Property p2 = createProperty("propName2", new Double(1.0));
+ Property p3 = createProperty("propName3", "String value");
+ graph.batch().set(p1).on(validPath).and().set(p2).on(validPath).and().set(p3).on(validPath).execute();
+ assertNextRequestUpdateProperties(Location.create(validPath), p1, p2, p3);
+ }
+
+ @Test
+ public void shouldNotCombineNonAdjacentSetPropertyCalls() {
+ Property p1 = createProperty("propName1", new Float(3.0f));
+ Property p2 = createProperty("propName2", new Double(1.0));
+ Property p3 = createProperty("propName3", "String value");
+ graph.batch().set(p1).on(validPath).and().set(p2).on(validPath).and().set(p3).on(validUuid).execute();
+ extractRequestsFromComposite();
+ assertNextRequestUpdateProperties(Location.create(validPath), p1, p2);
+ assertNextRequestSetProperty(Location.create(validUuid), p3);
+ }
+
+ @Test
public void shouldReadNode() {
Location child1 = Location.create(createPath(validPath, "x"));
Location child2 = Location.create(createPath(validPath, "y"));
Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/AbstractConnectorTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/AbstractConnectorTest.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/AbstractConnectorTest.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -494,7 +494,7 @@
if (stopwatch != null) {
stopwatch.stop();
if (output != null) {
- output.println(" " + getTotalAndAverageDuration(stopwatch));
+ output.println(" " + getTotalAndAverageDuration(stopwatch, totalNumberCreated));
}
// Perform second batch ...
@@ -504,20 +504,21 @@
sw.start();
batch.execute();
sw.stop();
- System.out.println(" final " + getTotalAndAverageDuration(stopwatch));
+ System.out.println(" final " + getTotalAndAverageDuration(sw, totalNumberCreated));
assertThat(totalNumberCreated, is(totalNumber + calculateTotalNumberOfNodesInTree(2, 2, false)));
}
return (int)totalNumberCreated;
}
- protected String getTotalAndAverageDuration( Stopwatch stopwatch ) {
- long totalDurationInMicroseconds = TimeUnit.NANOSECONDS.toMicros(stopwatch.getTotalDuration().longValue());
- long totalNumber = stopwatch.getCount();
- long avgDuration = totalDurationInMicroseconds / totalNumber / 1000L;
+ protected String getTotalAndAverageDuration( Stopwatch stopwatch,
+ long numNodes ) {
+ long totalDurationInMilliseconds = TimeUnit.NANOSECONDS.toMillis(stopwatch.getTotalDuration().longValue());
+ long avgDuration = totalDurationInMilliseconds / numNodes;
String units = " millisecond(s)";
- if (avgDuration == 0L) {
- avgDuration = totalDurationInMicroseconds / totalNumber;
+ if (avgDuration < 1L) {
+ long totalDurationInMicroseconds = TimeUnit.NANOSECONDS.toMicros(stopwatch.getTotalDuration().longValue());
+ avgDuration = totalDurationInMicroseconds / numNodes;
units = " microsecond(s)";
}
return "total = " + stopwatch.getTotalDuration() + "; avg = " + avgDuration + units;
Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/RemovePropertiesRequestTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/RemovePropertiesRequestTest.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/RemovePropertiesRequestTest.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -1,190 +0,0 @@
-/*
- * JBoss DNA (http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
- * is licensed to you under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * JBoss DNA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.graph.request;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.hasItems;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import org.jboss.dna.graph.property.Name;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class RemovePropertiesRequestTest extends AbstractRequestTest {
-
- private RemovePropertiesRequest request;
- private Name validPropertyName1;
- private Name validPropertyName2;
- private Name validPropertyName3;
-
- @Override
- @Before
- public void beforeEach() {
- super.beforeEach();
- validPropertyName1 = createName("foo1");
- validPropertyName2 = createName("foo2");
- validPropertyName3 = createName("foo3");
- }
-
- @Override
- protected Request createRequest() {
- return new RemovePropertiesRequest(validPathLocation1, workspace1, validPropertyName1);
- }
-
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowCreatingRequestWithNullFromLocation() {
- new RemovePropertiesRequest(null, workspace1, validPropertyName1);
- }
-
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowCreatingRequestWithNullFromWorkspaceName() {
- new RemovePropertiesRequest(validPathLocation1, null, validPropertyName1);
- }
-
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowCreatingRequestWithNullPropertyName() {
- new RemovePropertiesRequest(validPathLocation, workspace1, (Name[])null);
- }
-
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowCreatingRequestWithEmptyPropertyNameArray() {
- new RemovePropertiesRequest(validPathLocation, workspace1, new Name[] {});
- }
-
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowCreatingRequestWithNullPropertyNameIterator() {
- new RemovePropertiesRequest(validPathLocation, workspace1, (Iterator<Name>)null);
- }
-
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowCreatingRequestWithEmptyPropertyNameIterator() {
- new RemovePropertiesRequest(validPathLocation, workspace1, new ArrayList<Name>().iterator());
- }
-
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowCreatingRequestWithNullPropertyNameIterable() {
- new RemovePropertiesRequest(validPathLocation, workspace1, (Iterable<Name>)null);
- }
-
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowCreatingRequestWithEmptyPropertyNameIterable() {
- new RemovePropertiesRequest(validPathLocation, workspace1, new ArrayList<Name>());
- }
-
- @Test
- public void shouldCreateValidRequestWithValidLocationAndValidPropertyName() {
- request = new RemovePropertiesRequest(validPathLocation1, workspace1, validPropertyName1);
- assertThat(request.from(), is(sameInstance(validPathLocation1)));
- assertThat(request.inWorkspace(), is(sameInstance(workspace1)));
- assertThat(request.hasError(), is(false));
- assertThat(request.getError(), is(nullValue()));
- assertThat(request.propertyNames(), hasItems(validPropertyName1));
- }
-
- @Test
- public void shouldCreateValidRequestWithValidLocationAndValidPropertyNames() {
- request = new RemovePropertiesRequest(validPathLocation1, workspace1, validPropertyName1, validPropertyName2);
- assertThat(request.from(), is(sameInstance(validPathLocation1)));
- assertThat(request.hasError(), is(false));
- assertThat(request.getError(), is(nullValue()));
- assertThat(request.propertyNames(), hasItems(validPropertyName1, validPropertyName2));
- }
-
- @Test
- public void shouldCreateValidRequestWithValidLocationAndIteratorOverValidPropertyName() {
- List<Name> names = new ArrayList<Name>();
- names.add(validPropertyName1);
- request = new RemovePropertiesRequest(validPathLocation1, workspace1, names);
- assertThat(request.from(), is(sameInstance(validPathLocation1)));
- assertThat(request.hasError(), is(false));
- assertThat(request.getError(), is(nullValue()));
- assertThat(request.propertyNames(), hasItems(validPropertyName1));
- }
-
- @Test
- public void shouldCreateValidRequestWithValidLocationAndIteratorOverValidPropertyNames() {
- List<Name> names = new ArrayList<Name>();
- names.add(validPropertyName1);
- names.add(validPropertyName2);
- names.add(validPropertyName3);
- request = new RemovePropertiesRequest(validPathLocation1, workspace1, names.iterator());
- assertThat(request.from(), is(sameInstance(validPathLocation1)));
- assertThat(request.hasError(), is(false));
- assertThat(request.getError(), is(nullValue()));
- assertThat(request.propertyNames(), hasItems(validPropertyName1, validPropertyName2, validPropertyName3));
- }
-
- @Test
- public void shouldCreateValidRequestWithValidLocationAndIterableWithValidPropertyNames() {
- List<Name> names = new ArrayList<Name>();
- names.add(validPropertyName1);
- names.add(validPropertyName2);
- names.add(validPropertyName3);
- request = new RemovePropertiesRequest(validPathLocation1, workspace1, names);
- assertThat(request.from(), is(sameInstance(validPathLocation1)));
- assertThat(request.hasError(), is(false));
- assertThat(request.getError(), is(nullValue()));
- assertThat(request.propertyNames(), hasItems(validPropertyName1, validPropertyName2, validPropertyName3));
- }
-
- @Test
- public void shouldConsiderEqualTwoRequestsWithSameLocationsAndSamePropertyNames() {
- request = new RemovePropertiesRequest(validPathLocation1, workspace1, validPropertyName1, validPropertyName2);
- RemovePropertiesRequest request2 = new RemovePropertiesRequest(validPathLocation1, workspace1, validPropertyName1,
- validPropertyName2);
- assertThat(request, is(request2));
- }
-
- @Test
- public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
- request = new RemovePropertiesRequest(validPathLocation1, workspace1, validPropertyName1, validPropertyName2);
- RemovePropertiesRequest request2 = new RemovePropertiesRequest(validPathLocation2, workspace1, validPropertyName1,
- validPropertyName2);
- assertThat(request.equals(request2), is(false));
- }
-
- @Test
- public void shouldConsiderNotEqualTwoRequestsWithDifferentWorkspaceNames() {
- request = new RemovePropertiesRequest(validPathLocation1, workspace1, validPropertyName1, validPropertyName2);
- RemovePropertiesRequest request2 = new RemovePropertiesRequest(validPathLocation1, workspace2, validPropertyName1,
- validPropertyName2);
- assertThat(request.equals(request2), is(false));
- }
-
- @Test
- public void shouldConsiderNotEqualTwoRequestsWithSameLocationButDifferentPropertyNames() {
- request = new RemovePropertiesRequest(validPathLocation1, workspace1, validPropertyName1, validPropertyName2);
- RemovePropertiesRequest request2 = new RemovePropertiesRequest(validPathLocation2, workspace1, validPropertyName2,
- validPropertyName3);
- assertThat(request.equals(request2), is(false));
- }
-
-}
Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/UpdatePropertiesRequestTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/UpdatePropertiesRequestTest.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/request/UpdatePropertiesRequestTest.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -28,9 +28,10 @@
import static org.hamcrest.core.IsSame.sameInstance;
import static org.junit.Assert.assertThat;
import static org.junit.matchers.JUnitMatchers.hasItems;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.Property;
import org.junit.Before;
import org.junit.Test;
@@ -41,151 +42,78 @@
public class UpdatePropertiesRequestTest extends AbstractRequestTest {
private UpdatePropertiesRequest request;
+ private Map<Name, Property> validProperties;
@Override
@Before
public void beforeEach() {
super.beforeEach();
+ validProperties = new HashMap<Name, Property>();
+ validProperties.put(validProperty1.getName(), validProperty1);
+ validProperties.put(validProperty2.getName(), validProperty2);
}
@Override
protected Request createRequest() {
- return new UpdatePropertiesRequest(validPathLocation1, workspace1, validProperty1);
+ return new UpdatePropertiesRequest(validPathLocation1, workspace1, validProperties);
}
@Test( expected = IllegalArgumentException.class )
public void shouldNotAllowCreatingRequestWithNullFromLocation() {
- new UpdatePropertiesRequest(null, workspace1, validProperty1);
+ new UpdatePropertiesRequest(null, workspace1, validProperties);
}
@Test( expected = IllegalArgumentException.class )
public void shouldNotAllowCreatingRequestWithNullWorkspaceName() {
- new UpdatePropertiesRequest(validPathLocation1, null, validProperty1);
+ new UpdatePropertiesRequest(validPathLocation1, null, validProperties);
}
@Test( expected = IllegalArgumentException.class )
public void shouldNotAllowCreatingRequestWithNullPropertyName() {
- new UpdatePropertiesRequest(validPathLocation, workspace1, (Property[])null);
+ new UpdatePropertiesRequest(validPathLocation, workspace1, null);
}
@Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowCreatingRequestWithEmptyPropertyNameArray() {
- new UpdatePropertiesRequest(validPathLocation, workspace1, new Property[] {});
+ public void shouldNotAllowCreatingRequestWithEmptyPropertyMap() {
+ new UpdatePropertiesRequest(validPathLocation, workspace1, Collections.<Name, Property>emptyMap());
}
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowCreatingRequestWithNullPropertyNameIterator() {
- new UpdatePropertiesRequest(validPathLocation, workspace1, (Iterator<Property>)null);
- }
-
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowCreatingRequestWithEmptyPropertyNameIterator() {
- new UpdatePropertiesRequest(validPathLocation, workspace1, new ArrayList<Property>().iterator());
- }
-
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowCreatingRequestWithNullPropertyNameIterable() {
- new UpdatePropertiesRequest(validPathLocation, workspace1, (Iterable<Property>)null);
- }
-
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowCreatingRequestWithEmptyPropertyNameIterable() {
- new UpdatePropertiesRequest(validPathLocation, workspace1, new ArrayList<Property>());
- }
-
@Test
public void shouldCreateValidRequestWithValidLocationAndValidProperty() {
- request = new UpdatePropertiesRequest(validPathLocation1, workspace1, validProperty1);
+ request = new UpdatePropertiesRequest(validPathLocation1, workspace1, validProperties);
assertThat(request.on(), is(sameInstance(validPathLocation1)));
assertThat(request.inWorkspace(), is(sameInstance(workspace1)));
assertThat(request.hasError(), is(false));
assertThat(request.getError(), is(nullValue()));
- assertThat(request.properties(), hasItems(validProperty1));
+ assertThat(request.properties().values(), hasItems(validProperty1, validProperty2));
}
@Test
- public void shouldCreateValidRequestWithValidLocationAndValidPropertyNames() {
- request = new UpdatePropertiesRequest(validPathLocation1, workspace1, validProperty1, validProperty2);
- assertThat(request.on(), is(sameInstance(validPathLocation1)));
- assertThat(request.hasError(), is(false));
- assertThat(request.getError(), is(nullValue()));
- assertThat(request.properties(), hasItems(validProperty1, validProperty2));
- }
-
- @Test
- public void shouldCreateValidRequestWithValidLocationAndIteratorOverValidPropertyName() {
- List<Property> properties = new ArrayList<Property>();
- properties.add(validProperty1);
- request = new UpdatePropertiesRequest(validPathLocation1, workspace1, properties.iterator());
- assertThat(request.on(), is(sameInstance(validPathLocation1)));
- assertThat(request.hasError(), is(false));
- assertThat(request.getError(), is(nullValue()));
- assertThat(request.properties(), hasItems(validProperty1));
- }
-
- @Test
- public void shouldCreateValidRequestWithValidLocationAndIteratorOverValidPropertyNames() {
- List<Property> properties = new ArrayList<Property>();
- properties.add(validProperty1);
- properties.add(validProperty2);
- request = new UpdatePropertiesRequest(validPathLocation1, workspace1, properties.iterator());
- assertThat(request.on(), is(sameInstance(validPathLocation1)));
- assertThat(request.hasError(), is(false));
- assertThat(request.getError(), is(nullValue()));
- assertThat(request.properties(), hasItems(validProperty1, validProperty2));
- }
-
- @Test
- public void shouldCreateValidRequestWithValidLocationAndIterableWithValidPropertyName() {
- List<Property> properties = new ArrayList<Property>();
- properties.add(validProperty1);
- request = new UpdatePropertiesRequest(validPathLocation1, workspace1, properties);
- assertThat(request.on(), is(sameInstance(validPathLocation1)));
- assertThat(request.hasError(), is(false));
- assertThat(request.getError(), is(nullValue()));
- assertThat(request.properties(), hasItems(validProperty1));
- }
-
- @Test
- public void shouldCreateValidRequestWithValidLocationAndIterableWithValidPropertyNames() {
- List<Property> properties = new ArrayList<Property>();
- properties.add(validProperty1);
- properties.add(validProperty2);
- request = new UpdatePropertiesRequest(validPathLocation1, workspace1, properties);
- assertThat(request.on(), is(sameInstance(validPathLocation1)));
- assertThat(request.hasError(), is(false));
- assertThat(request.getError(), is(nullValue()));
- assertThat(request.properties(), hasItems(validProperty1, validProperty2));
- }
-
- @Test
- public void shouldConsiderEqualTwoRequestsWithSameLocationsAndSamePropertyNames() {
- request = new UpdatePropertiesRequest(validPathLocation1, new String(workspace1), validProperty1, validProperty2);
- UpdatePropertiesRequest request2 = new UpdatePropertiesRequest(validPathLocation1, workspace1, validProperty1,
- validProperty2);
+ public void shouldConsiderEqualTwoRequestsWithSameLocationsAndSameProperties() {
+ request = new UpdatePropertiesRequest(validPathLocation1, new String(workspace1), validProperties);
+ UpdatePropertiesRequest request2 = new UpdatePropertiesRequest(validPathLocation1, workspace1, validProperties);
assertThat(request, is(request2));
}
@Test
public void shouldConsiderNotEqualTwoRequestsWithDifferentLocations() {
- request = new UpdatePropertiesRequest(validPathLocation1, workspace1, validProperty1, validProperty2);
- UpdatePropertiesRequest request2 = new UpdatePropertiesRequest(validPathLocation2, workspace1, validProperty1,
- validProperty2);
+ request = new UpdatePropertiesRequest(validPathLocation1, workspace1, validProperties);
+ UpdatePropertiesRequest request2 = new UpdatePropertiesRequest(validPathLocation2, workspace1, validProperties);
assertThat(request.equals(request2), is(false));
}
@Test
public void shouldConsiderNotEqualTwoRequestsWithDifferentWorkspaceNames() {
- request = new UpdatePropertiesRequest(validPathLocation1, workspace1, validProperty1, validProperty2);
- UpdatePropertiesRequest request2 = new UpdatePropertiesRequest(validPathLocation1, workspace2, validProperty1,
- validProperty2);
+ request = new UpdatePropertiesRequest(validPathLocation1, workspace1, validProperties);
+ UpdatePropertiesRequest request2 = new UpdatePropertiesRequest(validPathLocation1, workspace2, validProperties);
assertThat(request.equals(request2), is(false));
}
@Test
- public void shouldConsiderNotEqualTwoRequestsWithSameLocationButDifferentPropertyNames() {
- request = new UpdatePropertiesRequest(validPathLocation1, workspace1, validProperty1, validProperty2);
- UpdatePropertiesRequest request2 = new UpdatePropertiesRequest(validPathLocation2, workspace1, validProperty1);
+ public void shouldConsiderNotEqualTwoRequestsWithSameLocationButDifferentProperties() {
+ request = new UpdatePropertiesRequest(validPathLocation1, workspace1, validProperties);
+ Map<Name, Property> otherValidProperties = Collections.singletonMap(validProperty1.getName(), validProperty1);
+ UpdatePropertiesRequest request2 = new UpdatePropertiesRequest(validPathLocation2, workspace1, otherValidProperties);
assertThat(request.equals(request2), is(false));
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -66,6 +66,7 @@
import org.jboss.dna.graph.property.ValueFactories;
import org.jboss.dna.graph.property.ValueFactory;
import org.jboss.dna.graph.property.ValueFormatException;
+import org.jboss.dna.graph.request.BatchRequestBuilder;
import org.jboss.dna.graph.request.ChangeRequest;
import org.jboss.dna.graph.request.Request;
import org.jboss.dna.jcr.cache.ChangedNodeInfo;
@@ -148,6 +149,7 @@
protected final HashMap<UUID, NodeInfo> deletedNodes;
private LinkedList<Request> requests;
+ private BatchRequestBuilder requestBuilder;
protected Graph.Batch operations;
public SessionCache( JcrSession session,
@@ -183,6 +185,7 @@
// Create the batch operations ...
this.requests = new LinkedList<Request>();
+ this.requestBuilder = new BatchRequestBuilder(this.requests);
this.operations = this.store.batch();
}
@@ -233,7 +236,8 @@
// Create a new batch for future operations ...
// LinkedList<Request> oldRequests = this.requests;
this.requests = new LinkedList<Request>();
- operations = store.batch(this.requests);
+ this.requestBuilder = new BatchRequestBuilder(this.requests);
+ operations = store.batch(this.requestBuilder);
// Remove all the cached items that have been changed or deleted ...
for (UUID changedUuid : changedNodes.keySet()) {
@@ -273,6 +277,9 @@
// Find the path of the given node ...
Path path = getPathFor(nodeUuid);
+ // Make sure the builder has finished all the requests ...
+ this.requestBuilder.finishPendingRequest();
+
// Remove all of the enqueued requests for this branch ...
LinkedList<Request> branchRequests = new LinkedList<Request>();
LinkedList<Request> nonBranchRequests = new LinkedList<Request>();
@@ -297,13 +304,14 @@
}
// Now execute the branch ...
- Graph.Batch branchBatch = store.batch(branchRequests);
+ Graph.Batch branchBatch = store.batch(new BatchRequestBuilder(branchRequests));
try {
branchBatch.execute();
// Still have non-branch related requests that we haven't executed ...
this.requests = nonBranchRequests;
- this.operations = store.batch(nonBranchRequests);
+ this.requestBuilder = new BatchRequestBuilder(this.requests);
+ this.operations = store.batch(this.requestBuilder);
// Remove all the cached, changed or deleted items that were just saved ...
for (UUID changedUuid : branchUuids) {
Modified: trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemRequestProcessor.java
===================================================================
--- trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemRequestProcessor.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemRequestProcessor.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -59,7 +59,6 @@
import org.jboss.dna.graph.request.MoveBranchRequest;
import org.jboss.dna.graph.request.ReadAllChildrenRequest;
import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
-import org.jboss.dna.graph.request.RemovePropertiesRequest;
import org.jboss.dna.graph.request.RenameNodeRequest;
import org.jboss.dna.graph.request.Request;
import org.jboss.dna.graph.request.UpdatePropertiesRequest;
@@ -304,16 +303,6 @@
/**
* {@inheritDoc}
*
- * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.RemovePropertiesRequest)
- */
- @Override
- public void process( RemovePropertiesRequest request ) {
- if (updatesAllowed(request)) super.process(request);
- }
-
- /**
- * {@inheritDoc}
- *
* @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.RenameNodeRequest)
*/
@Override
Modified: trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheRequestProcessor.java
===================================================================
--- trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheRequestProcessor.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheRequestProcessor.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -190,16 +190,18 @@
if (node == null) return;
// Now set (or remove) the properties to the supplied node ...
- for (Property property : request.properties()) {
- Name propName = property.getName();
+ for (Map.Entry<Name, Property> entry : request.properties().entrySet()) {
+ Name propName = entry.getKey();
// Don't allow the child list property to be removed or changed
if (propName.equals(JBossCacheLexicon.CHILD_PATH_SEGMENT_LIST)) continue;
- if (property.size() == 0) {
+
+ Property property = entry.getValue();
+ if (property == null) {
node.remove(propName);
continue;
}
Object value = null;
- if (property.size() == 1) {
+ if (property.isSingle()) {
value = property.iterator().next();
} else {
value = property.getValuesAsArray();
@@ -502,7 +504,8 @@
assert original != null;
assert newParent != null;
// Get or create the new node ...
- Path.Segment name = desiredName != null ? context.getValueFactories().getPathFactory().createSegment(desiredName) : (Path.Segment)original.getFqn().getLastElement();
+ Path.Segment name = desiredName != null ? context.getValueFactories().getPathFactory().createSegment(desiredName) : (Path.Segment)original.getFqn()
+ .getLastElement();
// Update the children to account for same-name siblings.
// This not only updates the FQN of the child nodes, but it also sets the property that stores the
Modified: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -864,12 +864,12 @@
ObjectOutputStream oos = new ObjectOutputStream(os);
int numProps = 0;
LargeValueSerializer largeValues = null;
- Collection<Property> props = request.properties();
+ Map<Name, Property> props = request.properties();
References refs = enforceReferentialIntegrity ? new References() : null;
if (originalData == null) {
largeValues = new LargeValueSerializer(entity);
numProps = props.size();
- serializer.serializeProperties(oos, numProps, props, largeValues, refs);
+ serializer.serializeProperties(oos, numProps, props.values(), largeValues, refs);
} else {
boolean hadLargeValues = !entity.getLargeValues().isEmpty();
Set<String> largeValueHashesWritten = hadLargeValues ? new HashSet<String>() : null;
@@ -940,7 +940,7 @@
}
} catch (NoResultException e) {
// there are no properties yet ...
- createProperties(workspaceId, actual.uuid, request.properties());
+ createProperties(workspaceId, actual.uuid, request.properties().values());
}
} catch (Throwable e) { // Includes PathNotFoundException
Modified: trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Serializer.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Serializer.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Serializer.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -361,7 +361,7 @@
*/
public int reserializeProperties( ObjectInputStream input,
ObjectOutputStream output,
- Collection<Property> updatedProperties,
+ Map<Name, Property> updatedProperties,
LargeValues largeValues,
LargeValues removedLargeValues,
ReferenceValues references ) throws IOException, ClassNotFoundException {
@@ -371,10 +371,6 @@
assert largeValues != null;
assert references != null;
// Assemble a set of property names to skip deserializing
- Set<Name> skipNames = new HashSet<Name>();
- for (Property property : updatedProperties) {
- skipNames.add(property.getName());
- }
Map<Name, Property> allProperties = new HashMap<Name, Property>();
// Read the number of properties ...
@@ -385,7 +381,7 @@
String nameStr = (String)input.readObject();
Name name = valueFactories.getNameFactory().create(nameStr);
assert name != null;
- if (skipNames.contains(name)) {
+ if (updatedProperties.containsKey(name)) {
// Deserialized, but don't materialize ...
deserializePropertyValues(input, name, true, largeValues, removedLargeValues, references);
} else {
@@ -399,9 +395,10 @@
}
// Add all the updated properties ...
- for (Property updated : updatedProperties) {
- if (updated.isEmpty()) {
- allProperties.remove(updated.getName());
+ for (Map.Entry<Name, Property> entry : updatedProperties.entrySet()) {
+ Property updated = entry.getValue();
+ if (updated == null) {
+ allProperties.remove(entry.getKey());
} else {
allProperties.put(updated.getName(), updated);
}
Modified: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorReadingTest.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorReadingTest.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorReadingTest.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -24,6 +24,7 @@
package org.jboss.dna.connector.store.jpa;
import org.jboss.dna.common.statistic.Stopwatch;
+import org.jboss.dna.common.util.Logger;
import org.jboss.dna.graph.Graph;
import org.jboss.dna.graph.connector.RepositorySource;
import org.jboss.dna.graph.connector.test.ReadableConnectorTest;
@@ -55,6 +56,17 @@
source.setMaximumConnectionIdleTimeInSeconds(0);
source.setLargeValueSizeInBytes(150);
+ // Create a graph and look up the root node. We do this to initialize the connection pool and
+ // force the database to be setup at this point. By doing it now, we don't include this overhead
+ // in our test timings.
+ try {
+ Graph graph = Graph.create(source, context);
+ graph.getNodeAt("/");
+ } catch (Throwable t) {
+ Logger.getLogger(getClass()).debug("Unable to read the root node while setting up the \"" + source.getName()
+ + "\" JPA source");
+ }
+
return source;
}
Modified: trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/util/SerializerTest.java
===================================================================
--- trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/util/SerializerTest.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/util/SerializerTest.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -268,8 +268,9 @@
Property[] initial = new Property[] {prop1, prop2, prop3, prop4, prop5, prop6, prop7, prop8};
Property[] updated = new Property[] {prop2b, prop3b, prop6b};
+ Name[] deleted = new Name[] {};
SkippedLargeValues removedLargeValues = new SkippedLargeValues();
- assertReserializable(serializer, removedLargeValues, initial, updated);
+ assertReserializable(serializer, removedLargeValues, initial, updated, deleted);
assertThat(largeValues.getCount(), is(3));
assertThat(removedLargeValues.getCount(), is(2)); // p2's value and p6's original value
@@ -411,26 +412,29 @@
protected void assertReserializable( Serializer serializer,
Serializer.LargeValues removedLargeValues,
Property[] originalProperties,
- Property... updatedProperties ) throws IOException, ClassNotFoundException {
+ Property[] updatedProperties,
+ Name[] removedProperties ) throws IOException, ClassNotFoundException {
Collection<Name> propertiesThatStay = new HashSet<Name>();
Collection<Name> propertiesThatAreDeleted = new HashSet<Name>();
for (Property prop : originalProperties) {
propertiesThatStay.add(prop.getName());
}
for (Property prop : updatedProperties) {
- if (prop.isEmpty()) {
- propertiesThatAreDeleted.add(prop.getName());
- propertiesThatStay.remove(prop.getName());
- } else {
- propertiesThatStay.add(prop.getName());
- }
+ propertiesThatStay.add(prop.getName());
}
+ for (Name removedPropertyName : removedProperties) {
+ propertiesThatAreDeleted.add(removedPropertyName);
+ propertiesThatStay.remove(removedPropertyName);
+ }
// Serialize the properties one at a time ...
byte[] bytes = serialize(serializer, originalProperties);
// Now reserialize, updating the properties ...
- Collection<Property> updatedProps = Arrays.asList(updatedProperties);
+ Map<Name, Property> updatedProps = new HashMap<Name, Property>();
+ for (Property property : updatedProperties) {
+ updatedProps.put(property.getName(), property);
+ }
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Modified: trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryRequestProcessor.java
===================================================================
--- trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryRequestProcessor.java 2009-04-06 15:55:23 UTC (rev 808)
+++ trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryRequestProcessor.java 2009-04-07 21:23:28 UTC (rev 809)
@@ -61,7 +61,6 @@
import org.jboss.dna.graph.request.MoveBranchRequest;
import org.jboss.dna.graph.request.ReadAllChildrenRequest;
import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
-import org.jboss.dna.graph.request.RemovePropertiesRequest;
import org.jboss.dna.graph.request.RenameNodeRequest;
import org.jboss.dna.graph.request.Request;
import org.jboss.dna.graph.request.UpdatePropertiesRequest;
@@ -347,18 +346,6 @@
/**
* {@inheritDoc}
*
- * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.RemovePropertiesRequest)
- */
- @Override
- public void process( RemovePropertiesRequest request ) {
- logger.trace(request.toString());
- verifyUpdatesAllowed();
- super.process(request);
- }
-
- /**
- * {@inheritDoc}
- *
* @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.RenameNodeRequest)
*/
@Override
@@ -727,6 +714,7 @@
/**
* Create a file.
+ *
* @param path
* @param file
* @param content
@@ -735,14 +723,17 @@
*/
private void newFile( String path,
String file,
- byte[] content, String message ) throws SVNException {
+ byte[] content,
+ String message ) throws SVNException {
SVNNodeKind childKind = repository.checkPath(file, -1);
if (childKind == SVNNodeKind.NONE) {
ScmAction addFileNodeAction = addFile(path, file, content);
SVNActionExecutor executor = new SVNActionExecutor(repository);
- executor.execute(addFileNodeAction,message);
+ executor.execute(addFileNodeAction, message);
} else {
- SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.UNKNOWN, "Item with name '{0}' can't be created (already exist)", file);
+ SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.UNKNOWN,
+ "Item with name '{0}' can't be created (already exist)",
+ file);
throw new SVNException(err);
}
}
@@ -764,7 +755,7 @@
*/
public ScmAction addFile( String path,
String file,
- byte[] content) {
+ byte[] content ) {
return new AddFile(path, file, content);
}
@@ -858,16 +849,16 @@
}
-// private Date getCreatedOn( Object[] objs ) {
-// Date createdOn = null;
-// for (Object object : objs) {
-// if (object instanceof Date) {
-// createdOn = (Date)object;
-//
-// }
-// }
-// return createdOn;
-// }
+ // private Date getCreatedOn( Object[] objs ) {
+ // Date createdOn = null;
+ // for (Object object : objs) {
+ // if (object instanceof Date) {
+ // createdOn = (Date)object;
+ //
+ // }
+ // }
+ // return createdOn;
+ // }
private byte[] getContent( Object[] objs ) {
byte[] content = null;
16 years, 8 months
DNA SVN: r808 - in trunk/dna-jcr/src: test/java/org/jboss/dna/jcr and 1 other directory.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-04-06 11:55:23 -0400 (Mon, 06 Apr 2009)
New Revision: 808
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
Log:
DNA-344 JcrSession.getValueFactory.create(String, int) Does Not Fail Fast as per Specification
Applied patch to correct the behavior.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-04-06 14:37:57 UTC (rev 807)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-04-06 15:55:23 UTC (rev 808)
@@ -44,6 +44,7 @@
import javax.jcr.SimpleCredentials;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
+import javax.jcr.ValueFormatException;
import javax.jcr.Workspace;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
@@ -451,8 +452,10 @@
return new ValueFactory() {
public Value createValue( String value,
- int propertyType ) {
- return new JcrValue(valueFactories, sessionCache, propertyType, value);
+ int propertyType )
+ throws ValueFormatException
+ {
+ return new JcrValue(valueFactories, sessionCache, propertyType, convertValueToType(value, propertyType));
}
public Value createValue( Node value ) throws RepositoryException {
@@ -485,6 +488,79 @@
public Value createValue( String value ) {
return new JcrValue(valueFactories, sessionCache, PropertyType.STRING, value);
}
+
+ Object convertValueToType(Object value, int toType) throws ValueFormatException {
+ switch (toType) {
+ case PropertyType.BOOLEAN:
+ try {
+ return valueFactories.getBooleanFactory().create(value);
+ } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
+ throw new ValueFormatException(vfe);
+ }
+
+ case PropertyType.DATE:
+ try {
+ return valueFactories.getDateFactory().create(value);
+ } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
+ throw new ValueFormatException(vfe);
+ }
+
+ case PropertyType.NAME:
+ try {
+ return valueFactories.getNameFactory().create(value);
+ } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
+ throw new ValueFormatException(vfe);
+ }
+
+ case PropertyType.PATH:
+ try {
+ return valueFactories.getPathFactory().create(value);
+ } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
+ throw new ValueFormatException(vfe);
+ }
+
+ case PropertyType.REFERENCE:
+ try {
+ return valueFactories.getReferenceFactory().create(value);
+ } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
+ throw new ValueFormatException(vfe);
+ }
+ case PropertyType.DOUBLE:
+ try {
+ return valueFactories.getDoubleFactory().create(value);
+ } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
+ throw new ValueFormatException(vfe);
+ }
+ case PropertyType.LONG:
+ try {
+ return valueFactories.getLongFactory().create(value);
+ } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
+ throw new ValueFormatException(vfe);
+ }
+
+ // Anything can be converted to these types
+ case PropertyType.BINARY:
+ try {
+ return valueFactories.getBinaryFactory().create(value);
+ } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
+ throw new ValueFormatException(vfe);
+ }
+ case PropertyType.STRING:
+ try {
+ return valueFactories.getStringFactory().create(value);
+ } catch (org.jboss.dna.graph.property.ValueFormatException vfe) {
+ throw new ValueFormatException(vfe);
+ }
+ case PropertyType.UNDEFINED:
+ return value;
+
+ default:
+ assert false : "Unexpected JCR property type " + toType;
+ // This should still throw an exception even if assertions are turned off
+ throw new IllegalStateException("Invalid property type " + toType);
+ }
+ }
+
};
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-04-06 14:37:57 UTC (rev 807)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-04-06 15:55:23 UTC (rev 808)
@@ -40,11 +40,13 @@
import org.apache.jackrabbit.test.api.NamespaceRegistryTest;
import org.apache.jackrabbit.test.api.PropertyTest;
import org.apache.jackrabbit.test.api.RepositoryLoginTest;
+import org.apache.jackrabbit.test.api.SessionUUIDTest;
import org.apache.jackrabbit.test.api.SetValueBooleanTest;
import org.apache.jackrabbit.test.api.SetValueDateTest;
import org.apache.jackrabbit.test.api.SetValueDoubleTest;
import org.apache.jackrabbit.test.api.SetValueLongTest;
import org.apache.jackrabbit.test.api.SetValueReferenceTest;
+import org.apache.jackrabbit.test.api.ValueFactoryTest;
import org.jboss.dna.graph.DnaLexicon;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
@@ -156,7 +158,7 @@
addTestSuite(NamespaceRegistryTest.class);
// addTestSuite(ReferencesTest.class);
// addTestSuite(SessionTest.class);
- // addTestSuite(SessionUUIDTest.class);
+ addTestSuite(SessionUUIDTest.class);
// addTestSuite(NodeTest.class);
// addTestSuite(NodeUUIDTest.class);
// addTestSuite(NodeOrderableChildNodesTest.class);
@@ -216,8 +218,8 @@
//
// addTestSuite(DocumentViewImportTest.class);
// addTestSuite(SerializationTest.class);
- //
- // addTestSuite(ValueFactoryTest.class);
+
+ addTestSuite(ValueFactoryTest.class);
}
}
@@ -337,6 +339,18 @@
/**
* {@inheritDoc}
*
+ * @see org.apache.jackrabbit.test.RepositoryStub#getReadOnlyCredentials()
+ */
+ @Override
+ public Credentials getReadWriteCredentials() {
+ // TODO: Why must we override this method? The default TCK implementation just returns a particular instance of
+ // SimpleCredentials.
+ return credentials;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see org.apache.jackrabbit.test.RepositoryStub#getRepository()
*/
@Override
16 years, 8 months
DNA SVN: r807 - trunk/dna-jcr/src/main/java/org/jboss/dna/jcr.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-04-06 10:37:57 -0400 (Mon, 06 Apr 2009)
New Revision: 807
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
Log:
DNA-342 Wrong Values is Cast When Setting Property with Castable Type
Applied patch to correct the use of a wrong variable.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-04-02 20:39:44 UTC (rev 806)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-04-06 14:37:57 UTC (rev 807)
@@ -583,7 +583,7 @@
// A cast is required ...
org.jboss.dna.graph.property.PropertyType dnaPropertyType = PropertyTypeUtil.dnaPropertyTypeFor(propertyType);
ValueFactory<?> factory = factories().getValueFactory(dnaPropertyType);
- objValue = factory.create(value);
+ objValue = factory.create(objValue);
}
Property dnaProp = propertyFactory.create(name, objValue);
16 years, 8 months
DNA SVN: r806 - in trunk: dna-jcr/src/test/java/org/jboss/dna/jcr and 1 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-04-02 16:39:44 -0400 (Thu, 02 Apr 2009)
New Revision: 806
Modified:
trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/InMemoryRepositoryStub.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/RepositoryNodeTypeManagerTest.java
Log:
DNA-340 Projection of Node Types onto System View
Changed the name of JcrRepository.Settings to JcrRepository.Options, added a mechanism for setting up defaults, and added a public method to get the unmodifiable options map. Also changed JcrWorkspace to use the repository's options map (rather than a custom boolean constructor parameter) to determine whether it should project the node types as content.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java 2009-04-02 20:15:09 UTC (rev 805)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java 2009-04-02 20:39:44 UTC (rev 806)
@@ -73,30 +73,47 @@
public class JcrRepository implements Repository {
/**
- * List of settings for the {@code JcrRepository}.
- * <p>
- * The attributes that may be set are:
- * <ul>
- * <li>{@code PROJECT_NODE_TYPES} (boolean) - if {@code true}, project the registered node types onto the system view at the
- * path {@code /jcr:system/jcr:nodeTypes}.</li>
- * </ul>
- * </p>
+ * The available options for the {@code JcrRepository}.
*/
- public enum Settings {
+ public enum Options {
+
/**
- * Flag that defines whether or not the node types should be exposed as content under the "
- * <code>/jcr:system/dna:nodeTypes</code>" node. By default, the flag is false.
+ * Flag that defines whether or not the node types should be exposed as content under the "{@code
+ * /jcr:system/jcr:nodeTypes}" node. Value is either "<code>true</code>" or "<code>false</code>" (default).
+ *
+ * @see DefaultOptions#PROJECT_NODE_TYPES
*/
PROJECT_NODE_TYPES,
+ }
+ /**
+ * The default values for each of the {@link Options}.
+ */
+ public static class DefaultOptions {
+ /**
+ * The default value for the {@link Options#PROJECT_NODE_TYPES} option is {@value} .
+ */
+ public static final String PROJECT_NODE_TYPES = Boolean.FALSE.toString();
}
+ /**
+ * The static unmodifiable map of default options, which are initialized in the static initializer.
+ */
+ protected static final Map<Options, String> DEFAULT_OPTIONS;
+
+ static {
+ // Initialize the unmodifiable map of default options ...
+ EnumMap<Options, String> defaults = new EnumMap<Options, String>(Options.class);
+ defaults.put(Options.PROJECT_NODE_TYPES, DefaultOptions.PROJECT_NODE_TYPES);
+ DEFAULT_OPTIONS = Collections.<Options, String>unmodifiableMap(defaults);
+ }
+
private final String sourceName;
private final Map<String, String> descriptors;
private final ExecutionContext executionContext;
private final RepositoryConnectionFactory connectionFactory;
private final RepositoryNodeTypeManager repositoryTypeManager;
- private final Map<Settings, String> settings;
+ private final Map<Options, String> options;
/**
* Creates a JCR repository that uses the supplied {@link RepositoryConnectionFactory repository connection factory} to
@@ -122,7 +139,7 @@
* @param connectionFactory the factory for repository connections
* @param repositorySourceName the name of the repository source (in the connection factory) that should be used
* @param descriptors the {@link #getDescriptorKeys() descriptors} for this repository; may be <code>null</code>.
- * @param settings the optional {@link Settings settings} for this repository; may be null
+ * @param options the optional {@link Options settings} for this repository; may be null
* @throws IllegalArgumentException If <code>executionContextFactory</code> or <code>connectionFactory</code> is
* <code>null</code>.
*/
@@ -130,7 +147,7 @@
RepositoryConnectionFactory connectionFactory,
String repositorySourceName,
Map<String, String> descriptors,
- Map<Settings, String> settings ) {
+ Map<Options, String> options ) {
CheckArg.isNotNull(executionContext, "executionContext");
CheckArg.isNotNull(connectionFactory, "connectionFactory");
CheckArg.isNotNull(repositorySourceName, "repositorySourceName");
@@ -175,10 +192,13 @@
source = new DnaBuiltinNodeTypeSource(this.executionContext, source);
this.repositoryTypeManager = new RepositoryNodeTypeManager(this.executionContext, source);
- if (settings == null) {
- this.settings = Collections.<Settings, String>emptyMap();
+ if (options == null) {
+ this.options = DEFAULT_OPTIONS;
} else {
- this.settings = Collections.unmodifiableMap(new EnumMap<Settings, String>(settings));
+ // Initialize with defaults, then add supplied options ...
+ EnumMap<Options, String> localOptions = new EnumMap<Options, String>(DEFAULT_OPTIONS);
+ localOptions.putAll(options);
+ this.options = Collections.unmodifiableMap(localOptions);
}
}
@@ -192,6 +212,15 @@
}
/**
+ * Get the options as configured for this repository.
+ *
+ * @return the unmodifiable options; never null
+ */
+ public Map<Options, String> getOptions() {
+ return options;
+ }
+
+ /**
* Get the name of the repository source that this repository is using.
*
* @return the name of the RepositorySource
@@ -352,10 +381,8 @@
}
// Create the workspace, which will create its own session ...
- boolean shouldProjectNodeTypes = Boolean.valueOf(settings.get(Settings.PROJECT_NODE_TYPES));
-
sessionAttributes = Collections.unmodifiableMap(sessionAttributes);
- JcrWorkspace workspace = new JcrWorkspace(this, workspaceName, execContext, sessionAttributes, shouldProjectNodeTypes);
+ JcrWorkspace workspace = new JcrWorkspace(this, workspaceName, execContext, sessionAttributes);
return workspace.getSession();
}
}
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-04-02 20:15:09 UTC (rev 805)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java 2009-04-02 20:39:44 UTC (rev 806)
@@ -58,6 +58,7 @@
import org.jboss.dna.graph.property.PropertyFactory;
import org.jboss.dna.graph.property.ValueFormatException;
import org.jboss.dna.graph.property.basic.GraphNamespaceRegistry;
+import org.jboss.dna.jcr.JcrRepository.Options;
import org.xml.sax.ContentHandler;
/**
@@ -120,15 +121,7 @@
String workspaceName,
ExecutionContext context,
Map<String, Object> sessionAttributes ) {
- this(repository, workspaceName, context, sessionAttributes, true);
- }
- JcrWorkspace( JcrRepository repository,
- String workspaceName,
- ExecutionContext context,
- Map<String, Object> sessionAttributes,
- boolean projectTypesOntoSystemView ) {
-
assert workspaceName != null;
assert context != null;
assert repository != null;
@@ -166,7 +159,7 @@
this.nodeTypeManager = new JcrNodeTypeManager(session.getExecutionContext(), repoTypeManager);
this.queryManager = new JcrQueryManager(this.session);
- if (projectTypesOntoSystemView) {
+ if (Boolean.valueOf(repository.getOptions().get(Options.PROJECT_NODE_TYPES))) {
Path parentOfTypeNodes = context.getValueFactories().getPathFactory().create(root,
JcrLexicon.SYSTEM,
JcrLexicon.NODE_TYPES);
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java 2009-04-02 20:15:09 UTC (rev 805)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java 2009-04-02 20:39:44 UTC (rev 806)
@@ -154,6 +154,13 @@
}
@Test
+ public void shouldHaveDefaultOptionsWhenNotOverridden() {
+ JcrRepository repository = new JcrRepository(context, connectionFactory, sourceName, descriptors, null);
+ assertThat(repository.getOptions().get(JcrRepository.Options.PROJECT_NODE_TYPES),
+ is(JcrRepository.DefaultOptions.PROJECT_NODE_TYPES));
+ }
+
+ @Test
public void shouldProvideUserSuppliedDescriptors() {
Map<String, String> descriptors = new HashMap<String, String>();
descriptors.put("property", "value");
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-04-02 20:15:09 UTC (rev 805)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-04-02 20:39:44 UTC (rev 806)
@@ -55,7 +55,7 @@
import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
import org.jboss.dna.graph.property.Path;
-import org.jboss.dna.jcr.JcrRepository.Settings;
+import org.jboss.dna.jcr.JcrRepository.Options;
/**
* Test suite to wrap Apache Jackrabbit JCR technology compatibility kit (TCK) unit tests. Note that technically these are not the
@@ -278,10 +278,10 @@
source.setName("TestRepositorySource");
// Wrap a connection to the in-memory (DNA) repository in a (JCR) repository
- Map<Settings, String> settings = Collections.singletonMap(Settings.PROJECT_NODE_TYPES, "false");
+ Map<Options, String> options = Collections.singletonMap(Options.PROJECT_NODE_TYPES, "false");
connection = source.getConnection();
repository = new JcrRepository(executionContext.create(accessControlContext), connectionFactory, source.getName(),
- null, settings);
+ null, options);
// Make sure the path to the namespaces exists ...
Graph graph = Graph.create(source.getName(), connectionFactory, executionContext);
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/RepositoryNodeTypeManagerTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/RepositoryNodeTypeManagerTest.java 2009-04-02 20:15:09 UTC (rev 805)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/RepositoryNodeTypeManagerTest.java 2009-04-02 20:39:44 UTC (rev 806)
@@ -32,6 +32,7 @@
import static org.mockito.Mockito.stub;
import java.util.Collection;
import java.util.Collections;
+import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@@ -70,6 +71,7 @@
private RepositoryConnectionFactory connectionFactory;
private RepositoryNodeTypeManager repoTypeManager;
private Map<String, Object> sessionAttributes;
+ private Map<JcrRepository.Options, String> options;
@Mock
private JcrRepository repository;
@@ -122,6 +124,11 @@
stub(repository.getRepositorySourceName()).toReturn(repositorySourceName);
stub(repository.getConnectionFactory()).toReturn(connectionFactory);
+ // Stub out the repository options ...
+ options = new EnumMap<JcrRepository.Options, String>(JcrRepository.Options.class);
+ options.put(JcrRepository.Options.PROJECT_NODE_TYPES, Boolean.TRUE.toString());
+ stub(repository.getOptions()).toReturn(options);
+
// Set up the session attributes ...
sessionAttributes = new HashMap<String, Object>();
sessionAttributes.put("attribute1", "value1");
Modified: trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/InMemoryRepositoryStub.java
===================================================================
--- trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/InMemoryRepositoryStub.java 2009-04-02 20:15:09 UTC (rev 805)
+++ trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/InMemoryRepositoryStub.java 2009-04-02 20:39:44 UTC (rev 806)
@@ -43,7 +43,7 @@
import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
import org.jboss.dna.graph.property.Path;
-import org.jboss.dna.jcr.JcrRepository.Settings;
+import org.jboss.dna.jcr.JcrRepository.Options;
/**
* Class with TCK repository stub. This class does not contain any tests.
@@ -86,10 +86,10 @@
source.setName("TestRepositorySource");
// Wrap a connection to the in-memory (DNA) repository in a (JCR) repository
- Map<Settings, String> settings = Collections.singletonMap(Settings.PROJECT_NODE_TYPES, "true");
+ Map<Options, String> options = Collections.singletonMap(Options.PROJECT_NODE_TYPES, "true");
connection = source.getConnection();
repository = new JcrRepository(executionContext.create(accessControlContext), connectionFactory, source.getName(), null,
- settings);
+ options);
// Make sure the path to the namespaces exists ...
Graph graph = Graph.create(source.getName(), connectionFactory, executionContext);
16 years, 8 months
DNA SVN: r805 - in trunk: dna-jcr/src/test/java/org/jboss/dna/jcr and 1 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-04-02 16:15:09 -0400 (Thu, 02 Apr 2009)
New Revision: 805
Modified:
trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/InMemoryRepositoryStub.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
Log:
DNA-340 Projection of Node Types onto System View
Applied the 2nd patch, which adds support to JcrRepository for configurable options, with a single option as to whether or not the node types should be projected under "/jcr:system/dna:nodeTypes". Minor change from the patch was to reorder the constructor parameters of JcrRepository to match the other existing constructor.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java 2009-04-02 19:02:05 UTC (rev 804)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java 2009-04-02 20:15:09 UTC (rev 805)
@@ -26,6 +26,7 @@
import java.lang.reflect.Method;
import java.security.AccessControlContext;
import java.util.Collections;
+import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@@ -71,11 +72,31 @@
@ThreadSafe
public class JcrRepository implements Repository {
+ /**
+ * List of settings for the {@code JcrRepository}.
+ * <p>
+ * The attributes that may be set are:
+ * <ul>
+ * <li>{@code PROJECT_NODE_TYPES} (boolean) - if {@code true}, project the registered node types onto the system view at the
+ * path {@code /jcr:system/jcr:nodeTypes}.</li>
+ * </ul>
+ * </p>
+ */
+ public enum Settings {
+ /**
+ * Flag that defines whether or not the node types should be exposed as content under the "
+ * <code>/jcr:system/dna:nodeTypes</code>" node. By default, the flag is false.
+ */
+ PROJECT_NODE_TYPES,
+
+ }
+
private final String sourceName;
private final Map<String, String> descriptors;
private final ExecutionContext executionContext;
private final RepositoryConnectionFactory connectionFactory;
private final RepositoryNodeTypeManager repositoryTypeManager;
+ private final Map<Settings, String> settings;
/**
* Creates a JCR repository that uses the supplied {@link RepositoryConnectionFactory repository connection factory} to
@@ -90,24 +111,26 @@
public JcrRepository( ExecutionContext executionContext,
RepositoryConnectionFactory connectionFactory,
String repositorySourceName ) {
- this(null, executionContext, connectionFactory, repositorySourceName);
+ this(executionContext, connectionFactory, repositorySourceName, null, null);
}
/**
* Creates a JCR repository that uses the supplied {@link RepositoryConnectionFactory repository connection factory} to
* establish {@link Session sessions} to the underlying repository source upon {@link #login() login}.
*
- * @param descriptors The {@link #getDescriptorKeys() descriptors} for this repository; may be <code>null</code>.
* @param executionContext the execution context in which this repository is to operate
* @param connectionFactory the factory for repository connections
* @param repositorySourceName the name of the repository source (in the connection factory) that should be used
+ * @param descriptors the {@link #getDescriptorKeys() descriptors} for this repository; may be <code>null</code>.
+ * @param settings the optional {@link Settings settings} for this repository; may be null
* @throws IllegalArgumentException If <code>executionContextFactory</code> or <code>connectionFactory</code> is
* <code>null</code>.
*/
- public JcrRepository( Map<String, String> descriptors,
- ExecutionContext executionContext,
+ public JcrRepository( ExecutionContext executionContext,
RepositoryConnectionFactory connectionFactory,
- String repositorySourceName ) {
+ String repositorySourceName,
+ Map<String, String> descriptors,
+ Map<Settings, String> settings ) {
CheckArg.isNotNull(executionContext, "executionContext");
CheckArg.isNotNull(connectionFactory, "connectionFactory");
CheckArg.isNotNull(repositorySourceName, "repositorySourceName");
@@ -146,21 +169,28 @@
modifiableDescriptors.put(Repository.SPEC_NAME_DESC, JcrI18n.SPEC_NAME_DESC.text());
modifiableDescriptors.put(Repository.SPEC_VERSION_DESC, "1.0");
this.descriptors = Collections.unmodifiableMap(modifiableDescriptors);
-
+
JcrNodeTypeSource source = null;
source = new JcrBuiltinNodeTypeSource(this.executionContext);
source = new DnaBuiltinNodeTypeSource(this.executionContext, source);
this.repositoryTypeManager = new RepositoryNodeTypeManager(this.executionContext, source);
+
+ if (settings == null) {
+ this.settings = Collections.<Settings, String>emptyMap();
+ } else {
+ this.settings = Collections.unmodifiableMap(new EnumMap<Settings, String>(settings));
+ }
}
/**
* Returns the repository-level node type manager
+ *
* @return the repository-level node type manager
*/
RepositoryNodeTypeManager getRepositoryTypeManager() {
return repositoryTypeManager;
}
-
+
/**
* Get the name of the repository source that this repository is using.
*
@@ -322,8 +352,10 @@
}
// Create the workspace, which will create its own session ...
+ boolean shouldProjectNodeTypes = Boolean.valueOf(settings.get(Settings.PROJECT_NODE_TYPES));
+
sessionAttributes = Collections.unmodifiableMap(sessionAttributes);
- JcrWorkspace workspace = new JcrWorkspace(this, workspaceName, execContext, sessionAttributes);
+ JcrWorkspace workspace = new JcrWorkspace(this, workspaceName, execContext, sessionAttributes, shouldProjectNodeTypes);
return workspace.getSession();
}
}
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-04-02 19:02:05 UTC (rev 804)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java 2009-04-02 20:15:09 UTC (rev 805)
@@ -120,6 +120,15 @@
String workspaceName,
ExecutionContext context,
Map<String, Object> sessionAttributes ) {
+ this(repository, workspaceName, context, sessionAttributes, true);
+ }
+
+ JcrWorkspace( JcrRepository repository,
+ String workspaceName,
+ ExecutionContext context,
+ Map<String, Object> sessionAttributes,
+ boolean projectTypesOntoSystemView ) {
+
assert workspaceName != null;
assert context != null;
assert repository != null;
@@ -157,10 +166,12 @@
this.nodeTypeManager = new JcrNodeTypeManager(session.getExecutionContext(), repoTypeManager);
this.queryManager = new JcrQueryManager(this.session);
- Path parentOfTypeNodes = context.getValueFactories().getPathFactory().create(root,
- JcrLexicon.SYSTEM,
- JcrLexicon.NODE_TYPES);
- repoTypeManager.projectOnto(this.graph, parentOfTypeNodes);
+ if (projectTypesOntoSystemView) {
+ Path parentOfTypeNodes = context.getValueFactories().getPathFactory().create(root,
+ JcrLexicon.SYSTEM,
+ JcrLexicon.NODE_TYPES);
+ repoTypeManager.projectOnto(this.graph, parentOfTypeNodes);
+ }
}
final String getSourceName() {
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java 2009-04-02 19:02:05 UTC (rev 804)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java 2009-04-02 20:15:09 UTC (rev 805)
@@ -37,6 +37,7 @@
import javax.jcr.nodetype.PropertyDefinition;
import javax.jcr.version.OnParentVersionAction;
import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextEncoder;
import org.jboss.dna.common.text.XmlNameEncoder;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
@@ -60,6 +61,8 @@
@Immutable
class RepositoryNodeTypeManager {
+ private static final TextEncoder NAME_ENCODER = new XmlNameEncoder();
+
private final ExecutionContext context;
private final Map<Name, JcrNodeType> nodeTypes;
private final Map<PropertyDefinitionId, JcrPropertyDefinition> propertyDefinitions;
@@ -652,8 +655,7 @@
projectNodeTypeOnto(nodeType, parentOfTypeNodes, batch);
}
- // TODO: Add back in; see DNA-340 ...
- // batch.execute();
+ batch.execute();
}
/**
@@ -730,7 +732,7 @@
assert batch != null;
JcrPropertyDefinition jcrPropDef = (JcrPropertyDefinition)propertyDef;
- String propName = jcrPropDef.getInternalName().getString(context.getNamespaceRegistry(), new XmlNameEncoder());
+ String propName = jcrPropDef.getInternalName().getString(context.getNamespaceRegistry(), NAME_ENCODER);
Path propDefPath = pathFactory.create(nodeTypePath, JcrLexicon.PROPERTY_DEFINITION);
List<Property> propsList = new ArrayList<Property>();
@@ -793,7 +795,7 @@
assert batch != null;
JcrNodeDefinition jcrNodeDef = (JcrNodeDefinition)childNodeDef;
- String nodeName = jcrNodeDef.getInternalName().getString(context.getNamespaceRegistry(), new XmlNameEncoder());
+ String nodeName = jcrNodeDef.getInternalName().getString(context.getNamespaceRegistry(), NAME_ENCODER);
Path nodeDefPath = pathFactory.create(nodeTypePath, JcrLexicon.CHILD_NODE_DEFINITION);
List<Property> propsList = new ArrayList<Property>();
@@ -817,5 +819,4 @@
batch.create(nodeDefPath).with(propsList).and();
}
-
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java 2009-04-02 19:02:05 UTC (rev 804)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java 2009-04-02 20:15:09 UTC (rev 805)
@@ -103,27 +103,27 @@
// Set up the repository ...
descriptors = new HashMap<String, String>();
- repository = new JcrRepository(descriptors, context, connectionFactory, sourceName);
+ repository = new JcrRepository(context, connectionFactory, sourceName, descriptors, null);
}
@Test
public void shouldAllowNullDescriptors() {
- new JcrRepository(null, context, connectionFactory, sourceName);
+ new JcrRepository(context, connectionFactory, sourceName, null, null);
}
@Test( expected = IllegalArgumentException.class )
public void shouldNotAllowNullExecutionContext() throws Exception {
- new JcrRepository(descriptors, null, connectionFactory, sourceName);
+ new JcrRepository(null, connectionFactory, sourceName, descriptors, null);
}
@Test( expected = IllegalArgumentException.class )
public void shouldNotAllowNullConnectionFactories() throws Exception {
- new JcrRepository(descriptors, context, null, sourceName);
+ new JcrRepository(context, null, sourceName, descriptors, null);
}
@Test( expected = IllegalArgumentException.class )
public void shouldNotAllowNullSourceName() throws Exception {
- new JcrRepository(descriptors, context, connectionFactory, null);
+ new JcrRepository(context, connectionFactory, null, descriptors, null);
}
@Test( expected = IllegalArgumentException.class )
@@ -148,7 +148,7 @@
@Test
public void shouldProvideBuiltInDescriptorsWhenNotSuppliedDescriptors() {
- Repository repository = new JcrRepository(descriptors, context, connectionFactory, sourceName);
+ Repository repository = new JcrRepository(context, connectionFactory, sourceName, descriptors, null);
testDescriptorKeys(repository);
testDescriptorValues(repository);
}
@@ -157,7 +157,7 @@
public void shouldProvideUserSuppliedDescriptors() {
Map<String, String> descriptors = new HashMap<String, String>();
descriptors.put("property", "value");
- Repository repository = new JcrRepository(descriptors, context, connectionFactory, sourceName);
+ Repository repository = new JcrRepository(context, connectionFactory, sourceName, descriptors, null);
testDescriptorKeys(repository);
testDescriptorValues(repository);
assertThat(repository.getDescriptor("property"), is("value"));
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-04-02 19:02:05 UTC (rev 804)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-04-02 20:15:09 UTC (rev 805)
@@ -28,6 +28,7 @@
import java.security.AccessControlContext;
import java.security.AccessController;
import java.util.Collections;
+import java.util.Map;
import java.util.Properties;
import javax.jcr.Credentials;
import javax.jcr.Repository;
@@ -54,6 +55,7 @@
import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.jcr.JcrRepository.Settings;
/**
* Test suite to wrap Apache Jackrabbit JCR technology compatibility kit (TCK) unit tests. Note that technically these are not the
@@ -276,9 +278,10 @@
source.setName("TestRepositorySource");
// Wrap a connection to the in-memory (DNA) repository in a (JCR) repository
+ Map<Settings, String> settings = Collections.singletonMap(Settings.PROJECT_NODE_TYPES, "false");
connection = source.getConnection();
- repository = new JcrRepository(Collections.<String, String>emptyMap(), executionContext.create(accessControlContext),
- connectionFactory, source.getName());
+ repository = new JcrRepository(executionContext.create(accessControlContext), connectionFactory, source.getName(),
+ null, settings);
// Make sure the path to the namespaces exists ...
Graph graph = Graph.create(source.getName(), connectionFactory, executionContext);
@@ -291,7 +294,7 @@
executionContext.getNamespaceRegistry().register(DnaLexicon.Namespace.PREFIX, DnaLexicon.Namespace.URI);
executionContext.getNamespaceRegistry().register(JcrLexicon.Namespace.PREFIX, JcrLexicon.Namespace.URI);
executionContext.getNamespaceRegistry().register(JcrNtLexicon.Namespace.PREFIX, JcrNtLexicon.Namespace.URI);
- executionContext.getNamespaceRegistry().register("sv", "http://www.jcp.org/jcr/sv/1.0");
+ executionContext.getNamespaceRegistry().register(JcrSvLexicon.Namespace.PREFIX, JcrSvLexicon.Namespace.URI);
Path destinationPath = executionContext.getValueFactories().getPathFactory().create("/");
GraphImporter importer = new GraphImporter(graph);
Modified: trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/InMemoryRepositoryStub.java
===================================================================
--- trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/InMemoryRepositoryStub.java 2009-04-02 19:02:05 UTC (rev 804)
+++ trunk/dna-jcr-tck/src/test/java/org/jboss/dna/jcr/InMemoryRepositoryStub.java 2009-04-02 20:15:09 UTC (rev 805)
@@ -28,6 +28,7 @@
import java.security.AccessControlContext;
import java.security.AccessController;
import java.util.Collections;
+import java.util.Map;
import java.util.Properties;
import javax.jcr.Credentials;
import javax.jcr.Repository;
@@ -42,6 +43,7 @@
import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.jcr.JcrRepository.Settings;
/**
* Class with TCK repository stub. This class does not contain any tests.
@@ -84,9 +86,10 @@
source.setName("TestRepositorySource");
// Wrap a connection to the in-memory (DNA) repository in a (JCR) repository
+ Map<Settings, String> settings = Collections.singletonMap(Settings.PROJECT_NODE_TYPES, "true");
connection = source.getConnection();
- repository = new JcrRepository(Collections.<String, String>emptyMap(), executionContext.create(accessControlContext),
- connectionFactory, source.getName());
+ repository = new JcrRepository(executionContext.create(accessControlContext), connectionFactory, source.getName(), null,
+ settings);
// Make sure the path to the namespaces exists ...
Graph graph = Graph.create(source.getName(), connectionFactory, executionContext);
@@ -99,7 +102,7 @@
executionContext.getNamespaceRegistry().register(DnaLexicon.Namespace.PREFIX, DnaLexicon.Namespace.URI);
executionContext.getNamespaceRegistry().register(JcrLexicon.Namespace.PREFIX, JcrLexicon.Namespace.URI);
executionContext.getNamespaceRegistry().register(JcrNtLexicon.Namespace.PREFIX, JcrNtLexicon.Namespace.URI);
- executionContext.getNamespaceRegistry().register("sv", "http://www.jcp.org/jcr/sv/1.0");
+ executionContext.getNamespaceRegistry().register(JcrSvLexicon.Namespace.PREFIX, JcrSvLexicon.Namespace.URI);
Path destinationPath = executionContext.getValueFactories().getPathFactory().create("/");
GraphImporter importer = new GraphImporter(graph);
16 years, 8 months
DNA SVN: r804 - in trunk/dna-jcr/src: test/java/org/jboss/dna/jcr and 1 other directory.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-04-02 15:02:05 -0400 (Thu, 02 Apr 2009)
New Revision: 804
Added:
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/RepositoryNodeTypeManagerTest.java
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java
Log:
DNA-340 Projection of Node Types onto System View
Applied the patch, which stores the node type information in the repository graph, with one exception. For various reasons (including those related to performance of running so many TCK unit tests), we want to be able to have a JcrRepository configuration property that says whether the node types should be stored in the graph. So, the "batch.execute()" line was commented out at the end of the RepositoryNodeTypeManager.projectOnto(Graph,Path) method. This essentially prevents the node types from being added, but still ensures that the "/jcr:system/dna:nodeTypes" node exists.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java 2009-04-02 18:52:26 UTC (rev 803)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java 2009-04-02 19:02:05 UTC (rev 804)
@@ -63,6 +63,14 @@
throw new IllegalStateException(JcrI18n.supertypeNotFound.text(baseTypeName, namespaceTypeName));
}
+ JcrNodeType nodeType = findType(JcrNtLexicon.NODE_TYPE);
+
+ if (nodeType == null) {
+ String baseTypeName = JcrNtLexicon.NODE_TYPE.getString(context.getNamespaceRegistry());
+ String namespaceTypeName = DnaLexicon.NODE_TYPES.getString(context.getNamespaceRegistry());
+ throw new IllegalStateException(JcrI18n.supertypeNotFound.text(baseTypeName, namespaceTypeName));
+ }
+
// Stubbing in child node and property definitions for now
JcrNodeType namespace = new JcrNodeType(
context,
@@ -104,25 +112,39 @@
new JcrNodeType[] {namespace})}),
NO_PROPERTIES, NOT_MIXIN, UNORDERABLE_CHILD_NODES);
- JcrNodeType system = new JcrNodeType(
- context,
- NO_NODE_TYPE_MANAGER,
- DnaLexicon.SYSTEM,
- Arrays.asList(new JcrNodeType[] {base}),
- NO_PRIMARY_ITEM_NAME,
- Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition(
- context,
- null,
- DnaLexicon.NAMESPACES,
- OnParentVersionBehavior.VERSION.getJcrValue(),
- true,
- true,
- true,
- false,
- DnaLexicon.NAMESPACES,
- new JcrNodeType[] {namespaces})}),
- NO_PROPERTIES, NOT_MIXIN, UNORDERABLE_CHILD_NODES);
+ JcrNodeType dnaNodeTypes = new JcrNodeType(
+ context,
+ NO_NODE_TYPE_MANAGER,
+ DnaLexicon.NODE_TYPES,
+ Arrays.asList(new JcrNodeType[] {base}),
+ NO_PRIMARY_ITEM_NAME,
+ Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition(
+ context,
+ null,
+ null,
+ OnParentVersionBehavior.VERSION.getJcrValue(),
+ false,
+ false,
+ true,
+ true,
+ JcrNtLexicon.NODE_TYPE,
+ new JcrNodeType[] {nodeType})}),
+ NO_PROPERTIES, NOT_MIXIN, UNORDERABLE_CHILD_NODES);
+ JcrNodeType system = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, DnaLexicon.SYSTEM,
+ Arrays.asList(new JcrNodeType[] {base}), NO_PRIMARY_ITEM_NAME,
+ Arrays.asList(new JcrNodeDefinition[] {
+ new JcrNodeDefinition(context, null, DnaLexicon.NAMESPACES,
+ OnParentVersionBehavior.VERSION.getJcrValue(), true, true,
+ true, false, DnaLexicon.NAMESPACES,
+ new JcrNodeType[] {namespaces}),
+
+ new JcrNodeDefinition(context, null, JcrLexicon.NODE_TYPES,
+ OnParentVersionBehavior.VERSION.getJcrValue(), true, true,
+ true, false, DnaLexicon.NODE_TYPES,
+ new JcrNodeType[] {dnaNodeTypes})}), NO_PROPERTIES,
+ NOT_MIXIN, UNORDERABLE_CHILD_NODES);
+
JcrNodeType root = new JcrNodeType(context, NO_NODE_TYPE_MANAGER, DnaLexicon.ROOT, Arrays.asList(new JcrNodeType[] {base,
referenceable}), NO_PRIMARY_ITEM_NAME, Arrays.asList(new JcrNodeDefinition[] {
new JcrNodeDefinition(context, null, JcrLexicon.SYSTEM, OnParentVersionBehavior.IGNORE.getJcrValue(), true, true,
@@ -137,8 +159,7 @@
NO_DEFAULT_VALUES, PropertyType.UNDEFINED, NO_CONSTRAINTS, true),}), NOT_MIXIN,
ORDERABLE_CHILD_NODES);
- nodeTypes.addAll(Arrays.asList(new JcrNodeType[] {root, system, namespaces, namespace,}));
- nodeTypes.addAll(Arrays.asList(new JcrNodeType[] {}));
+ nodeTypes.addAll(Arrays.asList(new JcrNodeType[] {root, system, dnaNodeTypes, namespaces, namespace,}));
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java 2009-04-02 18:52:26 UTC (rev 803)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java 2009-04-02 19:02:05 UTC (rev 804)
@@ -33,6 +33,7 @@
public static final Name NAMESPACE = new BasicName(Namespace.URI, "namespace");
public static final Name NODE_DEFINITON = new BasicName(Namespace.URI, "nodeDefinition");
+ public static final Name NODE_TYPES = new BasicName(Namespace.URI, "nodeTypes");
public static final Name ROOT = new BasicName(Namespace.URI, "root");
public static final Name SYSTEM = new BasicName(Namespace.URI, "system");
public static final Name URI = new BasicName(Namespace.URI, "uri");
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java 2009-04-02 18:52:26 UTC (rev 803)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java 2009-04-02 19:02:05 UTC (rev 804)
@@ -55,6 +55,7 @@
public static final Name MERGE_FAILED = new BasicName(Namespace.URI, "mergeFailed");
public static final Name MULTIPLE = new BasicName(Namespace.URI, "multiple");
public static final Name NAME = new BasicName(Namespace.URI, "name");
+ public static final Name NODE_TYPES = new BasicName(Namespace.URI, "nodeTypes");
public static final Name NODE_TYPE_NAME = new BasicName(Namespace.URI, "nodeTypeName");
public static final Name ON_PARENT_VERSION = new BasicName(Namespace.URI, "onParentVersion");
public static final Name PREDECESSORS = new BasicName(Namespace.URI, "predecessors");
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-04-02 18:52:26 UTC (rev 803)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java 2009-04-02 19:02:05 UTC (rev 804)
@@ -110,7 +110,7 @@
* Reference to the JCR query manager for this workspace.
*/
private final JcrQueryManager queryManager;
-
+
/**
* The {@link Session} instance that this corresponds with this workspace.
*/
@@ -153,8 +153,14 @@
this.session = new JcrSession(this.repository, this, this.context, sessionAttributes);
// This must be initialized after the session
- this.nodeTypeManager = new JcrNodeTypeManager(session.getExecutionContext(), repository.getRepositoryTypeManager());
+ RepositoryNodeTypeManager repoTypeManager = repository.getRepositoryTypeManager();
+ this.nodeTypeManager = new JcrNodeTypeManager(session.getExecutionContext(), repoTypeManager);
this.queryManager = new JcrQueryManager(this.session);
+
+ Path parentOfTypeNodes = context.getValueFactories().getPathFactory().create(root,
+ JcrLexicon.SYSTEM,
+ JcrLexicon.NODE_TYPES);
+ repoTypeManager.projectOnto(this.graph, parentOfTypeNodes);
}
final String getSourceName() {
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java 2009-04-02 18:52:26 UTC (rev 803)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryNodeTypeManager.java 2009-04-02 19:02:05 UTC (rev 804)
@@ -30,12 +30,22 @@
import java.util.List;
import java.util.Map;
import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.nodetype.NodeDefinition;
+import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.PropertyDefinition;
+import javax.jcr.version.OnParentVersionAction;
import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.XmlNameEncoder;
import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Graph;
import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.PathNotFoundException;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
/**
* The {@link RepositoryNodeTypeManager} is the maintainer of node type information for the entire repository at run-time. The
@@ -50,12 +60,19 @@
@Immutable
class RepositoryNodeTypeManager {
+ private final ExecutionContext context;
private final Map<Name, JcrNodeType> nodeTypes;
private final Map<PropertyDefinitionId, JcrPropertyDefinition> propertyDefinitions;
private final Map<NodeDefinitionId, JcrNodeDefinition> childNodeDefinitions;
+ private final PropertyFactory propertyFactory;
+ private final PathFactory pathFactory;
RepositoryNodeTypeManager( ExecutionContext context,
JcrNodeTypeSource source ) {
+ this.context = context;
+ this.propertyFactory = context.getPropertyFactory();
+ this.pathFactory = context.getValueFactories().getPathFactory();
+
Collection<JcrNodeType> types = source.getNodeTypes();
propertyDefinitions = new HashMap<PropertyDefinitionId, JcrPropertyDefinition>();
childNodeDefinitions = new HashMap<NodeDefinitionId, JcrNodeDefinition>();
@@ -78,21 +95,21 @@
public Collection<JcrNodeType> getMixinNodeTypes() {
List<JcrNodeType> types = new ArrayList<JcrNodeType>(nodeTypes.size());
-
+
for (JcrNodeType nodeType : nodeTypes.values()) {
if (nodeType.isMixin()) types.add(nodeType);
}
-
+
return types;
}
public Collection<JcrNodeType> getPrimaryNodeTypes() {
List<JcrNodeType> types = new ArrayList<JcrNodeType>(nodeTypes.size());
-
+
for (JcrNodeType nodeType : nodeTypes.values()) {
if (!nodeType.isMixin()) types.add(nodeType);
}
-
+
return types;
}
@@ -594,4 +611,211 @@
skipProtected);
return false;
}
+
+ /**
+ * Projects the node types onto the provided graph under the location of <code>parentOfTypeNodes</code>. If no node currently
+ * exists at that path, one will be created and assigned a primary type of {@code DnaLexicon.NODE_TYPES}.
+ * <p>
+ * All node creation is performed through the graph layer. If the primary type of the node at <code>parentOfPathNodes</code>
+ * does not contain a residual definition that allows child nodes of type <code>nt:nodeType</code>, this method will create
+ * nodes for which the JCR layer cannot determine the corresponding node definition. This WILL corrupt the graph from a JCR
+ * standpoint and make it unusable through the DNA JCR layer.
+ * </p>
+ * <p>
+ * For each node type, a node is created as a child node of <code>parentOfPathNodes</code>. The created node has a name that
+ * corresponds to the node types name and a primary type of <code>nt:nodeType</code>. All other properties and child nodes for
+ * the newly created node are added in a manner consistent with the guidance provide in section 6.7.22 of the JCR 1.0
+ * specification and section 4.7.24 of the (draft) JCR 2.0 specification where possible.
+ * </p>
+ *
+ * @param graph the graph onto which the type information should be projected
+ * @param parentOfTypeNodes the path under which the type information should be projected
+ */
+ void projectOnto( Graph graph,
+ Path parentOfTypeNodes ) {
+ assert graph != null;
+ assert parentOfTypeNodes != null;
+
+ // Make sure that the parent of the type nodes exists in the graph.
+ try {
+ graph.getNodeAt(parentOfTypeNodes);
+ } catch (PathNotFoundException pnfe) {
+ PropertyFactory propertyFactory = context.getPropertyFactory();
+ graph.create(parentOfTypeNodes,
+ propertyFactory.create(JcrLexicon.PRIMARY_TYPE,
+ DnaLexicon.NODE_TYPES.getString(context.getNamespaceRegistry())));
+ }
+
+ Graph.Batch batch = graph.batch();
+
+ for (JcrNodeType nodeType : nodeTypes.values()) {
+ projectNodeTypeOnto(nodeType, parentOfTypeNodes, batch);
+ }
+
+ // TODO: Add back in; see DNA-340 ...
+ // batch.execute();
+ }
+
+ /**
+ * Projects the node types onto the provided graph under the location of <code>parentOfTypeNodes</code>. The operations needed
+ * to create the node (and any child nodes or properties) will be added to the batch specified in <code>batch</code>.
+ *
+ * @param nodeType the node type to be projected
+ * @param parentOfTypeNodes the path under which the type information should be projected
+ * @param batch the batch to which any required graph modification operations should be added
+ * @see #projectOnto(Graph, Path)
+ */
+ private void projectNodeTypeOnto( JcrNodeType nodeType,
+ Path parentOfTypeNodes,
+ Graph.Batch batch ) {
+ assert nodeType != null;
+ assert parentOfTypeNodes != null;
+ assert batch != null;
+
+ Path nodeTypePath = pathFactory.create(parentOfTypeNodes, nodeType.getInternalName());
+
+ NodeType[] supertypes = nodeType.getDeclaredSupertypes();
+ List<Name> supertypeNames = new ArrayList<Name>(supertypes.length);
+ for (int i = 0; i < supertypes.length; i++) {
+ supertypeNames.add(((JcrNodeType)supertypes[i]).getInternalName());
+ }
+
+ List<Property> propsList = new ArrayList<Property>();
+ propsList.add(propertyFactory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.NODE_TYPE));
+ propsList.add(propertyFactory.create(JcrLexicon.IS_MIXIN, nodeType.isMixin()));
+
+ if (nodeType.getPrimaryItemName() != null) {
+ propsList.add(propertyFactory.create(JcrLexicon.PRIMARY_ITEM_NAME, nodeType.getPrimaryItemName()));
+ }
+
+ propsList.add(propertyFactory.create(JcrLexicon.NODE_TYPE_NAME, nodeType.getName()));
+ propsList.add(propertyFactory.create(JcrLexicon.HAS_ORDERABLE_CHILD_NODES, nodeType.hasOrderableChildNodes()));
+ propsList.add(propertyFactory.create(JcrLexicon.SUPERTYPES, supertypeNames));
+
+ batch.create(nodeTypePath).with(propsList).and();
+
+ PropertyDefinition[] propertyDefs = nodeType.getDeclaredPropertyDefinitions();
+ for (int i = 0; i < propertyDefs.length; i++) {
+ projectPropertyDefinitionOnto(propertyDefs[i], nodeTypePath, batch);
+ }
+
+ NodeDefinition[] childNodeDefs = nodeType.getDeclaredChildNodeDefinitions();
+ for (int i = 0; i < childNodeDefs.length; i++) {
+ projectChildNodeDefinitionOnto(childNodeDefs[i], nodeTypePath, batch);
+ }
+
+ }
+
+ /**
+ * Projects a single property definition onto the provided graph under the location of <code>nodeTypePath</code>. The
+ * operations needed to create the property definition and any of its properties will be added to the batch specified in
+ * <code>batch</code>.
+ * <p>
+ * All node creation is performed through the graph layer. If the primary type of the node at <code>nodeTypePath</code> does
+ * not contain a residual definition that allows child nodes of type <code>nt:propertyDefinition</code>, this method creates
+ * nodes for which the JCR layer cannot determine the corresponding node definition. This WILL corrupt the graph from a JCR
+ * standpoint and make it unusable through the DNA JCR layer.
+ * </p>
+ *
+ * @param propertyDef the property definition to be projected
+ * @param nodeTypePath the path under which the property definition should be projected
+ * @param batch the batch to which any required graph modification operations should be added
+ * @see #projectOnto(Graph, Path)
+ */
+ private void projectPropertyDefinitionOnto( PropertyDefinition propertyDef,
+ Path nodeTypePath,
+ Graph.Batch batch ) {
+ assert propertyDef != null;
+ assert nodeTypePath != null;
+ assert batch != null;
+
+ JcrPropertyDefinition jcrPropDef = (JcrPropertyDefinition)propertyDef;
+ String propName = jcrPropDef.getInternalName().getString(context.getNamespaceRegistry(), new XmlNameEncoder());
+ Path propDefPath = pathFactory.create(nodeTypePath, JcrLexicon.PROPERTY_DEFINITION);
+
+ List<Property> propsList = new ArrayList<Property>();
+ propsList.add(propertyFactory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.PROPERTY_DEFINITION));
+
+ if (!JcrNodeType.RESIDUAL_ITEM_NAME.equals(jcrPropDef.getName())) {
+ propsList.add(propertyFactory.create(JcrLexicon.NAME, propName));
+ }
+ propsList.add(propertyFactory.create(JcrLexicon.AUTO_CREATED, jcrPropDef.isAutoCreated()));
+ propsList.add(propertyFactory.create(JcrLexicon.MANDATORY, jcrPropDef.isMandatory()));
+ propsList.add(propertyFactory.create(JcrLexicon.MULTIPLE, jcrPropDef.isMultiple()));
+ propsList.add(propertyFactory.create(JcrLexicon.PROTECTED, jcrPropDef.isProtected()));
+ propsList.add(propertyFactory.create(JcrLexicon.ON_PARENT_VERSION,
+ OnParentVersionAction.nameFromValue(jcrPropDef.getOnParentVersion())));
+ propsList.add(propertyFactory.create(JcrLexicon.REQUIRED_TYPE, PropertyType.nameFromValue(jcrPropDef.getRequiredType())));
+
+ Value[] defaultValues = jcrPropDef.getDefaultValues();
+ if (defaultValues.length > 0) {
+ String[] defaultsAsString = new String[defaultValues.length];
+
+ for (int i = 0; i < defaultValues.length; i++) {
+ try {
+ defaultsAsString[i] = defaultValues[i].getString();
+ } catch (RepositoryException re) {
+ // Really shouldn't get here as all values are convertible to string
+ throw new IllegalStateException(re);
+ }
+ }
+ propsList.add(propertyFactory.create(JcrLexicon.DEFAULT_VALUES, (Object[])defaultsAsString));
+ }
+
+ String[] valueConstraints = jcrPropDef.getValueConstraints();
+ if (valueConstraints.length > 0) {
+ propsList.add(propertyFactory.create(JcrLexicon.DEFAULT_VALUES, (Object[])valueConstraints));
+ }
+ batch.create(propDefPath).with(propsList).and();
+ }
+
+ /**
+ * Projects a single child node definition onto the provided graph under the location of <code>nodeTypePath</code>. The
+ * operations needed to create the child node definition and any of its properties will be added to the batch specified in
+ * <code>batch</code>.
+ * <p>
+ * All node creation is performed through the graph layer. If the primary type of the node at <code>nodeTypePath</code> does
+ * not contain a residual definition that allows child nodes of type <code>nt:childNodeDefinition</code>, this method creates
+ * nodes for which the JCR layer cannot determine the corresponding node definition. This WILL corrupt the graph from a JCR
+ * standpoint and make it unusable through the DNA JCR layer.
+ * </p>
+ *
+ * @param childNodeDef the child node definition to be projected
+ * @param nodeTypePath the path under which the child node definition should be projected
+ * @param batch the batch to which any required graph modification operations should be added
+ * @see #projectOnto(Graph, Path)
+ */
+ private void projectChildNodeDefinitionOnto( NodeDefinition childNodeDef,
+ Path nodeTypePath,
+ Graph.Batch batch ) {
+ assert childNodeDef != null;
+ assert nodeTypePath != null;
+ assert batch != null;
+
+ JcrNodeDefinition jcrNodeDef = (JcrNodeDefinition)childNodeDef;
+ String nodeName = jcrNodeDef.getInternalName().getString(context.getNamespaceRegistry(), new XmlNameEncoder());
+ Path nodeDefPath = pathFactory.create(nodeTypePath, JcrLexicon.CHILD_NODE_DEFINITION);
+
+ List<Property> propsList = new ArrayList<Property>();
+ propsList.add(propertyFactory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.CHILD_NODE_DEFINITION));
+
+ if (!JcrNodeType.RESIDUAL_ITEM_NAME.equals(jcrNodeDef.getName())) {
+ propsList.add(propertyFactory.create(JcrLexicon.NAME, nodeName));
+ }
+
+ if (jcrNodeDef.getDefaultPrimaryType() != null) {
+ propsList.add(propertyFactory.create(JcrLexicon.DEFAULT_PRIMARY_TYPE, jcrNodeDef.getDefaultPrimaryType().getName()));
+ }
+
+ propsList.add(propertyFactory.create(JcrLexicon.REQUIRED_PRIMARY_TYPES, jcrNodeDef.getRequiredPrimaryTypeNames()));
+ propsList.add(propertyFactory.create(JcrLexicon.SAME_NAME_SIBLINGS, jcrNodeDef.allowsSameNameSiblings()));
+ propsList.add(propertyFactory.create(JcrLexicon.ON_PARENT_VERSION,
+ OnParentVersionAction.nameFromValue(jcrNodeDef.getOnParentVersion())));
+ propsList.add(propertyFactory.create(JcrLexicon.AUTO_CREATED, jcrNodeDef.isAutoCreated()));
+ propsList.add(propertyFactory.create(JcrLexicon.MANDATORY, jcrNodeDef.isMandatory()));
+ propsList.add(propertyFactory.create(JcrLexicon.PROTECTED, jcrNodeDef.isProtected()));
+
+ batch.create(nodeDefPath).with(propsList).and();
+ }
+
}
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-04-02 18:52:26 UTC (rev 803)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java 2009-04-02 19:02:05 UTC (rev 804)
@@ -55,7 +55,8 @@
private Map<String, Object> sessionAttributes;
@Mock
private JcrRepository repository;
-
+ private RepositoryNodeTypeManager repoManager;
+
@Before
public void beforeEach() throws Exception {
final String repositorySourceName = "repository";
@@ -93,7 +94,14 @@
// Stub out the repository, since we only need a few methods ...
MockitoAnnotations.initMocks(this);
+
+ JcrNodeTypeSource source = null;
+ source = new JcrBuiltinNodeTypeSource(context, source);
+ source = new DnaBuiltinNodeTypeSource(context, source);
+ repoManager = new RepositoryNodeTypeManager(context, source);
+
stub(repository.getRepositorySourceName()).toReturn(repositorySourceName);
+ stub(repository.getRepositoryTypeManager()).toReturn(repoManager);
stub(repository.getConnectionFactory()).toReturn(connectionFactory);
// Now create the workspace ...
Added: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/RepositoryNodeTypeManagerTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/RepositoryNodeTypeManagerTest.java (rev 0)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/RepositoryNodeTypeManagerTest.java 2009-04-02 19:02:05 UTC (rev 804)
@@ -0,0 +1,504 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.jcr;
+
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.stub;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.Value;
+import javax.jcr.nodetype.NodeDefinition;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.PropertyDefinition;
+import javax.jcr.version.OnParentVersionAction;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoAnnotations.Mock;
+
+public class RepositoryNodeTypeManagerTest {
+
+ private String workspaceName;
+ private ExecutionContext context;
+ private InMemoryRepositorySource source;
+ private JcrWorkspace workspace;
+ private JcrSession session;
+ private Graph graph;
+ private RepositoryConnectionFactory connectionFactory;
+ private RepositoryNodeTypeManager repoTypeManager;
+ private Map<String, Object> sessionAttributes;
+ @Mock
+ private JcrRepository repository;
+
+ @Before
+ public void beforeEach() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ workspaceName = "workspace1";
+ final String repositorySourceName = "repository";
+
+ // Set up the source ...
+ source = new InMemoryRepositorySource();
+ source.setName(workspaceName);
+ source.setDefaultWorkspaceName(workspaceName);
+
+ // Set up the execution context ...
+ context = new ExecutionContext();
+ // Register the test namespace
+ context.getNamespaceRegistry().register(TestLexicon.Namespace.PREFIX, TestLexicon.Namespace.URI);
+
+ // Set up the initial content ...
+ graph = Graph.create(source, context);
+
+ // Make sure the path to the namespaces exists ...
+ graph.create("/jcr:system"); // .and().create("/jcr:system/dna:namespaces");
+ graph.set("jcr:primaryType").on("/jcr:system").to(DnaLexicon.SYSTEM);
+
+ graph.create("/a").and().create("/a/b").and().create("/a/b/c");
+ graph.set("jcr:mixinTypes").on("/a").to(JcrMixLexicon.REFERENCEABLE);
+
+ // Stub out the connection factory ...
+ connectionFactory = new RepositoryConnectionFactory() {
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.connector.RepositoryConnectionFactory#createConnection(java.lang.String)
+ */
+ @SuppressWarnings( "synthetic-access" )
+ public RepositoryConnection createConnection( String sourceName ) throws RepositorySourceException {
+ return repositorySourceName.equals(sourceName) ? source.getConnection() : null;
+ }
+ };
+
+ // Stub out the repository, since we only need a few methods ...
+ JcrNodeTypeSource source = null;
+ source = new JcrBuiltinNodeTypeSource(this.context, source);
+ source = new DnaBuiltinNodeTypeSource(this.context, source);
+ repoTypeManager = new RepositoryNodeTypeManager(context, source);
+ stub(repository.getRepositoryTypeManager()).toReturn(repoTypeManager);
+ stub(repository.getRepositorySourceName()).toReturn(repositorySourceName);
+ stub(repository.getConnectionFactory()).toReturn(connectionFactory);
+
+ // Set up the session attributes ...
+ sessionAttributes = new HashMap<String, Object>();
+ sessionAttributes.put("attribute1", "value1");
+
+ // Now create the workspace ...
+ workspace = new JcrWorkspace(repository, workspaceName, context, sessionAttributes);
+
+ // Create the session and log in ...
+ session = (JcrSession)workspace.getSession();
+
+ graph.set("jcr:primaryType").on("/jcr:system/dna:namespaces").to(DnaLexicon.NAMESPACES);
+
+ }
+
+ @After
+ public void after() throws Exception {
+ if (session != null && session.isLive()) {
+ session.logout();
+ }
+ }
+
+ @Test
+ public void shouldOnlyHaveOneDnaNamespacesNode() throws Exception {
+ NamespaceRegistry registry = context.getNamespaceRegistry();
+
+ Node rootNode = session.getRootNode();
+ assertThat(rootNode, is(notNullValue()));
+
+ Node systemNode = rootNode.getNode(JcrLexicon.SYSTEM.getString(registry));
+ assertThat(systemNode, is(notNullValue()));
+
+ NodeIterator namespacesNodes = systemNode.getNodes(DnaLexicon.NAMESPACES.getString(registry));
+ assertEquals(namespacesNodes.getSize(), 1);
+ }
+
+ @Test
+ public void shouldOnlyHaveOneNodeTypesNode() throws Exception {
+ NamespaceRegistry registry = context.getNamespaceRegistry();
+
+ Node rootNode = session.getRootNode();
+ assertThat(rootNode, is(notNullValue()));
+
+ Node systemNode = rootNode.getNode(JcrLexicon.SYSTEM.getString(registry));
+ assertThat(systemNode, is(notNullValue()));
+
+ NodeIterator nodeTypesNodes = systemNode.getNodes(JcrLexicon.NODE_TYPES.getString(registry));
+ assertEquals(nodeTypesNodes.getSize(), 1);
+ }
+
+ @Test
+ public void shouldAllowMultipleSiblingsDefinitionIfOneSibling() throws Exception {
+ NamespaceRegistry registry = context.getNamespaceRegistry();
+
+ // There's no definition for this node or for a * child node that does not allow SNS
+ JcrNodeDefinition def = repoTypeManager.findChildNodeDefinition(JcrNtLexicon.NODE_TYPE,
+ Collections.<Name>emptyList(),
+ JcrLexicon.PROPERTY_DEFINITION,
+ JcrNtLexicon.PROPERTY_DEFINITION,
+ 1,
+ false);
+
+ assertThat(def, is(notNullValue()));
+ assertEquals(def.getName(), JcrLexicon.PROPERTY_DEFINITION.getString(registry));
+ }
+
+ public void shouldProjectOntoWorkspaceGraph() throws Exception {
+ // projectOnto is called in the JcrWorkspace constructor... just test that the nodes show up
+ NamespaceRegistry registry = context.getNamespaceRegistry();
+
+ Node rootNode = session.getRootNode();
+ assertThat(rootNode, is(notNullValue()));
+
+ Node systemNode = rootNode.getNode(JcrLexicon.SYSTEM.getString(registry));
+ assertThat(systemNode, is(notNullValue()));
+
+ Node typesNode = systemNode.getNode(JcrLexicon.NODE_TYPES.getString(registry));
+ assertThat(typesNode, is(notNullValue()));
+
+ Collection<JcrNodeType> allNodeTypes = repoTypeManager.getAllNodeTypes();
+ assertThat(allNodeTypes.size(), greaterThan(0));
+ for (JcrNodeType nodeType : allNodeTypes) {
+ Node typeNode = typesNode.getNode(nodeType.getName());
+
+ compareNodeTypes(nodeType, typeNode, registry);
+
+ }
+ }
+
+ private void compareNodeTypes( JcrNodeType nodeType,
+ Node typeNode,
+ NamespaceRegistry registry ) throws Exception {
+ assertThat(nodeType.isMixin(), is(typeNode.getProperty(JcrLexicon.IS_MIXIN.getString(registry)).getBoolean()));
+ assertThat(nodeType.hasOrderableChildNodes(),
+ is(typeNode.getProperty(JcrLexicon.HAS_ORDERABLE_CHILD_NODES.getString(registry)).getBoolean()));
+ try {
+ assertThat(nodeType.getPrimaryItemName(), is(typeNode.getProperty(JcrLexicon.PRIMARY_ITEM_NAME.getString(registry))
+ .getString()));
+ } catch (PathNotFoundException pnfe) {
+ assertThat(nodeType.getPrimaryItemName(), is(nullValue()));
+ }
+ assertThat(nodeType.getName(), is(typeNode.getProperty(JcrLexicon.NODE_TYPE_NAME.getString(registry)).getString()));
+
+ NodeType[] supertypesFromManager = nodeType.getDeclaredSupertypes();
+ Value[] supertypesFromGraph = new Value[0];
+ try {
+ supertypesFromGraph = typeNode.getProperty(JcrLexicon.SUPERTYPES.getString(registry)).getValues();
+ } catch (PathNotFoundException pnfe) {
+ // Not a mandatory property
+ }
+
+ assertThat(supertypesFromGraph.length, is(supertypesFromManager.length));
+ for (int i = 0; i < supertypesFromManager.length; i++) {
+ assertEquals(supertypesFromManager[i].getName(), supertypesFromGraph[i].getString());
+ }
+
+ Map<PropertyDefinitionKey, Node> propertyDefsFromGraph = new HashMap<PropertyDefinitionKey, Node>();
+ NodeIterator properties = typeNode.getNodes(JcrLexicon.PROPERTY_DEFINITION.getString(registry));
+ while (properties.hasNext()) {
+ Node def = properties.nextNode();
+ propertyDefsFromGraph.put(new PropertyDefinitionKey(def, registry), def);
+ }
+
+ PropertyDefinition[] propertyDefs = nodeType.getDeclaredPropertyDefinitions();
+ for (int i = 0; i < propertyDefs.length; i++) {
+ JcrPropertyDefinition propertyDef = (JcrPropertyDefinition)propertyDefs[i];
+ Node propNode = propertyDefsFromGraph.get(new PropertyDefinitionKey(propertyDef));
+ compareProperty(propertyDef, propNode, registry);
+ }
+
+ Map<NodeDefinitionKey, Node> nodeDefsFromGraph = new HashMap<NodeDefinitionKey, Node>();
+ NodeIterator nodes = typeNode.getNodes(JcrLexicon.CHILD_NODE_DEFINITION.getString(registry));
+ while (nodes.hasNext()) {
+ Node def = nodes.nextNode();
+ nodeDefsFromGraph.put(new NodeDefinitionKey(def, registry), def);
+ }
+
+ NodeDefinition[] nodeDefs = nodeType.getDeclaredChildNodeDefinitions();
+ for (int i = 0; i < nodeDefs.length; i++) {
+ JcrNodeDefinition childNodeDef = (JcrNodeDefinition)nodeDefs[i];
+ Node childNodeNode = nodeDefsFromGraph.get(new NodeDefinitionKey(childNodeDef));
+
+ compareChildNode(childNodeDef, childNodeNode, registry);
+ }
+ }
+
+ private void compareChildNode( JcrNodeDefinition nodeDef,
+ Node childNodeNode,
+ NamespaceRegistry registry ) throws Exception {
+ assertThat(childNodeNode, is(notNullValue()));
+
+ try {
+ Property nameProp = childNodeNode.getProperty(JcrLexicon.NAME.getString(registry));
+ assertEquals(nameProp.getString(), nodeDef.getName());
+ } catch (PathNotFoundException pnfe) {
+ assertThat(nodeDef.getName(), is(JcrNodeType.RESIDUAL_ITEM_NAME));
+ }
+
+ Set<Name> requiredPrimaryTypeNames = nodeDef.getRequiredPrimaryTypeNames();
+ try {
+ Value[] requiredPrimaryTypes = childNodeNode.getProperty(JcrLexicon.REQUIRED_PRIMARY_TYPES.getString(registry))
+ .getValues();
+ assertEquals(requiredPrimaryTypes.length, requiredPrimaryTypeNames.size());
+ for (int i = 0; i < requiredPrimaryTypes.length; i++) {
+ Name rptName = context.getValueFactories().getNameFactory().create(requiredPrimaryTypes[i].getString());
+ assertEquals(requiredPrimaryTypeNames.contains(rptName), true);
+ }
+ } catch (PathNotFoundException pnfe) {
+ assertEquals(requiredPrimaryTypeNames.size(), 0);
+ }
+
+ try {
+ Property nameProp = childNodeNode.getProperty(JcrLexicon.DEFAULT_PRIMARY_TYPE.getString(registry));
+ assertEquals(nameProp.getString(), nodeDef.getDefaultPrimaryType().getName());
+ } catch (PathNotFoundException pnfe) {
+ assertThat(nodeDef.getDefaultPrimaryType(), is(nullValue()));
+ }
+
+ assertEquals(nodeDef.isAutoCreated(), childNodeNode.getProperty(JcrLexicon.AUTO_CREATED.getString(registry)).getBoolean());
+ assertEquals(nodeDef.isMandatory(), childNodeNode.getProperty(JcrLexicon.MANDATORY.getString(registry)).getBoolean());
+ assertEquals(nodeDef.isProtected(), childNodeNode.getProperty(JcrLexicon.PROTECTED.getString(registry)).getBoolean());
+ assertEquals(nodeDef.allowsSameNameSiblings(),
+ childNodeNode.getProperty(JcrLexicon.SAME_NAME_SIBLINGS.getString(registry)).getBoolean());
+ assertEquals(nodeDef.getOnParentVersion(),
+ OnParentVersionAction.valueFromName(childNodeNode.getProperty(JcrLexicon.ON_PARENT_VERSION.getString(registry))
+ .getString()));
+
+ }
+
+ private void compareProperty( JcrPropertyDefinition propertyDef,
+ Node propNode,
+ NamespaceRegistry registry ) throws Exception {
+ assertThat(propNode, is(notNullValue()));
+
+ try {
+ Property nameProp = propNode.getProperty(JcrLexicon.NAME.getString(registry));
+ assertEquals(nameProp.getString(), propertyDef.getName());
+ } catch (PathNotFoundException pnfe) {
+ assertThat(propertyDef.getName(), is(JcrNodeType.RESIDUAL_ITEM_NAME));
+ }
+
+ assertEquals(propertyDef.isAutoCreated(), propNode.getProperty(JcrLexicon.AUTO_CREATED.getString(registry)).getBoolean());
+ assertEquals(propertyDef.isMandatory(), propNode.getProperty(JcrLexicon.MANDATORY.getString(registry)).getBoolean());
+ assertEquals(propertyDef.isMultiple(), propNode.getProperty(JcrLexicon.MULTIPLE.getString(registry)).getBoolean());
+ assertEquals(propertyDef.isProtected(), propNode.getProperty(JcrLexicon.PROTECTED.getString(registry)).getBoolean());
+ assertEquals(propertyDef.getOnParentVersion(),
+ OnParentVersionAction.valueFromName(propNode.getProperty(JcrLexicon.ON_PARENT_VERSION.getString(registry))
+ .getString()));
+ assertEquals(propertyDef.getRequiredType(),
+ PropertyType.valueFromName(propNode.getProperty(JcrLexicon.REQUIRED_TYPE.getString(registry)).getString()));
+
+ Value[] defaultValues = propertyDef.getDefaultValues();
+ try {
+ Property defaultsProp = propNode.getProperty(JcrLexicon.DEFAULT_VALUES.getString(registry));
+ Value[] defaultsFromGraph = defaultsProp.getValues();
+
+ assertEquals(defaultValues.length, defaultsFromGraph.length);
+ for (int i = 0; i < defaultValues.length; i++) {
+ assertEquals(defaultValues[i].getString(), defaultsFromGraph[i].getString());
+ }
+ } catch (PathNotFoundException pnfe) {
+ assertEquals(defaultValues.length, 0);
+
+ }
+
+ String[] constraintValues = propertyDef.getValueConstraints();
+ try {
+ Property constraintsProp = propNode.getProperty(JcrLexicon.VALUE_CONSTRAINTS.getString(registry));
+ Value[] constraintsFromGraph = constraintsProp.getValues();
+
+ assertEquals(constraintValues.length, constraintsFromGraph.length);
+ for (int i = 0; i < constraintValues.length; i++) {
+ assertEquals(constraintValues[i], constraintsFromGraph[i].getString());
+ }
+ } catch (PathNotFoundException pnfe) {
+ assertEquals(constraintValues.length, 0);
+ }
+ }
+
+ // @Test
+ // public void shouldInferEmptyFromBadPath() throws Exception {
+ // PathFactory pathFactory = context.getValueFactories().getPathFactory();
+ // assertThat(repoTypeManager.inferFrom(graph, pathFactory.create("/a")).isEmpty(), is(true));
+ // }
+ //
+ // @Test
+ // public void shouldInferEmptyFromInvalidPath() throws Exception {
+ // PathFactory pathFactory = context.getValueFactories().getPathFactory();
+ // assertThat(repoTypeManager.inferFrom(graph, pathFactory.create("/abc")).isEmpty(), is(true));
+ // }
+ //
+ // @Test
+ // public void shouldInferOwnTypesFromOwnProjection() throws Exception {
+ // PathFactory pathFactory = context.getValueFactories().getPathFactory();
+ // Path nodeTypePath = pathFactory.create(pathFactory.createRootPath(), JcrLexicon.SYSTEM, JcrLexicon.NODE_TYPES);
+ //
+ // Collection<JcrNodeType> inferredTypes = repoTypeManager.inferFrom(graph, nodeTypePath);
+ //
+ // Collection<JcrNodeType> allNodeTypes = repoTypeManager.getAllNodeTypes();
+ // assertThat(inferredTypes.size(), is(allNodeTypes.size()));
+ //
+ // Map<Name, JcrNodeType> allNodeTypesByName = new HashMap<Name, JcrNodeType>();
+ // for (JcrNodeType jnt : allNodeTypes) {
+ // allNodeTypesByName.put(jnt.getInternalName(), jnt);
+ // }
+ //
+ // for (JcrNodeType nodeType : inferredTypes) {
+ // JcrNodeType other = allNodeTypesByName.get(nodeType.getInternalName());
+ //
+ // System.out.println("Checking: " + other.getName());
+ //
+ // assertThat(other, is(notNullValue()));
+ // assertThat(areSame(nodeType, other), is(true));
+ // }
+ // }
+
+ /**
+ * Internal class that encapsulates composite unique identifier for property definitions
+ */
+ class PropertyDefinitionKey {
+ String keyString;
+
+ PropertyDefinitionKey( Node node,
+ NamespaceRegistry registry ) throws Exception {
+ String propertyName = JcrNodeType.RESIDUAL_ITEM_NAME;
+
+ try {
+ propertyName = node.getProperty(JcrLexicon.NAME.getString(registry)).getString();
+ } catch (PathNotFoundException pnfe) {
+ // Ignorable, means name is not set.
+ }
+ String requiredType = node.getProperty(JcrLexicon.REQUIRED_TYPE.getString(registry)).getString();
+ boolean allowsMultiple = node.getProperty(JcrLexicon.MULTIPLE.getString(registry)).getBoolean();
+
+ this.keyString = propertyName + "-" + requiredType + "-" + allowsMultiple;
+ }
+
+ PropertyDefinitionKey( PropertyDefinition def ) {
+ String requiredType = PropertyType.nameFromValue(def.getRequiredType());
+
+ this.keyString = def.getName() + "-" + requiredType + "-" + def.isMultiple();
+ }
+
+ @Override
+ public boolean equals( Object ob ) {
+ if (!(ob instanceof PropertyDefinitionKey)) {
+ return false;
+ }
+
+ return keyString.equals(((PropertyDefinitionKey)ob).keyString);
+ }
+
+ @Override
+ public int hashCode() {
+ return keyString.hashCode();
+ }
+ }
+
+ /**
+ * Internal class that encapsulates composite unique identifier for child node definitions
+ */
+ class NodeDefinitionKey {
+ String keyString;
+
+ NodeDefinitionKey( Node node,
+ NamespaceRegistry registry ) throws Exception {
+ StringBuffer buff = new StringBuffer();
+
+ try {
+ String nodeName = node.getProperty(JcrLexicon.NAME.getString(registry)).getString();
+ buff.append(nodeName);
+ } catch (PathNotFoundException pnfe) {
+ // Ignorable, means name is not set.
+ buff.append(JcrNodeType.RESIDUAL_ITEM_NAME);
+ }
+
+ try {
+ Value[] requiredTypes = node.getProperty(JcrLexicon.REQUIRED_PRIMARY_TYPES.getString(registry)).getValues();
+
+ for (int i = 0; i < requiredTypes.length; i++) {
+ buff.append('_').append(requiredTypes[i].getString());
+ }
+ } catch (PathNotFoundException pnfe) {
+ // No required types. Weird, but not debilitating.
+ }
+
+ buff.append('_').append(node.getProperty(JcrLexicon.SAME_NAME_SIBLINGS.getString(registry)).getBoolean());
+
+ this.keyString = buff.toString();
+ }
+
+ NodeDefinitionKey( NodeDefinition def ) {
+ StringBuffer buff = new StringBuffer();
+ buff.append(def.getName());
+
+ NodeType[] requiredTypes = def.getRequiredPrimaryTypes();
+ for (int i = 0; i < requiredTypes.length; i++) {
+ buff.append('_').append(requiredTypes[i].getName());
+ }
+
+ buff.append('_').append(def.allowsSameNameSiblings());
+
+ this.keyString = buff.toString();
+ }
+
+ @Override
+ public boolean equals( Object ob ) {
+ if (!(ob instanceof NodeDefinitionKey)) {
+ return false;
+ }
+
+ return keyString.equals(((NodeDefinitionKey)ob).keyString);
+ }
+
+ @Override
+ public int hashCode() {
+ return keyString.hashCode();
+ }
+ }
+
+}
Property changes on: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/RepositoryNodeTypeManagerTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
16 years, 8 months
DNA SVN: r803 - in trunk: dna-graph/src/main/java/org/jboss/dna/graph/property/basic and 2 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-04-02 14:52:26 -0400 (Thu, 02 Apr 2009)
New Revision: 803
Modified:
trunk/dna-common/src/main/java/org/jboss/dna/common/util/IoUtil.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/InMemoryBinary.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSingleValueProperty.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
Log:
DNA-194 Implement update JCR capability
Added more support for Node.setProperty(...), and enabled several TCK unit tests.
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/util/IoUtil.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/util/IoUtil.java 2009-04-02 00:03:04 UTC (rev 802)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/util/IoUtil.java 2009-04-02 18:52:26 UTC (rev 803)
@@ -34,6 +34,7 @@
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
+import java.util.Arrays;
/**
* @author Randall Hauch
@@ -352,6 +353,58 @@
}
}
+ /**
+ * Write the entire contents of the supplied string to the given stream. This method always flushes and closes the stream when
+ * finished.
+ *
+ * @param input1 the first stream
+ * @param input2 the second stream
+ * @return true if the streams contain the same content, or false otherwise
+ * @throws IOException
+ * @throws IllegalArgumentException if the stream is null
+ */
+ public static boolean isSame( InputStream input1,
+ InputStream input2 ) throws IOException {
+ CheckArg.isNotNull(input1, "input1");
+ CheckArg.isNotNull(input2, "input2");
+ boolean error = false;
+ try {
+ byte[] buffer1 = new byte[1024];
+ byte[] buffer2 = new byte[1024];
+ try {
+ int numRead1 = 0;
+ int numRead2 = 0;
+ while (true) {
+ numRead1 = input1.read(buffer1);
+ numRead2 = input2.read(buffer2);
+ if (numRead1 > -1) {
+ if (numRead2 != numRead1) return false;
+ // Otherwise same number of bytes read
+ if (!Arrays.equals(buffer1, buffer2)) return false;
+ // Otherwise same bytes read, so continue ...
+ } else {
+ // Nothing more in stream 1 ...
+ return numRead2 < 0;
+ }
+ }
+ } finally {
+ input1.close();
+ }
+ } catch (IOException e) {
+ error = true; // this error should be thrown, even if there is an error closing stream 2
+ throw e;
+ } catch (RuntimeException e) {
+ error = true; // this error should be thrown, even if there is an error closing stream 2
+ throw e;
+ } finally {
+ try {
+ input2.close();
+ } catch (IOException e) {
+ if (!error) throw e;
+ }
+ }
+ }
+
private IoUtil() {
// Prevent construction
}
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/InMemoryBinary.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/InMemoryBinary.java 2009-04-02 00:03:04 UTC (rev 802)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/InMemoryBinary.java 2009-04-02 18:52:26 UTC (rev 803)
@@ -44,6 +44,7 @@
private final byte[] bytes;
private byte[] sha1hash;
+ private int hc;
public InMemoryBinary( byte[] bytes ) {
CheckArg.isNotNull(bytes, "bytes");
@@ -52,7 +53,22 @@
/**
* {@inheritDoc}
+ *
+ * @see java.lang.Object#hashCode()
*/
+ @Override
+ public int hashCode() {
+ if (sha1hash == null) {
+ // Idempotent, so doesn't matter if we recompute in concurrent threads ...
+ sha1hash = computeHash(bytes);
+ hc = sha1hash.hashCode();
+ }
+ return hc;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public long getSize() {
return this.bytes.length;
}
@@ -66,6 +82,7 @@
if (sha1hash == null) {
// Idempotent, so doesn't matter if we recompute in concurrent threads ...
sha1hash = computeHash(bytes);
+ hc = sha1hash.hashCode();
}
return sha1hash;
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-04-02 00:03:04 UTC (rev 802)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-04-02 18:52:26 UTC (rev 803)
@@ -24,6 +24,7 @@
package org.jboss.dna.jcr;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Iterator;
@@ -57,9 +58,12 @@
import net.jcip.annotations.Immutable;
import org.jboss.dna.common.i18n.I18n;
import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTime;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.NamespaceRegistry;
import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.ValueFactories;
import org.jboss.dna.graph.property.ValueFormatException;
import org.jboss.dna.jcr.SessionCache.NodeEditor;
import org.jboss.dna.jcr.cache.ChildNode;
@@ -118,6 +122,40 @@
}
}
+ final JcrValue valueFrom( int propertyType,
+ Object value ) {
+ return new JcrValue(cache.factories(), cache, propertyType, value);
+ }
+
+ final JcrValue valueFrom( Calendar value ) {
+ ValueFactories factories = cache.factories();
+ DateTime dateTime = factories.getDateFactory().create(value);
+ return new JcrValue(factories, cache, PropertyType.DATE, dateTime);
+ }
+
+ final JcrValue valueFrom( InputStream value ) {
+ ValueFactories factories = cache.factories();
+ Binary binary = factories.getBinaryFactory().create(value);
+ return new JcrValue(factories, cache, PropertyType.DATE, binary);
+ }
+
+ final JcrValue valueFrom( Node value ) throws UnsupportedRepositoryOperationException, RepositoryException {
+ ValueFactories factories = cache.factories();
+ String uuid = factories.getStringFactory().create(value.getUUID());
+ return new JcrValue(factories, cache, PropertyType.REFERENCE, uuid);
+ }
+
+ final JcrValue[] valuesFrom( int propertyType,
+ Object[] values ) {
+ int len = values.length;
+ ValueFactories factories = cache.factories();
+ JcrValue[] results = new JcrValue[values.length];
+ for (int i = 0; i != len; ++i) {
+ results[i] = new JcrValue(factories, cache, propertyType, values[i]);
+ }
+ return results;
+ }
+
@Override
Path path() throws RepositoryException {
return cache.getPathFor(nodeInfo());
@@ -672,159 +710,184 @@
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Node#setProperty(java.lang.String, boolean)
*/
public final Property setProperty( String name,
- boolean value ) {
- throw new UnsupportedOperationException();
+ boolean value )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(PropertyType.BOOLEAN, value)));
+
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Node#setProperty(java.lang.String, java.util.Calendar)
*/
public final Property setProperty( String name,
- Calendar value ) {
- throw new UnsupportedOperationException();
+ Calendar value )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(value)));
+
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Node#setProperty(java.lang.String, double)
*/
public final Property setProperty( String name,
- double value ) {
- throw new UnsupportedOperationException();
+ double value )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(PropertyType.DOUBLE, value)));
+
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Node#setProperty(java.lang.String, java.io.InputStream)
*/
public final Property setProperty( String name,
- InputStream value ) {
- throw new UnsupportedOperationException();
+ InputStream value )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(value)));
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Node#setProperty(java.lang.String, long)
*/
public final Property setProperty( String name,
- long value ) {
- throw new UnsupportedOperationException();
+ long value )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(PropertyType.LONG, value)));
+
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Node#setProperty(java.lang.String, javax.jcr.Node)
*/
public final Property setProperty( String name,
- Node value ) {
- throw new UnsupportedOperationException();
+ Node value )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(value)));
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Node#setProperty(java.lang.String, java.lang.String)
*/
public final Property setProperty( String name,
- String value ) {
- throw new UnsupportedOperationException();
+ String value )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(PropertyType.STRING, value)));
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Node#setProperty(java.lang.String, java.lang.String, int)
*/
public final Property setProperty( String name,
String value,
- int type ) {
- throw new UnsupportedOperationException();
+ int type )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(type, value)));
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Node#setProperty(java.lang.String, java.lang.String[])
*/
public final Property setProperty( String name,
- String[] values ) {
- throw new UnsupportedOperationException();
+ String[] values )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ return cache.findJcrProperty(editor().setProperty(nameFrom(name), valuesFrom(PropertyType.STRING, values)));
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Node#setProperty(java.lang.String, java.lang.String[], int)
*/
public final Property setProperty( String name,
String[] values,
- int type ) {
- throw new UnsupportedOperationException();
+ int type )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ return cache.findJcrProperty(editor().setProperty(nameFrom(name), valuesFrom(type, values)));
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Node#setProperty(java.lang.String, javax.jcr.Value)
*/
public final Property setProperty( String name,
- Value value ) {
- throw new UnsupportedOperationException();
+ Value value )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ return cache.findJcrProperty(editor().setProperty(nameFrom(name), (JcrValue)value));
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Node#setProperty(java.lang.String, javax.jcr.Value, int)
*/
public final Property setProperty( String name,
Value value,
- int type ) {
- throw new UnsupportedOperationException();
+ int type )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ return cache.findJcrProperty(editor().setProperty(nameFrom(name), ((JcrValue)value).asType(type)));
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Node#setProperty(java.lang.String, javax.jcr.Value[])
*/
public final Property setProperty( String name,
- Value[] values ) {
- throw new UnsupportedOperationException();
+ Value[] values )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ return cache.findJcrProperty(editor().setProperty(nameFrom(name), values));
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Node#setProperty(java.lang.String, javax.jcr.Value[], int)
*/
public final Property setProperty( String name,
Value[] values,
- int type ) {
- throw new UnsupportedOperationException();
+ int type )
+ throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ int len = values.length;
+ Value[] newValues = null;
+ if (len == 0) {
+ newValues = JcrMultiValueProperty.EMPTY_VALUES;
+ } else {
+ List<Value> valuesWithDesiredType = new ArrayList<Value>(len);
+ for (int i = 0; i != len; ++i) {
+ Value value = values[i];
+ if (value == null) continue;
+ if (value.getType() != type) {
+ value = ((JcrValue)value).asType(type);
+ }
+ valuesWithDesiredType.add(value);
+ }
+ if (valuesWithDesiredType.isEmpty()) {
+ newValues = JcrMultiValueProperty.EMPTY_VALUES;
+ } else {
+ newValues = valuesWithDesiredType.toArray(new Value[valuesWithDesiredType.size()]);
+ }
+ }
+ // Set the value, perhaps to an empty array ...
+ return cache.findJcrProperty(editor().setProperty(nameFrom(name), newValues));
}
/**
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java 2009-04-02 00:03:04 UTC (rev 802)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java 2009-04-02 18:52:26 UTC (rev 803)
@@ -23,17 +23,23 @@
*/
package org.jboss.dna.jcr;
+import javax.jcr.InvalidItemStateException;
import javax.jcr.Item;
+import javax.jcr.ItemNotFoundException;
import javax.jcr.ItemVisitor;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
+import javax.jcr.lock.LockException;
+import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.PropertyDefinition;
+import javax.jcr.version.VersionException;
import net.jcip.annotations.NotThreadSafe;
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.jcr.SessionCache.NodeEditor;
import org.jboss.dna.jcr.cache.PropertyInfo;
/**
@@ -51,6 +57,12 @@
this.propertyId = propertyId;
}
+ final NodeEditor editor() throws ItemNotFoundException, InvalidItemStateException, RepositoryException {
+ return cache.getEditorFor(propertyId.getNodeId());
+ }
+
+ abstract boolean isMultiple();
+
/**
* {@inheritDoc}
*
@@ -179,11 +191,10 @@
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Item#remove()
*/
- public void remove() {
- throw new UnsupportedOperationException();
+ public void remove() throws VersionException, LockException, ConstraintViolationException, RepositoryException {
+ editor().removeProperty(propertyId.getPropertyName());
}
/**
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java 2009-04-02 00:03:04 UTC (rev 802)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java 2009-04-02 18:52:26 UTC (rev 803)
@@ -24,8 +24,10 @@
package org.jboss.dna.jcr;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
+import java.util.List;
import javax.jcr.Node;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
@@ -44,6 +46,8 @@
@NotThreadSafe
final class JcrMultiValueProperty extends AbstractJcrProperty {
+ static final JcrValue[] EMPTY_VALUES = new JcrValue[] {};
+
JcrMultiValueProperty( SessionCache cache,
PropertyId propertyId ) {
super(cache, propertyId);
@@ -52,6 +56,16 @@
/**
* {@inheritDoc}
*
+ * @see org.jboss.dna.jcr.AbstractJcrProperty#isMultiple()
+ */
+ @Override
+ boolean isMultiple() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @throws ValueFormatException always
* @see javax.jcr.Property#getBoolean()
*/
@@ -170,16 +184,19 @@
*/
public final void setValue( Value[] values )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
- JcrValue[] jcrValues = null;
+ Value[] newValues = null;
if (values != null && values.length != 0) {
int numValues = values.length;
- jcrValues = new JcrValue[numValues];
+ List<Value> valuesList = new ArrayList<Value>(numValues);
ValueFactory<?> factory = null;
for (int i = 0; i != numValues; ++i) {
Value value = values[i];
- if (value instanceof JcrValue) {
+ if (value == null) {
+ // skip null values ...
+ continue;
+ } else if (value instanceof JcrValue) {
// just use the value ...
- jcrValues[i] = (JcrValue)value;
+ valuesList.add(value);
} else {
// This isn't our implementation, so create one for use
if (factory == null) {
@@ -219,11 +236,18 @@
default:
throw new RepositoryException();
}
- jcrValues[i] = createValue(factory.create(data), type);
+ valuesList.add(createValue(factory.create(data), type));
}
}
+ if (valuesList.isEmpty()) {
+ newValues = EMPTY_VALUES;
+ } else {
+ newValues = valuesList.toArray(new Value[valuesList.size()]);
+ }
+ } else {
+ newValues = EMPTY_VALUES;
}
- cache.getEditorFor(propertyId.getNodeId()).setProperty(propertyId.getPropertyName(), jcrValues);
+ cache.getEditorFor(propertyId.getNodeId()).setProperty(propertyId.getPropertyName(), newValues);
}
/**
@@ -233,13 +257,23 @@
*/
public final void setValue( String[] values )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
- JcrValue[] jcrValues = null;
+ Value[] jcrValues = null;
if (values != null && values.length != 0) {
int numValues = values.length;
+ List<Value> valuesList = new ArrayList<Value>(numValues);
jcrValues = new JcrValue[numValues];
for (int i = 0; i != numValues; ++i) {
- jcrValues[i] = createValue(values[i], PropertyType.STRING);
+ String value = values[i];
+ if (value == null) continue; // skip null values
+ valuesList.add(createValue(values[i], PropertyType.STRING));
}
+ if (valuesList.isEmpty()) {
+ jcrValues = EMPTY_VALUES;
+ } else {
+ jcrValues = valuesList.toArray(new Value[valuesList.size()]);
+ }
+ } else {
+ jcrValues = EMPTY_VALUES;
}
cache.getEditorFor(propertyId.getNodeId()).setProperty(propertyId.getPropertyName(), jcrValues);
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java 2009-04-02 00:03:04 UTC (rev 802)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java 2009-04-02 18:52:26 UTC (rev 803)
@@ -531,7 +531,8 @@
Node node = null;
try {
- node = cache.findJcrNode((UUID)jcrValue.value());
+ UUID uuid = cache.factories().getUuidFactory().create(jcrValue.value());
+ node = cache.findJcrNode(uuid);
} catch (RepositoryException re) {
return false;
}
@@ -643,9 +644,9 @@
public boolean matches( Value valueToMatch ) {
assert valueToMatch instanceof JcrValue;
-
- JcrValue jcrValue = (JcrValue) valueToMatch;
+ JcrValue jcrValue = (JcrValue)valueToMatch;
+
/*
* Need two path factories here. One uses the permanent namespace mappings to parse the constraints.
* The other also looks at the transient mappings to parse the checked value
@@ -658,7 +659,7 @@
for (int i = 0; i < constraints.length; i++) {
boolean matchesDescendants = constraints[i].endsWith("*");
Path constraintPath = repoPathFactory.create(matchesDescendants ? constraints[i].substring(0,
- constraints[i].length() - 2) : constraints[i]);
+ constraints[i].length() - 2) : constraints[i]);
if (matchesDescendants && value.isDecendantOf(constraintPath)) {
return true;
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-04-02 00:03:04 UTC (rev 802)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-04-02 18:52:26 UTC (rev 803)
@@ -52,6 +52,8 @@
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.DateTime;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.NamespaceRegistry;
import org.jboss.dna.graph.property.Path;
@@ -454,15 +456,18 @@
}
public Value createValue( Node value ) throws RepositoryException {
- return new JcrValue(valueFactories, sessionCache, PropertyType.REFERENCE, UUID.fromString(value.getUUID()));
+ String uuid = valueFactories.getStringFactory().create(value.getUUID());
+ return new JcrValue(valueFactories, sessionCache, PropertyType.REFERENCE, uuid);
}
public Value createValue( InputStream value ) {
- return new JcrValue(valueFactories, sessionCache, PropertyType.BINARY, value);
+ Binary binary = valueFactories.getBinaryFactory().create(value);
+ return new JcrValue(valueFactories, sessionCache, PropertyType.BINARY, binary);
}
public Value createValue( Calendar value ) {
- return new JcrValue(valueFactories, sessionCache, PropertyType.DATE, value);
+ DateTime dateTime = valueFactories.getDateFactory().create(value);
+ return new JcrValue(valueFactories, sessionCache, PropertyType.DATE, dateTime);
}
public Value createValue( boolean value ) {
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSingleValueProperty.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSingleValueProperty.java 2009-04-02 00:03:04 UTC (rev 802)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSingleValueProperty.java 2009-04-02 18:52:26 UTC (rev 803)
@@ -51,6 +51,16 @@
/**
* {@inheritDoc}
*
+ * @see org.jboss.dna.jcr.AbstractJcrProperty#isMultiple()
+ */
+ @Override
+ boolean isMultiple() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see javax.jcr.Property#getBoolean()
*/
public boolean getBoolean() throws RepositoryException {
@@ -184,6 +194,11 @@
cache.getEditorFor(propertyId.getNodeId()).setProperty(propertyId.getPropertyName(), jcrValue);
return;
}
+ if (value == null) {
+ // Then we're to delete the property ...
+ cache.getEditorFor(propertyId.getNodeId()).removeProperty(propertyId.getPropertyName());
+ return;
+ }
// We have to convert from one Value implementation to ours ...
switch (value.getType()) {
case PropertyType.STRING:
@@ -220,6 +235,7 @@
protected void setValue( JcrValue jcrValue )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ assert jcrValue != null;
cache.getEditorFor(propertyId.getNodeId()).setProperty(propertyId.getPropertyName(), jcrValue);
}
@@ -230,6 +246,10 @@
*/
public void setValue( String value )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ if (value == null) {
+ this.remove();
+ return;
+ }
setValue(createValue(value, PropertyType.STRING));
}
@@ -240,6 +260,10 @@
*/
public void setValue( InputStream value )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ if (value == null) {
+ this.remove();
+ return;
+ }
setValue(createValue(context().getValueFactories().getBinaryFactory().create(value), PropertyType.DATE));
}
@@ -270,6 +294,10 @@
*/
public void setValue( Calendar value )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ if (value == null) {
+ this.remove();
+ return;
+ }
setValue(createValue(context().getValueFactories().getDateFactory().create(value), PropertyType.DATE));
}
@@ -290,6 +318,10 @@
*/
public void setValue( Node value )
throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException {
+ if (value == null) {
+ this.remove();
+ return;
+ }
String uuid = value.getUUID();
setValue(createValue(uuid, PropertyType.REFERENCE));
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java 2009-04-02 00:03:04 UTC (rev 802)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java 2009-04-02 18:52:26 UTC (rev 803)
@@ -23,6 +23,7 @@
*/
package org.jboss.dna.jcr;
+import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import javax.jcr.Node;
@@ -31,9 +32,16 @@
import javax.jcr.Value;
import javax.jcr.ValueFormatException;
import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.common.SystemFailureException;
+import org.jboss.dna.common.util.IoUtil;
import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.BinaryFactory;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.DateTimeFactory;
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.ValueFactories;
/**
@@ -211,6 +219,104 @@
return type;
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ // Use the value's hash code
+ return value.hashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof JcrValue) {
+ JcrValue that = (JcrValue)obj;
+ if (this.type != that.type) return false;
+ try {
+ switch (this.type) {
+ case PropertyType.STRING:
+ return this.getString().equals(that.getString());
+ case PropertyType.BINARY:
+ BinaryFactory binaryFactory = valueFactories.getBinaryFactory();
+ Binary thisValue = binaryFactory.create(this.value);
+ Binary thatValue = binaryFactory.create(that.value);
+ return thisValue.equals(thatValue);
+ case PropertyType.BOOLEAN:
+ return this.getBoolean() == that.getBoolean();
+ case PropertyType.DOUBLE:
+ return this.getDouble() == that.getDouble();
+ case PropertyType.LONG:
+ return this.getLong() == that.getLong();
+ case PropertyType.DATE:
+ DateTimeFactory dateFactory = valueFactories.getDateFactory();
+ DateTime thisDateValue = dateFactory.create(this.value);
+ DateTime thatDateValue = dateFactory.create(that.value);
+ return thisDateValue.equals(thatDateValue);
+ case PropertyType.PATH:
+ PathFactory pathFactory = valueFactories.getPathFactory();
+ Path thisPathValue = pathFactory.create(this.value);
+ Path thatPathValue = pathFactory.create(that.value);
+ return thisPathValue.equals(thatPathValue);
+ case PropertyType.NAME:
+ NameFactory nameFactory = valueFactories.getNameFactory();
+ Name thisNameValue = nameFactory.create(this.value);
+ Name thatNameValue = nameFactory.create(that.value);
+ return thisNameValue.equals(thatNameValue);
+ case PropertyType.REFERENCE:
+ return this.getString().equals(that.getString());
+ default:
+ throw new SystemFailureException();
+ }
+ } catch (RepositoryException e) {
+ return false;
+ }
+ // will not get here
+ }
+ if (obj instanceof Value) {
+ Value that = (Value)obj;
+ if (this.type != that.getType()) return false;
+ try {
+ switch (this.type) {
+ case PropertyType.STRING:
+ return this.getString().equals(that.getString());
+ case PropertyType.BINARY:
+ return IoUtil.isSame(this.getStream(), that.getStream());
+ case PropertyType.BOOLEAN:
+ return this.getBoolean() == that.getBoolean();
+ case PropertyType.DOUBLE:
+ return this.getDouble() == that.getDouble();
+ case PropertyType.LONG:
+ return this.getLong() == that.getLong();
+ case PropertyType.DATE:
+ return this.getDate().equals(that.getDate());
+ case PropertyType.PATH:
+ return this.getString().equals(that.getString());
+ case PropertyType.NAME:
+ return this.getString().equals(that.getString());
+ case PropertyType.REFERENCE:
+ return this.getString().equals(that.getString());
+ default:
+ throw new SystemFailureException();
+ }
+ } catch (IOException e) {
+ return false;
+ } catch (RepositoryException e) {
+ return false;
+ }
+ // will not get here
+ }
+ return false;
+ }
+
private JcrValue withTypeAndValue( int type,
Object value ) {
return new JcrValue(this.valueFactories, this.sessionCache, type, value);
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-04-02 00:03:04 UTC (rev 802)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-04-02 18:52:26 UTC (rev 803)
@@ -127,6 +127,7 @@
private final JcrSession session;
private final String workspaceName;
protected final ExecutionContext context;
+ protected final ValueFactories factories;
protected final PathFactory pathFactory;
protected final NameFactory nameFactory;
protected final ValueFactory<String> stringFactory;
@@ -162,8 +163,9 @@
this.workspaceName = workspaceName;
this.store = store;
this.context = context;
- this.pathFactory = context.getValueFactories().getPathFactory();
- this.nameFactory = context.getValueFactories().getNameFactory();
+ this.factories = context.getValueFactories();
+ this.pathFactory = this.factories.getPathFactory();
+ this.nameFactory = this.factories.getNameFactory();
this.stringFactory = context.getValueFactories().getStringFactory();
this.namespaces = context.getNamespaceRegistry();
this.propertyFactory = context.getPropertyFactory();
@@ -196,6 +198,10 @@
return context;
}
+ ValueFactories factories() {
+ return factories;
+ }
+
PathFactory pathFactory() {
return pathFactory;
}
@@ -519,11 +525,12 @@
*
* @param name the property name; may not be null
* @param value the new property values; may not be null
+ * @return the identifier for the property; never null
* @throws ConstraintViolationException if the property could not be set because of a node type constraint or property
* definition constraint
*/
- public void setProperty( Name name,
- JcrValue value ) throws ConstraintViolationException {
+ public PropertyId setProperty( Name name,
+ JcrValue value ) throws ConstraintViolationException {
assert name != null;
assert value != null;
JcrPropertyDefinition definition = null;
@@ -575,7 +582,7 @@
} else {
// A cast is required ...
org.jboss.dna.graph.property.PropertyType dnaPropertyType = PropertyTypeUtil.dnaPropertyTypeFor(propertyType);
- ValueFactory<?> factory = context.getValueFactories().getValueFactory(dnaPropertyType);
+ ValueFactory<?> factory = factories().getValueFactory(dnaPropertyType);
objValue = factory.create(value);
}
Property dnaProp = propertyFactory.create(name, objValue);
@@ -584,8 +591,9 @@
PropertyInfo newProperty = new PropertyInfo(id, definition.getId(), propertyType, dnaProp, definition.isMultiple());
// Finally update the cached information and record the change ...
- node.setProperty(newProperty, context().getValueFactories());
+ node.setProperty(newProperty, factories());
operations.set(dnaProp).on(currentLocation);
+ return newProperty.getPropertyId();
}
/**
@@ -594,16 +602,16 @@
*
* @param name the property name; may not be null
* @param values new property values, all of which must have the same {@link Value#getType() property type}; may not be
- * null or empty
+ * null but may be empty
+ * @return the identifier for the property; never null
* @throws ConstraintViolationException if the property could not be set because of a node type constraint or property
* definition constraint
*/
- public void setProperty( Name name,
- JcrValue[] values ) throws ConstraintViolationException {
+ public PropertyId setProperty( Name name,
+ Value[] values ) throws ConstraintViolationException {
assert name != null;
assert values != null;
int numValues = values.length;
- assert numValues != 0;
JcrPropertyDefinition definition = null;
PropertyId id = null;
@@ -622,6 +630,7 @@
if (numValues == 0) {
// Just use the definition as is ...
} else {
+ // Use the property type for the first non-null value ...
int type = values[0].getType();
if (definition.getRequiredType() != PropertyType.UNDEFINED && definition.getRequiredType() != type) {
// The property type is not right, so we have to check if we can cast.
@@ -656,15 +665,15 @@
// Can use the values as is ...
propertyType = type;
for (int i = 0; i != numValues; ++i) {
- objValues[i] = values[i].value();
+ objValues[i] = ((JcrValue)values[i]).value();
}
} else {
// A cast is required ...
assert propertyType != type;
org.jboss.dna.graph.property.PropertyType dnaPropertyType = PropertyTypeUtil.dnaPropertyTypeFor(propertyType);
- ValueFactory<?> factory = context.getValueFactories().getValueFactory(dnaPropertyType);
+ ValueFactory<?> factory = factories().getValueFactory(dnaPropertyType);
for (int i = 0; i != numValues; ++i) {
- objValues[i] = factory.create(values[i].value());
+ objValues[i] = factory.create(((JcrValue)values[i]).value());
}
}
Property dnaProp = propertyFactory.create(name, objValues);
@@ -673,8 +682,9 @@
PropertyInfo newProperty = new PropertyInfo(id, definition.getId(), propertyType, dnaProp, definition.isMultiple());
// Finally update the cached information and record the change ...
- node.setProperty(newProperty, context().getValueFactories());
+ node.setProperty(newProperty, factories());
operations.set(dnaProp).on(currentLocation);
+ return newProperty.getPropertyId();
}
/**
@@ -739,8 +749,8 @@
if (!definition.getId().equals(node.getDefinitionId())) {
// The node definition changed, so try to set the property ...
try {
- JcrValue value = new JcrValue(context().getValueFactories(), SessionCache.this, PropertyType.STRING,
- definition.getId().getString());
+ JcrValue value = new JcrValue(factories(), SessionCache.this, PropertyType.STRING, definition.getId()
+ .getString());
setProperty(DnaLexicon.NODE_DEFINITON, value);
} catch (ConstraintViolationException e) {
// We can't set this property on the node (according to the node definition).
@@ -932,12 +942,15 @@
int propertyType,
boolean skipProtected ) {
JcrPropertyDefinition definition = null;
+ if (propertyType == PropertyType.UNDEFINED) {
+ propertyType = PropertyTypeUtil.jcrPropertyTypeFor(dnaProperty);
+ }
// If single-valued ...
if (dnaProperty.isSingle()) {
// Create a value for the DNA property value ...
Object value = dnaProperty.getFirstValue();
- Value jcrValue = new JcrValue(context().getValueFactories(), SessionCache.this, propertyType, value);
+ Value jcrValue = new JcrValue(factories(), SessionCache.this, propertyType, value);
definition = nodeTypes().findPropertyDefinition(primaryTypeNameOfParent,
mixinTypeNamesOfParent,
dnaProperty.getName(),
@@ -949,7 +962,7 @@
Value[] jcrValues = new Value[dnaProperty.size()];
int index = 0;
for (Object value : dnaProperty) {
- jcrValues[index++] = new JcrValue(context().getValueFactories(), SessionCache.this, propertyType, value);
+ jcrValues[index++] = new JcrValue(factories(), SessionCache.this, propertyType, value);
}
definition = nodeTypes().findPropertyDefinition(primaryTypeNameOfParent,
mixinTypeNamesOfParent,
@@ -1355,7 +1368,6 @@
NodeInfo parentInfo ) throws RepositoryException {
// Now get the DNA node's UUID and find the DNA property containing the UUID ...
Location location = graphNode.getLocation();
- ValueFactories factories = context.getValueFactories();
UUID uuid = location.getUuid();
org.jboss.dna.graph.property.Property uuidProperty = null;
if (uuid != null) {
@@ -1537,7 +1549,7 @@
// Now add the "jcr:uuid" property if and only if referenceable ...
if (referenceable) {
// We know that this property is single-valued
- JcrValue value = new JcrValue(context.getValueFactories(), this, PropertyType.STRING, uuid);
+ JcrValue value = new JcrValue(factories(), this, PropertyType.STRING, uuid);
PropertyDefinition propertyDefinition = nodeTypes().findPropertyDefinition(primaryTypeName,
mixinTypeNames,
JcrLexicon.UUID,
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java 2009-04-02 00:03:04 UTC (rev 802)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java 2009-04-02 18:52:26 UTC (rev 803)
@@ -29,9 +29,7 @@
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.stub;
-import java.io.InputStream;
import java.util.Arrays;
-import java.util.Calendar;
import java.util.List;
import java.util.UUID;
import javax.jcr.Item;
@@ -729,76 +727,6 @@
node.restoreByLabel(null, false);
}
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetBooleanProperty() throws Exception {
- node.setProperty(null, false);
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetCalendarProperty() throws Exception {
- node.setProperty(null, (Calendar)null);
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetDoubleProperty() throws Exception {
- node.setProperty(null, 0.0);
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetInputStreamProperty() throws Exception {
- node.setProperty(null, (InputStream)null);
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetLongProperty() throws Exception {
- node.setProperty(null, 0L);
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetNodeProperty() throws Exception {
- node.setProperty(null, (Node)null);
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetStringProperty() throws Exception {
- node.setProperty(null, (String)null);
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetStringsProperty() throws Exception {
- node.setProperty(null, (String[])null);
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetValueProperty() throws Exception {
- node.setProperty(null, (Value)null);
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetValuesProperty() throws Exception {
- node.setProperty(null, (Value[])null);
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetStringPropertyWithType() throws Exception {
- node.setProperty(null, (String)null, 0);
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetStringsPropertyWithType() throws Exception {
- node.setProperty(null, (String[])null, 0);
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetValuePropertyWithType() throws Exception {
- node.setProperty(null, (Value)null, 0);
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowSetValuesPropertyWithType() throws Exception {
- node.setProperty(null, (Value[])null, 0);
- }
-
@Test( expected = UnsupportedRepositoryOperationException.class )
public void shouldNotAllowUnlock() throws Exception {
node.unlock();
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java 2009-04-02 00:03:04 UTC (rev 802)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java 2009-04-02 18:52:26 UTC (rev 803)
@@ -286,6 +286,16 @@
/**
* {@inheritDoc}
*
+ * @see org.jboss.dna.jcr.AbstractJcrProperty#isMultiple()
+ */
+ @Override
+ boolean isMultiple() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see javax.jcr.Property#getNode()
*/
@SuppressWarnings( "synthetic-access" )
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-04-02 00:03:04 UTC (rev 802)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-04-02 18:52:26 UTC (rev 803)
@@ -37,7 +37,13 @@
import org.apache.jackrabbit.test.RepositoryStub;
import org.apache.jackrabbit.test.api.AddNodeTest;
import org.apache.jackrabbit.test.api.NamespaceRegistryTest;
+import org.apache.jackrabbit.test.api.PropertyTest;
import org.apache.jackrabbit.test.api.RepositoryLoginTest;
+import org.apache.jackrabbit.test.api.SetValueBooleanTest;
+import org.apache.jackrabbit.test.api.SetValueDateTest;
+import org.apache.jackrabbit.test.api.SetValueDoubleTest;
+import org.apache.jackrabbit.test.api.SetValueLongTest;
+import org.apache.jackrabbit.test.api.SetValueReferenceTest;
import org.jboss.dna.graph.DnaLexicon;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
@@ -152,14 +158,14 @@
// addTestSuite(NodeTest.class);
// addTestSuite(NodeUUIDTest.class);
// addTestSuite(NodeOrderableChildNodesTest.class);
- // addTestSuite(PropertyTest.class);
+ addTestSuite(PropertyTest.class);
//
// addTestSuite(SetValueBinaryTest.class);
- // addTestSuite(SetValueBooleanTest.class);
- // addTestSuite(SetValueDateTest.class);
- // addTestSuite(SetValueDoubleTest.class);
- // addTestSuite(SetValueLongTest.class);
- // addTestSuite(SetValueReferenceTest.class);
+ addTestSuite(SetValueBooleanTest.class);
+ addTestSuite(SetValueDateTest.class);
+ addTestSuite(SetValueDoubleTest.class);
+ addTestSuite(SetValueLongTest.class);
+ addTestSuite(SetValueReferenceTest.class);
// addTestSuite(SetValueStringTest.class);
// addTestSuite(SetValueConstraintViolationExceptionTest.class);
// addTestSuite(SetValueValueFormatExceptionTest.class);
16 years, 8 months
DNA SVN: r802 - trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-04-01 20:03:04 -0400 (Wed, 01 Apr 2009)
New Revision: 802
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryNode.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRepository.java
Log:
Change to the InMemory connector to make adding nodes more efficient.
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryNode.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryNode.java 2009-04-01 23:16:08 UTC (rev 801)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryNode.java 2009-04-02 00:03:04 UTC (rev 802)
@@ -24,9 +24,10 @@
package org.jboss.dna.graph.connector.inmemory;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedList;
-import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
import net.jcip.annotations.NotThreadSafe;
import org.jboss.dna.graph.ExecutionContext;
@@ -45,7 +46,8 @@
private InMemoryNode parent;
private Path.Segment name;
private final Map<Name, Property> properties = new HashMap<Name, Property>();
- private final List<InMemoryNode> children = new LinkedList<InMemoryNode>();
+ private final LinkedList<InMemoryNode> children = new LinkedList<InMemoryNode>();
+ final Set<Name> existingNames = new HashSet<Name>();
public InMemoryNode( UUID uuid ) {
assert uuid != null;
@@ -90,7 +92,7 @@
/**
* @return children
*/
- protected List<InMemoryNode> getChildren() {
+ LinkedList<InMemoryNode> getChildren() {
return children;
}
@@ -109,8 +111,8 @@
}
public InMemoryNode setProperty( ExecutionContext context,
- String name,
- Object... values ) {
+ String name,
+ Object... values ) {
PropertyFactory propertyFactory = context.getPropertyFactory();
Name propertyName = context.getValueFactories().getNameFactory().create(name);
return setProperty(propertyFactory.create(propertyName, values));
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRepository.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRepository.java 2009-04-01 23:16:08 UTC (rev 801)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRepository.java 2009-04-02 00:03:04 UTC (rev 802)
@@ -28,6 +28,7 @@
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@@ -316,10 +317,22 @@
InMemoryNode node = new InMemoryNode(uuid);
nodesByUuid.put(node.getUuid(), node);
node.setParent(parentNode);
- Path.Segment newName = context.getValueFactories().getPathFactory().createSegment(name);
+ // Find the last node with this same name ...
+ int nextIndex = 1;
+ if (parentNode.existingNames.contains(name)) {
+ ListIterator<InMemoryNode> iter = parentNode.getChildren().listIterator(parentNode.getChildren().size());
+ while (iter.hasPrevious()) {
+ InMemoryNode prev = iter.previous();
+ if (prev.getName().getName().equals(name)) {
+ nextIndex = prev.getName().getIndex() + 1;
+ break;
+ }
+ }
+ }
+ Path.Segment newName = context.getValueFactories().getPathFactory().createSegment(name, nextIndex);
node.setName(newName);
parentNode.getChildren().add(node);
- correctSameNameSiblingIndexes(context, parentNode, name);
+ parentNode.existingNames.add(name);
return node;
}
16 years, 8 months
DNA SVN: r801 - trunk/dna-jcr/src/test/java/org/jboss/dna/jcr.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-04-01 19:16:08 -0400 (Wed, 01 Apr 2009)
New Revision: 801
Modified:
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java
Log:
DNA-194 Implement update JCR capability
Removed unit tests that were requiring UnsupportedOperationException on methods that were just recently implemented.
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java 2009-04-01 22:37:07 UTC (rev 800)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java 2009-04-01 23:16:08 UTC (rev 801)
@@ -236,16 +236,6 @@
node.addMixin(null);
}
- @Test( expected = UnsupportedOperationException.class )
- public void shoudNotAllowAddNode() throws Exception {
- node.addNode(null);
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shoudNotAllowAddNodeWithType() throws Exception {
- node.addNode(null, null);
- }
-
@Test
public void shoudNotAllowCanAddMixin() throws Exception {
assertThat(node.canAddMixin(null), is(false));
16 years, 8 months
DNA SVN: r800 - trunk/dna-jcr/src/test/java/org/jboss/dna/jcr.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-04-01 18:37:07 -0400 (Wed, 01 Apr 2009)
New Revision: 800
Modified:
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
Log:
DNA-194 Implement update JCR capability
Enabled one additional TCK unit test.
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-04-01 22:27:52 UTC (rev 799)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-04-01 22:37:07 UTC (rev 800)
@@ -36,6 +36,7 @@
import org.apache.jackrabbit.test.JCRTestSuite;
import org.apache.jackrabbit.test.RepositoryStub;
import org.apache.jackrabbit.test.api.AddNodeTest;
+import org.apache.jackrabbit.test.api.NamespaceRegistryTest;
import org.apache.jackrabbit.test.api.RepositoryLoginTest;
import org.jboss.dna.graph.DnaLexicon;
import org.jboss.dna.graph.ExecutionContext;
@@ -144,7 +145,7 @@
// level 2 tests
addTestSuite(AddNodeTest.class);
- // addTestSuite(NamespaceRegistryTest.class);
+ addTestSuite(NamespaceRegistryTest.class);
// addTestSuite(ReferencesTest.class);
// addTestSuite(SessionTest.class);
// addTestSuite(SessionUUIDTest.class);
16 years, 8 months