[dna-commits] DNA SVN: r621 - in trunk/dna-graph/src: main/java/org/jboss/dna/graph/requests/processor and 1 other directories.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Wed Nov 12 17:12:46 EST 2008


Author: rhauch
Date: 2008-11-12 17:12:46 -0500 (Wed, 12 Nov 2008)
New Revision: 621

Added:
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNextBlockOfChildrenRequest.java
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/processor/LoggingRequestProcessor.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/processor/RequestProcessor.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java
Log:
Added a new Request that retrieves a block of children starting immediately after a child that was found from a previous request.

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-11-12 04:35:25 UTC (rev 620)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadBlockOfChildrenRequest.java	2008-11-12 22:12:46 UTC (rev 621)
@@ -32,19 +32,22 @@
 import org.jboss.dna.graph.properties.Property;
 
 /**
- * Instruction to read a block of the children of a node, where the block is dictated by the {@link #startingAt() starting index}
- * and the {@link #count() maximum number of children} to include in the block. This command is useful when paging through a large
- * number of children.
+ * Instruction to read a block of the children of a node, where the block is dictated by the {@link #startingAtIndex() starting
+ * index} and the {@link #count() maximum number of children} to include in the block. This command is useful when paging through
+ * a large number of children.
  * 
+ * @see ReadNextBlockOfChildrenRequest
  * @author Randall Hauch
  */
 public class ReadBlockOfChildrenRequest extends CacheableRequest {
 
+    public static final int INDEX_NOT_USED = -1;
+
     private static final long serialVersionUID = 1L;
 
     private final Location of;
     private final List<Location> children = new LinkedList<Location>();
-    private final int startingAt;
+    private final int startingAtIndex;
     private final int count;
     private Location actualLocation;
 
@@ -67,7 +70,7 @@
         CheckArg.isNonNegative(startingIndex, "startingIndex");
         CheckArg.isPositive(count, "count");
         this.of = of;
-        this.startingAt = startingIndex;
+        this.startingAtIndex = startingIndex;
         this.count = count;
     }
 
@@ -94,7 +97,7 @@
      * Get the maximum number of children that may be returned in the block.
      * 
      * @return the block's maximum count
-     * @see #startingAt()
+     * @see #startingAtIndex()
      * @see #endingBefore()
      */
     public int count() {
@@ -109,8 +112,8 @@
      * @see #endingBefore()
      * @see #count()
      */
-    public int startingAt() {
-        return this.startingAt;
+    public int startingAtIndex() {
+        return this.startingAtIndex;
     }
 
     /**
@@ -118,12 +121,12 @@
      * in the list, not the {@link Path.Segment#getIndex() same-name-sibiling index}.
      * 
      * @return the index just past the last child included in the block; always positive and always greater than
-     *         {@link #startingAt()}.
-     * @see #startingAt()
+     *         {@link #startingAtIndex()}.
+     * @see #startingAtIndex()
      * @see #count()
      */
     public int endingBefore() {
-        return this.startingAt + this.count;
+        return this.startingAtIndex + this.count;
     }
 
     /**
@@ -222,7 +225,7 @@
         if (this.getClass().isInstance(obj)) {
             ReadBlockOfChildrenRequest that = (ReadBlockOfChildrenRequest)obj;
             if (!this.of().equals(that.of())) return false;
-            if (this.startingAt() != that.startingAt()) return false;
+            if (this.startingAtIndex() != that.startingAtIndex()) return false;
             if (this.count() != that.count()) return false;
             return true;
         }
@@ -238,10 +241,10 @@
     public String toString() {
         Inflector inflector = Inflector.getInstance();
         if (count() == 1) {
-            return "read " + inflector.ordinalize(startingAt()) + " thru " + inflector.ordinalize(endingBefore() - 1)
+            return "read " + inflector.ordinalize(startingAtIndex()) + " thru " + inflector.ordinalize(endingBefore() - 1)
                    + " children of " + of();
         }
-        return "read " + inflector.ordinalize(startingAt()) + " child of " + of();
+        return "read " + inflector.ordinalize(startingAtIndex()) + " child of " + of();
     }
 
 }

Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNextBlockOfChildrenRequest.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNextBlockOfChildrenRequest.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNextBlockOfChildrenRequest.java	2008-11-12 22:12:46 UTC (rev 621)
@@ -0,0 +1,233 @@
+/*
+ * 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.LinkedList;
+import java.util.List;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+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;
+
+/**
+ * Instruction to read a block of the children of a node, where the block is dictated by the {@link #startingAfter location of the
+ * child preceding the block} and the {@link #count() maximum number of children} to include in the block. This command is useful
+ * when paging through a large number of children.
+ * 
+ * @see ReadBlockOfChildrenRequest
+ * @author Randall Hauch
+ */
+public class ReadNextBlockOfChildrenRequest extends CacheableRequest {
+
+    public static final int INDEX_NOT_USED = -1;
+
+    private static final long serialVersionUID = 1L;
+
+    private final Location of;
+    private final List<Location> children = new LinkedList<Location>();
+    private final Location startingAfter;
+    private final int count;
+    private Location actualLocation;
+
+    /**
+     * Create a request to read a block of the children of a node at the supplied location. The block is defined by the starting
+     * index of the first child and the number of children to include. Note that this index is <i>not</i> the
+     * {@link Path.Segment#getIndex() same-name-sibiling index}, but rather is the index of the child as if the children were in
+     * an array.
+     * 
+     * @param of the location of the node whose children are to be read
+     * @param startingAfter the child that was the last child of the previous block of children read
+     * @param count the maximum number of children that should be included in the block
+     * @throws IllegalArgumentException if the location is null, if <code>startingAfter</code> is null, or if
+     *         <code>count</count> is less than 1.
+     */
+    public ReadNextBlockOfChildrenRequest( Location of,
+                                           Location startingAfter,
+                                           int count ) {
+        CheckArg.isNotNull(of, "of");
+        CheckArg.isNotNull(startingAfter, "startingAfter");
+        CheckArg.isPositive(count, "count");
+        this.of = of;
+        this.startingAfter = startingAfter;
+        this.count = count;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.requests.Request#isReadOnly()
+     */
+    @Override
+    public boolean isReadOnly() {
+        return true;
+    }
+
+    /**
+     * Get the location defining the node whose children are to be read.
+     * 
+     * @return the location of the parent node; never null
+     */
+    public Location of() {
+        return of;
+    }
+
+    /**
+     * Get the maximum number of children that may be returned in the block.
+     * 
+     * @return the block's maximum count
+     * @see #startingAfter()
+     */
+    public int count() {
+        return this.count;
+    }
+
+    /**
+     * Get the location of the child after which the block begins. This form may be easier to use when paging through blocks, as
+     * the last children retrieved with the previous block can be supplied with the next read request.
+     * 
+     * @return the location of the child that is immediately before the start of the block; index at which this block starts;
+     *         never negative
+     * @see #count()
+     */
+    public Location startingAfter() {
+        return this.startingAfter;
+    }
+
+    /**
+     * Get the children that were read from the {@link RepositoryConnection} after the request was processed. Each child is
+     * represented by a location.
+     * 
+     * @return the children that were read; never null
+     */
+    public List<Location> getChildren() {
+        return children;
+    }
+
+    /**
+     * Add to the list of children that has been read the child with the given path and identification properties. The children
+     * should be added in order.
+     * 
+     * @param child the location of the child that was read
+     * @throws IllegalArgumentException if the location is null
+     * @see #addChild(Path, Property)
+     * @see #addChild(Path, Property, Property...)
+     */
+    public void addChild( Location child ) {
+        CheckArg.isNotNull(child, "child");
+        this.children.add(child);
+    }
+
+    /**
+     * Add to the list of children that has been read the child with the given path and identification properties. The children
+     * should be added in order.
+     * 
+     * @param pathToChild the path of the child that was just read
+     * @param firstIdProperty the first identification property of the child that was just read
+     * @param remainingIdProperties the remaining identification properties of the child that was just read
+     * @throws IllegalArgumentException if the path or identification properties are null
+     * @see #addChild(Location)
+     * @see #addChild(Path, Property)
+     */
+    public void addChild( Path pathToChild,
+                          Property firstIdProperty,
+                          Property... remainingIdProperties ) {
+        Location child = new Location(pathToChild, firstIdProperty, remainingIdProperties);
+        this.children.add(child);
+    }
+
+    /**
+     * Add to the list of children that has been read the child with the given path and identification property. The children
+     * should be added in order.
+     * 
+     * @param pathToChild the path of the child that was just read
+     * @param idProperty the identification property of the child that was just read
+     * @throws IllegalArgumentException if the path or identification properties are null
+     * @see #addChild(Location)
+     * @see #addChild(Path, Property, Property...)
+     */
+    public void addChild( Path pathToChild,
+                          Property idProperty ) {
+        Location child = new Location(pathToChild, idProperty);
+        this.children.add(child);
+    }
+
+    /**
+     * Sets the actual and complete location of the node whose children have been read. This method must be called when processing
+     * the request, and the actual location must have a {@link Location#getPath() path}.
+     * 
+     * @param actual the actual location of the node being read, or null if the {@link #of() current location} should be used
+     * @throws IllegalArgumentException if the actual location does not represent the {@link Location#isSame(Location) same
+     *         location} as the {@link #of() current location}, or if the actual location does not have a path.
+     */
+    public void setActualLocationOfNode( Location actual ) {
+        if (!of.isSame(actual)) { // not same if actual is null
+            throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, of));
+        }
+        assert actual != null;
+        if (!actual.hasPath()) {
+            throw new IllegalArgumentException(GraphI18n.actualLocationMustHavePath.text(actual));
+        }
+        this.actualLocation = actual;
+    }
+
+    /**
+     * Get the actual location of the node whose children were read.
+     * 
+     * @return the actual location, or null if the actual location was not set
+     */
+    public Location getActualLocationOfNode() {
+        return actualLocation;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (this.getClass().isInstance(obj)) {
+            ReadNextBlockOfChildrenRequest that = (ReadNextBlockOfChildrenRequest)obj;
+            if (!this.of().equals(that.of())) return false;
+            if (!this.startingAfter().equals(that.startingAfter())) return false;
+            if (this.count() != that.count()) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        if (count() == 1) {
+            return "read one child of " + of() + " starting after " + startingAfter();
+        }
+        return "read " + count() + " children of " + of();
+    }
+
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/ReadNextBlockOfChildrenRequest.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/processor/LoggingRequestProcessor.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/processor/LoggingRequestProcessor.java	2008-11-12 04:35:25 UTC (rev 620)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/processor/LoggingRequestProcessor.java	2008-11-12 22:12:46 UTC (rev 621)
@@ -33,6 +33,7 @@
 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.ReadNextBlockOfChildrenRequest;
 import org.jboss.dna.graph.requests.ReadNodeRequest;
 import org.jboss.dna.graph.requests.ReadPropertyRequest;
 import org.jboss.dna.graph.requests.RemovePropertiesRequest;
@@ -177,6 +178,18 @@
     /**
      * {@inheritDoc}
      * 
+     * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadNextBlockOfChildrenRequest)
+     */
+    @Override
+    public void process( ReadNextBlockOfChildrenRequest request ) {
+        logger.log(level, GraphI18n.executingRequest, request);
+        delegate.process(request);
+        logger.log(level, GraphI18n.executedRequest, request);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
      * @see org.jboss.dna.graph.requests.processor.RequestProcessor#process(org.jboss.dna.graph.requests.ReadBranchRequest)
      */
     @Override

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/processor/RequestProcessor.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/processor/RequestProcessor.java	2008-11-12 04:35:25 UTC (rev 620)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/processor/RequestProcessor.java	2008-11-12 22:12:46 UTC (rev 621)
@@ -46,6 +46,7 @@
 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.ReadNextBlockOfChildrenRequest;
 import org.jboss.dna.graph.requests.ReadNodeRequest;
 import org.jboss.dna.graph.requests.ReadPropertyRequest;
 import org.jboss.dna.graph.requests.RemovePropertiesRequest;
@@ -133,6 +134,8 @@
             process((MoveBranchRequest)request);
         } else if (request instanceof ReadAllChildrenRequest) {
             process((ReadAllChildrenRequest)request);
+        } else if (request instanceof ReadNextBlockOfChildrenRequest) {
+            process((ReadNextBlockOfChildrenRequest)request);
         } else if (request instanceof ReadBlockOfChildrenRequest) {
             process((ReadBlockOfChildrenRequest)request);
         } else if (request instanceof ReadBranchRequest) {
@@ -235,7 +238,7 @@
 
     /**
      * Process a request to read a block of the children of a node. The block is defined by a
-     * {@link ReadBlockOfChildrenRequest#startingAt() starting index} and a {@link ReadBlockOfChildrenRequest#count() maximum
+     * {@link ReadBlockOfChildrenRequest#startingAtIndex() starting index} and a {@link ReadBlockOfChildrenRequest#count() maximum
      * number of children to include in the block}.
      * <p>
      * This method does nothing if the request is null. The default implementation converts the command to a
@@ -257,11 +260,11 @@
         List<Location> allChildren = readAll.getChildren();
 
         // If there aren't enough children for the block's range ...
-        if (allChildren.size() < request.startingAt()) return;
+        if (allChildren.size() < request.startingAtIndex()) return;
 
         // Now, find the children in the block ...
         int endIndex = Math.min(request.endingBefore(), allChildren.size());
-        for (int i = request.startingAt(); i != endIndex; ++i) {
+        for (int i = request.startingAtIndex(); i != endIndex; ++i) {
             request.addChild(allChildren.get(i));
         }
         // Set the actual location ...
@@ -269,6 +272,46 @@
     }
 
     /**
+     * Process a request to read the next block of the children of a node, starting after a previously-retrieved child.
+     * <p>
+     * This method does nothing if the request is null. The default implementation converts the command to a
+     * {@link ReadAllChildrenRequest}, and then finds the children within the block. Obviously for large numbers of children, this
+     * implementation may not be efficient and may need to be overridden.
+     * </p>
+     * 
+     * @param request the read request
+     */
+    public void process( ReadNextBlockOfChildrenRequest request ) {
+        if (request == null) return;
+        // Convert the request to a ReadAllChildrenRequest and execute it ...
+        ReadAllChildrenRequest readAll = new ReadAllChildrenRequest(request.of());
+        process(readAll);
+        if (readAll.hasError()) {
+            request.setError(readAll.getError());
+            return;
+        }
+        List<Location> allChildren = readAll.getChildren();
+
+        // Iterate through the children, looking for the 'startingAfter' child ...
+        boolean found = false;
+        int count = 0;
+        for (Location child : allChildren) {
+            if (count > request.count()) break;
+            if (!found) {
+                // Set to true if we find the child we're looking for ...
+                found = child.equals(request.startingAfter());
+            } else {
+                // Add the child to the block ...
+                ++count;
+                request.addChild(child);
+            }
+        }
+
+        // Set the actual location ...
+        request.setActualLocationOfNode(readAll.getActualLocationOfNode());
+    }
+
+    /**
      * Process a request to read a branch or subgraph that's below a node at a specified location.
      * <p>
      * This method does nothing if the request is null. The default implementation processes the branch by submitting the

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	2008-11-12 04:35:25 UTC (rev 620)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java	2008-11-12 22:12:46 UTC (rev 621)
@@ -204,7 +204,7 @@
         assertThat(request, is(instanceOf(ReadBlockOfChildrenRequest.class)));
         ReadBlockOfChildrenRequest read = (ReadBlockOfChildrenRequest)request;
         assertThat(read.of(), is(at));
-        assertThat(read.startingAt(), is(startIndex));
+        assertThat(read.startingAtIndex(), is(startIndex));
         assertThat(read.endingBefore(), is(startIndex + maxCount));
         assertThat(read.count(), is(maxCount));
         assertThat(read.getChildren(), hasItems(children));




More information about the dna-commits mailing list