[dna-commits] DNA SVN: r1317 - in trunk/dna-graph/src: test/java/org/jboss/dna/graph and 1 other directory.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Mon Nov 9 14:29:51 EST 2009


Author: rhauch
Date: 2009-11-09 14:29:50 -0500 (Mon, 09 Nov 2009)
New Revision: 1317

Modified:
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java
Log:
DNA-550 Added methods to Graph to allow reading of one or more properties on multiple nodes, all in a single operation

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java	2009-10-30 21:34:28 UTC (rev 1316)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java	2009-11-09 19:29:50 UTC (rev 1317)
@@ -2062,8 +2062,9 @@
      * @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 OnMultiple<Property> getProperty( final Name name ) {
+        CheckArg.isNotNull(name, "name");
+        return new OnMultiple<Property>() {
             public Property on( String path ) {
                 return on(Location.create(createPath(path)));
             }
@@ -2092,10 +2093,237 @@
             public Property on( Location at ) {
                 return requests.readProperty(at, getCurrentWorkspaceName(), name).getProperty();
             }
+
+            public Map<Location, Property> on( Collection<Location> locations ) {
+                CheckArg.isNotNull(locations, "locations");
+                final List<ReadPropertyRequest> requests = new LinkedList<ReadPropertyRequest>();
+                String workspace = getCurrentWorkspaceName();
+                for (Location location : locations) {
+                    requests.add(new ReadPropertyRequest(location, workspace, name));
+                }
+                return execute(requests);
+            }
+
+            public Map<Location, Property> on( Location first,
+                                               Location... additional ) {
+                CheckArg.isNotNull(first, "first");
+                final List<ReadPropertyRequest> requests = new LinkedList<ReadPropertyRequest>();
+                String workspace = getCurrentWorkspaceName();
+                requests.add(new ReadPropertyRequest(first, workspace, name));
+                for (Location location : additional) {
+                    requests.add(new ReadPropertyRequest(location, workspace, name));
+                }
+                return execute(requests);
+            }
+
+            public Map<Location, Property> on( String first,
+                                               String... additional ) {
+                CheckArg.isNotNull(first, "first");
+                final List<ReadPropertyRequest> requests = new LinkedList<ReadPropertyRequest>();
+                String workspace = getCurrentWorkspaceName();
+                requests.add(new ReadPropertyRequest(Location.create(createPath(first)), workspace, name));
+                for (String path : additional) {
+                    requests.add(new ReadPropertyRequest(Location.create(createPath(path)), workspace, name));
+                }
+                return execute(requests);
+            }
+
+            public Map<Location, Property> on( Path first,
+                                               Path... additional ) {
+                CheckArg.isNotNull(first, "first");
+                final List<ReadPropertyRequest> requests = new LinkedList<ReadPropertyRequest>();
+                String workspace = getCurrentWorkspaceName();
+                requests.add(new ReadPropertyRequest(Location.create(first), workspace, name));
+                for (Path path : additional) {
+                    requests.add(new ReadPropertyRequest(Location.create(path), workspace, name));
+                }
+                return execute(requests);
+            }
+
+            public Map<Location, Property> on( UUID first,
+                                               UUID... additional ) {
+                CheckArg.isNotNull(first, "first");
+                final List<ReadPropertyRequest> requests = new LinkedList<ReadPropertyRequest>();
+                String workspace = getCurrentWorkspaceName();
+                requests.add(new ReadPropertyRequest(Location.create(first), workspace, name));
+                for (UUID uuid : additional) {
+                    requests.add(new ReadPropertyRequest(Location.create(uuid), workspace, name));
+                }
+                return execute(requests);
+            }
+
+            protected Map<Location, Property> execute( List<ReadPropertyRequest> requests ) {
+                // Create a composite request ...
+                Request composite = CompositeRequest.with(requests);
+                Graph.this.execute(composite);
+                Map<Location, Property> results = new HashMap<Location, Property>();
+                for (ReadPropertyRequest request : requests) {
+                    Property property = request.getProperty();
+                    Location location = request.getActualLocationOfNode();
+                    results.put(location, property);
+                }
+                return results;
+            }
         };
     }
 
     /**
+     * Request that the properties with the given names 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 names the name of the property that are to be read
+     * @return the object that is used to specified the node whose properties are to be read, and which will return the map of
+     *         properties keyed by their name; never null
+     */
+    public OnMultiple<Map<Name, Property>> getProperties( final Name... names ) {
+        return new OnMultiple<Map<Name, Property>>() {
+            public Map<Name, Property> on( String path ) {
+                return on(Location.create(createPath(path)));
+            }
+
+            public Map<Name, Property> on( Path path ) {
+                return on(Location.create(path));
+            }
+
+            public Map<Name, Property> on( Property idProperty ) {
+                return on(Location.create(idProperty));
+            }
+
+            public Map<Name, Property> on( Property firstIdProperty,
+                                           Property... additionalIdProperties ) {
+                return on(Location.create(firstIdProperty, additionalIdProperties));
+            }
+
+            public Map<Name, Property> on( Iterable<Property> idProperties ) {
+                return on(Location.create(idProperties));
+            }
+
+            public Map<Name, Property> on( UUID uuid ) {
+                return on(Location.create(uuid));
+            }
+
+            public Map<Name, Property> on( Location at ) {
+                final List<ReadPropertyRequest> requests = new LinkedList<ReadPropertyRequest>();
+                String workspace = getCurrentWorkspaceName();
+                for (Name propertyName : names) {
+                    requests.add(new ReadPropertyRequest(at, workspace, propertyName));
+                }
+                // Create a composite request ...
+                Request composite = CompositeRequest.with(requests);
+                Graph.this.execute(composite);
+                Map<Name, Property> results = new HashMap<Name, Property>();
+                for (ReadPropertyRequest request : requests) {
+                    Property property = request.getProperty();
+                    results.put(property.getName(), property);
+                }
+                return results;
+            }
+
+            public Map<Location, Map<Name, Property>> on( Collection<Location> locations ) {
+                CheckArg.isNotNull(locations, "locations");
+                final List<ReadPropertyRequest> requests = new LinkedList<ReadPropertyRequest>();
+                String workspace = getCurrentWorkspaceName();
+                for (Location location : locations) {
+                    if (location == null) continue;
+                    for (Name propertyName : names) {
+                        if (propertyName == null) continue;
+                        requests.add(new ReadPropertyRequest(location, workspace, propertyName));
+                    }
+                }
+                return execute(requests);
+            }
+
+            /**
+             * {@inheritDoc}
+             * 
+             * @see org.jboss.dna.graph.Graph.OnMultiple#on(org.jboss.dna.graph.Location, org.jboss.dna.graph.Location[])
+             */
+            public Map<Location, Map<Name, Property>> on( Location first,
+                                                          Location... additional ) {
+                CheckArg.isNotNull(first, "first");
+                final List<ReadPropertyRequest> requests = new LinkedList<ReadPropertyRequest>();
+                String workspace = getCurrentWorkspaceName();
+                for (Location location : additional) {
+                    if (location == null) continue;
+                    for (Name propertyName : names) {
+                        if (propertyName == null) continue;
+                        requests.add(new ReadPropertyRequest(first, workspace, propertyName));
+                        requests.add(new ReadPropertyRequest(location, workspace, propertyName));
+                    }
+                }
+                return execute(requests);
+            }
+
+            /**
+             * {@inheritDoc}
+             * 
+             * @see org.jboss.dna.graph.Graph.OnMultiple#on(org.jboss.dna.graph.property.Path,
+             *      org.jboss.dna.graph.property.Path[])
+             */
+            public Map<Location, Map<Name, Property>> on( Path first,
+                                                          Path... additional ) {
+                CheckArg.isNotNull(first, "first");
+                List<Location> locations = new LinkedList<Location>();
+                locations.add(Location.create(first));
+                for (Path path : additional) {
+                    if (path != null) locations.add(Location.create(path));
+                }
+                return on(locations);
+            }
+
+            /**
+             * {@inheritDoc}
+             * 
+             * @see org.jboss.dna.graph.Graph.OnMultiple#on(java.lang.String, java.lang.String[])
+             */
+            public Map<Location, Map<Name, Property>> on( String first,
+                                                          String... additional ) {
+                CheckArg.isNotNull(first, "first");
+                List<Location> locations = new LinkedList<Location>();
+                locations.add(Location.create(createPath(first)));
+                for (String path : additional) {
+                    if (path != null) locations.add(Location.create(createPath(path)));
+                }
+                return on(locations);
+            }
+
+            /**
+             * {@inheritDoc}
+             * 
+             * @see org.jboss.dna.graph.Graph.OnMultiple#on(java.util.UUID, java.util.UUID[])
+             */
+            public Map<Location, Map<Name, Property>> on( UUID first,
+                                                          UUID... additional ) {
+                CheckArg.isNotNull(first, "first");
+                List<Location> locations = new LinkedList<Location>();
+                locations.add(Location.create(first));
+                for (UUID uuid : additional) {
+                    if (uuid != null) locations.add(Location.create(uuid));
+                }
+                return on(locations);
+            }
+
+            protected Map<Location, Map<Name, Property>> execute( List<ReadPropertyRequest> requests ) {
+                // Create a composite request ...
+                Request composite = CompositeRequest.with(requests);
+                Graph.this.execute(composite);
+                Map<Location, Map<Name, Property>> results = new HashMap<Location, Map<Name, Property>>();
+                for (ReadPropertyRequest request : requests) {
+                    Property property = request.getProperty();
+                    Location location = request.getActualLocationOfNode();
+                    Map<Name, Property> properties = results.get(location);
+                    if (properties == null) {
+                        properties = new HashMap<Name, Property>();
+                        results.put(location, properties);
+                    }
+                    properties.put(property.getName(), property);
+                }
+                return results;
+            }
+        };
+    }
+
+    /**
      * Request to read the node with the supplied UUID.
      * 
      * @param uuid the UUID of the node that is to be read
@@ -2395,8 +2623,6 @@
      * 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<Node> {
@@ -4259,7 +4485,6 @@
     /**
      * A interface used to execute the accumulated {@link Batch requests}.
      * 
-     * @author Randall Hauch
      * @param <NodeType> the type of node that is returned
      */
     public interface Executable<NodeType extends Node> {
@@ -4281,7 +4506,6 @@
      * 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> {
         /**
@@ -4296,7 +4520,6 @@
      * 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> {
         /**
@@ -4376,7 +4599,6 @@
      * or copied node as the last child of the new parent.
      * 
      * @param <Next> The interface that is to be returned when this request is completed
-     * @author Randall Hauch
      */
     public interface Before<Next> {
         /**
@@ -4480,7 +4702,6 @@
      * A component that defines the location to 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 To<Next> {
         /**
@@ -4555,7 +4776,6 @@
      * A component that defines a new name for a node.
      * 
      * @param <Next> The interface that is to be returned when this request is completed
-     * @author Randall Hauch
      */
     public interface AsName<Next> {
         /**
@@ -4579,7 +4799,6 @@
      * 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> {
         /**
@@ -4647,7 +4866,6 @@
      * 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 AsName<Into<Next>>, Into<Next>, Before<Next>, And<Move<Next>> {
     }
@@ -4659,7 +4877,6 @@
      * is to be placed, which will assume the new copy will have the same name as the original.
      * 
      * @param <Next> The interface that is to be returned when this request is completed
-     * @author Randall Hauch
      */
     public interface Copy<Next> extends FromWorkspace<CopyTarget<Next>>, CopyTarget<Next>, And<Copy<Next>> {
     }
@@ -4780,7 +4997,6 @@
      * 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> {
         /**
@@ -4929,7 +5145,6 @@
      * 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 CreateAt<Next> extends Conjunction<Next> {
         /**
@@ -5060,7 +5275,6 @@
      * 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> {
         /**
@@ -5125,10 +5339,64 @@
     }
 
     /**
+     * The interface for defining the node upon which a request operates, including a method that accepts multiple locations.
+     * 
+     * @param <Next> The interface that is to be returned when the request is completed
+     */
+    public interface OnMultiple<Next> extends On<Next> {
+        /**
+         * Specify the location of each node upon which the requests are to operate.
+         * 
+         * @param to the locations
+         * @return the interface for additional requests or actions
+         */
+        Map<Location, Next> on( Collection<Location> to );
+
+        /**
+         * Specify the location of each node upon which the requests are to operate.
+         * 
+         * @param firstTo the first location
+         * @param additional the additional location
+         * @return the interface for additional requests or actions
+         */
+        Map<Location, Next> on( Location firstTo,
+                                Location... additional );
+
+        /**
+         * Specify the path of each node upon which the requests are to operate.
+         * 
+         * @param firstPath the first path
+         * @param additional the additional path
+         * @return the interface for additional requests or actions
+         */
+        Map<Location, Next> on( String firstPath,
+                                String... additional );
+
+        /**
+         * Specify the path of each node upon which the requests are to operate.
+         * 
+         * @param firstPath the first path
+         * @param additional the additional path
+         * @return the interface for additional requests or actions
+         */
+        Map<Location, Next> on( Path firstPath,
+                                Path... additional );
+
+        /**
+         * Specify the UUID of each node upon which the requests are to operate.
+         * 
+         * @param firstPath the first UUID of the node
+         * @param additional the additional UUIDs
+         * @return the interface for additional requests or actions
+         */
+        Map<Location, Next> on( UUID firstPath,
+                                UUID... additional );
+    }
+
+    /**
      * 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> {
         /**
@@ -5196,7 +5464,6 @@
      * 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> {
         /**
@@ -5267,7 +5534,6 @@
      * the {@link BlockOfChildren block size and parent}.
      * 
      * @param <Next>
-     * @author Randall Hauch
      */
     public interface Children<Next> extends Of<Next> {
         /**
@@ -5284,7 +5550,6 @@
      * {@link #startingAfter(Location) after a previous sibling}.
      * 
      * @param <Next>
-     * @author Randall Hauch
      */
     public interface BlockOfChildren<Next> {
         /**
@@ -5364,7 +5629,6 @@
      * The interface for defining the node under which which a request operates.
      * 
      * @param <Next> The interface that is to be returned when the request is completed
-     * @author Randall Hauch
      */
     public interface Under<Next> {
         /**
@@ -5587,7 +5851,6 @@
      * A component used to set the values on a property.
      * 
      * @param <Next> the next command
-     * @author Randall Hauch
      */
     public interface SetValues<Next> extends On<SetValuesTo<Next>>, SetValuesTo<On<Next>> {
     }
@@ -5596,7 +5859,6 @@
      * A component used to set the values on a property.
      * 
      * @param <Next>
-     * @author Randall Hauch
      */
     public interface SetValuesTo<Next> {
 
@@ -5842,7 +6104,6 @@
      * A component that defines a node that is to be created.
      * 
      * @param <Next> The interface that is to be returned to complete the create request
-     * @author Randall Hauch
      */
     public interface CreateNode<Next> {
         /**
@@ -5880,7 +6141,6 @@
      * A component that defines a node that is to be created.
      * 
      * @param <Next> The interface that is to be returned to complete the create request
-     * @author Randall Hauch
      */
     public interface CreateNodeNamed<Next> {
         /**
@@ -5904,7 +6164,6 @@
      * 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 ImportInto<Next> {
         /**
@@ -7183,7 +7442,6 @@
      * 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
      * @param <NodeType> the type of node that tis results deals with
      */
     @Immutable

Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java	2009-10-30 21:34:28 UTC (rev 1316)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java	2009-11-09 19:29:50 UTC (rev 1317)
@@ -32,6 +32,7 @@
 import static org.junit.matchers.JUnitMatchers.hasItems;
 import static org.mockito.Matchers.argThat;
 import static org.mockito.Mockito.stub;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Collection;
@@ -1112,6 +1113,64 @@
     }
 
     // ----------------------------------------------------------------------------------------------------------------
+    // Read set number of properties on multiple nodes ...
+    // ----------------------------------------------------------------------------------------------------------------
+
+    @Test
+    public void shouldReadOnePropertyOnMultipleNodes() {
+        List<Location> locations = new ArrayList<Location>();
+        locations.add(Location.create(createPath("/x/y/a")));
+        locations.add(Location.create(createPath("/x/y/b")));
+        locations.add(Location.create(createPath("/x/y/c")));
+        for (Location location : locations) {
+            Property prop1 = context.getPropertyFactory().create(validName, "1");
+            Property prop2 = context.getPropertyFactory().create(createName("otherName"), "2");
+            setPropertiesToReadOn(location, prop1, prop2);
+        }
+
+        Map<Location, Property> propertiesByLocation = graph.getProperty(validName).on(locations);
+        assertThat(numberOfExecutions, is(1));
+        extractRequestsFromComposite();
+        for (Location location : locations) {
+            Property prop = this.properties.get(location).iterator().next();
+            assertNextRequestReadProperty(location, prop);
+            assertThat(propertiesByLocation.get(location), is(prop));
+        }
+        assertNoMoreRequests();
+    }
+
+    @Test
+    public void shouldReadMultiplePropertiesOnMultipleNodes() {
+        List<Location> locations = new ArrayList<Location>();
+        locations.add(Location.create(createPath("/x/y/a")));
+        locations.add(Location.create(createPath("/x/y/b")));
+        locations.add(Location.create(createPath("/x/y/c")));
+        Name name1 = createName("name1");
+        Name name2 = createName("name2");
+        for (Location location : locations) {
+            Property prop1 = context.getPropertyFactory().create(name1, "1");
+            Property prop2 = context.getPropertyFactory().create(name2, "2");
+            setPropertiesToReadOn(location, prop1, prop2);
+        }
+        Map<Location, Map<Name, Property>> propertiesByLocation = graph.getProperties(name1, name2).on(locations);
+        assertThat(numberOfExecutions, is(1));
+        extractRequestsFromComposite();
+        for (Location location : locations) {
+            Map<Name, Property> expectedProps = new HashMap<Name, Property>();
+            for (Property prop : this.properties.get(location)) {
+                expectedProps.put(prop.getName(), prop);
+            }
+            Property prop1 = expectedProps.get(name1);
+            Property prop2 = expectedProps.get(name2);
+            assertNextRequestReadProperty(location, prop1);
+            assertNextRequestReadProperty(location, prop2);
+            assertThat(propertiesByLocation.get(location).get(name1), is(prop1));
+            assertThat(propertiesByLocation.get(location).get(name2), is(prop2));
+        }
+        assertNoMoreRequests();
+    }
+
+    // ----------------------------------------------------------------------------------------------------------------
     // Implementation of RepositoryConnection and RequestProcessor for tests
     // ----------------------------------------------------------------------------------------------------------------
 
@@ -1148,7 +1207,7 @@
             if (request.into().hasPath()) {
                 Name childName = request.desiredName();
                 if (childName == null) childName = request.desiredSegment().getName();
-                
+
                 Path childPath = context.getValueFactories().getPathFactory().create(request.into().getPath(), childName);
                 Location newChild = actualLocationOf(Location.create(childPath));
                 // Just update the actual location



More information about the dna-commits mailing list