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));