Author: rhauch
Date: 2008-11-26 11:42:23 -0500 (Wed, 26 Nov 2008)
New Revision: 649
Added:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/IsNodeWithChildren.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/IsNodeWithProperty.java
Modified:
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/requests/CreateNodeRequest.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java
Log:
DNA-40 Persistant storage for information not stored in other repository sources
Improved functionality and testing, including some performance testing of creating 100s
and 1000s of nodes. (These tests are commented out due to the time required to run
them.)
Also made minor improvements to the Graph API. Specifically, added the ability to get the
UUID out of a Location, changed the CreateNodeRequest.toString() to be more readable, and
corrected the interface returned from Graph.create(...) and Graph.Batch.create(...)
methods (previously required two .and() calls).
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 2008-11-25 19:31:22 UTC
(rev 648)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java 2008-11-26 16:42:23 UTC
(rev 649)
@@ -89,6 +89,27 @@
return new Graph(sourceName, connectionFactory, context);
}
+ /**
+ * Create a graph instance that uses the supplied {@link RepositoryConnection} and
{@link ExecutionContext context}.
+ *
+ * @param connection the connection that should be used
+ * @param context the context in which all executions should be performed
+ * @return the new graph
+ * @throws IllegalArgumentException if the connection or context parameters are null
+ */
+ public static Graph create( final RepositoryConnection connection,
+ ExecutionContext context ) {
+ CheckArg.isNotNull(connection, "connection");
+ final String connectorSourceName = connection.getSourceName();
+ RepositoryConnectionFactory connectionFactory = new RepositoryConnectionFactory()
{
+ public RepositoryConnection createConnection( String sourceName ) throws
RepositorySourceException {
+ if (connectorSourceName.equals(sourceName)) return connection;
+ return null;
+ }
+ };
+ return new Graph(connectorSourceName, connectionFactory, context);
+ }
+
private final String sourceName;
private final RepositoryConnectionFactory connectionFactory;
private final ExecutionContext context;
@@ -659,6 +680,46 @@
}
/**
+ * Set a property on a node, starting with the name. The interface returned from this
method should be used to specify the
+ * value(s) and the location of the node onto which the property should be set.
+ *
+ * @param propertyName the property name
+ * @return the interface used to specify the values
+ */
+ public SetValuesTo<On<Conjunction<Graph>>> set( String propertyName
) {
+ Name name =
getContext().getValueFactories().getNameFactory().create(propertyName);
+ return set(name);
+ }
+
+ /**
+ * Set a property on a node, starting with the name. The interface returned from this
method should be used to specify the
+ * value(s) and the location of the node onto which the property should be set.
+ *
+ * @param propertyName the property name
+ * @return the interface used to specify the values
+ */
+ public SetValuesTo<On<Conjunction<Graph>>> set( final Name
propertyName ) {
+ return new SetValuesTo<On<Conjunction<Graph>>>() {
+ public On<Conjunction<Graph>> to( Object value ) {
+ return set(getContext().getPropertyFactory().create(propertyName,
value));
+ }
+
+ public On<Conjunction<Graph>> to( Object firstValue,
+ Object... otherValues ) {
+ return set(getContext().getPropertyFactory().create(propertyName,
firstValue, otherValues));
+ }
+
+ public On<Conjunction<Graph>> to( Iterable<?> values ) {
+ return set(getContext().getPropertyFactory().create(propertyName,
values));
+ }
+
+ public On<Conjunction<Graph>> to( Iterator<?> values ) {
+ return set(getContext().getPropertyFactory().create(propertyName,
values));
+ }
+ };
+ }
+
+ /**
* Remove properties from the node at the given location.
*
* @param propertyNames the names of the properties to be removed
@@ -1594,12 +1655,12 @@
* @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 ) {
+ public Create<Batch> create( String atPath ) {
assertNotExecuted();
Path at = createPath(atPath);
Path parent = at.getParent();
Name name = at.getLastSegment().getName();
- return new CreateAction<BatchConjunction>(nextRequests, requestQueue,
new Location(parent), name);
+ return new CreateAction<Batch>(this, requestQueue, new
Location(parent), name);
}
/**
@@ -1614,13 +1675,13 @@
* @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 ) {
+ public Create<Batch> create( String atPath,
+ Property property ) {
assertNotExecuted();
Path at = createPath(atPath);
Path parent = at.getParent();
Name name = at.getLastSegment().getName();
- return new CreateAction<BatchConjunction>(nextRequests, requestQueue,
new Location(parent), name).with(property);
+ return new CreateAction<Batch>(this, requestQueue, new
Location(parent), name).with(property);
}
/**
@@ -1636,15 +1697,15 @@
* @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 ) {
+ public Create<Batch> create( String atPath,
+ Property firstProperty,
+ Property... additionalProperties ) {
assertNotExecuted();
Path at = createPath(atPath);
Path parent = at.getParent();
Name name = at.getLastSegment().getName();
- return new CreateAction<BatchConjunction>(nextRequests, requestQueue,
new Location(parent), name).with(firstProperty,
-
additionalProperties);
+ return new CreateAction<Batch>(this, requestQueue, new
Location(parent), name).with(firstProperty,
+
additionalProperties);
}
/**
@@ -1658,12 +1719,12 @@
* @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 ) {
+ public Create<Batch> create( Path at ) {
assertNotExecuted();
CheckArg.isNotNull(at, "at");
Path parent = at.getParent();
Name name = at.getLastSegment().getName();
- return new CreateAction<BatchConjunction>(nextRequests, requestQueue,
new Location(parent), name);
+ return new CreateAction<Batch>(this, requestQueue, new
Location(parent), name);
}
/**
@@ -1678,14 +1739,13 @@
* @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,
- Iterable<Property> properties ) {
+ public Create<Batch> create( Path at,
+ Iterable<Property> properties ) {
assertNotExecuted();
CheckArg.isNotNull(at, "at");
Path parent = at.getParent();
Name name = at.getLastSegment().getName();
- CreateAction<BatchConjunction> action = new
CreateAction<BatchConjunction>(nextRequests, requestQueue,
-
new Location(parent), name);
+ CreateAction<Batch> action = new CreateAction<Batch>(this,
requestQueue, new Location(parent), name);
for (Property property : properties) {
action.and(property);
}
@@ -1704,13 +1764,13 @@
* @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 ) {
+ public Create<Batch> create( Path at,
+ Property property ) {
assertNotExecuted();
CheckArg.isNotNull(at, "at");
Path parent = at.getParent();
Name name = at.getLastSegment().getName();
- return new CreateAction<BatchConjunction>(nextRequests, requestQueue,
new Location(parent), name).with(property);
+ return new CreateAction<Batch>(this, requestQueue, new
Location(parent), name).with(property);
}
/**
@@ -1726,15 +1786,15 @@
* @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 ) {
+ public Create<Batch> create( Path at,
+ Property firstProperty,
+ Property... additionalProperties ) {
assertNotExecuted();
CheckArg.isNotNull(at, "at");
Path parent = at.getParent();
Name name = at.getLastSegment().getName();
- return new CreateAction<BatchConjunction>(nextRequests, requestQueue,
new Location(parent), name).with(firstProperty,
-
additionalProperties);
+ return new CreateAction<Batch>(this, requestQueue, new
Location(parent), name).with(firstProperty,
+
additionalProperties);
}
/**
@@ -1744,16 +1804,16 @@
* @param parent the location of the parent
* @return the object used to start creating a node
*/
- public CreateNodeNamed<BatchConjunction> createUnder( Location parent ) {
+ public CreateNodeNamed<Batch> createUnder( Location parent ) {
CheckArg.isNotNull(parent, "parent");
- return new CreateNodeNamedAction<BatchConjunction>(nextRequests,
requestQueue, parent);
+ return new CreateNodeNamedAction<Batch>(this, requestQueue, parent);
}
/**
* Set the properties on a node.
*
* @param properties the properties to set
- * @return the remove request object that should be used to specify the node on
which the properties are to be set.
+ * @return the interface that should be used to specify the node on which the
properties are to be set.
*/
public On<BatchConjunction> set( final Property... properties ) {
return new On<BatchConjunction>() {
@@ -1787,6 +1847,46 @@
}
/**
+ * Set a property on a node, starting with the name. The interface returned from
this method should be used to specify the
+ * value(s) and the location of the node onto which the property should be set.
+ *
+ * @param propertyName the property name
+ * @return the interface used to specify the values
+ */
+ public SetValuesTo<On<BatchConjunction>> set( String propertyName )
{
+ Name name =
getContext().getValueFactories().getNameFactory().create(propertyName);
+ return set(name);
+ }
+
+ /**
+ * Set a property on a node, starting with the name. The interface returned from
this method should be used to specify the
+ * value(s) and the location of the node onto which the property should be set.
+ *
+ * @param propertyName the property name
+ * @return the interface used to specify the values
+ */
+ public SetValuesTo<On<BatchConjunction>> set( final Name propertyName
) {
+ return new SetValuesTo<On<BatchConjunction>>() {
+ public On<BatchConjunction> to( Object value ) {
+ return set(getContext().getPropertyFactory().create(propertyName,
value));
+ }
+
+ public On<BatchConjunction> to( Object firstValue,
+ Object... otherValues ) {
+ return set(getContext().getPropertyFactory().create(propertyName,
firstValue, otherValues));
+ }
+
+ public On<BatchConjunction> to( Iterable<?> values ) {
+ return set(getContext().getPropertyFactory().create(propertyName,
values));
+ }
+
+ public On<BatchConjunction> to( Iterator<?> values ) {
+ return set(getContext().getPropertyFactory().create(propertyName,
values));
+ }
+ };
+ }
+
+ /**
* Remove properties from the node at the given location.
*
* @param propertyNames the names of the properties to be removed
@@ -2596,6 +2696,48 @@
}
/**
+ * A component used to set the values on a property.
+ *
+ * @param <Next>
+ * @author Randall Hauch
+ */
+ public interface SetValuesTo<Next> {
+ /**
+ * Set the property value to the given object.
+ *
+ * @param value the property value
+ * @return the interface for additional requests or actions
+ */
+ Next to( Object value );
+
+ /**
+ * Set the property value to the given objects.
+ *
+ * @param firstValue the first property value
+ * @param otherValues the remaining property values
+ * @return the interface for additional requests or actions
+ */
+ Next to( Object firstValue,
+ Object... otherValues );
+
+ /**
+ * Set the property value to the given object.
+ *
+ * @param values the container for the property values
+ * @return the interface for additional requests or actions
+ */
+ Next to( Iterable<?> values );
+
+ /**
+ * Set the property value to the given object.
+ *
+ * @param values the iterator over the property values
+ * @return the interface for additional requests or actions
+ */
+ Next to( Iterator<?> values );
+ }
+
+ /**
* 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
@@ -3572,6 +3714,7 @@
@Override
public Results execute() {
+ this.queue().submit(new CreateNodeRequest(parent, childName,
this.properties));
return queue().execute();
}
}
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java 2008-11-25 19:31:22
UTC (rev 648)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java 2008-11-26 16:42:23
UTC (rev 649)
@@ -333,6 +333,15 @@
return null;
}
+ public UUID getUuid() {
+ Property property = getIdProperty(DnaLexicon.UUID);
+ if (property != null && !property.isEmpty()) {
+ Object value = property.getFirstValue();
+ if (value instanceof UUID) return (UUID)value;
+ }
+ return null;
+ }
+
/**
* Compare this location to the supplied location, and determine whether the two
locations represent the same logical
* location. One location is considered the same as another location when one
location is a superset of the other. For
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-11-25
19:31:22 UTC (rev 648)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/requests/CreateNodeRequest.java 2008-11-26
16:42:23 UTC (rev 649)
@@ -308,7 +308,9 @@
*/
@Override
public String toString() {
- return "create node \"" + childName + "\" under " +
under() + " with properties " + properties();
+ String parent = under() + "/";
+ if (under.hasPath() && under.getPath().isRoot()) parent = "/";
+ return "create node \"" + parent + childName + "\" with
properties " + properties();
}
}
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-25 19:31:22
UTC (rev 648)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/GraphTest.java 2008-11-26 16:42:23
UTC (rev 649)
@@ -80,6 +80,7 @@
private UUID validUuid;
private Property validIdProperty1;
private Property validIdProperty2;
+ private Location validLocation;
private String sourceName;
private MockRepositoryConnection connection;
private LinkedList<Request> executedRequests;
@@ -107,6 +108,7 @@
Name idProperty2Name = createName("id2");
validIdProperty1 = context.getPropertyFactory().create(idProperty1Name,
"1");
validIdProperty2 = context.getPropertyFactory().create(idProperty2Name,
"2");
+ validLocation = new Location(validPath);
properties = new HashMap<Location, Collection<Property>>();
children = new HashMap<Location, List<Location>>();
@@ -339,6 +341,13 @@
}
@Test
+ public void shouldCreateNodesWithBatch() {
+ graph.batch().create(validPath,
validIdProperty1).and().remove("prop").on(validPathString).execute();
+
graph.batch().move(validPath).and(validPath).into(validPathString).and().create(validPath).execute();
+
graph.batch().createUnder(validLocation).nodeNamed("someName").and().delete(validLocation).execute();
+ }
+
+ @Test
public void shouldGetPropertiesOnNode() {
setPropertiesToReadOn(new Location(validPath), validIdProperty1,
validIdProperty2);
Collection<Property> props = graph.getProperties().on(validPath);
Added: trunk/dna-graph/src/test/java/org/jboss/dna/graph/IsNodeWithChildren.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/IsNodeWithChildren.java
(rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/IsNodeWithChildren.java 2008-11-26
16:42:23 UTC (rev 649)
@@ -0,0 +1,82 @@
+/*
+ * 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.List;
+import org.hamcrest.Description;
+import org.hamcrest.Factory;
+import org.hamcrest.Matcher;
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.properties.basic.BasicPathSegment;
+import org.junit.matchers.IsCollectionContaining;
+import org.junit.matchers.TypeSafeMatcher;
+
+/**
+ * @author Randall Hauch
+ */
+public class IsNodeWithChildren extends TypeSafeMatcher<Node> {
+ private final Matcher<Iterable<Path.Segment>> childMatcher;
+
+ public IsNodeWithChildren( Matcher<Iterable<Path.Segment>> childMatcher )
{
+ this.childMatcher = childMatcher;
+ }
+
+ @Override
+ public boolean matchesSafely( Node node ) {
+ List<Location> children = node.getChildren();
+ List<Path.Segment> childSegments = new
ArrayList<Path.Segment>(children.size());
+ for (Location child : children) {
+ childSegments.add(child.getPath().getLastSegment());
+ }
+ return childMatcher.matches(childSegments);
+ }
+
+ public void describeTo( Description description ) {
+ description.appendText("a node containing
children").appendDescriptionOf(childMatcher);
+ }
+
+ @Factory
+ public static IsNodeWithChildren hasChild( Name name,
+ int sameNameSiblingIndex ) {
+ Path.Segment segment = new BasicPathSegment(name, sameNameSiblingIndex);
+ return new IsNodeWithChildren(IsCollectionContaining.hasItem(segment));
+ }
+
+ @Factory
+ public static IsNodeWithChildren hasChild( Path.Segment child ) {
+ return new IsNodeWithChildren(IsCollectionContaining.hasItem(child));
+ }
+
+ @Factory
+ public static IsNodeWithChildren hasChildren( Path.Segment... childSegments ) {
+ return new IsNodeWithChildren(IsCollectionContaining.hasItems(childSegments));
+ }
+
+ @Factory
+ public static IsNodeWithChildren hasNoChildren() {
+ Path.Segment[] childSegments = new Path.Segment[] {};
+ return new IsNodeWithChildren(IsCollectionContaining.hasItems(childSegments));
+ }
+
+}
Property changes on:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/IsNodeWithChildren.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/dna-graph/src/test/java/org/jboss/dna/graph/IsNodeWithProperty.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/IsNodeWithProperty.java
(rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/IsNodeWithProperty.java 2008-11-26
16:42:23 UTC (rev 649)
@@ -0,0 +1,75 @@
+/*
+ * 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 org.hamcrest.Description;
+import org.hamcrest.Factory;
+import org.hamcrest.Matcher;
+import org.jboss.dna.graph.Node;
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.properties.Property;
+import org.junit.matchers.IsCollectionContaining;
+import org.junit.matchers.TypeSafeMatcher;
+
+/**
+ * @author Randall Hauch
+ */
+public class IsNodeWithProperty extends TypeSafeMatcher<Node> {
+ private final String propertyNameStr;
+ private final Name propertyName;
+ private final Matcher<Iterable<Object>> valueMatcher;
+
+ public IsNodeWithProperty( String propertyNameStr,
+ Name propertyName,
+ Matcher<Iterable<Object>> valueMatcher ) {
+ this.propertyNameStr = propertyNameStr;
+ this.propertyName = propertyName;
+ this.valueMatcher = valueMatcher;
+ }
+
+ @Override
+ public boolean matchesSafely( Node node ) {
+ Property prop = propertyNameStr != null ? node.getProperty(propertyNameStr) :
node.getProperty(propertyName);
+ if (prop != null) {
+ return valueMatcher.matches(prop);
+ }
+ return false;
+ }
+
+ public void describeTo( Description description ) {
+ Object name = propertyNameStr != null ? propertyNameStr : propertyName;
+ description.appendText("a property \"" + name +
"\"containing ").appendDescriptionOf(valueMatcher);
+ }
+
+ @Factory
+ public static IsNodeWithProperty hasProperty( Name name,
+ Object... values ) {
+ return new IsNodeWithProperty(null, name,
IsCollectionContaining.hasItems(values));
+ }
+
+ @Factory
+ public static IsNodeWithProperty hasProperty( String name,
+ Object... values ) {
+ return new IsNodeWithProperty(name, null,
IsCollectionContaining.hasItems(values));
+ }
+
+}
Property changes on:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/IsNodeWithProperty.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain