Author: rhauch
Date: 2008-10-13 15:58:03 -0400 (Mon, 13 Oct 2008)
New Revision: 567
Added:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/Locations.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/Node.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/Results.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/Subgraph.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java
Removed:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/Location.java
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphI18n.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositoryConnection.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositoryConnectionPool.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CompositeRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CopyBranchRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CreateNodeRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/DeleteBranchRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/MoveBranchRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadAllChildrenRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadAllPropertiesRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBlockOfChildrenRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBranchRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNodeRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadPropertyRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RemovePropertiesRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RenameNodeRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RequestProcessor.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/UpdatePropertiesRequest.java
trunk/dna-graph/src/main/resources/org/jboss/dna/graph/GraphI18n.properties
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/SimpleRepositorySource.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/TimeDelayingRepositorySource.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/AbstractRequestTest.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/util/GraphImporterTest.java
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConnection.java
trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryConnection.java
trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheConnection.java
Log:
DNA-215 - Graph API for working with repository content
http://jira.jboss.com/jira/browse/DNA-215
Created a new API implementation that evolved from the two previous prototypes. This
design is actually pretty efficient, since very few intermediate API objects are created
(unlike the previous prototypes), and it offers the ability to execute requests
immediately (by invoking methods directly on the graph) or to batch together multiple
requests (by first using Graph.batch() to obtain a batch, then adding various requests to
the batch, and finally executing the batch to obtain the batch results.
Like the previous designs, this API uses an internal DSL approach to make the code that
uses the API more readable, and to rely upon returned interfaces to help guide the
developer (especially when they have code-completion in their IDE). Method chaining is
also possible with this design.
Here are a few simple examples of using this new API:
for ( Property property : graph.getProperties().on("/a/b") ) { ... }
for ( Location child : graph.getChildren().of("/a/b") ) { ... }
Node node = graph.getNodeAt("/a/b");
Subgraph subgraph = graph.getSubgraphOfDepth(3).at("/c/d");
graph.delete("/a/b/c").and().move(uuid).into(path1);
graph.create("/a/b/c/d", property1, property2, property3);
Obviously this is just a sample, but it shows the main intent of the design. Notice that
these operations are invoked directly on the graph (which is returned by the
"and()" method, allowing methods to be chained). These operations are executed
immediately upon completion, and the read methods return their results immediately.
It's also possible to do similar operations in batches:
graph.batch().delete("/a/b/c").
and().move(uuid).into(path1).
and().create("/a/b/c/d", property1, property2,
property3).execute();
Here, all 3 requests (1 delete, 1 move, and 1 create) are submitted to the repository
source in a single CompositeRequest when the "execute()" method is called. It is
possible to read information, too, but the results must be fetched after execution:
Results results = graph.batch().delete("/a/b/c").
and().move(uuid).into(path1).
and().create("/a/b/c/d", property1, property2, property3).
and().read("/j/k/m").and().readSubgraphOfDepth(3).at("/x/y").execute();
Node jkm = results.getNode("/j/k/m");
for ( Location child : jkm.getChildren() ) { ... }
Node xy = results.getNode("/x/y");
for ( Location child : xy ) {
for ( Property prop : child.getProperties() ) {...}
}
Again, these samples just show a few of the things that are possible. For more
information, see the org.jboss.dna.graph.Graph class (as well as its test case).
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java
(rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java 2008-10-13 19:58:03 UTC
(rev 567)
@@ -0,0 +1,2954 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ * This software 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;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.connectors.RepositoryConnection;
+import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connectors.RepositorySource;
+import org.jboss.dna.graph.connectors.RepositorySourceException;
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.properties.NameFactory;
+import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.properties.PropertyFactory;
+import org.jboss.dna.graph.requests.CompositeRequest;
+import org.jboss.dna.graph.requests.CopyBranchRequest;
+import org.jboss.dna.graph.requests.CreateNodeRequest;
+import org.jboss.dna.graph.requests.DeleteBranchRequest;
+import org.jboss.dna.graph.requests.MoveBranchRequest;
+import org.jboss.dna.graph.requests.ReadAllChildrenRequest;
+import org.jboss.dna.graph.requests.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.requests.ReadBlockOfChildrenRequest;
+import org.jboss.dna.graph.requests.ReadBranchRequest;
+import org.jboss.dna.graph.requests.ReadNodeRequest;
+import org.jboss.dna.graph.requests.ReadPropertyRequest;
+import org.jboss.dna.graph.requests.Request;
+
+/**
+ * A graph representation of the content within a {@link RepositorySource}, including
mechanisms to interact and manipulate that
+ * content. The graph is designed to be an <i><a
href="http://en.wikipedia.org/wiki/Domain_Specific_Language">... domain
+ * specific language</a></i>, meaning calls to it are designed to read like
sentences even though they are really just Java
+ * methods. And to be more readable, methods can be chained together.
+ *
+ * @author Randall Hauch
+ */
+@NotThreadSafe
+public class Graph {
+
+ /**
+ * Create a graph instance that uses the supplied repository and {@link
ExecutionContext context}.
+ *
+ * @param sourceName the name of the source that should be used
+ * @param connectionFactory the factory of repository connections
+ * @param context the context in which all executions should be performed
+ * @return the new graph
+ * @throws IllegalArgumentException if the source or context parameters are null
+ */
+ public static Graph create( String sourceName,
+ RepositoryConnectionFactory connectionFactory,
+ ExecutionContext context ) {
+ return new Graph(sourceName, connectionFactory, context);
+ }
+
+ private final String sourceName;
+ private final RepositoryConnectionFactory connectionFactory;
+ private final ExecutionContext context;
+ private final RequestQueue requestQueue;
+ private final Conjunction<Graph> nextGraph;
+
+ protected Graph( String sourceName,
+ RepositoryConnectionFactory connectionFactory,
+ ExecutionContext context ) {
+ CheckArg.isNotNull(sourceName, "sourceName");
+ CheckArg.isNotNull(connectionFactory, "connectionFactory");
+ CheckArg.isNotNull(context, "context");
+ this.sourceName = sourceName;
+ this.connectionFactory = connectionFactory;
+ this.context = context;
+ this.requestQueue = new GraphRequestQueue();
+ this.nextGraph = new Conjunction<Graph>() {
+ public Graph and() {
+ return Graph.this;
+ }
+ };
+ }
+
+ /**
+ * Get the RepositoryConnectionFactory that this graph uses to create {@link
RepositoryConnection repository connections}.
+ *
+ * @return the factory repository connections used by this graph; never null
+ */
+ public RepositoryConnectionFactory getConnectionFactory() {
+ return connectionFactory;
+ }
+
+ /**
+ * The name of the repository that will be used by this graph. This name is passed to
the {@link #getConnectionFactory()
+ * connection factory} when this graph needs to {@link
RepositoryConnectionFactory#createConnection(String) obtain} a
+ * {@link RepositoryConnection repository connection}.
+ *
+ * @return the name of the source
+ */
+ public String getSourceName() {
+ return sourceName;
+ }
+
+ /**
+ * Get the context of execution within which operations on this graph are performed.
+ *
+ * @return the execution context; never null
+ */
+ public ExecutionContext getContext() {
+ return context;
+ }
+
+ /*package*/RequestQueue queue() {
+ return this.requestQueue;
+ }
+
+ /**
+ * Begin the request to move the specified node into a parent node at a different
location, which is specified via the
+ * <code>into(...)</code> method on the returned {@link Move} object.
+ * <p>
+ * Like all other methods on the {@link Graph}, the move request will be performed
immediately when the <code>into(...)</code>
+ * method is called.
+ * </p>
+ *
+ * @param from the node that is to be moved.
+ * @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<Conjunction<Graph>> move( Node from ) {
+ return new MoveAction<Conjunction<Graph>>(this.nextGraph,
this.requestQueue, from.getLocation());
+ }
+
+ /**
+ * Begin the request to move a node at the specified location into a parent node at a
different location, which is specified
+ * via the <code>into(...)</code> method on the returned {@link Move}
object.
+ * <p>
+ * Like all other methods on the {@link Graph}, the move request will be performed
immediately when the <code>into(...)</code>
+ * method is called.
+ * </p>
+ *
+ * @param from the location of the node that is to be moved.
+ * @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<Conjunction<Graph>> move( Location from ) {
+ return new MoveAction<Conjunction<Graph>>(this.nextGraph,
this.requestQueue, from);
+ }
+
+ /**
+ * Begin the request to move a node located at the supplied path into a parent node
at a different location, which is
+ * specified via the <code>into(...)</code> method on the returned {@link
Move} object.
+ * <p>
+ * Like all other methods on the {@link Graph}, the move request will be performed
immediately when the <code>into(...)</code>
+ * method is called.
+ * </p>
+ *
+ * @param fromPath the path to the node that is to be moved.
+ * @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<Conjunction<Graph>> move( String fromPath ) {
+ return new MoveAction<Conjunction<Graph>>(this.nextGraph,
this.requestQueue, new Location(createPath(fromPath)));
+ }
+
+ /**
+ * Begin the request to move a node located at the supplied path into a parent node
at a different location, which is
+ * specified via the <code>into(...)</code> method on the returned {@link
Move} object.
+ * <p>
+ * Like all other methods on the {@link Graph}, the move request will be performed
immediately when the <code>into(...)</code>
+ * method is called.
+ * </p>
+ *
+ * @param from the path to the node that is to be moved.
+ * @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<Conjunction<Graph>> move( Path from ) {
+ return new MoveAction<Conjunction<Graph>>(this.nextGraph,
this.requestQueue, new Location(from));
+ }
+
+ /**
+ * Begin the request to move a node with the specified unique identifier into a
parent node at a different location, which is
+ * specified via the <code>into(...)</code> method on the returned {@link
Move} object.
+ * <p>
+ * Like all other methods on the {@link Graph}, the move request will be performed
immediately when the <code>into(...)</code>
+ * method is called.
+ * </p>
+ *
+ * @param from the UUID of the node that is to be moved.
+ * @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<Conjunction<Graph>> move( UUID from ) {
+ return new MoveAction<Conjunction<Graph>>(this.nextGraph,
this.requestQueue, new Location(from));
+ }
+
+ /**
+ * Begin the request to move a node with the specified unique identification property
into a parent node at a different
+ * location, which is specified via the <code>into(...)</code> method on
the returned {@link Move} object. The identification
+ * property should uniquely identify a single node.
+ * <p>
+ * Like all other methods on the {@link Graph}, the move request will be performed
immediately when the <code>into(...)</code>
+ * method is called.
+ * </p>
+ *
+ * @param idProperty the unique identification property of the node that is to be
moved.
+ * @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<Conjunction<Graph>> move( Property idProperty ) {
+ return new MoveAction<Conjunction<Graph>>(this.nextGraph,
this.requestQueue, new Location(idProperty));
+ }
+
+ /**
+ * Begin the request to move a node with the specified identification properties into
a parent node at a different location,
+ * which is specified via the <code>into(...)</code> method on the
returned {@link Move} object. The identification properties
+ * should uniquely identify a single node.
+ * <p>
+ * Like all other methods on the {@link Graph}, the move request will be performed
immediately when the <code>into(...)</code>
+ * method is called.
+ * </p>
+ *
+ * @param firstIdProperty the first identification property of the node that is to be
moved
+ * @param additionalIdProperties the remaining idenficiation properties of the node
that is to be moved
+ * @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<Conjunction<Graph>> move( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ return new MoveAction<Conjunction<Graph>>(this.nextGraph,
this.requestQueue, new Location(firstIdProperty,
+
additionalIdProperties));
+ }
+
+ /**
+ * Begin the request to copy the specified node into a parent node at a different
location, which is specified via the
+ * <code>into(...)</code> method on the returned {@link Copy} object.
+ * <p>
+ * Like all other methods on the {@link Graph}, the copy request will be performed
immediately when the <code>into(...)</code>
+ * method is called.
+ * </p>
+ *
+ * @param from the node that is to be copied.
+ * @return the object that can be used to specify addition nodes to be copied or the
location of the node where the node is to
+ * be copied
+ */
+ public Copy<Graph> copy( Node from ) {
+ return new CopyAction<Graph>(this, this.requestQueue, from.getLocation());
+ }
+
+ /**
+ * Begin the request to copy a node at the specified location into a parent node at a
different location, which is specified
+ * via the <code>into(...)</code> method on the returned {@link Copy}
object.
+ * <p>
+ * Like all other methods on the {@link Graph}, the copy request will be performed
immediately when the <code>into(...)</code>
+ * method is called.
+ * </p>
+ *
+ * @param from the location of the node that is to be copied.
+ * @return the object that can be used to specify addition nodes to be copied or the
location of the node where the node is to
+ * be copied
+ */
+ public Copy<Graph> copy( Location from ) {
+ return new CopyAction<Graph>(this, this.requestQueue, from);
+ }
+
+ /**
+ * Begin the request to copy a node located at the supplied path into a parent node
at a different location, which is
+ * specified via the <code>into(...)</code> method on the returned {@link
Copy} object.
+ * <p>
+ * Like all other methods on the {@link Graph}, the copy request will be performed
immediately when the <code>into(...)</code>
+ * method is called.
+ * </p>
+ *
+ * @param fromPath the path to the node that is to be copied.
+ * @return the object that can be used to specify addition nodes to be copied or the
location of the node where the node is to
+ * be copied
+ */
+ public Copy<Graph> copy( String fromPath ) {
+ return new CopyAction<Graph>(this, this.requestQueue, new
Location(createPath(fromPath)));
+ }
+
+ /**
+ * Begin the request to copy a node located at the supplied path into a parent node
at a different location, which is
+ * specified via the <code>into(...)</code> method on the returned {@link
Copy} object.
+ * <p>
+ * Like all other methods on the {@link Graph}, the copy request will be performed
immediately when the <code>into(...)</code>
+ * method is called.
+ * </p>
+ *
+ * @param from the path to the node that is to be copied.
+ * @return the object that can be used to specify addition nodes to be copied or the
location of the node where the node is to
+ * be copied
+ */
+ public Copy<Graph> copy( Path from ) {
+ return new CopyAction<Graph>(this, this.requestQueue, new Location(from));
+ }
+
+ /**
+ * Begin the request to copy a node with the specified unique identifier into a
parent node at a different location, which is
+ * specified via the <code>into(...)</code> method on the returned {@link
Copy} object.
+ * <p>
+ * Like all other methods on the {@link Graph}, the copy request will be performed
immediately when the <code>into(...)</code>
+ * method is called.
+ * </p>
+ *
+ * @param from the UUID of the node that is to be copied.
+ * @return the object that can be used to specify addition nodes to be copied or the
location of the node where the node is to
+ * be copied
+ */
+ public Copy<Graph> copy( UUID from ) {
+ return new CopyAction<Graph>(this, this.requestQueue, new Location(from));
+ }
+
+ /**
+ * Begin the request to copy a node with the specified unique identification property
into a parent node at a different
+ * location, which is specified via the <code>into(...)</code> method on
the returned {@link Copy} object. The identification
+ * property should uniquely identify a single node.
+ * <p>
+ * Like all other methods on the {@link Graph}, the copy request will be performed
immediately when the <code>into(...)</code>
+ * method is called.
+ * </p>
+ *
+ * @param idProperty the unique identification property of the node that is to be
copied.
+ * @return the object that can be used to specify addition nodes to be copied or the
location of the node where the node is to
+ * be copied
+ */
+ public Copy<Graph> copy( Property idProperty ) {
+ return new CopyAction<Graph>(this, this.requestQueue, new
Location(idProperty));
+ }
+
+ /**
+ * Begin the request to copy a node with the specified identification properties into
a parent node at a different location,
+ * which is specified via the <code>into(...)</code> method on the
returned {@link Copy} object. The identification properties
+ * should uniquely identify a single node.
+ * <p>
+ * Like all other methods on the {@link Graph}, the copy request will be performed
immediately when the <code>into(...)</code>
+ * method is called.
+ * </p>
+ *
+ * @param firstIdProperty the first identification property of the node that is to be
copied
+ * @param additionalIdProperties the remaining idenficiation properties of the node
that is to be copied
+ * @return the object that can be used to specify addition nodes to be copied or the
location of the node where the node is to
+ * be copied
+ */
+ public Copy<Graph> copy( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ return new CopyAction<Graph>(this, this.requestQueue, new
Location(firstIdProperty, additionalIdProperties));
+ }
+
+ /**
+ * Request to delete the specified node. This request is submitted to the repository
immediately.
+ *
+ * @param at the node that is to be deleted
+ * @return an object that may be used to start another request
+ */
+ public Conjunction<Graph> delete( Node at ) {
+ this.requestQueue.submit(new DeleteBranchRequest(at.getLocation()));
+ return nextGraph;
+ }
+
+ /**
+ * Request to delete the node at the given location. This request is submitted to the
repository immediately.
+ *
+ * @param at the location of the node that is to be deleted
+ * @return an object that may be used to start another request
+ */
+ public Conjunction<Graph> delete( Location at ) {
+ this.requestQueue.submit(new DeleteBranchRequest(at));
+ return nextGraph;
+ }
+
+ /**
+ * Request to delete the node at the given path. This request is submitted to the
repository immediately.
+ *
+ * @param atPath the path of the node that is to be deleted
+ * @return an object that may be used to start another request
+ */
+ public Conjunction<Graph> delete( String atPath ) {
+ this.requestQueue.submit(new DeleteBranchRequest(new
Location(createPath(atPath))));
+ return nextGraph;
+ }
+
+ /**
+ * Request to delete the node at the given path. This request is submitted to the
repository immediately.
+ *
+ * @param at the path of the node that is to be deleted
+ * @return an object that may be used to start another request
+ */
+ public Conjunction<Graph> delete( Path at ) {
+ this.requestQueue.submit(new DeleteBranchRequest(new Location(at)));
+ return nextGraph;
+ }
+
+ /**
+ * Request to delete the node with the given UUID. This request is submitted to the
repository immediately.
+ *
+ * @param at the UUID of the node that is to be deleted
+ * @return an object that may be used to start another request
+ */
+ public Conjunction<Graph> delete( UUID at ) {
+ this.requestQueue.submit(new DeleteBranchRequest(new Location(at)));
+ return nextGraph;
+ }
+
+ /**
+ * Request to delete the node with the given unique identification property. This
request is submitted to the repository
+ * immediately.
+ *
+ * @param idProperty the unique identifying property of the node that is to be
deleted
+ * @return an object that may be used to start another request
+ */
+ public Conjunction<Graph> delete( Property idProperty ) {
+ this.requestQueue.submit(new DeleteBranchRequest(new Location(idProperty)));
+ return nextGraph;
+ }
+
+ /**
+ * Request to delete the node with the given identification properties. The
identification properties should uniquely identify
+ * a single node. This request is submitted to the repository immediately.
+ *
+ * @param firstIdProperty the first identification property of the node that is to be
copied
+ * @param additionalIdProperties the remaining idenficiation properties of the node
that is to be copied
+ * @return an object that may be used to start another request
+ */
+ public Conjunction<Graph> delete( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ this.requestQueue.submit(new DeleteBranchRequest(new Location(firstIdProperty,
additionalIdProperties)));
+ return nextGraph;
+ }
+
+ /**
+ * Begin the request to create a node located at the supplied path. This request is
submitted to the repository immediately.
+ *
+ * @param atPath the path to the node that is to be created.
+ * @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 Conjunction<Graph> create( String atPath ) {
+ this.requestQueue.submit(new CreateNodeRequest(new
Location(createPath(atPath))));
+ return nextGraph;
+ }
+
+ /**
+ * Begin the request to create a node located at the supplied path. This request is
submitted to the repository immediately.
+ *
+ * @param atPath the path to the node that is to be created.
+ * @param properties the properties for the new node
+ * @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 Conjunction<Graph> create( String atPath,
+ Property... properties ) {
+ this.requestQueue.submit(new CreateNodeRequest(new Location(createPath(atPath)),
properties));
+ return nextGraph;
+ }
+
+ /**
+ * Begin the request to create a node located at the supplied path. This request is
submitted to the repository immediately.
+ *
+ * @param at the path to the node that is to be created.
+ * @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 Conjunction<Graph> create( Path at ) {
+ this.requestQueue.submit(new CreateNodeRequest(new Location(at)));
+ return nextGraph;
+ }
+
+ /**
+ * Begin the request to create a node located at the supplied path. This request is
submitted to the repository immediately.
+ *
+ * @param at the path to the node that is to be created.
+ * @param properties the properties for the new node
+ * @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 Conjunction<Graph> create( Path at,
+ Property... properties ) {
+ this.requestQueue.submit(new CreateNodeRequest(new Location(at), properties));
+ return nextGraph;
+ }
+
+ /**
+ * Request that the properties be read on the node defined via the
<code>on(...)</code> method on the returned {@link On}
+ * object. Once the location is specified, the {@link Collection collection of
properties} are read and then returned.
+ *
+ * @return the object that is used to specified the node whose properties are to be
read, and which will return the properties
+ */
+ public On<Collection<Property>> getProperties() {
+ return new On<Collection<Property>>() {
+ public Collection<Property> on( Location location ) {
+ ReadAllPropertiesRequest request = new
ReadAllPropertiesRequest(location);
+ queue().submit(request);
+ return request.getProperties();
+ }
+
+ public Collection<Property> on( String path ) {
+ return on(new Location(createPath(path)));
+ }
+
+ public Collection<Property> on( Path path ) {
+ return on(new Location(path));
+ }
+
+ public Collection<Property> on( Property idProperty ) {
+ return on(new Location(idProperty));
+ }
+
+ public Collection<Property> on( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ return on(new Location(firstIdProperty, additionalIdProperties));
+ }
+
+ public Collection<Property> on( UUID uuid ) {
+ return on(new Location(uuid));
+ }
+ };
+ }
+
+ /**
+ * Request that the properties be read on the node defined via the
<code>on(...)</code> method on the returned {@link On}
+ * object. Once the location is specified, the {@link Map map of properties} are read
and then returned.
+ *
+ * @return the object that is used to specified the node whose properties are to be
read, and which will return the properties
+ * as a map keyed by their name
+ */
+ public On<Map<Name, Property>> getPropertiesByName() {
+ return new On<Map<Name, Property>>() {
+ public Map<Name, Property> on( Location location ) {
+ ReadAllPropertiesRequest request = new
ReadAllPropertiesRequest(location);
+ queue().submit(request);
+ return request.getPropertiesByName();
+ }
+
+ public Map<Name, Property> on( String path ) {
+ return on(new Location(createPath(path)));
+ }
+
+ public Map<Name, Property> on( Path path ) {
+ return on(new Location(path));
+ }
+
+ public Map<Name, Property> on( Property idProperty ) {
+ return on(new Location(idProperty));
+ }
+
+ public Map<Name, Property> on( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ return on(new Location(firstIdProperty, additionalIdProperties));
+ }
+
+ public Map<Name, Property> on( UUID uuid ) {
+ return on(new Location(uuid));
+ }
+ };
+ }
+
+ /**
+ * Request that the children be read on the node defined via the
<code>of(...)</code> method on the returned {@link Of}
+ * object. Once the location is specified, the {@link List list of children} are read
and then returned.
+ *
+ * @return the object that is used to specified the node whose children are to be
read, and which will return the children
+ */
+ public Of<List<Location>> getChildren() {
+ return new Of<List<Location>>() {
+ public List<Location> of( String path ) {
+ return of(new Location(createPath(path)));
+ }
+
+ public List<Location> of( Path path ) {
+ return of(new Location(path));
+ }
+
+ public List<Location> of( Property idProperty ) {
+ return of(new Location(idProperty));
+ }
+
+ public List<Location> of( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ return of(new Location(firstIdProperty, additionalIdProperties));
+ }
+
+ public List<Location> of( UUID uuid ) {
+ return of(new Location(uuid));
+ }
+
+ public List<Location> of( Location at ) {
+ ReadAllChildrenRequest request = new ReadAllChildrenRequest(at);
+ queue().submit(request);
+ return request.getChildren();
+ }
+ };
+ }
+
+ /**
+ * Request that the children in the specified index range be read on the node defined
via the <code>of(...)</code> method on
+ * the returned {@link Of} object. Once the location is specified, the {@link List
list of children} are read and then
+ * returned.
+ *
+ * @param startingIndex the index of the first child to be read
+ * @param endingIndex the index past the last the first child to be read
+ * @return the object that is used to specified the node whose children are to be
read, and which will return the children
+ */
+ public Of<List<Location>> getChildrenInRange( final int startingIndex,
+ final int endingIndex ) {
+ CheckArg.isNonNegative(startingIndex, "startingIndex");
+ CheckArg.isPositive(endingIndex, "endingIndex");
+ int count = endingIndex - startingIndex;
+ return getChildrenInBlock(startingIndex, count);
+ }
+
+ /**
+ * Request that the children in the specified block be read on the node defined via
the <code>of(...)</code> method on the
+ * returned {@link Of} object. Once the location is specified, the {@link List list
of children} are read and then returned.
+ *
+ * @param startingIndex the index of the first child to be read
+ * @param blockSize the maximum number of children that should be read
+ * @return the object that is used to specified the node whose children are to be
read, and which will return the children
+ */
+ public Of<List<Location>> getChildrenInBlock( final int startingIndex,
+ final int blockSize ) {
+ CheckArg.isNonNegative(startingIndex, "startingIndex");
+ CheckArg.isPositive(blockSize, "blockSize");
+ return new Of<List<Location>>() {
+ public List<Location> of( String path ) {
+ return of(new Location(createPath(path)));
+ }
+
+ public List<Location> of( Path path ) {
+ return of(new Location(path));
+ }
+
+ public List<Location> of( Property idProperty ) {
+ return of(new Location(idProperty));
+ }
+
+ public List<Location> of( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ return of(new Location(firstIdProperty, additionalIdProperties));
+ }
+
+ public List<Location> of( UUID uuid ) {
+ return of(new Location(uuid));
+ }
+
+ public List<Location> of( Location at ) {
+ ReadBlockOfChildrenRequest request = new ReadBlockOfChildrenRequest(at,
startingIndex, blockSize);
+ queue().submit(request);
+ return request.getChildren();
+ }
+ };
+ }
+
+ /**
+ * Request that the property with the given name be read on the node defined via the
<code>on(...)</code> method on the
+ * returned {@link On} object. Once the location is specified, the {@link Property
property} is read and then returned.
+ *
+ * @param name the name of the property that is to be read
+ * @return the object that is used to specified the node whose property is to be
read, and which will return the property
+ */
+ public On<Property> getProperty( final String name ) {
+ Name nameObj = context.getValueFactories().getNameFactory().create(name);
+ return getProperty(nameObj);
+ }
+
+ /**
+ * Request that the property with the given name be read on the node defined via the
<code>on(...)</code> method on the
+ * returned {@link On} object. Once the location is specified, the {@link Property
property} is read and then returned.
+ *
+ * @param name the name of the property that is to be read
+ * @return the object that is used to specified the node whose property is to be
read, and which will return the property
+ */
+ public On<Property> getProperty( final Name name ) {
+ return new On<Property>() {
+ public Property on( String path ) {
+ return on(new Location(createPath(path)));
+ }
+
+ public Property on( Path path ) {
+ return on(new Location(path));
+ }
+
+ public Property on( Property idProperty ) {
+ return on(new Location(idProperty));
+ }
+
+ public Property on( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ return on(new Location(firstIdProperty, additionalIdProperties));
+ }
+
+ public Property on( UUID uuid ) {
+ return on(new Location(uuid));
+ }
+
+ public Property on( Location at ) {
+ ReadPropertyRequest request = new ReadPropertyRequest(at, name);
+ queue().submit(request);
+ return request.getProperty();
+ }
+ };
+ }
+
+ /**
+ * Request to read the node with the supplied UUID.
+ *
+ * @param uuid the UUID of the node that is to be read
+ * @return the node that is read from the repository
+ */
+ public Node getNodeAt( UUID uuid ) {
+ return getNodeAt(new Location(uuid));
+ }
+
+ /**
+ * Request to read the node at the supplied location.
+ *
+ * @param location the location of the node that is to be read
+ * @return the node that is read from the repository
+ */
+ public Node getNodeAt( Location location ) {
+ ReadNodeRequest request = new ReadNodeRequest(location);
+ this.requestQueue.submit(request);
+ return new GraphNode(request);
+ }
+
+ /**
+ * Request to read the node at the supplied path.
+ *
+ * @param path the path of the node that is to be read
+ * @return the node that is read from the repository
+ */
+ public Node getNodeAt( String path ) {
+ return getNodeAt(new Location(createPath(path)));
+ }
+
+ /**
+ * Request to read the node at the supplied path.
+ *
+ * @param path the path of the node that is to be read
+ * @return the node that is read from the repository
+ */
+ public Node getNodeAt( Path path ) {
+ return getNodeAt(new Location(path));
+ }
+
+ /**
+ * Request to read the node with the supplied unique identifier property.
+ *
+ * @param idProperty the identification property that is unique to the node that is
to be read
+ * @return the node that is read from the repository
+ */
+ public Node getNodeAt( Property idProperty ) {
+ return getNodeAt(new Location(idProperty));
+ }
+
+ /**
+ * Request to read the node with the supplied unique identifier properties.
+ *
+ * @param firstIdProperty the first of the identification properties that uniquely
identify the node that is to be read
+ * @param additionalIdProperties the remaining identification properties that
uniquely identify the node that is to be read
+ * @return the node that is read from the repository
+ */
+ public Node getNodeAt( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ return getNodeAt(new Location(firstIdProperty, additionalIdProperties));
+ }
+
+ /**
+ * Request to read a subgraph of the specified depth, rooted at a location that will
be specified via <code>at(...)</code> in
+ * the resulting {@link At} object. All properties and children of every node in the
subgraph will be read and returned in the
+ * {@link Subgraph} object returned from the <code>at(...)</code>
methods.
+ *
+ * @param depth the maximum depth of the subgraph that should be read
+ * @return the component that should be used to specify the location of the node that
is the top of the subgraph, and which
+ * will return the {@link Subgraph} containing the results
+ */
+ public At<Subgraph> getSubgraphOfDepth( final int depth ) {
+ return new At<Subgraph>() {
+ public Subgraph at( Location location ) {
+ ReadBranchRequest request = new ReadBranchRequest(location, depth);
+ queue().submit(request);
+ return new SubgraphResults(request);
+ }
+
+ public Subgraph at( String path ) {
+ return at(new Location(createPath(path)));
+ }
+
+ public Subgraph at( Path path ) {
+ return at(new Location(path));
+ }
+
+ public Subgraph at( UUID uuid ) {
+ return at(new Location(uuid));
+ }
+
+ public Subgraph at( Property idProperty ) {
+ return at(new Location(idProperty));
+ }
+
+ public Subgraph at( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ return at(new Location(firstIdProperty, additionalIdProperties));
+ }
+ };
+ }
+
+ /*package*/Path createPath( String path ) {
+ return getContext().getValueFactories().getPathFactory().create(path);
+ }
+
+ /*package*/void execute( Request request ) {
+ RepositoryConnection connection =
Graph.this.getConnectionFactory().createConnection(Graph.this.getSourceName());
+ try {
+ connection.execute(Graph.this.getContext(), request);
+ } finally {
+ connection.close();
+ }
+ if (request.hasError()) {
+ Throwable error = request.getError();
+ if (error instanceof RuntimeException) throw (RuntimeException)error;
+ throw new RepositorySourceException(getSourceName(), error);
+ }
+ }
+
+ /**
+ * Begin a batch of requests to perform various operations. Use this approach when
multiple operations are to be built and
+ * then executed with one submission to the underlying {@link #getSourceName()
repository source}. The {@link Results results}
+ * are not available until the {@link Batch#execute()} method is invoked.
+ *
+ * @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() {
+ return new Batch();
+ }
+
+ /**
+ * Interface for creating multiple requests to perform various operations. Note that
all the requests are accumulated until
+ * the {@link #execute()} method is called. The results of all the operations are
then available in the {@link Results} object
+ * returned by the {@link #execute()}.
+ *
+ * @author Randall Hauch
+ */
+ @Immutable
+ public final class Batch implements Executable {
+ protected final CompositingRequestQueue requestQueue = new
CompositingRequestQueue();
+ protected final BatchConjunction nextRequests;
+ protected boolean executed = false;
+
+ /*package*/Batch() {
+ this.nextRequests = new BatchConjunction() {
+ public Batch and() {
+ return Batch.this;
+ }
+
+ public Results execute() {
+ executed = true;
+ return Batch.this.requestQueue.execute();
+ }
+ };
+ }
+
+ protected final void assertNotExecuted() {
+ if (executed) {
+ throw new
IllegalStateException(GraphI18n.unableToAddMoreRequestsToAlreadyExecutedBatch.text());
+ }
+ }
+
+ /**
+ * Begin the request to move the specified node into a parent node at a different
location, which is specified via the
+ * <code>into(...)</code> method on the returned {@link Move}
object.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param from the node that is to be moved.
+ * @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( Node from ) {
+ assertNotExecuted();
+ return new MoveAction<BatchConjunction>(this.nextRequests,
this.requestQueue, from.getLocation());
+ }
+
+ /**
+ * Begin the request to move a node at the specified location into a parent node
at a different location, which is
+ * specified via the <code>into(...)</code> method on the returned
{@link Move} object.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param from the location of the node that is to be moved.
+ * @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 ) {
+ assertNotExecuted();
+ return new MoveAction<BatchConjunction>(this.nextRequests,
this.requestQueue, from);
+ }
+
+ /**
+ * Begin the request to move a node located at the supplied path into a parent
node at a different location, which is
+ * specified via the <code>into(...)</code> method on the returned
{@link Move} object.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param fromPath the path to the node that is to be moved.
+ * @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( String fromPath ) {
+ assertNotExecuted();
+ return new MoveAction<BatchConjunction>(this.nextRequests,
this.requestQueue, new Location(createPath(fromPath)));
+ }
+
+ /**
+ * Begin the request to move a node located at the supplied path into a parent
node at a different location, which is
+ * specified via the <code>into(...)</code> method on the returned
{@link Move} object.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param from the path to the node that is to be moved.
+ * @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( Path from ) {
+ assertNotExecuted();
+ return new MoveAction<BatchConjunction>(this.nextRequests,
this.requestQueue, new Location(from));
+ }
+
+ /**
+ * Begin the request to move a node with the specified unique identifier into a
parent node at a different location, which
+ * is specified via the <code>into(...)</code> method on the returned
{@link Move} object.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param from the UUID of the node that is to be moved.
+ * @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( UUID from ) {
+ assertNotExecuted();
+ return new MoveAction<BatchConjunction>(this.nextRequests,
this.requestQueue, new Location(from));
+ }
+
+ /**
+ * Begin the request to move a node with the specified unique identification
property into a parent node at a different
+ * location, which is specified via the <code>into(...)</code> method
on the returned {@link Move} object. The
+ * identification property should uniquely identify a single node.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param idProperty the unique identification property of the node that is to be
moved.
+ * @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( Property idProperty ) {
+ assertNotExecuted();
+ return new MoveAction<BatchConjunction>(this.nextRequests,
this.requestQueue, new Location(idProperty));
+ }
+
+ /**
+ * Begin the request to move a node with the specified identification properties
into a parent node at a different
+ * location, which is specified via the <code>into(...)</code> method
on the returned {@link Move} object. The
+ * identification properties should uniquely identify a single node.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param firstIdProperty the first identification property of the node that is
to be moved
+ * @param additionalIdProperties the remaining idenficiation properties of the
node that is to be moved
+ * @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( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ assertNotExecuted();
+ return new MoveAction<BatchConjunction>(this.nextRequests,
this.requestQueue, new Location(firstIdProperty,
+
additionalIdProperties));
+ }
+
+ /**
+ * Begin the request to copy the specified node into a parent node at a different
location, which is specified via the
+ * <code>into(...)</code> method on the returned {@link Copy}
object.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param from the node that is to be copied.
+ * @return the object that can be used to specify addition nodes to be copied or
the location of the node where the node
+ * is to be copied
+ */
+ public Copy<BatchConjunction> copy( Node from ) {
+ assertNotExecuted();
+ return new CopyAction<BatchConjunction>(nextRequests,
this.requestQueue, from.getLocation());
+ }
+
+ /**
+ * Begin the request to copy a node at the specified location into a parent node
at a different location, which is
+ * specified via the <code>into(...)</code> method on the returned
{@link Copy} object.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param from the location of the node that is to be copied.
+ * @return the object that can be used to specify addition nodes to be copied or
the location of the node where the node
+ * is to be copied
+ */
+ public Copy<BatchConjunction> copy( Location from ) {
+ assertNotExecuted();
+ return new CopyAction<BatchConjunction>(nextRequests,
this.requestQueue, from);
+ }
+
+ /**
+ * Begin the request to copy a node located at the supplied path into a parent
node at a different location, which is
+ * specified via the <code>into(...)</code> method on the returned
{@link Copy} object.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param fromPath the path to the node that is to be copied.
+ * @return the object that can be used to specify addition nodes to be copied or
the location of the node where the node
+ * is to be copied
+ */
+ public Copy<BatchConjunction> copy( String fromPath ) {
+ assertNotExecuted();
+ return new CopyAction<BatchConjunction>(nextRequests,
this.requestQueue, new Location(createPath(fromPath)));
+ }
+
+ /**
+ * Begin the request to copy a node located at the supplied path into a parent
node at a different location, which is
+ * specified via the <code>into(...)</code> method on the returned
{@link Copy} object.
+ * <p>
+ * Like all other methods on the {@link Graph}, the copy request will be
performed immediately when the
+ * <code>into(...)</code> method is called.
+ * </p>
+ *
+ * @param from the path to the node that is to be copied.
+ * @return the object that can be used to specify addition nodes to be copied or
the location of the node where the node
+ * is to be copied
+ */
+ public Copy<BatchConjunction> copy( Path from ) {
+ assertNotExecuted();
+ return new CopyAction<BatchConjunction>(nextRequests,
this.requestQueue, new Location(from));
+ }
+
+ /**
+ * Begin the request to copy a node with the specified unique identifier into a
parent node at a different location, which
+ * is specified via the <code>into(...)</code> method on the returned
{@link Copy} object.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param from the UUID of the node that is to be copied.
+ * @return the object that can be used to specify addition nodes to be copied or
the location of the node where the node
+ * is to be copied
+ */
+ public Copy<BatchConjunction> copy( UUID from ) {
+ assertNotExecuted();
+ return new CopyAction<BatchConjunction>(nextRequests,
this.requestQueue, new Location(from));
+ }
+
+ /**
+ * Begin the request to copy a node with the specified unique identification
property into a parent node at a different
+ * location, which is specified via the <code>into(...)</code> method
on the returned {@link Copy} object. The
+ * identification property should uniquely identify a single node.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param idProperty the unique identification property of the node that is to be
copied.
+ * @return the object that can be used to specify addition nodes to be copied or
the location of the node where the node
+ * is to be copied
+ */
+ public Copy<BatchConjunction> copy( Property idProperty ) {
+ assertNotExecuted();
+ return new CopyAction<BatchConjunction>(nextRequests,
this.requestQueue, new Location(idProperty));
+ }
+
+ /**
+ * Begin the request to copy a node with the specified identification properties
into a parent node at a different
+ * location, which is specified via the <code>into(...)</code> method
on the returned {@link Copy} object. The
+ * identification properties should uniquely identify a single node.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param firstIdProperty the first identification property of the node that is
to be copied
+ * @param additionalIdProperties the remaining idenficiation properties of the
node that is to be copied
+ * @return the object that can be used to specify addition nodes to be copied or
the location of the node where the node
+ * is to be copied
+ */
+ public Copy<BatchConjunction> copy( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ assertNotExecuted();
+ return new CopyAction<BatchConjunction>(nextRequests,
this.requestQueue, new Location(firstIdProperty,
+
additionalIdProperties));
+ }
+
+ /**
+ * Request to delete the specified node.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param at the node that is to be deleted
+ * @return an object that may be used to start another request
+ */
+ public BatchConjunction delete( Node at ) {
+ assertNotExecuted();
+ this.requestQueue.submit(new DeleteBranchRequest(at.getLocation()));
+ return nextRequests;
+ }
+
+ /**
+ * Request to delete the node at the given location.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param at the location of the node that is to be deleted
+ * @return an object that may be used to start another request
+ */
+ public BatchConjunction delete( Location at ) {
+ assertNotExecuted();
+ this.requestQueue.submit(new DeleteBranchRequest(at));
+ return nextRequests;
+ }
+
+ /**
+ * Request to delete the node at the given path.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param atPath the path of the node that is to be deleted
+ * @return an object that may be used to start another request
+ */
+ public BatchConjunction delete( String atPath ) {
+ assertNotExecuted();
+ this.requestQueue.submit(new DeleteBranchRequest(new
Location(createPath(atPath))));
+ return nextRequests;
+ }
+
+ /**
+ * Request to delete the node at the given path.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param at the path of the node that is to be deleted
+ * @return an object that may be used to start another request
+ */
+ public BatchConjunction delete( Path at ) {
+ assertNotExecuted();
+ this.requestQueue.submit(new DeleteBranchRequest(new Location(at)));
+ return nextRequests;
+ }
+
+ /**
+ * Request to delete the node with the given UUID.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param at the UUID of the node that is to be deleted
+ * @return an object that may be used to start another request
+ */
+ public BatchConjunction delete( UUID at ) {
+ assertNotExecuted();
+ this.requestQueue.submit(new DeleteBranchRequest(new Location(at)));
+ return nextRequests;
+ }
+
+ /**
+ * Request to delete the node with the given unique identification property.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param idProperty the unique identifying property of the node that is to be
deleted
+ * @return an object that may be used to start another request
+ */
+ public BatchConjunction delete( Property idProperty ) {
+ assertNotExecuted();
+ this.requestQueue.submit(new DeleteBranchRequest(new Location(idProperty)));
+ return nextRequests;
+ }
+
+ /**
+ * Request to delete the node with the given identification properties. The
identification properties should uniquely
+ * identify a single node.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param firstIdProperty the first identification property of the node that is
to be copied
+ * @param additionalIdProperties the remaining idenficiation properties of the
node that is to be copied
+ * @return an object that may be used to start another request
+ */
+ public BatchConjunction delete( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ assertNotExecuted();
+ this.requestQueue.submit(new DeleteBranchRequest(new
Location(firstIdProperty, additionalIdProperties)));
+ return nextRequests;
+ }
+
+ /**
+ * Begin the request to create a node located at the supplied path.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param atPath the path to the node that is to be created.
+ * @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<BatchConjunction> create( String atPath ) {
+ assertNotExecuted();
+ return new CreateAction<BatchConjunction>(nextRequests, requestQueue,
new Location(createPath(atPath)));
+ }
+
+ /**
+ * Begin the request to create a node located at the supplied path.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param atPath the path to the node that is to be created.
+ * @param property a property for the new node
+ * @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<BatchConjunction> create( String atPath,
+ Property property ) {
+ assertNotExecuted();
+ return new CreateAction<BatchConjunction>(nextRequests, requestQueue,
new Location(createPath(atPath))).with(property);
+ }
+
+ /**
+ * Begin the request to create a node located at the supplied path.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param atPath the path to the node that is to be created.
+ * @param firstProperty a property for the new node
+ * @param additionalProperties additional properties for the new node
+ * @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<BatchConjunction> create( String atPath,
+ Property firstProperty,
+ Property... additionalProperties ) {
+ assertNotExecuted();
+ return new CreateAction<BatchConjunction>(nextRequests, requestQueue,
new Location(createPath(atPath))).with(firstProperty,
+
additionalProperties);
+ }
+
+ /**
+ * Begin the request to create a node located at the supplied path.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param at the path to the node that is to be created.
+ * @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<BatchConjunction> create( Path at ) {
+ assertNotExecuted();
+ return new CreateAction<BatchConjunction>(nextRequests, requestQueue,
new Location(at));
+ }
+
+ /**
+ * Begin the request to create a node located at the supplied path.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param at the path to the node that is to be created.
+ * @param property a property for the new node
+ * @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<BatchConjunction> create( Path at,
+ Property property ) {
+ assertNotExecuted();
+ return new CreateAction<BatchConjunction>(nextRequests, requestQueue,
new Location(at)).with(property);
+ }
+
+ /**
+ * Begin the request to create a node located at the supplied path.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param at the path to the node that is to be created.
+ * @param firstProperty a property for the new node
+ * @param additionalProperties additional properties for the new node
+ * @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<BatchConjunction> create( Path at,
+ Property firstProperty,
+ Property... additionalProperties ) {
+ assertNotExecuted();
+ return new CreateAction<BatchConjunction>(nextRequests, requestQueue,
new Location(at)).with(firstProperty,
+
additionalProperties);
+ }
+
+ /**
+ * Request to read the node with the supplied UUID.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param uuid the UUID of the node that is to be read
+ * @return the interface that can either execute the batched requests or continue
to add additional requests to the batch
+ */
+ public BatchConjunction read( UUID uuid ) {
+ return read(new Location(uuid));
+ }
+
+ /**
+ * Request to read the node at the supplied location.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param location the location of the node that is to be read
+ * @return the interface that can either execute the batched requests or continue
to add additional requests to the batch
+ */
+ public BatchConjunction read( Location location ) {
+ assertNotExecuted();
+ ReadNodeRequest request = new ReadNodeRequest(location);
+ requestQueue.submit(request);
+ return nextRequests;
+ }
+
+ /**
+ * Request to read the node at the supplied path.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param path the path of the node that is to be read
+ * @return the interface that can either execute the batched requests or continue
to add additional requests to the batch
+ */
+ public BatchConjunction read( String path ) {
+ return read(new Location(createPath(path)));
+ }
+
+ /**
+ * Request to read the node at the supplied path.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param path the path of the node that is to be read
+ * @return the interface that can either execute the batched requests or continue
to add additional requests to the batch
+ */
+ public BatchConjunction read( Path path ) {
+ return read(new Location(path));
+ }
+
+ /**
+ * Request to read the node with the supplied unique identifier property.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param idProperty the identification property that is unique to the node that
is to be read
+ * @return the interface that can either execute the batched requests or continue
to add additional requests to the batch
+ */
+ public BatchConjunction read( Property idProperty ) {
+ return read(new Location(idProperty));
+ }
+
+ /**
+ * Request to read the node with the supplied unique identifier properties.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param firstIdProperty the first of the identification properties that
uniquely identify the node that is to be read
+ * @param additionalIdProperties the remaining identification properties that
uniquely identify the node that is to be
+ * read
+ * @return the interface that can either execute the batched requests or continue
to add additional requests to the batch
+ */
+ public BatchConjunction read( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ return read(new Location(firstIdProperty, additionalIdProperties));
+ }
+
+ /**
+ * Request that the property with the given name be read on the node defined via
the <code>on(...)</code> method on the
+ * returned {@link On} object.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param propertyName the name of the property that is to be read
+ * @return the object that is used to specified the node whose property is to be
read
+ */
+ public On<BatchConjunction> readProperty( String propertyName ) {
+ assertNotExecuted();
+ Name name =
Graph.this.getContext().getValueFactories().getNameFactory().create(propertyName);
+ return readProperty(name);
+ }
+
+ /**
+ * Request that the property with the given name be read on the node defined via
the <code>on(...)</code> method on the
+ * returned {@link On} object.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param name the name of the property that is to be read
+ * @return the object that is used to specified the node whose property is to be
read
+ */
+ public On<BatchConjunction> readProperty( final Name name ) {
+ assertNotExecuted();
+ return new On<BatchConjunction>() {
+ public BatchConjunction on( String path ) {
+ return on(new Location(createPath(path)));
+ }
+
+ public BatchConjunction on( Path path ) {
+ return on(new Location(path));
+ }
+
+ public BatchConjunction on( Property idProperty ) {
+ return on(new Location(idProperty));
+ }
+
+ public BatchConjunction on( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ return on(new Location(firstIdProperty, additionalIdProperties));
+ }
+
+ public BatchConjunction on( UUID uuid ) {
+ return on(new Location(uuid));
+ }
+
+ public BatchConjunction on( Location at ) {
+ ReadPropertyRequest request = new ReadPropertyRequest(at, name);
+ queue().submit(request);
+ return Batch.this.nextRequests;
+ }
+ };
+ }
+
+ /**
+ * Request that the properties be read on the node defined via the
<code>on(...)</code> method on the returned {@link On}
+ * object.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @return the object that is used to specified the node whose properties are to
be read,
+ */
+ public On<BatchConjunction> readProperties() {
+ assertNotExecuted();
+ return new On<BatchConjunction>() {
+ public BatchConjunction on( Location location ) {
+ ReadAllPropertiesRequest request = new
ReadAllPropertiesRequest(location);
+ queue().submit(request);
+ return Batch.this.nextRequests;
+ }
+
+ public BatchConjunction on( String path ) {
+ return on(new Location(createPath(path)));
+ }
+
+ public BatchConjunction on( Path path ) {
+ return on(new Location(path));
+ }
+
+ public BatchConjunction on( Property idProperty ) {
+ return on(new Location(idProperty));
+ }
+
+ public BatchConjunction on( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ return on(new Location(firstIdProperty, additionalIdProperties));
+ }
+
+ public BatchConjunction on( UUID uuid ) {
+ return on(new Location(uuid));
+ }
+ };
+ }
+
+ /**
+ * Request that the children be read on the node defined via the
<code>of(...)</code> method on the returned {@link Of}
+ * object.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @return the object that is used to specified the node whose children are to be
read
+ */
+ public Of<BatchConjunction> readChildren() {
+ assertNotExecuted();
+ return new Of<BatchConjunction>() {
+ public BatchConjunction of( String path ) {
+ return of(new Location(createPath(path)));
+ }
+
+ public BatchConjunction of( Path path ) {
+ return of(new Location(path));
+ }
+
+ public BatchConjunction of( Property idProperty ) {
+ return of(new Location(idProperty));
+ }
+
+ public BatchConjunction of( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ return of(new Location(firstIdProperty, additionalIdProperties));
+ }
+
+ public BatchConjunction of( UUID uuid ) {
+ return of(new Location(uuid));
+ }
+
+ public BatchConjunction of( Location at ) {
+ ReadAllChildrenRequest request = new ReadAllChildrenRequest(at);
+ queue().submit(request);
+ return Batch.this.nextRequests;
+ }
+ };
+ }
+
+ /**
+ * Request that the children in the specified index range be read on the node
defined via the <code>of(...)</code> method
+ * on the returned {@link Of} object.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param startingIndex the index of the first child to be read
+ * @param endingIndex the index past the last the first child to be read
+ * @return the object that is used to specified the node whose children are to be
read
+ */
+ public Of<BatchConjunction> readChildrenInRange( final int startingIndex,
+ final int endingIndex ) {
+ assertNotExecuted();
+ CheckArg.isNonNegative(startingIndex, "startingIndex");
+ CheckArg.isPositive(endingIndex, "endingIndex");
+ int count = endingIndex - startingIndex;
+ return readChildrenInBlock(startingIndex, count);
+ }
+
+ /**
+ * Request that the children in the specified block be read on the node defined
via the <code>of(...)</code> method on the
+ * returned {@link Of} object.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param startingIndex the index of the first child to be read
+ * @param blockSize the maximum number of children that should be read
+ * @return the object that is used to specified the node whose children are to be
read
+ */
+ public Of<BatchConjunction> readChildrenInBlock( final int startingIndex,
+ final int blockSize ) {
+ assertNotExecuted();
+ CheckArg.isNonNegative(startingIndex, "startingIndex");
+ CheckArg.isPositive(blockSize, "blockSize");
+ return new Of<BatchConjunction>() {
+ public BatchConjunction of( String path ) {
+ return of(new Location(createPath(path)));
+ }
+
+ public BatchConjunction of( Path path ) {
+ return of(new Location(path));
+ }
+
+ public BatchConjunction of( Property idProperty ) {
+ return of(new Location(idProperty));
+ }
+
+ public BatchConjunction of( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ return of(new Location(firstIdProperty, additionalIdProperties));
+ }
+
+ public BatchConjunction of( UUID uuid ) {
+ return of(new Location(uuid));
+ }
+
+ public BatchConjunction of( Location at ) {
+ ReadBlockOfChildrenRequest request = new
ReadBlockOfChildrenRequest(at, startingIndex, blockSize);
+ queue().submit(request);
+ return Batch.this.nextRequests;
+ }
+ };
+ }
+
+ /**
+ * Request to read a subgraph of the specified depth, rooted at a location that
will be specified via <code>at(...)</code>
+ * in the resulting {@link At} object.
+ * <p>
+ * Like all other methods on the {@link Batch}, the request will be performed
when the {@link #execute()} method is
+ * called.
+ * </p>
+ *
+ * @param depth the maximum depth of the subgraph that should be read
+ * @return the component that should be used to specify the location of the node
that is the top of the subgraph
+ */
+ public At<BatchConjunction> readSubgraphOfDepth( final int depth ) {
+ assertNotExecuted();
+ return new At<BatchConjunction>() {
+ public BatchConjunction at( Location location ) {
+ ReadBranchRequest request = new ReadBranchRequest(location, depth);
+ queue().submit(request);
+ return Batch.this.nextRequests;
+ }
+
+ public BatchConjunction at( String path ) {
+ return at(new Location(createPath(path)));
+ }
+
+ public BatchConjunction at( Path path ) {
+ return at(new Location(path));
+ }
+
+ public BatchConjunction at( UUID uuid ) {
+ return at(new Location(uuid));
+ }
+
+ public BatchConjunction at( Property idProperty ) {
+ return at(new Location(idProperty));
+ }
+
+ public BatchConjunction at( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ return at(new Location(firstIdProperty, additionalIdProperties));
+ }
+ };
+ }
+
+ public Results execute() {
+ return this.requestQueue.execute();
+ }
+ }
+
+ /**
+ * A interface used to execute the accumulated {@link Batch requests}.
+ *
+ * @author Randall Hauch
+ */
+ public interface Executable {
+ /**
+ * Stop accumulating the requests, submit them to the repository source, and
return the results.
+ *
+ * @return the results containing the requested information from the repository.
+ */
+ Results execute();
+ }
+
+ /**
+ * A interface that can be used to finish the current request and start another.
+ *
+ * @param <Next> the interface that will be used to start another request
+ * @author Randall Hauch
+ */
+ public interface Conjunction<Next> {
+ /**
+ * Finish the request and prepare to start another.
+ *
+ * @return the interface that can be used to start another request; never null
+ */
+ Next and();
+ }
+
+ /**
+ * A component that defines the location into which a node should be copied or
moved.
+ *
+ * @param <Next> The interface that is to be returned when this request is
completed
+ * @author Randall Hauch
+ */
+ public interface Into<Next> {
+ /**
+ * Finish the request by specifying the new location into which the node should
be copied/moved.
+ *
+ * @param to the location of the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next into( Location to );
+
+ /**
+ * Finish the request by specifying the new location into which the node should
be copied/moved.
+ *
+ * @param toPath the path of the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next into( String toPath );
+
+ /**
+ * Finish the request by specifying the new location into which the node should
be copied/moved.
+ *
+ * @param to the path of the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next into( Path to );
+
+ /**
+ * Finish the request by specifying the new location into which the node should
be copied/moved.
+ *
+ * @param to the UUID of the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next into( UUID to );
+
+ /**
+ * Finish the request by specifying the new location into which the node should
be copied/moved.
+ *
+ * @param idProperty the property that uniquely identifies the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next into( Property idProperty );
+
+ /**
+ * Finish the request by specifying the new location into which the node should
be copied/moved.
+ *
+ * @param firstIdProperty the first property that, with the
<code>additionalIdProperties</code>, uniquely identifies the
+ * new parent
+ * @param additionalIdProperties the additional properties that, with the
<code>additionalIdProperties</code>, uniquely
+ * identifies the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next into( Property firstIdProperty,
+ Property... additionalIdProperties );
+ }
+
+ /**
+ * A interface that is used to add more locations that are to be copied/moved.
+ *
+ * @param <Next> The interface that is to be returned when this request is
completed
+ * @author Randall Hauch
+ */
+ public interface And<Next> {
+ /**
+ * Specify that another node should also be copied or moved.
+ *
+ * @param from the location of the node to be copied or moved
+ * @return the interface for finishing the request
+ */
+ Next and( Location from );
+
+ /**
+ * Specify that another node should also be copied or moved.
+ *
+ * @param fromPath the path of the node to be copied or moved
+ * @return the interface for finishing the request
+ */
+ Next and( String fromPath );
+
+ /**
+ * Specify that another node should also be copied or moved.
+ *
+ * @param from the path of the node to be copied or moved
+ * @return the interface for finishing the request
+ */
+ Next and( Path from );
+
+ /**
+ * Specify that another node should also be copied or moved.
+ *
+ * @param from the UUID of the node to be copied or moved
+ * @return the interface for finishing the request
+ */
+ Next and( UUID from );
+
+ /**
+ * Specify that another node should also be copied or moved.
+ *
+ * @param idProperty the property that uniquely identifies the node to be copied
or moved
+ * @return the interface for finishing the request
+ */
+ Next and( Property idProperty );
+
+ /**
+ * Specify that another node should also be copied or moved.
+ *
+ * @param firstIdProperty the first property that, with the
<code>additionalIdProperties</code>, uniquely identifies the
+ * node to be copied or moved
+ * @param additionalIdProperties the additional properties that, with the
<code>additionalIdProperties</code>, uniquely
+ * identifies the node to be copied or moved
+ * @return the interface for finishing the request
+ */
+ Next and( Property firstIdProperty,
+ Property... additionalIdProperties );
+ }
+
+ /**
+ * The interface for defining additional nodes to be moved and the parent into which
the node(s) are to be moved.
+ *
+ * @param <Next> The interface that is to be returned when this request is
completed
+ * @author Randall Hauch
+ */
+ public interface Move<Next> extends Into<Next>,
And<Move<Next>> {
+ }
+
+ /**
+ * The interface for defining additional nodes to be copied and the parent into which
the node(s) are to be copied. where the
+ * node(s) are to be moved.
+ *
+ * @param <Next> The interface that is to be returned when this request is
completed
+ * @author Randall Hauch
+ */
+ public interface Copy<Next> extends Into<Next>,
And<Copy<Next>> {
+ }
+
+ /**
+ * The interface for defining additional properties on a new node.
+ *
+ * @param <Next> The interface that is to be returned when this create request
is completed
+ * @author Randall Hauch
+ */
+ public interface Create<Next> extends Conjunction<Next>, Executable {
+ /**
+ * Specify the UUID that should the new node should have. This is an alias for
{@link #and(UUID)}.
+ *
+ * @param uuid the UUID
+ * @return this same interface so additional properties may be added
+ */
+ Create<Next> with( UUID uuid );
+
+ /**
+ * Specify a property that should the new node should have. This is an alias for
{@link #and(Property)}.
+ *
+ * @param property the property
+ * @return this same interface so additional properties may be added
+ */
+ Create<Next> with( Property property );
+
+ /**
+ * Specify a property that should the new node should have. This is an alias for
{@link #and(String, Object...)}.
+ *
+ * @param propertyName the name of the property
+ * @param values the property values
+ * @return this same interface so additional properties may be added
+ */
+ Create<Next> with( String propertyName,
+ Object... values );
+
+ /**
+ * Specify a property that should the new node should have. This is an alias for
{@link #and(Name, Object...)}.
+ *
+ * @param propertyName the name of the property
+ * @param values the property values
+ * @return this same interface so additional properties may be added
+ */
+ Create<Next> with( Name propertyName,
+ Object... values );
+
+ /**
+ * Specify properties that should the new node should have. This is an alias for
{@link #and(Property, Property...)}.
+ *
+ * @param firstProperty the first property
+ * @param additionalProperties the additional property
+ * @return this same interface so additional properties may be added
+ */
+ Create<Next> with( Property firstProperty,
+ Property... additionalProperties );
+
+ /**
+ * Specify the UUID that should the new node should have.
+ *
+ * @param uuid the UUID
+ * @return this same interface so additional properties may be added
+ */
+ Create<Next> and( UUID uuid );
+
+ /**
+ * Specify a property that should the new node should have.
+ *
+ * @param property the property
+ * @return this same interface so additional properties may be added
+ */
+ Create<Next> and( Property property );
+
+ /**
+ * Specify a property that should the new node should have.
+ *
+ * @param propertyName the name of the property
+ * @param values the property values
+ * @return this same interface so additional properties may be added
+ */
+ Create<Next> and( String propertyName,
+ Object... values );
+
+ /**
+ * Specify a property that should the new node should have.
+ *
+ * @param propertyName the name of the property
+ * @param values the property values
+ * @return this same interface so additional properties may be added
+ */
+ Create<Next> and( Name propertyName,
+ Object... values );
+
+ /**
+ * Specify properties that should the new node should have.
+ *
+ * @param firstProperty the first property
+ * @param additionalProperties the additional property
+ * @return this same interface so additional properties may be added
+ */
+ Create<Next> and( Property firstProperty,
+ Property... additionalProperties );
+ }
+
+ /**
+ * The interface for defining the node upon which a request operates.
+ *
+ * @param <Next> The interface that is to be returned when the request is
completed
+ * @author Randall Hauch
+ */
+ public interface On<Next> {
+ /**
+ * Specify the location of the node upon which the request is to operate.
+ *
+ * @param to the location of the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next on( Location to );
+
+ /**
+ * Specify the path of the node upon which the request is to operate.
+ *
+ * @param toPath the path of the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next on( String toPath );
+
+ /**
+ * Specify the path of the node upon which the request is to operate.
+ *
+ * @param to the path of the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next on( Path to );
+
+ /**
+ * Specify the UUID of the node upon which the request is to operate.
+ *
+ * @param to the UUID of the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next on( UUID to );
+
+ /**
+ * Specify the unique identification property that identifies the node upon which
the request is to operate.
+ *
+ * @param idProperty the property that uniquely identifies the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next on( Property idProperty );
+
+ /**
+ * Specify the unique identification properties that identify the node upon which
the request is to operate.
+ *
+ * @param firstIdProperty the first property that, with the
<code>additionalIdProperties</code>, uniquely identifies the
+ * new parent
+ * @param additionalIdProperties the additional properties that, with the
<code>additionalIdProperties</code>, uniquely
+ * identifies the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next on( Property firstIdProperty,
+ Property... additionalIdProperties );
+ }
+
+ /**
+ * The interface for defining the node upon which a request operates.
+ *
+ * @param <Next> The interface that is to be returned when the request is
completed
+ * @author Randall Hauch
+ */
+ public interface Of<Next> {
+ /**
+ * Specify the location of the node upon which the request is to operate.
+ *
+ * @param to the location of the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next of( Location to );
+
+ /**
+ * Specify the path of the node upon which the request is to operate.
+ *
+ * @param toPath the path of the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next of( String toPath );
+
+ /**
+ * Specify the path of the node upon which the request is to operate.
+ *
+ * @param to the path of the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next of( Path to );
+
+ /**
+ * Specify the UUID of the node upon which the request is to operate.
+ *
+ * @param to the UUID of the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next of( UUID to );
+
+ /**
+ * Specify the unique identification property that identifies the node upon which
the request is to operate.
+ *
+ * @param idProperty the property that uniquely identifies the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next of( Property idProperty );
+
+ /**
+ * Specify the unique identification properties that identify the node upon which
the request is to operate.
+ *
+ * @param firstIdProperty the first property that, with the
<code>additionalIdProperties</code>, uniquely identifies the
+ * new parent
+ * @param additionalIdProperties the additional properties that, with the
<code>additionalIdProperties</code>, uniquely
+ * identifies the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next of( Property firstIdProperty,
+ Property... additionalIdProperties );
+ }
+
+ /**
+ * The interface for defining the node upon which which a request operates.
+ *
+ * @param <Next> The interface that is to be returned when the request is
completed
+ * @author Randall Hauch
+ */
+ public interface At<Next> {
+ /**
+ * Specify the location of the node upon which the request is to operate.
+ *
+ * @param to the location of the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next at( Location to );
+
+ /**
+ * Specify the path of the node upon which the request is to operate.
+ *
+ * @param toPath the path of the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next at( String toPath );
+
+ /**
+ * Specify the path of the node upon which the request is to operate.
+ *
+ * @param to the path of the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next at( Path to );
+
+ /**
+ * Specify the UUID of the node upon which the request is to operate.
+ *
+ * @param to the UUID of the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next at( UUID to );
+
+ /**
+ * Specify the unique identification property that identifies the node upon which
the request is to operate.
+ *
+ * @param idProperty the property that uniquely identifies the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next at( Property idProperty );
+
+ /**
+ * Specify the unique identification properties that identify the node upon which
the request is to operate.
+ *
+ * @param firstIdProperty the first property that, with the
<code>additionalIdProperties</code>, uniquely identifies the
+ * new parent
+ * @param additionalIdProperties the additional properties that, with the
<code>additionalIdProperties</code>, uniquely
+ * identifies the new parent
+ * @return the interface for additional requests or actions
+ */
+ Next at( Property firstIdProperty,
+ Property... additionalIdProperties );
+ }
+
+ public interface BatchConjunction extends Conjunction<Batch>, Executable {
+ }
+
+ //
----------------------------------------------------------------------------------------------------------------
+ // 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
+ */
+ /*package*/interface RequestQueue extends Executable {
+ 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
+ /*package*/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 List<Request> requests = new LinkedList<Request>();
+
+ public Graph getGraph() {
+ return Graph.this;
+ }
+
+ public List<Request> getRequests() {
+ return this.requests;
+ }
+
+ public void submit( Request request ) {
+ this.requests.add(request);
+ }
+
+ public void submit( List<Request> requests ) {
+ this.requests.addAll(requests);
+ }
+
+ public Results execute() {
+ // Execute the requests ...
+ Request request = CompositeRequest.with(requests);
+ Graph.this.execute(request);
+ return new BatchResults(requests);
+ }
+ }
+
+ //
----------------------------------------------------------------------------------------------------------------
+ // Node Implementation
+ //
----------------------------------------------------------------------------------------------------------------
+ @Immutable
+ protected class GraphNode implements Node {
+ private final ReadNodeRequest request;
+
+ /*package*/GraphNode( ReadNodeRequest request ) {
+ this.request = request;
+ }
+
+ public Location getLocation() {
+ return request.at();
+ }
+
+ public Graph getGraph() {
+ return Graph.this;
+ }
+
+ public Collection<Property> getProperties() {
+ return request.getProperties();
+ }
+
+ public Map<Name, Property> getPropertiesByName() {
+ return request.getPropertiesByName();
+ }
+
+ public List<Location> getChildren() {
+ return request.getChildren();
+ }
+
+ public boolean hasChildren() {
+ return request.getChildren().size() > 0;
+ }
+
+ public Iterator<Location> iterator() {
+ return request.getChildren().iterator();
+ }
+
+ @Override
+ public int hashCode() {
+ return getLocation().hashCode();
+ }
+
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj instanceof Node) {
+ Node that = (Node)obj;
+ return this.getLocation().equals(that.getLocation());
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "Node " + getLocation().toString();
+ }
+ }
+
+ //
----------------------------------------------------------------------------------------------------------------
+ // Results implementation for the batched requests
+ //
----------------------------------------------------------------------------------------------------------------
+ @Immutable
+ class BatchResults implements Results {
+ private final Map<Path, BatchResultsNode> nodes = new HashMap<Path,
BatchResultsNode>();
+
+ /*package*/BatchResults( List<Request> requests ) {
+ for (Request request : requests) {
+ if (request instanceof ReadAllPropertiesRequest) {
+ ReadAllPropertiesRequest read = (ReadAllPropertiesRequest)request;
+
getOrCreateNode(read.at()).setProperties(read.getPropertiesByName());
+ } else if (request instanceof ReadPropertyRequest) {
+ ReadPropertyRequest read = (ReadPropertyRequest)request;
+ getOrCreateNode(read.on()).addProperty(read.getProperty());
+ } else if (request instanceof ReadNodeRequest) {
+ ReadNodeRequest read = (ReadNodeRequest)request;
+ BatchResultsNode node = getOrCreateNode(read.at());
+ 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.of()).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();
+ }
+ }
+
+ private BatchResultsNode getOrCreateNode( Location location ) {
+ BatchResultsNode node = nodes.get(location);
+ if (node == null) {
+ node = new BatchResultsNode(location);
+ assert location.getPath() != null;
+ nodes.put(location.getPath(), node);
+ }
+ return node;
+ }
+
+ public Graph getGraph() {
+ return Graph.this;
+ }
+
+ protected void checkIsAbsolute( Path path ) {
+ if (!path.isAbsolute()) {
+ throw new
IllegalArgumentException(GraphI18n.pathIsNotAbsolute.text(path));
+ }
+ }
+
+ public Node getNode( String pathStr ) {
+ Path path = createPath(pathStr);
+ checkIsAbsolute(path);
+ return nodes.get(path);
+ }
+
+ public Node getNode( Path path ) {
+ CheckArg.isNotNull(path, "path");
+ checkIsAbsolute(path);
+ return nodes.get(path);
+ }
+
+ public Node getNode( Location location ) {
+ CheckArg.isNotNull(location, "location");
+ CheckArg.isNotNull(location.getPath(), "location.getPath()");
+ return nodes.get(location.getPath());
+ }
+
+ public boolean includes( String path ) {
+ return getNode(path) != null;
+ }
+
+ public boolean includes( Path path ) {
+ return getNode(path) != null;
+ }
+
+ public boolean includes( Location location ) {
+ return getNode(location) != null;
+ }
+
+ public Iterator<Node> iterator() {
+ List<Path> paths = new ArrayList<Path>(nodes.keySet());
+ Collections.sort(paths);
+ final Iterator<Path> pathIter = paths.iterator();
+ return new Iterator<Node>() {
+ public boolean hasNext() {
+ return pathIter.hasNext();
+ }
+
+ public Node next() {
+ Path nextPath = pathIter.next();
+ return getNode(nextPath);
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ }
+
+ @Immutable
+ class BatchResultsNode implements Node {
+ private final Location location;
+ private Map<Name, Property> properties;
+ private List<Location> children;
+
+ BatchResultsNode( Location location ) {
+ this.location = location;
+ }
+
+ void addProperty( Property property ) {
+ if (this.properties == null) this.properties = new HashMap<Name,
Property>();
+ this.properties.put(property.getName(), property);
+ }
+
+ void setProperties( Map<Name, Property> properties ) {
+ this.properties = properties;
+ }
+
+ void setChildren( List<Location> children ) {
+ this.children = children;
+ }
+
+ void freeze() {
+ if (properties != null) properties =
Collections.unmodifiableMap(properties);
+ else properties = Collections.emptyMap();
+ if (children != null) children = Collections.unmodifiableList(children);
+ else children = Collections.emptyList();
+ }
+
+ public Graph getGraph() {
+ return Graph.this;
+ }
+
+ public Location getLocation() {
+ return location;
+ }
+
+ public Collection<Property> getProperties() {
+ return properties.values();
+ }
+
+ public Map<Name, Property> getPropertiesByName() {
+ return properties;
+ }
+
+ public List<Location> getChildren() {
+ return children;
+ }
+
+ public boolean hasChildren() {
+ return children.size() != 0;
+ }
+
+ public Iterator<Location> iterator() {
+ return children.iterator();
+ }
+
+ @Override
+ public int hashCode() {
+ return location.hashCode();
+ }
+
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj instanceof Node) {
+ Node that = (Node)obj;
+ return this.location.equals(that.getLocation());
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "Node " + getLocation().toString();
+ }
+
+ }
+
+ //
----------------------------------------------------------------------------------------------------------------
+ // Subgraph and SubgraphNode implementations
+ //
----------------------------------------------------------------------------------------------------------------
+ @Immutable
+ class SubgraphResults implements Subgraph {
+ private final ReadBranchRequest request;
+
+ SubgraphResults( ReadBranchRequest request ) {
+ this.request = request;
+ }
+
+ public Graph getGraph() {
+ return Graph.this;
+ }
+
+ public Location getLocation() {
+ return request.at();
+ }
+
+ public int getMaximumDepth() {
+ return request.maximumDepth();
+ }
+
+ public Iterator<Node> iterator() {
+ final Iterator<Location> iter = request.iterator();
+ return new Iterator<Node>() {
+ public boolean hasNext() {
+ return iter.hasNext();
+ }
+
+ public Node next() {
+ return getNode(iter.next());
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ public boolean includes( Path path ) {
+ CheckArg.isNotNull(path, "path");
+ path = getAbsolutePath(path);
+ return includes(new Location(path));
+ }
+
+ public boolean includes( Location location ) {
+ CheckArg.isNotNull(location, "location");
+ return request.includes(location);
+ }
+
+ public boolean includes( String pathStr ) {
+ Path path = createPath(pathStr);
+ path = getAbsolutePath(path);
+ return includes(new Location(path));
+ }
+
+ public Node getNode( Location location ) {
+ if (!includes(location)) return null;
+ return new SubgraphNode(location, request);
+ }
+
+ public Node getNode( Path path ) {
+ path = getAbsolutePath(path);
+ return getNode(new Location(path));
+ }
+
+ public Node getNode( String pathStr ) {
+ CheckArg.isNotEmpty(pathStr, "path");
+ Path path = createPath(pathStr);
+ path = getAbsolutePath(path);
+ return getNode(new Location(path));
+ }
+
+ protected Path getAbsolutePath( Path absoluteOrRelative ) {
+ Path result = absoluteOrRelative;
+ if (!result.isAbsolute()) {
+ result =
getGraph().getContext().getValueFactories().getPathFactory().create(request.at().getPath(),
result);
+ result = result.getNormalizedPath();
+ }
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ return getLocation().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "Subgraph " + getLocation().toString();
+ }
+ }
+
+ @Immutable
+ class SubgraphNode implements Node {
+ private final Location location;
+ private final ReadBranchRequest request;
+
+ SubgraphNode( Location location,
+ ReadBranchRequest request ) {
+ this.location = location;
+ this.request = request;
+ }
+
+ public List<Location> getChildren() {
+ return request.getChildren(location);
+ }
+
+ public Graph getGraph() {
+ return Graph.this;
+ }
+
+ public Location getLocation() {
+ return location;
+ }
+
+ public Collection<Property> getProperties() {
+ return getPropertiesByName().values();
+ }
+
+ public Map<Name, Property> getPropertiesByName() {
+ return request.getPropertiesFor(location);
+ }
+
+ public boolean hasChildren() {
+ return getChildren().size() != 0;
+ }
+
+ public Iterator<Location> iterator() {
+ return request.iterator();
+ }
+
+ @Override
+ public int hashCode() {
+ return location.hashCode();
+ }
+
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj instanceof Node) {
+ Node that = (Node)obj;
+ return this.location.equals(that.getLocation());
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "Node " + getLocation().toString();
+ }
+ }
+
+ //
----------------------------------------------------------------------------------------------------------------
+ // Action Implementations
+ //
----------------------------------------------------------------------------------------------------------------
+ @Immutable
+ static abstract class AbstractAction<T> implements Conjunction<T>,
Executable {
+ private final RequestQueue queue;
+ private final T afterConjunction;
+
+ /*package*/AbstractAction( T afterConjunction,
+ RequestQueue queue ) {
+ this.queue = queue;
+ this.afterConjunction = afterConjunction;
+ }
+
+ /*package*/RequestQueue queue() {
+ return this.queue;
+ }
+
+ public T and() {
+ return this.afterConjunction;
+ }
+
+ /*package*/Path createPath( String path ) {
+ return
queue.getGraph().getContext().getValueFactories().getPathFactory().create(path);
+ }
+
+ public Results execute() {
+ return queue.execute();
+ }
+ }
+
+ @NotThreadSafe
+ static class MoveAction<T> extends AbstractAction<T> implements
Move<T> {
+ private final Locations from;
+
+ /*package*/MoveAction( T afterConjunction,
+ RequestQueue queue,
+ Location from ) {
+ super(afterConjunction, queue);
+ this.from = new Locations(from);
+ }
+
+ public Move<T> and( Location from ) {
+ this.from.add(from);
+ return this;
+ }
+
+ public Move<T> and( String from ) {
+ this.from.add(new Location(createPath(from)));
+ return this;
+ }
+
+ public Move<T> and( Path from ) {
+ this.from.add(new Location(from));
+ return this;
+ }
+
+ public Move<T> and( Property firstFrom,
+ Property... additionalFroms ) {
+ this.from.add(new Location(firstFrom, additionalFroms));
+ return this;
+ }
+
+ public Move<T> and( Property from ) {
+ this.from.add(new Location(from));
+ return this;
+ }
+
+ public Move<T> and( UUID from ) {
+ this.from.add(new Location(from));
+ return this;
+ }
+
+ /**
+ * Submit any requests to move the targets into the supplied parent location
+ *
+ * @param into the parent location
+ * @return this object, for method chaining
+ */
+ private T submit( Location into ) {
+ 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));
+ locations = locations.next();
+ }
+ queue().submit(requests);
+ } else {
+ queue().submit(new MoveBranchRequest(this.from.getLocation(), into));
+ }
+ return and();
+ }
+
+ public T into( Location into ) {
+ return submit(into);
+ }
+
+ public T into( Path into ) {
+ return submit(new Location(into));
+ }
+
+ public T into( UUID into ) {
+ return submit(new Location(into));
+ }
+
+ public T into( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ return submit(new Location(firstIdProperty, additionalIdProperties));
+ }
+
+ public T into( Property into ) {
+ return submit(new Location(into));
+ }
+
+ public T into( String into ) {
+ return submit(new Location(createPath(into)));
+ }
+
+ @Override
+ public Results execute() {
+ return queue().execute();
+ }
+ }
+
+ @NotThreadSafe
+ static class CopyAction<T> extends AbstractAction<T> implements
Copy<T> {
+ private final Locations from;
+
+ /*package*/CopyAction( T afterConjunction,
+ RequestQueue queue,
+ Location from ) {
+ super(afterConjunction, queue);
+ this.from = new Locations(from);
+ }
+
+ public Copy<T> and( Location from ) {
+ this.from.add(from);
+ return this;
+ }
+
+ public Copy<T> and( String from ) {
+ this.from.add(new Location(createPath(from)));
+ return this;
+ }
+
+ public Copy<T> and( Path from ) {
+ this.from.add(new Location(from));
+ return this;
+ }
+
+ public Copy<T> and( Property firstFrom,
+ Property... additionalFroms ) {
+ this.from.add(new Location(firstFrom, additionalFroms));
+ return this;
+ }
+
+ public Copy<T> and( Property from ) {
+ this.from.add(new Location(from));
+ return this;
+ }
+
+ public Copy<T> and( UUID from ) {
+ this.from.add(new Location(from));
+ return this;
+ }
+
+ /**
+ * Submit any requests to move the targets into the supplied parent location
+ *
+ * @param into the parent location
+ * @return this object, for method chaining
+ */
+ private T submit( Location into ) {
+ 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, into));
+ locations = locations.next();
+ }
+ queue().submit(requests);
+ } else {
+ queue().submit(new CopyBranchRequest(this.from.getLocation(), into));
+ }
+ return and();
+ }
+
+ public T into( Location into ) {
+ return submit(into);
+ }
+
+ public T into( Path into ) {
+ return submit(new Location(into));
+ }
+
+ public T into( UUID into ) {
+ return submit(new Location(into));
+ }
+
+ public T into( Property firstIdProperty,
+ Property... additionalIdProperties ) {
+ return submit(new Location(firstIdProperty, additionalIdProperties));
+ }
+
+ public T into( Property into ) {
+ return submit(new Location(into));
+ }
+
+ public T into( String into ) {
+ return submit(new Location(createPath(into)));
+ }
+
+ @Override
+ public Results execute() {
+ return queue().execute();
+ }
+ }
+
+ @NotThreadSafe
+ static class CreateAction<T> extends AbstractAction<T> implements
Create<T> {
+ private final Location at;
+ private final List<Property> properties = new
LinkedList<Property>();
+
+ /*package*/CreateAction( T afterConjunction,
+ RequestQueue queue,
+ Location at ) {
+ super(afterConjunction, queue);
+ this.at = at;
+ }
+
+ public Create<T> and( UUID uuid ) {
+ PropertyFactory factory =
queue().getGraph().getContext().getPropertyFactory();
+ properties.add(factory.create(DnaLexicon.UUID, uuid));
+ return this;
+ }
+
+ public Create<T> and( Property property ) {
+ properties.add(property);
+ return this;
+ }
+
+ public Create<T> and( String name,
+ Object... values ) {
+ ExecutionContext context = queue().getGraph().getContext();
+ PropertyFactory factory = context.getPropertyFactory();
+ NameFactory nameFactory = context.getValueFactories().getNameFactory();
+ properties.add(factory.create(nameFactory.create(name), 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));
+ return this;
+ }
+
+ public Create<T> and( Property property,
+ Property... additionalProperties ) {
+ properties.add(property);
+ for (Property additionalProperty : additionalProperties) {
+ properties.add(additionalProperty);
+ }
+ return this;
+ }
+
+ public Create<T> with( UUID uuid ) {
+ return and(uuid);
+ }
+
+ public Create<T> with( Property property ) {
+ return and(property);
+ }
+
+ public Create<T> with( Property property,
+ Property... additionalProperties ) {
+ return and(property, additionalProperties);
+ }
+
+ public Create<T> with( String name,
+ Object... values ) {
+ return and(name, values);
+ }
+
+ public Create<T> with( Name name,
+ Object... values ) {
+ return and(name, values);
+ }
+
+ @Override
+ public T and() {
+ this.queue().submit(new CreateNodeRequest(this.at, this.properties));
+ return super.and();
+ }
+
+ @Override
+ public Results execute() {
+ return queue().execute();
+ }
+ }
+
+}
Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphI18n.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphI18n.java 2008-10-09 21:25:44
UTC (rev 566)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphI18n.java 2008-10-13 19:58:03
UTC (rev 567)
@@ -65,6 +65,7 @@
public static I18n closingCommandExecutor;
public static I18n closedCommandExecutor;
public static I18n multipleErrorsWhileExecutingRequests;
+ public static I18n unableToAddMoreRequestsToAlreadyExecutedBatch;
// XML Sequencer
public static I18n errorSequencingXmlDocument;
Copied: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java (from rev 565,
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/Location.java)
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java
(rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java 2008-10-13 19:58:03
UTC (rev 567)
@@ -0,0 +1,275 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ * This software 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;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.common.util.HashCode;
+import org.jboss.dna.common.util.StringUtil;
+import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.properties.basic.BasicSingleValueProperty;
+
+/**
+ * The location of a node, as specified by either its path, UUID, and/or identification
properties.
+ *
+ * @author Randall Hauch
+ */
+@Immutable
+public class Location {
+
+ private final Path path;
+ private final List<Property> idProperties;
+
+ /**
+ * Create a location defined by a path.
+ *
+ * @param path the path
+ * @throws IllegalArgumentException if <code>path</code> is null
+ */
+ public Location( Path path ) {
+ CheckArg.isNotNull(path, "path");
+ this.path = path;
+ this.idProperties = null;
+ }
+
+ /**
+ * Create a location defined by a UUID.
+ *
+ * @param uuid the UUID
+ * @throws IllegalArgumentException if <code>uuid</code> is null
+ */
+ public Location( UUID uuid ) {
+ CheckArg.isNotNull(uuid, "uuid");
+ this.path = null;
+ Property idProperty = new BasicSingleValueProperty(DnaLexicon.UUID, uuid);
+ this.idProperties = Collections.singletonList(idProperty);
+ }
+
+ /**
+ * Create a location defined by a path and an UUID.
+ *
+ * @param path the path
+ * @param uuid the UUID
+ * @throws IllegalArgumentException if <code>uuid</code> is null
+ */
+ public Location( Path path,
+ UUID uuid ) {
+ CheckArg.isNotNull(uuid, "uuid");
+ CheckArg.isNotNull(path, "path");
+ this.path = path;
+ Property idProperty = new BasicSingleValueProperty(DnaLexicon.UUID, uuid);
+ this.idProperties = Collections.singletonList(idProperty);
+ }
+
+ /**
+ * Create a location defined by a path and a single identification property.
+ *
+ * @param path the path
+ * @param idProperty the identification property
+ * @throws IllegalArgumentException if <code>path</code> or
<code>idProperty</code> is null
+ */
+ public Location( Path path,
+ Property idProperty ) {
+ CheckArg.isNotNull(path, "path");
+ CheckArg.isNotNull(idProperty, "idProperty");
+ this.path = path;
+ this.idProperties = Collections.singletonList(idProperty);
+ }
+
+ /**
+ * Create a location defined by a path and multiple identification properties.
+ *
+ * @param path the path
+ * @param firstIdProperty the first identification property
+ * @param remainingIdProperties the remaining identification property
+ * @throws IllegalArgumentException if any of the arguments are null
+ */
+ public Location( Path path,
+ Property firstIdProperty,
+ Property... remainingIdProperties ) {
+ CheckArg.isNotNull(path, "path");
+ CheckArg.isNotNull(firstIdProperty, "firstIdProperty");
+ CheckArg.isNotNull(remainingIdProperties, "remainingIdProperties");
+ this.path = path;
+ List<Property> idProperties = new ArrayList<Property>(1 +
remainingIdProperties.length);
+ idProperties.add(firstIdProperty);
+ for (Property property : remainingIdProperties) {
+ idProperties.add(property);
+ }
+ this.idProperties = Collections.unmodifiableList(idProperties);
+ }
+
+ /**
+ * Create a location defined by a single identification property.
+ *
+ * @param idProperty the identification property
+ * @throws IllegalArgumentException if <code>idProperty</code> is null
+ */
+ public Location( Property idProperty ) {
+ CheckArg.isNotNull(idProperty, "idProperty");
+ this.path = null;
+ this.idProperties = Collections.singletonList(idProperty);
+ }
+
+ /**
+ * Create a location defined by multiple identification properties.
+ *
+ * @param firstIdProperty the first identification property
+ * @param remainingIdProperties the remaining identification property
+ * @throws IllegalArgumentException if any of the arguments are null
+ */
+ public Location( Property firstIdProperty,
+ Property... remainingIdProperties ) {
+ CheckArg.isNotNull(firstIdProperty, "firstIdProperty");
+ CheckArg.isNotNull(remainingIdProperties, "remainingIdProperties");
+ this.path = null;
+ List<Property> idProperties = new ArrayList<Property>(1 +
remainingIdProperties.length);
+ idProperties.add(firstIdProperty);
+ for (Property property : remainingIdProperties) {
+ idProperties.add(property);
+ }
+ this.idProperties = Collections.unmodifiableList(idProperties);
+ }
+
+ /**
+ * Create a location defined by multiple identification properties.
+ *
+ * @param idProperties the identification properties
+ * @throws IllegalArgumentException if <code>idProperties</code> is null
or empty
+ */
+ public Location( List<Property> idProperties ) {
+ CheckArg.isNotEmpty(idProperties, "idProperties");
+ this.path = null;
+ this.idProperties = idProperties;
+ }
+
+ /**
+ * Create a location defined by a path and multiple identification properties.
+ *
+ * @param path the path
+ * @param idProperties the identification properties
+ * @throws IllegalArgumentException if <code>path</code> or
<code>idProperties</code> is null, or if
<code>idProperties</code>
+ * is empty
+ */
+ public Location( Path path,
+ List<Property> idProperties ) {
+ CheckArg.isNotNull(path, "path");
+ CheckArg.isNotEmpty(idProperties, "idProperties");
+ this.path = path;
+ this.idProperties = idProperties;
+ }
+
+ /**
+ * Get the path that (at least in part) defines this location.
+ *
+ * @return the path, or null if this location is not defined with a path
+ */
+ public Path getPath() {
+ return path;
+ }
+
+ /**
+ * Return whether this location is defined (at least in part) by a path.
+ *
+ * @return true if a {@link #getPath() path} helps define this location
+ */
+ public boolean hasPath() {
+ return path != null;
+ }
+
+ /**
+ * Get the identification properties that (at least in part) define this location.
+ *
+ * @return the identification properties, or null if this location is not defined
with identification properties
+ */
+ public List<Property> getIdProperties() {
+ return idProperties;
+ }
+
+ /**
+ * Return whether this location is defined (at least in part) with identification
properties.
+ *
+ * @return true if a {@link #getIdProperties() identification properties} help define
this location
+ */
+ public boolean hasIdProperties() {
+ return idProperties != null && idProperties.size() != 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return HashCode.compute(path, idProperties);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj instanceof Location) {
+ Location that = (Location)obj;
+ if (this.hasPath()) {
+ if (!this.getPath().equals(that.getPath())) return false;
+ } else {
+ if (that.hasPath()) return false;
+ }
+ if (this.hasIdProperties()) {
+ if (!this.getIdProperties().equals(that.getIdProperties())) return
false;
+ } else {
+ if (that.hasIdProperties()) return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ if (this.hasPath()) {
+ if (this.hasIdProperties()) sb.append("[ ");
+ sb.append(this.getPath());
+ if (this.hasIdProperties()) sb.append(" && ");
+ }
+ if (this.hasIdProperties()) {
+ sb.append(StringUtil.readableString(this.getIdProperties()));
+ if (this.hasPath()) sb.append(" ]");
+ }
+ return sb.toString();
+ }
+}
Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Locations.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/Locations.java
(rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Locations.java 2008-10-13 19:58:03
UTC (rev 567)
@@ -0,0 +1,68 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ * This software 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;
+
+import net.jcip.annotations.NotThreadSafe;
+
+/**
+ * A class used by this package to manage a single {@link Location} or multiple {@link
Location} objects, without having the
+ * overhead of a collection (when only one is needed) and which can grow efficiently as
new locations are added. This is achieved
+ * through an effective linked list.
+ *
+ * @author Randall Hauch
+ */
+@NotThreadSafe
+class Locations {
+ private final Location location;
+ private Locations next;
+
+ /*package*/Locations( Location location ) {
+ this.location = location;
+ }
+
+ /*package*/void add( Location location ) {
+ if (this.next == null) {
+ this.next = new Locations(location);
+ } else {
+ Locations theNextOne = this.next;
+ while (theNextOne != null) {
+ if (theNextOne.next == null) {
+ theNextOne.next = new Locations(location);
+ break;
+ }
+ theNextOne = theNextOne.next;
+ }
+ }
+ }
+
+ /*package*/boolean hasNext() {
+ return this.next != null;
+ }
+
+ /*package*/Locations next() {
+ return this.next;
+ }
+
+ /*package*/Location getLocation() {
+ return this.location;
+ }
+}
Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Locations.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Node.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/Node.java
(rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Node.java 2008-10-13 19:58:03 UTC
(rev 567)
@@ -0,0 +1,81 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ * This software 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;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.properties.Property;
+
+/**
+ * A node in a {@link Graph graph}, with methods to access the properties and children.
+ *
+ * @author Randall Hauch
+ */
+@Immutable
+public interface Node extends Iterable<Location> {
+
+ /**
+ * Get the graph containing the node.
+ *
+ * @return the graph
+ */
+ Graph getGraph();
+
+ /**
+ * Get the location of the node.
+ *
+ * @return the node's location
+ */
+ Location getLocation();
+
+ /**
+ * Get the properties on the node.
+ *
+ * @return the properties
+ */
+ Collection<Property> getProperties();
+
+ /**
+ * Get the map of properties keyed by the property names.
+ *
+ * @return the map of properties keyed by property name
+ */
+ Map<Name, Property> getPropertiesByName();
+
+ /**
+ * Get the children of the node.
+ *
+ * @return the list of locations for each child
+ */
+ List<Location> getChildren();
+
+ /**
+ * Return whether this node has children.
+ *
+ * @return true if the node has children, or false otherwise
+ */
+ boolean hasChildren();
+
+}
Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Node.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Results.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/Results.java
(rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Results.java 2008-10-13 19:58:03 UTC
(rev 567)
@@ -0,0 +1,91 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ * This software 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;
+
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.graph.properties.Path;
+
+/**
+ * A set of nodes returned from a {@link Graph graph}, with methods to access the
properties and children of the nodes in the
+ * result. The {@link #iterator()} method can be used to iterate all over the nodes in
the result.
+ *
+ * @author Randall Hauch
+ */
+@Immutable
+public interface Results extends Iterable<Node> {
+
+ /**
+ * Get the graph containing the node.
+ *
+ * @return the graph
+ */
+ Graph getGraph();
+
+ /**
+ * Get the node at the supplied location.
+ *
+ * @param path the path of the node in these results
+ * @return the node, or null if the node is not {@link #includes(Path) included} in
these results
+ */
+ Node getNode( String path );
+
+ /**
+ * Get the node at the supplied location.
+ *
+ * @param path the path of the node in these results
+ * @return the node, or null if the node is not {@link #includes(Path) included} in
these results
+ */
+ Node getNode( Path path );
+
+ /**
+ * Get the node at the supplied location.
+ *
+ * @param location the location of the node
+ * @return the node, or null if the node is not {@link #includes(Path) included} in
these results
+ */
+ Node getNode( Location location );
+
+ /**
+ * Return whether these results include a node at the supplied location.
+ *
+ * @param path the path of the node in these results
+ * @return true if this subgraph includes the supplied location, or false otherwise
+ */
+ boolean includes( String path );
+
+ /**
+ * Return whether this subgraph has a node at the supplied location.
+ *
+ * @param path the path of the node in these results
+ * @return true if these results includes the supplied location, or false otherwise
+ */
+ boolean includes( Path path );
+
+ /**
+ * Return whether this subgraph has a node at the supplied location.
+ *
+ * @param location the location of the node in these results
+ * @return true if these results includes the supplied location, or false otherwise
+ */
+ boolean includes( Location location );
+
+}
Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Results.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Subgraph.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/Subgraph.java
(rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Subgraph.java 2008-10-13 19:58:03
UTC (rev 567)
@@ -0,0 +1,54 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ * This software 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;
+
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.graph.properties.Path;
+
+/**
+ * A subgraph returned by the {@link Graph}, containing the nodes in the subgraph as well
as the properties and children for each
+ * of those nodes. The {@link #iterator()} method may be used to walk the nodes in the
subgraph in a pre-order traversal.
+ * <p>
+ * Since this subgraph has a single {@link #getLocation() node that is the top of the
subgraph}, the methods that take a String
+ * path or {@link Path path object} will accept absolute or relative paths.
+ * </p>
+ *
+ * @author Randall Hauch
+ */
+@Immutable
+public interface Subgraph extends Results {
+
+ /**
+ * Get the location of the node.
+ *
+ * @return the node's location
+ */
+ Location getLocation();
+
+ /**
+ * Get the maximum depth requested for this subgraph. The actual subgraph may not be
as deep, but will never be deeper than
+ * this value.
+ *
+ * @return the maximum depth requested; always positive
+ */
+ int getMaximumDepth();
+}
Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Subgraph.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositoryConnection.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositoryConnection.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositoryConnection.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -27,6 +27,7 @@
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.cache.CachePolicy;
import org.jboss.dna.graph.commands.GraphCommand;
+import org.jboss.dna.graph.requests.Request;
/**
* A connection to a repository source.
@@ -91,6 +92,16 @@
GraphCommand... commands ) throws RepositorySourceException;
/**
+ * Execute the supplied commands against this repository source.
+ *
+ * @param context the environment in which the commands are being executed; never
null
+ * @param request the request to be executed; never null
+ * @throws RepositorySourceException if there is a problem loading the node data
+ */
+ void execute( ExecutionContext context,
+ Request request ) throws RepositorySourceException;
+
+ /**
* Close this connection to signal that it is no longer needed and that any
accumulated resources are to be released.
*/
void close();
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositoryConnectionPool.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositoryConnectionPool.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connectors/RepositoryConnectionPool.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -42,6 +42,7 @@
import org.jboss.dna.graph.GraphI18n;
import org.jboss.dna.graph.cache.CachePolicy;
import org.jboss.dna.graph.commands.GraphCommand;
+import org.jboss.dna.graph.requests.Request;
/**
* A reusable implementation of a managed pool of connections that is optimized for safe
concurrent operations.
@@ -988,7 +989,19 @@
/**
* {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.connectors.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
+ * org.jboss.dna.graph.requests.Request)
*/
+ public void execute( ExecutionContext context,
+ Request request ) throws RepositorySourceException {
+ if (closed) throw new
IllegalStateException(GraphI18n.closedConnectionMayNotBeUsed.text());
+ this.original.execute(context, request);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public boolean ping( long time,
TimeUnit unit ) throws InterruptedException {
if (closed) throw new
IllegalStateException(GraphI18n.closedConnectionMayNotBeUsed.text());
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CompositeRequest.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CompositeRequest.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CompositeRequest.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -90,6 +90,21 @@
}
/**
+ * Return a request that either wraps multiple requests, or the single request if
only one is supplied.
+ *
+ * @param requests the requests to wrap
+ * @return the requests wrapped in a CompositeRequest, or if only one request is
supplied that single request
+ * @throws IllegalArgumentException if there requests are null or empty
+ */
+ public static Request with( List<Request> requests ) {
+ CheckArg.isNotEmpty(requests, "requests");
+ if (requests.size() == 1) {
+ return requests.get(0);
+ }
+ return new CompositeRequest(requests);
+ }
+
+ /**
* Add requests to the supplied composite request.
*
* @param composite the composite request to which the requests are to be added
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CopyBranchRequest.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CopyBranchRequest.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CopyBranchRequest.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -22,6 +22,7 @@
package org.jboss.dna.graph.requests;
import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.Location;
/**
* Instruction that a branch be copied from one location into another.
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CreateNodeRequest.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CreateNodeRequest.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CreateNodeRequest.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -29,6 +29,7 @@
import java.util.List;
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.common.util.StringUtil;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.properties.Property;
/**
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/DeleteBranchRequest.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/DeleteBranchRequest.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/DeleteBranchRequest.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -22,6 +22,7 @@
package org.jboss.dna.graph.requests;
import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.Location;
/**
* Instruction that a branch be deleted.
Deleted: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/Location.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/Location.java 2008-10-09
21:25:44 UTC (rev 566)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/Location.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -1,276 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * 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.
- *
- * This software 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.requests;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.common.util.HashCode;
-import org.jboss.dna.common.util.StringUtil;
-import org.jboss.dna.graph.DnaLexicon;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.properties.basic.BasicSingleValueProperty;
-
-/**
- * The location of a node, as specified by either its path, UUID, and/or identification
properties.
- *
- * @author Randall Hauch
- */
-@Immutable
-public class Location {
-
- private final Path path;
- private final List<Property> idProperties;
-
- /**
- * Create a location defined by a path.
- *
- * @param path the path
- * @throws IllegalArgumentException if <code>path</code> is null
- */
- public Location( Path path ) {
- CheckArg.isNotNull(path, "path");
- this.path = path;
- this.idProperties = null;
- }
-
- /**
- * Create a location defined by a UUID.
- *
- * @param uuid the UUID
- * @throws IllegalArgumentException if <code>uuid</code> is null
- */
- public Location( UUID uuid ) {
- CheckArg.isNotNull(uuid, "uuid");
- this.path = null;
- Property idProperty = new BasicSingleValueProperty(DnaLexicon.UUID, uuid);
- this.idProperties = Collections.singletonList(idProperty);
- }
-
- /**
- * Create a location defined by a path and an UUID.
- *
- * @param path the path
- * @param uuid the UUID
- * @throws IllegalArgumentException if <code>uuid</code> is null
- */
- public Location( Path path,
- UUID uuid ) {
- CheckArg.isNotNull(uuid, "uuid");
- CheckArg.isNotNull(path, "path");
- this.path = path;
- Property idProperty = new BasicSingleValueProperty(DnaLexicon.UUID, uuid);
- this.idProperties = Collections.singletonList(idProperty);
- }
-
- /**
- * Create a location defined by a path and a single identification property.
- *
- * @param path the path
- * @param idProperty the identification property
- * @throws IllegalArgumentException if <code>path</code> or
<code>idProperty</code> is null
- */
- public Location( Path path,
- Property idProperty ) {
- CheckArg.isNotNull(path, "path");
- CheckArg.isNotNull(idProperty, "idProperty");
- this.path = path;
- this.idProperties = Collections.singletonList(idProperty);
- }
-
- /**
- * Create a location defined by a path and multiple identification properties.
- *
- * @param path the path
- * @param firstIdProperty the first identification property
- * @param remainingIdProperties the remaining identification property
- * @throws IllegalArgumentException if any of the arguments are null
- */
- public Location( Path path,
- Property firstIdProperty,
- Property... remainingIdProperties ) {
- CheckArg.isNotNull(path, "path");
- CheckArg.isNotNull(firstIdProperty, "firstIdProperty");
- CheckArg.isNotNull(remainingIdProperties, "remainingIdProperties");
- this.path = path;
- List<Property> idProperties = new ArrayList<Property>(1 +
remainingIdProperties.length);
- idProperties.add(firstIdProperty);
- for (Property property : remainingIdProperties) {
- idProperties.add(property);
- }
- this.idProperties = Collections.unmodifiableList(idProperties);
- }
-
- /**
- * Create a location defined by a single identification property.
- *
- * @param idProperty the identification property
- * @throws IllegalArgumentException if <code>idProperty</code> is null
- */
- public Location( Property idProperty ) {
- CheckArg.isNotNull(idProperty, "idProperty");
- this.path = null;
- this.idProperties = Collections.singletonList(idProperty);
- }
-
- /**
- * Create a location defined by multiple identification properties.
- *
- * @param firstIdProperty the first identification property
- * @param remainingIdProperties the remaining identification property
- * @throws IllegalArgumentException if any of the arguments are null
- */
- public Location( Property firstIdProperty,
- Property... remainingIdProperties ) {
- CheckArg.isNotNull(firstIdProperty, "firstIdProperty");
- CheckArg.isNotNull(remainingIdProperties, "remainingIdProperties");
- this.path = null;
- List<Property> idProperties = new ArrayList<Property>(1 +
remainingIdProperties.length);
- idProperties.add(firstIdProperty);
- for (Property property : remainingIdProperties) {
- idProperties.add(property);
- }
- this.idProperties = Collections.unmodifiableList(idProperties);
- }
-
- /**
- * Create a location defined by multiple identification properties.
- *
- * @param idProperties the identification properties
- * @throws IllegalArgumentException if <code>idProperties</code> is null
or empty
- */
- public Location( List<Property> idProperties ) {
- CheckArg.isNotEmpty(idProperties, "idProperties");
- this.path = null;
- this.idProperties = idProperties;
- }
-
- /**
- * Create a location defined by a path and multiple identification properties.
- *
- * @param path the path
- * @param idProperties the identification properties
- * @throws IllegalArgumentException if <code>path</code> or
<code>idProperties</code> is null, or if
<code>idProperties</code>
- * is empty
- */
- public Location( Path path,
- List<Property> idProperties ) {
- CheckArg.isNotNull(path, "path");
- CheckArg.isNotEmpty(idProperties, "idProperties");
- this.path = path;
- this.idProperties = idProperties;
- }
-
- /**
- * Get the path that (at least in part) defines this location.
- *
- * @return the path, or null if this location is not defined with a path
- */
- public Path getPath() {
- return path;
- }
-
- /**
- * Return whether this location is defined (at least in part) by a path.
- *
- * @return true if a {@link #getPath() path} helps define this location
- */
- public boolean hasPath() {
- return path != null;
- }
-
- /**
- * Get the identification properties that (at least in part) define this location.
- *
- * @return the identification properties, or null if this location is not defined
with identification properties
- */
- public List<Property> getIdProperties() {
- return idProperties;
- }
-
- /**
- * Return whether this location is defined (at least in part) with identification
properties.
- *
- * @return true if a {@link #getIdProperties() identification properties} help define
this location
- */
- public boolean hasIdProperties() {
- return idProperties != null && idProperties.size() != 0;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode() {
- return HashCode.compute(path, idProperties);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals( Object obj ) {
- if (obj instanceof Location) {
- Location that = (Location)obj;
- if (this.hasPath()) {
- if (!this.getPath().equals(that.getPath())) return false;
- } else {
- if (that.hasPath()) return false;
- }
- if (this.hasIdProperties()) {
- if (!this.getIdProperties().equals(that.getIdProperties())) return
false;
- } else {
- if (that.hasIdProperties()) return false;
- }
- return true;
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- if (this.hasPath()) {
- if (this.hasIdProperties()) sb.append("[ ");
- sb.append(this.getPath());
- if (this.hasIdProperties()) sb.append(" && ");
- }
- if (this.hasIdProperties()) {
- sb.append(StringUtil.readableString(this.getIdProperties()));
- if (this.hasPath()) sb.append(" ]");
- }
- return sb.toString();
- }
-}
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/MoveBranchRequest.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/MoveBranchRequest.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/MoveBranchRequest.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -22,6 +22,7 @@
package org.jboss.dna.graph.requests;
import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.Location;
/**
* Instruction that a branch be moved from one location into another.
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadAllChildrenRequest.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadAllChildrenRequest.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadAllChildrenRequest.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -25,6 +25,7 @@
import java.util.LinkedList;
import java.util.List;
import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.connectors.RepositoryConnection;
import org.jboss.dna.graph.properties.Path;
import org.jboss.dna.graph.properties.Property;
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadAllPropertiesRequest.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadAllPropertiesRequest.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadAllPropertiesRequest.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -26,6 +26,7 @@
import java.util.Iterator;
import java.util.Map;
import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.connectors.RepositoryConnection;
import org.jboss.dna.graph.properties.Name;
import org.jboss.dna.graph.properties.Property;
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBlockOfChildrenRequest.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBlockOfChildrenRequest.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBlockOfChildrenRequest.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -25,6 +25,7 @@
import java.util.List;
import org.jboss.dna.common.text.Inflector;
import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.connectors.RepositoryConnection;
import org.jboss.dna.graph.properties.Path;
import org.jboss.dna.graph.properties.Property;
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBranchRequest.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBranchRequest.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBranchRequest.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -29,13 +29,14 @@
import java.util.Map;
import net.jcip.annotations.NotThreadSafe;
import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.connectors.RepositoryConnection;
import org.jboss.dna.graph.properties.Name;
import org.jboss.dna.graph.properties.Property;
/**
- * Instruction to read the properties and children of the nodes in the branch at the
supplied location. The children of the nodes at
- * the bottom of the branch are not read.
+ * Instruction to read the properties and children of the nodes in the branch at the
supplied location. The children of the nodes
+ * at the bottom of the branch are not read.
*
* @author Randall Hauch
*/
@@ -95,6 +96,16 @@
}
/**
+ * Return whether this branch contains the specified location.
+ *
+ * @param location the location
+ * @return true if this branch includes the location, or false otherwise
+ */
+ public boolean includes( Location location ) {
+ return this.nodeProperties.containsKey(location);
+ }
+
+ /**
* Add a node that was read from the {@link RepositoryConnection}. This method does
not verify or check that the node is
* indeed on the branch and that it is at a level prescribed by the request.
*
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNodeRequest.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNodeRequest.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNodeRequest.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -28,6 +28,7 @@
import java.util.List;
import java.util.Map;
import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.connectors.RepositoryConnection;
import org.jboss.dna.graph.properties.Name;
import org.jboss.dna.graph.properties.Path;
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadPropertyRequest.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadPropertyRequest.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadPropertyRequest.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -22,6 +22,7 @@
package org.jboss.dna.graph.requests;
import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.connectors.RepositoryConnection;
import org.jboss.dna.graph.properties.Name;
import org.jboss.dna.graph.properties.Property;
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RemovePropertiesRequest.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RemovePropertiesRequest.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RemovePropertiesRequest.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -28,6 +28,7 @@
import java.util.Set;
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.common.util.StringUtil;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.properties.Name;
/**
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RenameNodeRequest.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RenameNodeRequest.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RenameNodeRequest.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -22,6 +22,7 @@
package org.jboss.dna.graph.requests;
import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.properties.Name;
/**
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RequestProcessor.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RequestProcessor.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/RequestProcessor.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -30,6 +30,7 @@
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.connectors.RepositorySourceException;
import org.jboss.dna.graph.properties.Name;
import org.jboss.dna.graph.properties.Path;
@@ -221,10 +222,11 @@
List<Location> allChildren = readAll.getChildren();
// If there aren't enough children for the block's range ...
- if (allChildren.size() < request.endingBefore()) return;
+ if (allChildren.size() < request.startingAt()) return;
// Now, find the children in the block ...
- for (int i = request.startingAt(); i != request.endingBefore(); ++i) {
+ int endIndex = Math.min(request.endingBefore(), allChildren.size());
+ for (int i = request.startingAt(); i != endIndex; ++i) {
request.addChild(allChildren.get(i));
}
}
@@ -250,7 +252,7 @@
LocationWithDepth read = locationsToRead.poll();
// Check the depth ...
- if (read.depth > request.maximumDepth()) continue;
+ if (read.depth > request.maximumDepth()) break;
// Read the properties ...
ReadNodeRequest readNode = new ReadNodeRequest(read.location);
@@ -409,6 +411,11 @@
this.location = location;
this.depth = depth;
}
+
+ @Override
+ public String toString() {
+ return location.toString() + " at depth " + depth;
+ }
}
}
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/UpdatePropertiesRequest.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/UpdatePropertiesRequest.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/UpdatePropertiesRequest.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -29,6 +29,7 @@
import java.util.List;
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.common.util.StringUtil;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.properties.Property;
/**
Modified: trunk/dna-graph/src/main/resources/org/jboss/dna/graph/GraphI18n.properties
===================================================================
--- trunk/dna-graph/src/main/resources/org/jboss/dna/graph/GraphI18n.properties 2008-10-09
21:25:44 UTC (rev 566)
+++ trunk/dna-graph/src/main/resources/org/jboss/dna/graph/GraphI18n.properties 2008-10-13
19:58:03 UTC (rev 567)
@@ -52,6 +52,7 @@
closingCommandExecutor = Closing command executor
closedCommandExecutor = Closed command executor
multipleErrorsWhileExecutingRequests = {0} of the {1} requests resulted in errors
+unableToAddMoreRequestsToAlreadyExecutedBatch = Unable to add more requests to a batch of
graph requests that has already been executed
errorSequencingXmlDocument = An error was received while sequencing XML: {0}
fatalErrorSequencingXmlDocument = A fatal error was received while sequencing XML: {0}
Added: trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java
(rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java 2008-10-13 19:58:03
UTC (rev 567)
@@ -0,0 +1,868 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ * This software 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;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.core.IsNull.notNullValue;
+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 static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.stub;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import javax.transaction.xa.XAResource;
+import org.jboss.dna.graph.cache.CachePolicy;
+import org.jboss.dna.graph.commands.GraphCommand;
+import org.jboss.dna.graph.connectors.BasicExecutionContext;
+import org.jboss.dna.graph.connectors.RepositoryConnection;
+import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connectors.RepositorySourceException;
+import org.jboss.dna.graph.connectors.RepositorySourceListener;
+import org.jboss.dna.graph.properties.InvalidPathException;
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.properties.Property;
+import org.jboss.dna.graph.requests.CompositeRequest;
+import org.jboss.dna.graph.requests.CopyBranchRequest;
+import org.jboss.dna.graph.requests.CreateNodeRequest;
+import org.jboss.dna.graph.requests.DeleteBranchRequest;
+import org.jboss.dna.graph.requests.MoveBranchRequest;
+import org.jboss.dna.graph.requests.ReadAllChildrenRequest;
+import org.jboss.dna.graph.requests.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.requests.ReadBlockOfChildrenRequest;
+import org.jboss.dna.graph.requests.ReadNodeRequest;
+import org.jboss.dna.graph.requests.ReadPropertyRequest;
+import org.jboss.dna.graph.requests.Request;
+import org.jboss.dna.graph.requests.RequestProcessor;
+import org.jboss.dna.graph.requests.UpdatePropertiesRequest;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoAnnotations.Mock;
+
+/**
+ * @author Randall Hauch
+ */
+public class GraphTest {
+
+ private Graph graph;
+ private Results results;
+ private ExecutionContext context;
+ private Path validPath;
+ private String validPathString;
+ private UUID validUuid;
+ private Property validIdProperty1;
+ private Property validIdProperty2;
+ private String sourceName;
+ private MockRepositoryConnection connection;
+ private LinkedList<Request> executedRequests;
+ private int numberOfExecutions;
+ /** Populate this with the properties (by location) that are to be read */
+ private Map<Location, Collection<Property>> properties;
+ /** Populate this with the children (by location) that are to be read */
+ private Map<Location, List<Location>> children;
+ @Mock
+ private RepositoryConnectionFactory connectionFactory;
+
+ @Before
+ public void beforeEach() {
+ MockitoAnnotations.initMocks(this);
+ executedRequests = new LinkedList<Request>();
+ sourceName = "Source";
+ context = new BasicExecutionContext();
+ connection = new MockRepositoryConnection();
+ stub(connectionFactory.createConnection(sourceName)).toReturn(connection);
+ graph = new Graph(sourceName, connectionFactory, context);
+ validPathString = "/a/b/c";
+ validUuid = UUID.randomUUID();
+ validPath = createPath(validPathString);
+ Name idProperty1Name = createName("id1");
+ Name idProperty2Name = createName("id2");
+ validIdProperty1 = context.getPropertyFactory().create(idProperty1Name,
"1");
+ validIdProperty2 = context.getPropertyFactory().create(idProperty2Name,
"2");
+
+ properties = new HashMap<Location, Collection<Property>>();
+ children = new HashMap<Location, List<Location>>();
+ }
+
+ static class IsAnyRequest extends ArgumentMatcher<Request> {
+ @Override
+ public boolean matches( Object request ) {
+ return request instanceof Request;
+ }
+ }
+
+ protected static Request anyRequest() {
+ return argThat(new IsAnyRequest());
+ }
+
+ protected Path createPath( String path ) {
+ return context.getValueFactories().getPathFactory().create(path);
+ }
+
+ protected Path createPath( Path parent,
+ String path ) {
+ return context.getValueFactories().getPathFactory().create(parent, path);
+ }
+
+ protected Name createName( String name ) {
+ return context.getValueFactories().getNameFactory().create(name);
+ }
+
+ protected void setPropertiesToReadOn( Location location,
+ Property... properties ) {
+ this.properties.put(location, Arrays.asList(properties));
+ }
+
+ protected void setChildrenToReadOn( Location location,
+ Location... children ) {
+ this.children.put(location, Arrays.asList(children));
+ }
+
+ protected void assertNextRequestIsMove( Location from,
+ Location to ) {
+ assertThat(executedRequests.poll(), is((Request)new MoveBranchRequest(from,
to)));
+ }
+
+ protected void assertNextRequestIsCopy( Location from,
+ Location to ) {
+ assertThat(executedRequests.poll(), is((Request)new CopyBranchRequest(from,
to)));
+ }
+
+ protected void assertNextRequestIsDelete( Location at ) {
+ assertThat(executedRequests.poll(), is((Request)new DeleteBranchRequest(at)));
+ }
+
+ protected void assertNextRequestIsCreate( Location at,
+ Property... properties ) {
+ assertThat(executedRequests.poll(), is((Request)new CreateNodeRequest(at,
properties)));
+ }
+
+ protected void assertNextRequestReadProperties( Location at,
+ Property... properties ) {
+ Request request = executedRequests.poll();
+ assertThat(request, is(instanceOf(ReadAllPropertiesRequest.class)));
+ ReadAllPropertiesRequest readAll = (ReadAllPropertiesRequest)request;
+ assertThat(readAll.at(), is(at));
+ Map<Name, Property> propsByName = new HashMap<Name,
Property>(readAll.getPropertiesByName());
+ for (Property prop : properties) {
+ assertThat(propsByName.remove(prop.getName()), is(prop));
+ }
+ assertThat(propsByName.isEmpty(), is(true));
+ }
+
+ protected void assertNextRequestReadProperty( Location at,
+ Property property ) {
+ Request request = executedRequests.poll();
+ assertThat(request, is(instanceOf(ReadPropertyRequest.class)));
+ ReadPropertyRequest read = (ReadPropertyRequest)request;
+ assertThat(read.on(), is(at));
+ assertThat(read.getProperty(), is(property));
+ }
+
+ protected void assertNextRequestReadChildren( Location at,
+ Location... children ) {
+ Request request = executedRequests.poll();
+ assertThat(request, is(instanceOf(ReadAllChildrenRequest.class)));
+ ReadAllChildrenRequest readAll = (ReadAllChildrenRequest)request;
+ assertThat(readAll.of(), is(at));
+ assertThat(readAll.getChildren(), hasItems(children));
+ }
+
+ protected void assertNextRequestReadBlockOfChildren( Location at,
+ int startIndex,
+ int maxCount,
+ Location... children ) {
+ Request request = executedRequests.poll();
+ assertThat(request, is(instanceOf(ReadBlockOfChildrenRequest.class)));
+ ReadBlockOfChildrenRequest read = (ReadBlockOfChildrenRequest)request;
+ assertThat(read.of(), is(at));
+ assertThat(read.startingAt(), is(startIndex));
+ assertThat(read.endingBefore(), is(startIndex + maxCount));
+ assertThat(read.count(), is(maxCount));
+ assertThat(read.getChildren(), hasItems(children));
+ }
+
+ protected void assertNextRequestReadRangeOfChildren( Location at,
+ int startIndex,
+ int endIndex,
+ Location... children ) {
+ assertNextRequestReadBlockOfChildren(at, startIndex, endIndex - startIndex,
children);
+ }
+
+ protected void assertNextRequestReadNode( Location at ) {
+ Request request = executedRequests.poll();
+ assertThat(request, is(instanceOf(ReadNodeRequest.class)));
+ ReadNodeRequest read = (ReadNodeRequest)request;
+ assertThat(read.at(), is(at));
+ }
+
+ protected void assertNoMoreRequests() {
+ assertThat(executedRequests.isEmpty(), is(true));
+ numberOfExecutions = 0;
+ }
+
+ protected void extractRequestsFromComposite() {
+ Request request = executedRequests.poll();
+ assertThat(request, is(instanceOf(CompositeRequest.class)));
+ executedRequests.addAll(0, ((CompositeRequest)request).getRequests());
+ }
+
+ //
----------------------------------------------------------------------------------------------------------------
+ // Immediate requests
+ //
----------------------------------------------------------------------------------------------------------------
+
+ @Test
+ public void shouldMoveNode() {
+ graph.move(validPath).into(validIdProperty1, validIdProperty2);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsMove(new Location(validPath), new Location(validIdProperty1,
validIdProperty2));
+ assertNoMoreRequests();
+
+ graph.move(validPathString).into(validIdProperty1, validIdProperty2);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsMove(new Location(validPath), new Location(validIdProperty1,
validIdProperty2));
+ assertNoMoreRequests();
+
+ graph.move(validUuid).into(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsMove(new Location(validUuid), new Location(validPath));
+ assertNoMoreRequests();
+ }
+
+ @Test
+ public void shouldCopyNode() {
+ graph.copy(validPath).into(validIdProperty1, validIdProperty2);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsCopy(new Location(validPath), new Location(validIdProperty1,
validIdProperty2));
+ assertNoMoreRequests();
+
+ graph.copy(validPathString).into(validIdProperty1, validIdProperty2);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsCopy(new Location(validPath), new Location(validIdProperty1,
validIdProperty2));
+ assertNoMoreRequests();
+
+ graph.copy(validUuid).into(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsCopy(new Location(validUuid), new Location(validPath));
+ assertNoMoreRequests();
+ }
+
+ @Test
+ public void shouldDeleteNode() {
+ graph.delete(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsDelete(new Location(validPath));
+ assertNoMoreRequests();
+
+ graph.delete(validPathString);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsDelete(new Location(validPath));
+ assertNoMoreRequests();
+
+ graph.delete(validUuid);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsDelete(new Location(validUuid));
+ assertNoMoreRequests();
+
+ graph.delete(validIdProperty1);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsDelete(new Location(validIdProperty1));
+ assertNoMoreRequests();
+
+ graph.delete(validIdProperty1, validIdProperty2);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsDelete(new Location(validIdProperty1, validIdProperty2));
+ assertNoMoreRequests();
+ }
+
+ @Test
+ public void shouldCreateNode() {
+ graph.create(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsCreate(new Location(validPath));
+ assertNoMoreRequests();
+
+ graph.create(validPath, validIdProperty1);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsCreate(new Location(validPath), validIdProperty1);
+ assertNoMoreRequests();
+
+ graph.create(validPath, validIdProperty1, validIdProperty2);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsCreate(new Location(validPath), validIdProperty1,
validIdProperty2);
+ assertNoMoreRequests();
+
+ graph.create(validPathString);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsCreate(new Location(validPath));
+ assertNoMoreRequests();
+
+ graph.create(validPathString, validIdProperty1);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsCreate(new Location(validPath), validIdProperty1);
+ assertNoMoreRequests();
+
+ graph.create(validPathString, validIdProperty1, validIdProperty2);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsCreate(new Location(validPath), validIdProperty1,
validIdProperty2);
+ assertNoMoreRequests();
+ }
+
+ @Test
+ public void shouldGetPropertiesOnNode() {
+ setPropertiesToReadOn(new Location(validPath), validIdProperty1,
validIdProperty2);
+ Collection<Property> props = graph.getProperties().on(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadProperties(new Location(validPath), validIdProperty1,
validIdProperty2);
+ assertNoMoreRequests();
+ assertThat(props, hasItems(validIdProperty1, validIdProperty2));
+
+ setPropertiesToReadOn(new Location(validPath));
+ props = graph.getProperties().on(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadProperties(new Location(validPath));
+ assertNoMoreRequests();
+ assertThat(props.size(), is(0));
+ }
+
+ @Test
+ public void shouldGetPropertiesByNameOnNode() {
+ setPropertiesToReadOn(new Location(validPath), validIdProperty1,
validIdProperty2);
+ Map<Name, Property> propsByName =
graph.getPropertiesByName().on(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadProperties(new Location(validPath), validIdProperty1,
validIdProperty2);
+ assertNoMoreRequests();
+ assertThat(propsByName.get(validIdProperty1.getName()), is(validIdProperty1));
+ assertThat(propsByName.get(validIdProperty2.getName()), is(validIdProperty2));
+
+ setPropertiesToReadOn(new Location(validPath));
+ propsByName = graph.getPropertiesByName().on(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadProperties(new Location(validPath));
+ assertNoMoreRequests();
+ assertThat(propsByName.isEmpty(), is(true));
+ }
+
+ @Test
+ public void shouldGetPropertyOnNode() {
+ setPropertiesToReadOn(new Location(validPath), validIdProperty1,
validIdProperty2);
+ graph.getProperty(validIdProperty2.getName()).on(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadProperty(new Location(validPath), validIdProperty2);
+ assertNoMoreRequests();
+
+ setPropertiesToReadOn(new Location(validPath), validIdProperty1,
validIdProperty2);
+
graph.getProperty(validIdProperty2.getName().getString(context.getNamespaceRegistry())).on(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadProperty(new Location(validPath), validIdProperty2);
+ assertNoMoreRequests();
+ }
+
+ @Test
+ public void shouldGetChildrenOnNode() {
+ Location child1 = new Location(createPath(validPath, "x"));
+ Location child2 = new Location(createPath(validPath, "y"));
+ Location child3 = new Location(createPath(validPath, "z"));
+ setChildrenToReadOn(new Location(validPath), child1, child2, child3);
+ List<Location> children = graph.getChildren().of(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadChildren(new Location(validPath), child1, child2, child3);
+ assertNoMoreRequests();
+ assertThat(children, hasItems(child1, child2, child3));
+
+ setChildrenToReadOn(new Location(validPath));
+ children = graph.getChildren().of(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadChildren(new Location(validPath));
+ assertNoMoreRequests();
+ assertThat(children.isEmpty(), is(true));
+ }
+
+ @Test
+ public void shouldGetChildrenInBlockOnNode() {
+ Location child1 = new Location(createPath(validPath, "x"));
+ Location child2 = new Location(createPath(validPath, "y"));
+ Location child3 = new Location(createPath(validPath, "z"));
+ setChildrenToReadOn(new Location(validPath), child1, child2, child3);
+ List<Location> children = graph.getChildrenInBlock(0, 2).of(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadBlockOfChildren(new Location(validPath), 0, 2, child1,
child2);
+ assertNoMoreRequests();
+ assertThat(children, hasItems(child1, child2));
+
+ children = graph.getChildrenInBlock(1, 2).of(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadBlockOfChildren(new Location(validPath), 1, 2, child2,
child3);
+ assertNoMoreRequests();
+ assertThat(children, hasItems(child2, child3));
+
+ children = graph.getChildrenInBlock(2, 2).of(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadBlockOfChildren(new Location(validPath), 2, 2, child3);
+ assertNoMoreRequests();
+ assertThat(children, hasItems(child3));
+
+ children = graph.getChildrenInBlock(20, 2).of(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadBlockOfChildren(new Location(validPath), 20, 2);
+ assertNoMoreRequests();
+ assertThat(children.isEmpty(), is(true));
+
+ children = graph.getChildrenInBlock(0, 20).of(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadBlockOfChildren(new Location(validPath), 0, 20, child1,
child2, child3);
+ assertNoMoreRequests();
+ assertThat(children, hasItems(child1, child2, child3));
+ }
+
+ @Test
+ public void shouldGetChildrenInRangeOnNode() {
+ Location child1 = new Location(createPath(validPath, "x"));
+ Location child2 = new Location(createPath(validPath, "y"));
+ Location child3 = new Location(createPath(validPath, "z"));
+ setChildrenToReadOn(new Location(validPath), child1, child2, child3);
+ List<Location> children = graph.getChildrenInRange(0, 2).of(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadRangeOfChildren(new Location(validPath), 0, 2, child1,
child2);
+ assertNoMoreRequests();
+ assertThat(children, hasItems(child1, child2));
+
+ children = graph.getChildrenInRange(1, 3).of(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadRangeOfChildren(new Location(validPath), 1, 3, child2,
child3);
+ assertNoMoreRequests();
+ assertThat(children, hasItems(child2, child3));
+
+ children = graph.getChildrenInRange(2, 4).of(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadRangeOfChildren(new Location(validPath), 2, 4, child3);
+ assertNoMoreRequests();
+ assertThat(children, hasItems(child3));
+
+ children = graph.getChildrenInRange(20, 21).of(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadRangeOfChildren(new Location(validPath), 20, 21);
+ assertNoMoreRequests();
+ assertThat(children.isEmpty(), is(true));
+
+ children = graph.getChildrenInRange(0, 20).of(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadRangeOfChildren(new Location(validPath), 0, 20, child1,
child2, child3);
+ assertNoMoreRequests();
+ assertThat(children, hasItems(child1, child2, child3));
+ }
+
+ @Test
+ public void shouldReadNode() {
+ Location child1 = new Location(createPath(validPath, "x"));
+ Location child2 = new Location(createPath(validPath, "y"));
+ Location child3 = new Location(createPath(validPath, "z"));
+ setChildrenToReadOn(new Location(validPath), child1, child2, child3);
+ setPropertiesToReadOn(new Location(validPath), validIdProperty1,
validIdProperty2);
+ Node node = graph.getNodeAt(validPath);
+ assertThat(node, is(notNullValue()));
+ assertThat(node.getChildren(), hasItems(child1, child2));
+ assertThat(node.getProperties(), hasItems(validIdProperty1, validIdProperty2));
+ assertThat(node.getLocation(), is(new Location(validPath)));
+ assertThat(node.getGraph(), is(sameInstance(graph)));
+ assertThat(node.getPropertiesByName().get(validIdProperty1.getName()),
is(validIdProperty1));
+ assertThat(node.getPropertiesByName().get(validIdProperty2.getName()),
is(validIdProperty2));
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadNode(new Location(validPath));
+ assertNoMoreRequests();
+ }
+
+ @Test
+ public void shouldReadSubgraph() {
+ Location child1 = new Location(createPath(validPath, "x"));
+ Location child2 = new Location(createPath(validPath, "y"));
+ Location child3 = new Location(createPath(validPath, "z"));
+ setChildrenToReadOn(new Location(validPath), child1, child2, child3);
+ Location child11 = new Location(createPath(child1.getPath(), "h"));
+ Location child12 = new Location(createPath(child1.getPath(), "i"));
+ Location child13 = new Location(createPath(child1.getPath(), "j"));
+ setChildrenToReadOn(child1, child11, child12, child13);
+ Location child121 = new Location(createPath(child12.getPath(), "m"));
+ Location child122 = new Location(createPath(child12.getPath(), "n"));
+ Location child123 = new Location(createPath(child12.getPath(), "o"));
+ setChildrenToReadOn(child12, child121, child122, child123);
+
+ setPropertiesToReadOn(new Location(validPath), validIdProperty1,
validIdProperty2);
+ setPropertiesToReadOn(child1, validIdProperty1);
+ setPropertiesToReadOn(child2, validIdProperty2);
+ setPropertiesToReadOn(child11, validIdProperty1);
+ setPropertiesToReadOn(child12, validIdProperty2);
+ setPropertiesToReadOn(child121, validIdProperty1);
+ setPropertiesToReadOn(child122, validIdProperty2);
+
+ Subgraph subgraph = graph.getSubgraphOfDepth(2).at(validPath);
+ assertThat(subgraph, is(notNullValue()));
+ assertThat(subgraph.getMaximumDepth(), is(2));
+ assertThat(subgraph.getLocation(), is(new Location(validPath)));
+
+ // Get nodes by absolute path
+ Node root = subgraph.getNode(new Location(validPath));
+ assertThat(root.getChildren(), hasItems(child1, child2, child3));
+ assertThat(root.getProperties(), hasItems(validIdProperty1, validIdProperty2));
+
+ Node node1 = subgraph.getNode(child1);
+ assertThat(node1.getChildren(), hasItems(child11, child12, child13));
+ assertThat(node1.getProperties(), hasItems(validIdProperty1));
+
+ Node node2 = subgraph.getNode(child2);
+ assertThat(node2.getChildren().isEmpty(), is(true));
+ assertThat(node2.getProperties(), hasItems(validIdProperty2));
+
+ Node node3 = subgraph.getNode(child3);
+ assertThat(node3.getChildren().isEmpty(), is(true));
+ assertThat(node3.getProperties().isEmpty(), is(true));
+
+ // Get nodes that don't exist in subgraph ...
+ assertThat(subgraph.getNode(child123), is(nullValue()));
+
+ // Get nodes by relative path ...
+ root = subgraph.getNode("./");
+ assertThat(root.getChildren(), hasItems(child1, child2, child3));
+ assertThat(root.getProperties(), hasItems(validIdProperty1, validIdProperty2));
+
+ node1 = subgraph.getNode("x");
+ assertThat(node1.getChildren(), hasItems(child11, child12, child13));
+ assertThat(node1.getProperties(), hasItems(validIdProperty1));
+
+ node2 = subgraph.getNode("y");
+ assertThat(node2.getChildren().isEmpty(), is(true));
+ assertThat(node2.getProperties(), hasItems(validIdProperty2));
+
+ node3 = subgraph.getNode("z");
+ assertThat(node3.getChildren().isEmpty(), is(true));
+ assertThat(node3.getProperties().isEmpty(), is(true));
+ }
+
+ //
----------------------------------------------------------------------------------------------------------------
+ // Batched requests
+ //
----------------------------------------------------------------------------------------------------------------
+
+ @Test
+ public void shouldMoveNodeInBatches() {
+ graph.batch().move(validPath).into(validIdProperty1,
validIdProperty2).execute();
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsMove(new Location(validPath), new Location(validIdProperty1,
validIdProperty2));
+ assertNoMoreRequests();
+
+ graph.batch().move(validPathString).into(validIdProperty1,
validIdProperty2).execute();
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsMove(new Location(validPath), new Location(validIdProperty1,
validIdProperty2));
+ assertNoMoreRequests();
+
+ graph.batch().move(validUuid).into(validPath).execute();
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsMove(new Location(validUuid), new Location(validPath));
+ assertNoMoreRequests();
+
+ graph.batch().move(validPath).into(validIdProperty1,
validIdProperty2).and().move(validPathString).into(validIdProperty1,
+
validIdProperty2).and().move(validUuid).into(validPath).execute();
+ assertThat(numberOfExecutions, is(1));
+ extractRequestsFromComposite();
+ assertNextRequestIsMove(new Location(validPath), new Location(validIdProperty1,
validIdProperty2));
+ assertNextRequestIsMove(new Location(validPath), new Location(validIdProperty1,
validIdProperty2));
+ assertNextRequestIsMove(new Location(validUuid), new Location(validPath));
+ assertNoMoreRequests();
+ }
+
+ @Test
+ public void shouldCopyNodeInBatches() {
+ graph.batch().copy(validPath).into(validIdProperty1,
validIdProperty2).execute();
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsCopy(new Location(validPath), new Location(validIdProperty1,
validIdProperty2));
+ assertNoMoreRequests();
+
+ graph.batch().copy(validPathString).into(validIdProperty1,
validIdProperty2).execute();
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsCopy(new Location(validPath), new Location(validIdProperty1,
validIdProperty2));
+ assertNoMoreRequests();
+
+ graph.batch().copy(validUuid).into(validPath).execute();
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsCopy(new Location(validUuid), new Location(validPath));
+ assertNoMoreRequests();
+
+ graph.batch().copy(validPath).into(validIdProperty1,
validIdProperty2).and().copy(validPathString).into(validIdProperty1,
+
validIdProperty2).and().copy(validUuid).into(validPath).execute();
+ assertThat(numberOfExecutions, is(1));
+ extractRequestsFromComposite();
+ assertNextRequestIsCopy(new Location(validPath), new Location(validIdProperty1,
validIdProperty2));
+ assertNextRequestIsCopy(new Location(validPath), new Location(validIdProperty1,
validIdProperty2));
+ assertNextRequestIsCopy(new Location(validUuid), new Location(validPath));
+ assertNoMoreRequests();
+ }
+
+ @Test
+ public void shouldReadNodesInBatches() {
+ Location child1 = new Location(createPath(validPath, "x"));
+ Location child2 = new Location(createPath(validPath, "y"));
+ Location child3 = new Location(createPath(validPath, "z"));
+ setChildrenToReadOn(new Location(validPath), child1, child2, child3);
+ Location child11 = new Location(createPath(child1.getPath(), "h"));
+ Location child12 = new Location(createPath(child1.getPath(), "i"));
+ Location child13 = new Location(createPath(child1.getPath(), "j"));
+ setChildrenToReadOn(child1, child11, child12, child13);
+ Location child121 = new Location(createPath(child12.getPath(), "m"));
+ Location child122 = new Location(createPath(child12.getPath(), "n"));
+ Location child123 = new Location(createPath(child12.getPath(), "o"));
+ setChildrenToReadOn(child12, child121, child122, child123);
+
+ setPropertiesToReadOn(new Location(validPath), validIdProperty1,
validIdProperty2);
+ setPropertiesToReadOn(child1, validIdProperty1);
+ setPropertiesToReadOn(child2, validIdProperty2);
+ setPropertiesToReadOn(child11, validIdProperty1);
+ setPropertiesToReadOn(child12, validIdProperty2);
+ setPropertiesToReadOn(child121, validIdProperty1);
+ setPropertiesToReadOn(child122, validIdProperty2);
+
+ results =
graph.batch().read(validPath).and().read(child11).and().read(child12).execute();
+ assertThat(numberOfExecutions, is(1));
+ extractRequestsFromComposite();
+ assertNextRequestReadNode(new Location(validPath));
+ assertNextRequestReadNode(child11);
+ assertNextRequestReadNode(child12);
+ assertNoMoreRequests();
+
+ assertThat(results, is(notNullValue()));
+ Node node = results.getNode(validPath);
+ assertThat(node, is(notNullValue()));
+ assertThat(node.getChildren(), hasItems(child1, child2, child3));
+ assertThat(node.getProperties(), hasItems(validIdProperty1, validIdProperty2));
+ assertThat(node.getLocation(), is(new Location(validPath)));
+ assertThat(node.getGraph(), is(sameInstance(graph)));
+ assertThat(node.getPropertiesByName().get(validIdProperty1.getName()),
is(validIdProperty1));
+ assertThat(node.getPropertiesByName().get(validIdProperty2.getName()),
is(validIdProperty2));
+
+ node = results.getNode(child11);
+ assertThat(node, is(notNullValue()));
+ assertThat(node.getChildren().size(), is(0));
+ assertThat(node.getProperties(), hasItems(validIdProperty1));
+ assertThat(node.getLocation(), is(child11));
+ assertThat(node.getGraph(), is(sameInstance(graph)));
+ assertThat(node.getPropertiesByName().get(validIdProperty1.getName()),
is(validIdProperty1));
+
+ node = results.getNode(child12);
+ assertThat(node, is(notNullValue()));
+ assertThat(node.getChildren(), hasItems(child121, child122, child123));
+ assertThat(node.getProperties(), hasItems(validIdProperty2));
+ assertThat(node.getLocation(), is(child12));
+ assertThat(node.getGraph(), is(sameInstance(graph)));
+ assertThat(node.getPropertiesByName().get(validIdProperty2.getName()),
is(validIdProperty2));
+ }
+
+ //
----------------------------------------------------------------------------------------------------------------
+ // Test that the test harness (helper methods and helper classes) are set up and
working ...
+ //
----------------------------------------------------------------------------------------------------------------
+ @Test( expected = AssertionError.class )
+ public void shouldPropertyCheckReadPropertiesUsingTestHarness1() {
+ setPropertiesToReadOn(new Location(validPath), validIdProperty1);
+ graph.getProperties().on(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadProperties(new Location(validPath), validIdProperty1,
validIdProperty2); // wrong!
+ }
+
+ @Test( expected = AssertionError.class )
+ public void shouldPropertyCheckReadPropertiesUsingTestHarness2() {
+ graph.getProperties().on(validPath);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestReadProperties(new Location(validPath), validIdProperty1,
validIdProperty2); // wrong!
+ }
+
+ //
----------------------------------------------------------------------------------------------------------------
+ // Requests that result in errors
+ //
----------------------------------------------------------------------------------------------------------------
+
+ @Test( expected = InvalidPathException.class )
+ public void shouldPropogateExceptionFromConnectorWhenMovingLocationIsNotFound() {
+ connection.error = new InvalidPathException();
+ graph.move(validUuid).into(validPath);
+ }
+
+ @Test( expected = InvalidPathException.class )
+ public void shouldPropogateExceptionFromConnectorWhenCopyLocationIsNotFound() {
+ connection.error = new InvalidPathException();
+ graph.copy(validUuid).into(validPath);
+ }
+
+ @Test( expected = InvalidPathException.class )
+ public void shouldPropogateExceptionFromConnectorWhenDeleteLocationIsNotFound() {
+ connection.error = new InvalidPathException();
+ graph.delete(validUuid);
+ }
+
+ //
----------------------------------------------------------------------------------------------------------------
+ // Multiple immediate requests via method chaining
+ //
----------------------------------------------------------------------------------------------------------------
+
+ @Test
+ public void shouldMoveNodesThroughMultipleMoveRequests() {
+ graph.move(validPath).into(validIdProperty1,
validIdProperty2).and().move(validUuid).into(validPathString);
+ assertThat(numberOfExecutions, is(2));
+ assertNextRequestIsMove(new Location(validPath), new Location(validIdProperty1,
validIdProperty2));
+ assertNextRequestIsMove(new Location(validUuid), new
Location(createPath(validPathString)));
+ assertNoMoreRequests();
+ }
+
+ @Test
+ public void shouldIgnoreIncompleteRequests() {
+ graph.move(validPath); // missing 'into(...)'
+ assertNoMoreRequests();
+
+ graph.move(validPath).into(validUuid);
+ assertThat(numberOfExecutions, is(1));
+ assertNextRequestIsMove(new Location(validPath), new Location(validUuid));
+ assertNoMoreRequests();
+ }
+
+ // @Test
+ // public void shouldBatchMultipleRequests() {
+ // // Get the children of one node and the properties of another ...
+ // results =
graph.batch().readChildren().of("/a/b").and().readProperties().on(validUuid).execute();
+ // }
+
+ //
----------------------------------------------------------------------------------------------------------------
+ // Implementation of RepositoryConnection and RequestProcessor for tests
+ //
----------------------------------------------------------------------------------------------------------------
+
+ /**
+ * Implementation used by the {@link MockRepositoryConnection} to process the
requests. The methods of this implementation do
+ * little, other than populate the incoming read {@link Request}s with the properties
and children that are to be read, using
+ * the {@link GraphTest#children} and {@link GraphTest#properties} values.
+ */
+ @SuppressWarnings( "synthetic-access" )
+ class Processor extends RequestProcessor {
+ protected Processor() {
+ super(sourceName, context);
+ }
+
+ @Override
+ public void process( CopyBranchRequest request ) {
+ // Do nothing
+ }
+
+ @Override
+ public void process( CreateNodeRequest request ) {
+ // Do nothing
+ }
+
+ @Override
+ public void process( DeleteBranchRequest request ) {
+ // Do nothing
+ }
+
+ @Override
+ public void process( MoveBranchRequest request ) {
+ // Do nothing
+ }
+
+ @Override
+ public void process( ReadAllChildrenRequest request ) {
+ // Read the children from the map ...
+ if (children.containsKey(request.of())) {
+ for (Location child : children.get(request.of())) {
+ request.addChild(child);
+ }
+ }
+ }
+
+ @Override
+ public void process( ReadAllPropertiesRequest request ) {
+ // Read the properties from the map ...
+ if (properties.containsKey(request.at())) {
+ for (Property property : properties.get(request.at())) {
+ request.addProperty(property);
+ }
+ }
+ }
+
+ @Override
+ public void process( UpdatePropertiesRequest request ) {
+ // Do nothing
+ }
+ }
+
+ /**
+ * A connection implementation that simply records the {@link Request} that is
submitted, storing the request in the
+ * {@link GraphTest#executedRequests} variable.
+ *
+ * @author Randall Hauch
+ */
+ class MockRepositoryConnection implements RepositoryConnection {
+ public Throwable error = null;
+ private final RequestProcessor processor = new Processor();
+
+ public void close() {
+ }
+
+ public void execute( ExecutionContext context,
+ GraphCommand... commands ) throws RepositorySourceException
{
+ }
+
+ @SuppressWarnings( "synthetic-access" )
+ public void execute( ExecutionContext context,
+ Request request ) throws RepositorySourceException {
+ if (error != null) {
+ request.setError(error);
+ return;
+ }
+ executedRequests.add(request);
+ ++numberOfExecutions;
+ processor.process(request);
+ }
+
+ public CachePolicy getDefaultCachePolicy() {
+ return null;
+ }
+
+ public String getSourceName() {
+ return null;
+ }
+
+ public XAResource getXAResource() {
+ return null;
+ }
+
+ public boolean ping( long time,
+ TimeUnit unit ) {
+ return true;
+ }
+
+ public void setListener( RepositorySourceListener listener ) {
+ }
+
+ }
+}
Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/SimpleRepositorySource.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/SimpleRepositorySource.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/SimpleRepositorySource.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -42,17 +42,12 @@
import org.jboss.dna.graph.commands.SetPropertiesCommand;
import org.jboss.dna.graph.commands.executor.AbstractCommandExecutor;
import org.jboss.dna.graph.commands.executor.CommandExecutor;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryContext;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.RepositorySourceCapabilities;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.connectors.RepositorySourceListener;
import org.jboss.dna.graph.properties.Name;
import org.jboss.dna.graph.properties.Path;
import org.jboss.dna.graph.properties.PathNotFoundException;
import org.jboss.dna.graph.properties.Property;
import org.jboss.dna.graph.properties.basic.BasicSingleValueProperty;
+import org.jboss.dna.graph.requests.Request;
/**
* A {@link RepositorySource} for a {@link SimpleRepository simple repository}.
@@ -270,6 +265,18 @@
/**
* {@inheritDoc}
*
+ * @see
org.jboss.dna.graph.connectors.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
+ * org.jboss.dna.graph.requests.Request)
+ */
+ public void execute( ExecutionContext context,
+ Request request ) throws RepositorySourceException {
+ // TODO
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see
org.jboss.dna.graph.connectors.RepositoryConnection#getDefaultCachePolicy()
*/
public CachePolicy getDefaultCachePolicy() {
Modified:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/TimeDelayingRepositorySource.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/TimeDelayingRepositorySource.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/TimeDelayingRepositorySource.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -35,12 +35,7 @@
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.cache.CachePolicy;
import org.jboss.dna.graph.commands.GraphCommand;
-import org.jboss.dna.graph.connectors.RepositoryConnection;
-import org.jboss.dna.graph.connectors.RepositoryContext;
-import org.jboss.dna.graph.connectors.RepositorySource;
-import org.jboss.dna.graph.connectors.RepositorySourceCapabilities;
-import org.jboss.dna.graph.connectors.RepositorySourceException;
-import org.jboss.dna.graph.connectors.RepositorySourceListener;
+import org.jboss.dna.graph.requests.Request;
/**
* A simple {@link RepositorySource} that simulates an imaginary source with a built-in
delay mechanism.
@@ -332,6 +327,18 @@
this.loadCount.incrementAndGet();
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.connectors.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
+ * org.jboss.dna.graph.requests.Request)
+ */
+ public void execute( ExecutionContext context,
+ Request request ) throws RepositorySourceException {
+ // TODO
+ throw new UnsupportedOperationException();
+ }
+
public void setLoadResponse( boolean response ) {
this.loadResponse.set(response);
}
Modified:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/AbstractRequestTest.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/AbstractRequestTest.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/requests/AbstractRequestTest.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -23,6 +23,7 @@
import java.util.UUID;
import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.connectors.BasicExecutionContext;
import org.jboss.dna.graph.properties.Name;
import org.jboss.dna.graph.properties.Path;
Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/util/GraphImporterTest.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/util/GraphImporterTest.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/util/GraphImporterTest.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -49,7 +49,7 @@
import org.jboss.dna.graph.properties.Name;
import org.jboss.dna.graph.properties.Path;
import org.jboss.dna.graph.properties.Property;
-import org.jboss.dna.graph.util.GraphImporter;
+import org.jboss.dna.graph.requests.Request;
import org.jboss.dna.graph.xml.DnaDtdLexicon;
import org.jboss.dna.graph.xml.DnaXmlLexicon;
import org.junit.Before;
@@ -68,6 +68,7 @@
private URI xmlContent;
private MockRepositoryConnection connection;
private GraphCommand lastExecutedCommand;
+ private Request lastExecutedRequest;
private Path destinationPath;
@Mock
private RepositoryConnectionFactory sources;
@@ -159,6 +160,12 @@
lastExecutedCommand = commands[0];
}
+ @SuppressWarnings( "synthetic-access" )
+ public void execute( ExecutionContext context,
+ Request request ) throws RepositorySourceException {
+ lastExecutedRequest = request;
+ }
+
public CachePolicy getDefaultCachePolicy() {
return null;
}
Modified:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConnection.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConnection.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConnection.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -32,6 +32,7 @@
import org.jboss.dna.graph.connectors.RepositoryConnection;
import org.jboss.dna.graph.connectors.RepositorySourceException;
import org.jboss.dna.graph.connectors.RepositorySourceListener;
+import org.jboss.dna.graph.requests.Request;
/**
* @author Randall Hauch
@@ -131,7 +132,19 @@
/**
* {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.connectors.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
+ * org.jboss.dna.graph.requests.Request)
*/
+ public void execute( ExecutionContext context,
+ Request request ) throws RepositorySourceException {
+ // TODO
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public void close() {
try {
this.repository.removeListener(this.listener.get());
Modified:
trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryConnection.java
===================================================================
---
trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryConnection.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryConnection.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -34,6 +34,7 @@
import org.jboss.dna.graph.connectors.RepositoryConnection;
import org.jboss.dna.graph.connectors.RepositorySourceException;
import org.jboss.dna.graph.connectors.RepositorySourceListener;
+import org.jboss.dna.graph.requests.Request;
/**
* @author Randall Hauch
@@ -150,6 +151,18 @@
}
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.connectors.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
+ * org.jboss.dna.graph.requests.Request)
+ */
+ public void execute( ExecutionContext context,
+ Request request ) throws RepositorySourceException {
+ // TODO
+ throw new UnsupportedOperationException();
+ }
+
protected InMemoryRepository getContent() {
return content;
}
Modified:
trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheConnection.java
===================================================================
---
trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheConnection.java 2008-10-09
21:25:44 UTC (rev 566)
+++
trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheConnection.java 2008-10-13
19:58:03 UTC (rev 567)
@@ -60,6 +60,7 @@
import org.jboss.dna.graph.properties.PropertyFactory;
import org.jboss.dna.graph.properties.ValueFactory;
import org.jboss.dna.graph.properties.Path.Segment;
+import org.jboss.dna.graph.requests.Request;
/**
* The repository connection to a JBoss Cache instance.
@@ -156,6 +157,18 @@
}
/**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.connectors.RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext,
+ * org.jboss.dna.graph.requests.Request)
+ */
+ public void execute( ExecutionContext context,
+ Request request ) throws RepositorySourceException {
+ // TODO
+ throw new UnsupportedOperationException();
+ }
+
+ /**
* @return listener
*/
protected RepositorySourceListener getListener() {