Author: rhauch
Date: 2009-07-09 12:26:04 -0400 (Thu, 09 Jul 2009)
New Revision: 1082
Added:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/session/GraphSessionTest.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/CorrespondenceId.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest2.java
Removed:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/session/GraphCacheTest.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/PropertyId.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChangedChildren.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChangedNodeInfo.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChildNode.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/Children.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/EmptyChildren.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ImmutableChildren.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ImmutableNodeInfo.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/InternalChildren.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/NewNodeInfo.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/NodeInfo.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/PropertyInfo.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/AbstractChildrenTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/ChangedChildrenTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/ChangedNodeInfoTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/ImmutableChildrenTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/IsNodeInfoWithChildrenHavingNames.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/IsNodeInfoWithChildrenHavingUuids.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/NewNodeInfoTest.java
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphI18n.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/Results.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Path.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractPath.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/RootPath.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/session/GraphSession.java
trunk/dna-graph/src/main/resources/org/jboss/dna/graph/GraphI18n.properties
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrChildNodeIterator.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNode.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRootNode.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSingleValueProperty.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrChildNodeIteratorTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrMultiValuePropertyTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRootNodeTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSingleValuePropertyTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/Vehicles.java
trunk/dna-jcr/src/test/resources/cars.xml
Log:
DNA-466 Completed major rewrite of how the JCR implementation manages session state. The
previous implementation did everything by UUIDs, but this was a major problem when the JCR
implementation used connectors that don't support UUIDs. There are a few outstanding
unit tests that still don't complete successfully, but most of those are related to
the XML import (which has not yet been fixed to use the new approach). However, most of
the JCR unit tests (including most of the JCR API/TCK unit tests) do pass.
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-07-09 16:23:09 UTC
(rev 1081)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Graph.java 2009-07-09 16:26:04 UTC
(rev 1082)
@@ -2611,9 +2611,11 @@
Locations from,
Location into,
Name copyName ) {
- String workspaceName = fromWorkspaceName != null ? fromWorkspaceName
: getCurrentWorkspaceName();
+
+ String intoWorkspaceName = getCurrentWorkspaceName();
+ if ( fromWorkspaceName == null ) fromWorkspaceName =
intoWorkspaceName;
do {
- requestQueue.copyBranch(from.getLocation(), workspaceName, into,
workspaceName, copyName, null);
+ requestQueue.copyBranch(from.getLocation(), fromWorkspaceName,
into, intoWorkspaceName, copyName, null);
} while ((from = from.next()) != null);
return and();
}
@@ -5440,8 +5442,11 @@
@Immutable
class BatchResults implements Results {
private final Map<Path, BatchResultsNode> nodes = new HashMap<Path,
BatchResultsNode>();
+ private final List<Request> requests;
/*package*/BatchResults( List<Request> requests ) {
+ this.requests = Collections.unmodifiableList(requests);
+ // Now create the results ...
for (Request request : requests) {
if (request instanceof ReadAllPropertiesRequest) {
ReadAllPropertiesRequest read = (ReadAllPropertiesRequest)request;
@@ -5479,6 +5484,8 @@
}
/*package*/BatchResults( Request request ) {
+ this.requests = Collections.singletonList(request);
+ // Now create the results ...
if (request instanceof ReadAllPropertiesRequest) {
ReadAllPropertiesRequest read = (ReadAllPropertiesRequest)request;
DateTime expires = computeExpirationTime(read);
@@ -5513,9 +5520,19 @@
}
}
- /*package*/BatchResults() {
+ BatchResults() {
+ this.requests = Collections.emptyList();
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.Results#getRequests()
+ */
+ public List<Request> getRequests() {
+ return requests;
+ }
+
private BatchResultsNode getOrCreateNode( Location location,
DateTime expirationTime ) {
BatchResultsNode node = nodes.get(location);
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphI18n.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphI18n.java 2009-07-09 16:23:09
UTC (rev 1081)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/GraphI18n.java 2009-07-09 16:26:04
UTC (rev 1082)
@@ -124,7 +124,10 @@
/* Session */
public static I18n
unableToRefreshBranchBecauseChangesDependOnChangesToNodesOutsideOfBranch;
public static I18n
unableToSaveBranchBecauseChangesDependOnChangesToNodesOutsideOfBranch;
+ public static I18n unableToSaveNodeThatWasCreatedSincePreviousSave;
public static I18n nodeHasAlreadyBeenRemovedFromThisSession;
+ public static I18n unableToMoveNodeToBeChildOfDecendent;
+ public static I18n childNotFound;
static {
try {
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 2009-07-09 16:23:09
UTC (rev 1081)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java 2009-07-09 16:26:04
UTC (rev 1082)
@@ -247,7 +247,7 @@
*/
public static Location create( List<Property> idProperties ) {
CheckArg.isNotEmpty(idProperties, "idProperties");
- return new LocationWithPathAndProperties(null, idProperties);
+ return new LocationWithProperties(idProperties);
}
/**
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Results.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/Results.java 2009-07-09 16:23:09 UTC
(rev 1081)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Results.java 2009-07-09 16:26:04 UTC
(rev 1082)
@@ -23,8 +23,10 @@
*/
package org.jboss.dna.graph;
+import java.util.List;
import net.jcip.annotations.Immutable;
import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.request.Request;
/**
* A set of nodes returned from a {@link Graph graph}, with methods to access the
properties and children of the nodes in the
@@ -90,4 +92,11 @@
*/
boolean includes( Location location );
+ /**
+ * Get the requests that were executed as part of these results.
+ *
+ * @return the requests; never null, but possibly empty if there were no results when
execute was called
+ */
+ List<Request> getRequests();
+
}
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Path.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Path.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Path.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -287,8 +287,8 @@
public boolean isAbsolute();
/**
- * Return whether this path is normalized and contains no "." segments and
as few ".." segments as possible. For example, the
- * path "../a" is normalized, while "/a/b/c/../d" is not
normalized.
+ * Return whether this path is normalized and contains no unnecessary "."
segments and as few ".." segments as possible. For
+ * example, the path "../a" is normalized, while "/a/b/c/../d" is
not normalized.
*
* @return true if this path is normalized, or false otherwise
*/
@@ -312,6 +312,14 @@
public Path getCanonicalPath();
/**
+ * Obtain a path that is relative to the root node. This is equivalent to calling
{@link #relativeTo(Path)} with the root
+ * path.
+ *
+ * @return the relative path from the root node; never null
+ */
+ public Path relativeToRoot();
+
+ /**
* Get a relative path from the supplied path to this path.
*
* @param startingPath the path specifying the starting point for the new relative
path; may not be null
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractPath.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractPath.java 2009-07-09
16:23:09 UTC (rev 1081)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractPath.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -432,13 +432,26 @@
/**
* {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.property.Path#relativeToRoot()
*/
+ public Path relativeToRoot() {
+ return new BasicPath(getSegmentsList(), false);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public Path relativeTo( Path startingPath ) {
CheckArg.isNotNull(startingPath, "to");
if (!this.isAbsolute()) {
String msg = GraphI18n.pathIsNotAbsolute.text(this);
throw new InvalidPathException(msg);
}
+ if (startingPath.isRoot()) {
+ // We just want a relative path containing the same segments ...
+ return relativeToRoot();
+ }
if (!startingPath.isAbsolute()) {
String msg = GraphI18n.pathIsNotAbsolute.text(startingPath);
throw new InvalidPathException(msg);
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/RootPath.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/RootPath.java 2009-07-09
16:23:09 UTC (rev 1081)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/RootPath.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -124,6 +124,16 @@
/**
* {@inheritDoc}
*
+ * @see org.jboss.dna.graph.property.basic.AbstractPath#relativeToRoot()
+ */
+ @Override
+ public Path relativeToRoot() {
+ return BasicPath.SELF_PATH;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see
org.jboss.dna.graph.property.basic.AbstractPath#resolve(org.jboss.dna.graph.property.Path)
*/
@Override
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/session/GraphSession.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/session/GraphSession.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/session/GraphSession.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -34,14 +34,12 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.UUID;
import net.jcip.annotations.Immutable;
import net.jcip.annotations.NotThreadSafe;
import net.jcip.annotations.ThreadSafe;
import org.jboss.dna.common.collection.ReadOnlyIterator;
import org.jboss.dna.common.i18n.I18n;
import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.common.util.HashCode;
import org.jboss.dna.common.util.StringUtil;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
@@ -58,9 +56,10 @@
import org.jboss.dna.graph.property.PathFactory;
import org.jboss.dna.graph.property.PathNotFoundException;
import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.Path.Segment;
import org.jboss.dna.graph.request.BatchRequestBuilder;
import org.jboss.dna.graph.request.ChangeRequest;
-import org.jboss.dna.graph.request.CreateNodeRequest;
+import org.jboss.dna.graph.request.CopyBranchRequest;
import org.jboss.dna.graph.request.InvalidWorkspaceException;
import org.jboss.dna.graph.request.Request;
import org.jboss.dna.graph.session.GraphSession.Authorizer.Action;
@@ -148,7 +147,7 @@
} else {
this.workspaceName = this.store.getCurrentWorkspaceName();
}
- this.nodeOperations = nodeOperations != null ? nodeOperations : new
SimpleNodeOperations<Payload, PropertyPayload>();
+ this.nodeOperations = nodeOperations != null ? nodeOperations : new
NodeOperations<Payload, PropertyPayload>();
this.pathFactory = context.getValueFactories().getPathFactory();
this.authorizer = authorizer != null ? authorizer : new NoOpAuthorizer();
// Create the NodeId factory ...
@@ -171,6 +170,22 @@
this.operations = this.store.batch(this.requestBuilder);
}
+ final String readable( Name name ) {
+ return name.getString(context.getNamespaceRegistry());
+ }
+
+ final String readable( Path.Segment segment ) {
+ return segment.getString(context.getNamespaceRegistry());
+ }
+
+ final String readable( Path path ) {
+ return path.getString(context.getNamespaceRegistry());
+ }
+
+ final String readable( Location location ) {
+ return location.getString(context.getNamespaceRegistry());
+ }
+
/**
* Get the subgraph depth that is read when a node is loaded from the persistence
store. By default, this value is 1.
*
@@ -211,6 +226,26 @@
}
/**
+ * Find in the session the node with the supplied location. If the location does not
have a path, this method must first query
+ * the actual persistent store, even if the session already has loaded the node.
Thus, this method may not be the most
+ * efficient technique to find a node.
+ *
+ * @param location the location of the node
+ * @return the cached node at the supplied location
+ * @throws PathNotFoundException if the node at the supplied location does not exist
+ * @throws AccessControlException if the user does not have permission to read the
node given by the supplied location
+ * @throws IllegalArgumentException if the location is null
+ */
+ public Node<Payload, PropertyPayload> findNodeWith( Location location ) throws
PathNotFoundException, AccessControlException {
+ if (!location.hasPath()) {
+ // Query for the actual location ...
+ location = store.getNodeAt(location).getLocation();
+ }
+ assert location.hasPath();
+ return findNodeWith(null, location.getPath());
+ }
+
+ /**
* Find in the session the node with the supplied identifier.
*
* @param id the identifier of the node
@@ -236,11 +271,13 @@
public Node<Payload, PropertyPayload> findNodeWith( NodeId id,
Path path ) throws
PathNotFoundException, AccessControlException {
if (id == null && path == null) {
- CheckArg.isNotNull(path, "path and id");
+ CheckArg.isNotNull(id, "id");
+ CheckArg.isNotNull(path, "path");
}
Node<Payload, PropertyPayload> result = nodes.get(id); // if found, the
user should have read privilege since it was
// already in the cache
- if (result == null && path != null) {
+ if (result == null || result.isStale()) {
+ assert path != null;
result = findNodeWith(path);
}
return result;
@@ -257,10 +294,29 @@
*/
public Node<Payload, PropertyPayload> findNodeWith( Path path ) throws
PathNotFoundException, AccessControlException {
if (path.isRoot()) return getRoot();
- return findNodeRelativeTo(root, path.relativeTo(root.getPath()));
+ return findNodeRelativeTo(root, path.relativeTo(root.getPath()), true);
}
/**
+ * Find the node with the supplied path. This node quickly finds the node if it
exists in the cache, or if it is not in the
+ * cache, it loads the nodes down the supplied path. However, if
<code>loadIfRequired</code> is <code>false</code>, then any
+ * node along the path that is not loaded will result in this method returning null.
+ *
+ * @param path the path to the node
+ * @param loadIfRequired true if any missing nodes should be loaded, or false if null
should be returned if any nodes along
+ * the path are not loaded
+ * @return the node information
+ * @throws PathNotFoundException if the node at the supplied path does not exist
+ * @throws AccessControlException if the user does not have permission to read the
nodes given by the supplied path
+ */
+ protected Node<Payload, PropertyPayload> findNodeWith( Path path,
+ boolean loadIfRequired )
+ throws PathNotFoundException, AccessControlException {
+ if (path.isRoot()) return getRoot();
+ return findNodeRelativeTo(root, path.relativeTo(root.getPath()),
loadIfRequired);
+ }
+
+ /**
* Find the node with the supplied path relative to another node. This node quickly
finds the node by walking the supplied
* relative path starting at the supplied node. As soon as a cached node is found to
not be fully loaded, the persistent
* information for that node and all remaining nodes along the relative path are read
from the persistent store and inserted
@@ -273,10 +329,32 @@
* @throws PathNotFoundException if the node at the supplied path does not exist
* @throws AccessControlException if the user does not have permission to read the
nodes given by the supplied path
*/
- @SuppressWarnings( "synthetic-access" )
public Node<Payload, PropertyPayload> findNodeRelativeTo( Node<Payload,
PropertyPayload> startingPoint,
Path relativePath )
throws PathNotFoundException, AccessControlException {
+ return findNodeRelativeTo(startingPoint, relativePath, true);
+ }
+
+ /**
+ * Find the node with the supplied path relative to another node. This node quickly
finds the node by walking the supplied
+ * relative path starting at the supplied node. As soon as a cached node is found to
not be fully loaded, the persistent
+ * information for that node and all remaining nodes along the relative path are read
from the persistent store and inserted
+ * into the cache.
+ *
+ * @param startingPoint the node from which the path is relative
+ * @param relativePath the relative path from the designated starting point to the
desired node; may not be null and may not
+ * be an {@link Path#isAbsolute() absolute} path
+ * @param loadIfRequired true if any missing nodes should be loaded, or false if null
should be returned if any nodes along
+ * the path are not loaded
+ * @return the node information, or null if the node was not yet loaded (and
<code>loadRequired</code> was false)
+ * @throws PathNotFoundException if the node at the supplied path does not exist
+ * @throws AccessControlException if the user does not have permission to read the
nodes given by the supplied path
+ */
+ @SuppressWarnings( "synthetic-access" )
+ protected Node<Payload, PropertyPayload> findNodeRelativeTo( Node<Payload,
PropertyPayload> startingPoint,
+ Path relativePath,
+ boolean loadIfRequired
)
+ throws PathNotFoundException, AccessControlException {
Node<Payload, PropertyPayload> node = startingPoint;
if (!relativePath.isRoot()) {
// Find the absolute path, which ensures that the relative path is
well-formed ...
@@ -301,6 +379,7 @@
// The child is the next node we need to process ...
node = node.getChild(segment);
} else {
+ if (!loadIfRequired) return null;
// The node has not yet been loaded into the cache, so read this
node
// from the store as well as all nodes along the path to the node
we're really
// interested in. We'll do this in a batch, so first create
this batch ...
@@ -351,7 +430,7 @@
node = previousNode;
}
}
- nodeOperations.update(persistentNode, previousNode);
+ nodeOperations.materialize(persistentNode, previousNode);
previousPath = path;
}
}
@@ -383,21 +462,29 @@
}
/**
- * Move this node from its current location so that is is a child of the supplied
parent, but do so immediately without
- * enqueuing the operation within the session's operations.
+ * Move this node from its current location so that is is a child of the supplied
parent, doing so immediately without
+ * enqueuing the operation within the session's operations. The current session
is modified immediately to reflect the move
+ * result.
*
- * @param nodeToMove the node that is to be moved; may not be null
- * @param newParent the new parent for this node; may not be null
- * @param newName the new name for the node, or null if the node is not to be
renamed
- * @throws RepositorySourceException if the parent node is to be loaded but a problem
is encountered while doing so
+ * @param nodeToMove the path to the node that is to be moved; may not be null
+ * @param destination the desired new path; may not be null
* @throws IllegalArgumentException if the node being moved is the root node
+ * @throws AccessControlException if the caller does not have the permission to
perform the operation
+ * @throws RepositorySourceException if any error resulting while performing the
operation
*/
- public void immediateMove( Node<Payload, PropertyPayload> nodeToMove,
- Node<Payload, PropertyPayload> newParent,
- Name newName ) {
+ public void immediateMove( Path nodeToMove,
+ Path destination ) throws AccessControlException,
RepositorySourceException {
CheckArg.isNotNull(nodeToMove, "nodeToMove");
- CheckArg.isNotNull(newParent, "newParent");
- nodeToMove.moveTo(newParent, newName, false);
+ CheckArg.isNotNull(destination, "destination");
+
+ Path newParentPath = destination.getParent();
+ Name newName = destination.getLastSegment().getName();
+
+ // Check authorization ...
+ authorizer.checkPermissions(newParentPath, Action.ADD_NODE);
+ authorizer.checkPermissions(nodeToMove.getParent(), Action.REMOVE);
+
+ store.move(nodeToMove).as(newName).into(newParentPath);
}
/**
@@ -410,11 +497,13 @@
* </p>
*
* @param source the path to the node that is to be copied; may not be null
- * @param destination the path where the copy is to be placed; may not be null index
+ * @param destination the path where the copy is to be placed; may not be null
* @throws IllegalArgumentException either path is null or invalid
+ * @throws AccessControlException if the caller does not have the permission to
perform the operation
+ * @throws RepositorySourceException if any error resulting while performing the
operation
*/
public void immediateCopy( Path source,
- Path destination ) {
+ Path destination ) throws AccessControlException,
RepositorySourceException {
immediateCopy(source, workspaceName, destination);
}
@@ -430,55 +519,73 @@
* @param source the path to the node that is to be copied; may not be null
* @param sourceWorkspace the name of the workspace where the source node is to be
found, or null if the current workspace
* should be used
- * @param destination the path where the copy is to be placed; may not be null index
+ * @param destination the path where the copy is to be placed; may not be null
* @throws IllegalArgumentException either path is null or invalid
+ * @throws PathNotFoundException if the node being copied or the parent of the
destination path do not exist
* @throws InvalidWorkspaceException if the source workspace name is invalid or does
not exist
+ * @throws AccessControlException if the caller does not have the permission to
perform the operation
+ * @throws RepositorySourceException if any error resulting while performing the
operation
*/
public void immediateCopy( Path source,
String sourceWorkspace,
- Path destination ) {
+ Path destination )
+ throws InvalidWorkspaceException, AccessControlException, PathNotFoundException,
RepositorySourceException {
CheckArg.isNotNull(source, "source");
CheckArg.isNotNull(destination, "destination");
if (sourceWorkspace == null) sourceWorkspace = workspaceName;
+ // Check authorization ...
+ authorizer.checkPermissions(destination, Action.ADD_NODE);
+ authorizer.checkPermissions(source, Action.READ);
+
// Perform the copy operation, but use the "to" form (not the
"into", which takes the parent), but
// but use a batch so that we can read the latest list of children ...
- Results results = store.batch()
- .copy(source)
- .fromWorkspace(sourceWorkspace)
- .to(destination)
- .and()
- .readChildren()
- .of(destination.getParent())
- .execute();
+ Results results =
store.batch().copy(source).fromWorkspace(sourceWorkspace).to(destination).execute();
- // Now get the children of the destination's parent ...
- Location parentLocation = results.getNode(destination).getLocation();
+ // Find the copy request to get the actual location of the copy ...
+ CopyBranchRequest request = (CopyBranchRequest)results.getRequests().get(0);
+ Location locationOfCopy = request.getActualLocationAfter();
+
// Find the parent node in the session ...
- Node<Payload, PropertyPayload> parent =
this.findNodeWith(parentLocation.getPath());
- if (parent.isLoaded()) {
+ Node<Payload, PropertyPayload> parent =
this.findNodeWith(locationOfCopy.getPath().getParent(), false);
+ if (parent != null && parent.isLoaded()) {
// Update the children to make them match the latest snapshot from the store
...
- List<Location> newChildren =
results.getNode(parentLocation).getChildren();
- parent.synchronize(newChildren);
+ parent.synchronizeWithNewlyPersistedNode(locationOfCopy);
}
}
/**
* Clone the supplied source branch and place into the destination location,
optionally removing any existing copy that
- * already exists in the destination location.
+ * already exists in the destination location, doing so immediately without enqueuing
the operation within the session's
+ * operations. The current session is modified immediately to reflect the clone
result.
*
- * @param source
- * @param sourceWorkspace
- * @param destination
+ * @param source the path to the node that is to be cloned; may not be null
+ * @param sourceWorkspace the name of the workspace where the source node is to be
found, or null if the current workspace
+ * should be used
+ * @param destination the path for the new cloned copy; may not be null index
* @param removeExisting true if the original should be removed, or false if the
original should be left
+ * @throws IllegalArgumentException either path is null or invalid
+ * @throws InvalidWorkspaceException if the source workspace name is invalid or does
not exist
* @throws UuidAlreadyExistsException if copy could not be completed because the
current workspace already includes at least
* one of the nodes at or below the <code>source</code> branch in
the source workspace
+ * @throws PathNotFoundException if the node being clone or the destination node do
not exist
+ * @throws AccessControlException if the caller does not have the permission to
perform the operation
+ * @throws RepositorySourceException if any error resulting while performing the
operation
*/
public void immediateClone( Path source,
String sourceWorkspace,
Path destination,
- boolean removeExisting ) {
+ boolean removeExisting )
+ throws InvalidWorkspaceException, AccessControlException,
UuidAlreadyExistsException, PathNotFoundException,
+ RepositorySourceException {
+ CheckArg.isNotNull(source, "source");
+ CheckArg.isNotNull(destination, "destination");
+ if (sourceWorkspace == null) sourceWorkspace = workspaceName;
+ // Check authorization ...
+ authorizer.checkPermissions(destination.getParent(), Action.ADD_NODE);
+ authorizer.checkPermissions(source, Action.READ);
+
// Perform the copy operation, but use the "to" form (not the
"into", which takes the parent), but
// but use a batch so that we can read the latest list of children ...
Graph.Batch batch = store.batch();
@@ -494,14 +601,15 @@
// Now execute these two operations ...
Results results = batch.execute();
- // Now get the children of the destination's parent ...
- Location parentLocation = results.getNode(destination).getLocation();
+ // Find the copy request to get the actual location of the copy ...
+ CopyBranchRequest request = (CopyBranchRequest)results.getRequests().get(0);
+ Location locationOfCopy = request.getActualLocationAfter();
+
// Find the parent node in the session ...
- Node<Payload, PropertyPayload> parent =
this.findNodeWith(parentLocation.getPath());
- if (parent.isLoaded()) {
+ Node<Payload, PropertyPayload> parent =
this.findNodeWith(locationOfCopy.getPath().getParent(), false);
+ if (parent != null && parent.isLoaded()) {
// Update the children to make them match the latest snapshot from the store
...
- List<Location> newChildren =
results.getNode(parentLocation).getChildren();
- parent.synchronize(newChildren);
+ parent.synchronizeWithNewlyPersistedNode(locationOfCopy);
}
}
@@ -528,9 +636,10 @@
requests.clear();
changeDependencies.clear();
// And force the root node to be 'unloaded' (in an efficient way)
...
- root.changed = false;
+ root.status = Status.UNCHANGED;
root.childrenByName = null;
root.expirationTime = Long.MAX_VALUE;
+ root.changedBelow = false;
}
}
@@ -571,7 +680,11 @@
}
// Execute the reads. No modifications have been made to the cache, so it
is not a problem
// if this throws a repository exception.
- readResults = batch.execute();
+ try {
+ readResults = batch.execute();
+ } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
+ throw new InvalidStateException(e.getLocalizedMessage(), e);
+ }
}
// Phase 2: update the cache by unloading or refreshing the nodes ...
@@ -609,19 +722,33 @@
*/
public void save() throws PathNotFoundException, ValidationException,
InvalidStateException {
if (!operations.isExecuteRequired()) return;
- assert root.isChanged(true);
+ if (!root.isChanged(true)) {
+ // Then a bunch of changes could have been made and rolled back manually, so
recompute the change state ...
+ root.recomputeChangedBelow();
+ if (!root.isChanged(true)) {
+ // If still no changes, then simply do a refresh ...
+ refresh(false);
+ return;
+ }
+ }
// Make sure that each of the changed node is valid. This process requires that
all children of
// all changed nodes are loaded, so in this process load all unloaded children in
one batch ...
root.onChangedNodes(new LoadAllChildrenVisitor() {
@Override
protected void finishParentAfterLoading( Node<Payload, PropertyPayload>
node ) {
- nodeOperations.validate(node);
+ nodeOperations.preSave(node);
}
});
// Execute the batched operations ...
- operations.execute();
+ try {
+ operations.execute();
+ } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
+ throw new InvalidStateException(e.getLocalizedMessage(), e);
+ } catch (RuntimeException e) {
+ throw new RepositorySourceException(e.getLocalizedMessage(), e);
+ }
// Create a new batch for future operations ...
// LinkedList<Request> oldRequests = this.requests;
@@ -659,6 +786,11 @@
I18n msg = GraphI18n.nodeHasAlreadyBeenRemovedFromThisSession;
throw new InvalidStateException(msg.text(readableLocation, workspaceName));
}
+ if (node.isNew()) {
+ String path = readable(node.getPath());
+ throw new
RepositorySourceException(GraphI18n.unableToSaveNodeThatWasCreatedSincePreviousSave.text(path,
+
workspaceName));
+ }
if (!node.isChanged(true)) {
// There are no changes within this branch
return;
@@ -668,7 +800,7 @@
if (!node.containsChangesWithExternalDependencies()) {
I18n msg =
GraphI18n.unableToSaveBranchBecauseChangesDependOnChangesToNodesOutsideOfBranch;
String path = node.getPath().getString(context.getNamespaceRegistry());
- throw new InvalidStateException(msg.text(path, workspaceName));
+ throw new ValidationException(msg.text(path, workspaceName));
}
// Make sure that each of the changed node is valid. This process requires that
all children of
@@ -676,7 +808,7 @@
root.onChangedNodes(new LoadAllChildrenVisitor() {
@Override
protected void finishParentAfterLoading( Node<Payload, PropertyPayload>
node ) {
- nodeOperations.validate(node);
+ nodeOperations.preSave(node);
}
});
@@ -687,22 +819,11 @@
Path path = node.getPath();
LinkedList<Request> branchRequests = new LinkedList<Request>();
LinkedList<Request> nonBranchRequests = new LinkedList<Request>();
- Set<UUID> branchUuids = new HashSet<UUID>();
for (Request request : this.requests) {
assert request instanceof ChangeRequest;
ChangeRequest change = (ChangeRequest)request;
if (change.changes(workspaceName, path)) {
branchRequests.add(request);
- // Record the UUID of the node being saved now ...
- UUID changedUuid = null;
- if (change instanceof CreateNodeRequest) {
- // We want the parent UUID ...
- changedUuid = ((CreateNodeRequest)change).under().getUuid();
- } else {
- changedUuid = change.changedLocation().getUuid();
- }
- assert changedUuid != null;
- branchUuids.add(changedUuid);
} else {
nonBranchRequests.add(request);
}
@@ -711,7 +832,13 @@
// Now execute the branch ...
Graph.Batch branchBatch = store.batch(new BatchRequestBuilder(branchRequests));
- branchBatch.execute();
+ try {
+ branchBatch.execute();
+ } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
+ throw new InvalidStateException(e.getLocalizedMessage(), e);
+ } catch (RuntimeException e) {
+ throw new RepositorySourceException(e.getLocalizedMessage(), e);
+ }
// Still have non-branch related requests that we haven't executed ...
this.requests = nonBranchRequests;
@@ -795,8 +922,8 @@
* @param persistentNode the persistent node that should be converted into a node
info; never null
* @param node the session's node representation that is to be updated; never
null
*/
- void update( org.jboss.dna.graph.Node persistentNode,
- Node<NodePayload, PropertyPayload> node );
+ void materialize( org.jboss.dna.graph.Node persistentNode,
+ Node<NodePayload, PropertyPayload> node );
/**
* Signal that the node's {@link GraphSession.Node#getLocation() location}
has been changed
@@ -804,16 +931,124 @@
* @param node the node with the new location
* @param oldLocation the old location of the node
*/
- void updateLocation( Node<NodePayload, PropertyPayload> node,
- Location oldLocation );
+ void postUpdateLocation( Node<NodePayload, PropertyPayload> node,
+ Location oldLocation );
+ void preSetProperty( Node<NodePayload, PropertyPayload> node,
+ Name propertyName,
+ PropertyInfo<PropertyPayload> newProperty ) throws
ValidationException;
+
+ void postSetProperty( Node<NodePayload, PropertyPayload> node,
+ Name propertyName,
+ PropertyInfo<PropertyPayload> oldProperty );
+
+ void preRemoveProperty( Node<NodePayload, PropertyPayload> node,
+ Name propertyName ) throws ValidationException;
+
+ void postRemoveProperty( Node<NodePayload, PropertyPayload> node,
+ Name propertyName,
+ PropertyInfo<PropertyPayload> oldProperty );
+
/**
+ * Notify that a new child with the supplied path segment is about to be created.
When this method is called, the child
+ * has not yet been added to the parent node.
+ *
+ * @param parentNode the parent node; never null
+ * @param newChild the path segment for the new child; never null
+ * @param properties the initial properties for the new child, which can be
manipulated directly; never null
+ * @throws ValidationException if the parent may not have a child with the
supplied name and the creation of the new node
+ * should be aborted
+ */
+ void preCreateChild( Node<NodePayload, PropertyPayload> parentNode,
+ Path.Segment newChild,
+ Map<Name, PropertyInfo<PropertyPayload>>
properties ) throws ValidationException;
+
+ /**
+ * Notify that a new child has been added to the supplied parent node. The child
may have an initial set of properties
+ * specified at creation time, although none of the PropertyInfo objects will
have a
+ * {@link GraphSession.PropertyInfo#getPayload() payload}.
+ *
+ * @param parentNode the parent node; never null
+ * @param newChild the child that was just added to the parent node; never null
+ * @param properties the properties of the child, which can be manipulated
directly; never null
+ * @throws ValidationException if the parent and child are not valid and the
creation of the new node should be aborted
+ */
+ void postCreateChild( Node<NodePayload, PropertyPayload> parentNode,
+ Node<NodePayload, PropertyPayload> newChild,
+ Map<Name, PropertyInfo<PropertyPayload>>
properties ) throws ValidationException;
+
+ /**
+ * Notify that an existing child will be moved from its current parent and placed
under the supplied parent. When this
+ * method is called, the child node has not yet been moved.
+ *
+ * @param nodeToBeMoved the existing node that is to be moved from its current
parent to the supplied parent; never null
+ * @param newParentNode the new parent node; never null
+ * @throws ValidationException if the child should not be moved
+ */
+ void preMove( Node<NodePayload, PropertyPayload> nodeToBeMoved,
+ Node<NodePayload, PropertyPayload> newParentNode ) throws
ValidationException;
+
+ /**
+ * Notify that an existing child has been moved from the supplied previous parent
into its new location. When this method
+ * is called, the child node has been moved and any same-name-siblings that were
after the child in the old parent have
+ * had their SNS indexes adjusted.
+ *
+ * @param movedNode the existing node that is was moved; never null
+ * @param oldParentNode the old parent node; never null
+ */
+ void postMove( Node<NodePayload, PropertyPayload> movedNode,
+ Node<NodePayload, PropertyPayload> oldParentNode );
+
+ /**
+ * Notify that an existing child will be copied with the new copy being placed
under the supplied parent. When this method
+ * is called, the copy has not yet been performed.
+ *
+ * @param original the existing node that is to be copied; never null
+ * @param newParentNode the parent node where the copy is to be placed; never
null
+ * @throws ValidationException if the copy is not valid
+ */
+ void preCopy( Node<NodePayload, PropertyPayload> original,
+ Node<NodePayload, PropertyPayload> newParentNode ) throws
ValidationException;
+
+ /**
+ * Notify that an existing child will be copied with the new copy being placed
under the supplied parent. When this method
+ * is called, the copy has been performed, but the new copy will not be loaded
nor will be capable of being loaded.
+ *
+ * @param original the original node that was copied; never null
+ * @param copy the new copy that was made; never null
+ */
+ void postCopy( Node<NodePayload, PropertyPayload> original,
+ Node<NodePayload, PropertyPayload> copy );
+
+ /**
+ * Notify that an existing child will be removed from the supplied parent. When
this method is called, the child node has
+ * not yet been removed.
+ *
+ * @param parentNode the parent node; never null
+ * @param child the child that is to be removed from the parent node; never null
+ * @throws ValidationException if the child should not be removed from the parent
node
+ */
+ void preRemoveChild( Node<NodePayload, PropertyPayload> parentNode,
+ Node<NodePayload, PropertyPayload> child ) throws
ValidationException;
+
+ /**
+ * Notify that an existing child has been removed from the supplied parent. When
this method is called, the child node has
+ * been removed and any same-name-siblings following the child have had their SNS
indexes adjusted. Additionally, the
+ * removed child no longer has a parent and is considered {@link
GraphSession.Node#isStale() stale}.
+ *
+ * @param parentNode the parent node; never null
+ * @param removedChild the child that is to be removed from the parent node;
never null
+ */
+ void postRemoveChild( Node<NodePayload, PropertyPayload> parentNode,
+ Node<NodePayload, PropertyPayload> removedChild );
+
+ /**
* Validate a node for consistency and well-formedness.
*
* @param node the node to be validated
* @throws ValidationException if there is a problem during validation
*/
- void validate( Node<NodePayload, PropertyPayload> node ) throws
ValidationException;
+ void preSave( Node<NodePayload, PropertyPayload> node ) throws
ValidationException;
}
@ThreadSafe
@@ -859,22 +1094,29 @@
}
}
+ /**
+ * A default implementation of {@link GraphSession.Operations} that provides all the
basic functionality required by a graph
+ * session. In this implementation, only the {@link
GraphSession.NodeOperations#materialize(org.jboss.dna.graph.Node, Node)
+ * materialize(...)} method does something.
+ *
+ * @param <Payload> the type of node payload object
+ * @param <PropertyPayload> the type of property payload object
+ */
@ThreadSafe
- protected static class SimpleNodeOperations<Payload, PropertyPayload>
implements Operations<Payload, PropertyPayload> {
+ public static class NodeOperations<Payload, PropertyPayload> implements
Operations<Payload, PropertyPayload> {
/**
* {@inheritDoc}
*
- * @see GraphSession.Operations#update(org.jboss.dna.graph.Node,
GraphSession.Node)
+ * @see GraphSession.Operations#materialize(org.jboss.dna.graph.Node,
GraphSession.Node)
*/
- public void update( org.jboss.dna.graph.Node persistentNode,
- Node<Payload, PropertyPayload> node ) {
+ public void materialize( org.jboss.dna.graph.Node persistentNode,
+ Node<Payload, PropertyPayload> node ) {
// Create the map of property info objects ...
Map<Name, PropertyInfo<PropertyPayload>> properties = new
HashMap<Name, PropertyInfo<PropertyPayload>>();
for (Property property : persistentNode.getProperties()) {
Name propertyName = property.getName();
- PropertyId id = new PropertyId(node.getNodeId(), propertyName);
- PropertyInfo<PropertyPayload> info = new
PropertyInfo<PropertyPayload>(id, property, property.isMultiple(),
-
PropertyStatus.UNCHANGED, null);
+ PropertyInfo<PropertyPayload> info = new
PropertyInfo<PropertyPayload>(property, property.isMultiple(),
+
Status.UNCHANGED, null);
properties.put(propertyName, info);
}
// Set only the children ...
@@ -884,21 +1126,150 @@
/**
* {@inheritDoc}
*
- * @see GraphSession.Operations#updateLocation(GraphSession.Node,
org.jboss.dna.graph.Location)
+ * @see GraphSession.Operations#postUpdateLocation(GraphSession.Node,
org.jboss.dna.graph.Location)
*/
- public void updateLocation( Node<Payload, PropertyPayload> node,
- Location oldLocation ) {
+ public void postUpdateLocation( Node<Payload, PropertyPayload> node,
+ Location oldLocation ) {
// do nothing here
}
/**
* {@inheritDoc}
*
- * @see GraphSession.Operations#validate(GraphSession.Node)
+ * @see GraphSession.Operations#preSave(GraphSession.Node)
*/
- public void validate( Node<Payload, PropertyPayload> node ) {
+ public void preSave( Node<Payload, PropertyPayload> node ) throws
ValidationException {
// do nothing here
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.session.GraphSession.Operations#preSetProperty(Node,
Name, PropertyInfo)
+ */
+ public void preSetProperty( Node<Payload, PropertyPayload> node,
+ Name propertyName,
+ PropertyInfo<PropertyPayload> newProperty )
throws ValidationException {
+ // do nothing here
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.session.GraphSession.Operations#postSetProperty(Node,
Name, PropertyInfo)
+ */
+ public void postSetProperty( Node<Payload, PropertyPayload> node,
+ Name propertyName,
+ PropertyInfo<PropertyPayload> oldProperty ) {
+ // do nothing here
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.session.GraphSession.Operations#preRemoveProperty(Node, Name)
+ */
+ public void preRemoveProperty( Node<Payload, PropertyPayload> node,
+ Name propertyName ) throws ValidationException {
+ // do nothing here
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.session.GraphSession.Operations#postRemoveProperty(Node, Name,
PropertyInfo)
+ */
+ public void postRemoveProperty( Node<Payload, PropertyPayload> node,
+ Name propertyName,
+ PropertyInfo<PropertyPayload> oldProperty )
{
+ // do nothing here
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.session.GraphSession.Operations#preCreateChild(org.jboss.dna.graph.session.GraphSession.Node,
+ * org.jboss.dna.graph.property.Path.Segment, java.util.Map)
+ */
+ public void preCreateChild( Node<Payload, PropertyPayload> parent,
+ Segment newChild,
+ Map<Name, PropertyInfo<PropertyPayload>>
properties ) throws ValidationException {
+ // do nothing here
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.session.GraphSession.Operations#postCreateChild(org.jboss.dna.graph.session.GraphSession.Node,
+ * org.jboss.dna.graph.session.GraphSession.Node, java.util.Map)
+ */
+ public void postCreateChild( Node<Payload, PropertyPayload> parent,
+ Node<Payload, PropertyPayload> childChild,
+ Map<Name, PropertyInfo<PropertyPayload>>
properties ) throws ValidationException {
+ // do nothing here
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.session.GraphSession.Operations#preCopy(org.jboss.dna.graph.session.GraphSession.Node,
+ * org.jboss.dna.graph.session.GraphSession.Node)
+ */
+ public void preCopy( Node<Payload, PropertyPayload> original,
+ Node<Payload, PropertyPayload> newParent ) throws
ValidationException {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.session.GraphSession.Operations#postCopy(org.jboss.dna.graph.session.GraphSession.Node,
+ * org.jboss.dna.graph.session.GraphSession.Node)
+ */
+ public void postCopy( Node<Payload, PropertyPayload> original,
+ Node<Payload, PropertyPayload> copy ) throws
ValidationException {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.session.GraphSession.Operations#preMove(org.jboss.dna.graph.session.GraphSession.Node,
+ * org.jboss.dna.graph.session.GraphSession.Node)
+ */
+ public void preMove( Node<Payload, PropertyPayload> nodeToBeMoved,
+ Node<Payload, PropertyPayload> newParent ) throws
ValidationException {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.session.GraphSession.Operations#postMove(org.jboss.dna.graph.session.GraphSession.Node,
+ * org.jboss.dna.graph.session.GraphSession.Node)
+ */
+ public void postMove( Node<Payload, PropertyPayload> movedNode,
+ Node<Payload, PropertyPayload> oldParent ) {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.session.GraphSession.Operations#preRemoveChild(org.jboss.dna.graph.session.GraphSession.Node,
+ * org.jboss.dna.graph.session.GraphSession.Node)
+ */
+ public void preRemoveChild( Node<Payload, PropertyPayload> parent,
+ Node<Payload, PropertyPayload> newChild )
throws ValidationException {
+ // do nothing here
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.session.GraphSession.Operations#postRemoveChild(org.jboss.dna.graph.session.GraphSession.Node,
+ * org.jboss.dna.graph.session.GraphSession.Node)
+ */
+ public void postRemoveChild( Node<Payload, PropertyPayload> parent,
+ Node<Payload, PropertyPayload> oldChild ) {
+ // do nothing here
+ }
}
@NotThreadSafe
@@ -908,16 +1279,16 @@
private Node<Payload, PropertyPayload> parent;
private long expirationTime = Long.MAX_VALUE;
private Location location;
- private boolean changed;
+ private Status status = Status.UNCHANGED;
private boolean changedBelow;
private Map<Name, PropertyInfo<PropertyPayload>> properties;
private ListMultimap<Name, Node<Payload, PropertyPayload>>
childrenByName;
private Payload payload;
- protected Node( GraphSession<Payload, PropertyPayload> cache,
- Node<Payload, PropertyPayload> parent,
- NodeId nodeId,
- Location location ) {
+ public Node( GraphSession<Payload, PropertyPayload> cache,
+ Node<Payload, PropertyPayload> parent,
+ NodeId nodeId,
+ Location location ) {
this.cache = cache;
this.parent = parent;
this.nodeId = nodeId;
@@ -929,6 +1300,15 @@
}
/**
+ * Get the session to which this node belongs.
+ *
+ * @return the session; never null
+ */
+ public GraphSession<Payload, PropertyPayload> getSession() {
+ return cache;
+ }
+
+ /**
* Get the time when this node expires.
*
* @return the time in milliseconds past the epoch when this node's cached
information expires, or {@link Long#MAX_VALUE
@@ -937,7 +1317,6 @@
* @see #isLoaded()
*/
public final long getExpirationTimeInMillis() {
- assert !isStale();
return expirationTime;
}
@@ -975,11 +1354,19 @@
/**
* Method that causes the information for this node to be read from the store and
loaded into the cache
*
+ * @throws AccessControlException if the caller does not have the permission to
perform the operation
* @throws RepositorySourceException if there is a problem reading the store
*/
protected final void load() throws RepositorySourceException {
if (isLoaded()) return;
assert !isStale();
+ // If this node is new, then there's nothing to read ...
+ if (status == Status.NEW) {
+ this.childrenByName = cache.NO_CHILDREN;
+ this.properties = cache.NO_PROPERTIES;
+ return;
+ }
+
// Check authorization before reading ...
Path path = getPath();
cache.authorizer.checkPermissions(path, Action.READ);
@@ -994,7 +1381,7 @@
this.location = actualLocation;
}
// Update the persistent information ...
- cache.nodeOperations.update(persistentNode, this);
+ cache.nodeOperations.materialize(persistentNode, this);
} else {
// Then read the node from the store ...
Subgraph subgraph =
cache.store.getSubgraphOfDepth(depth).at(getLocation());
@@ -1004,7 +1391,7 @@
this.location = actualLocation;
}
// Update the persistent information ...
- cache.nodeOperations.update(subgraph.getRoot(), this);
+ cache.nodeOperations.materialize(subgraph.getRoot(), this);
// Now update any nodes below this node ...
for (org.jboss.dna.graph.Node persistentNode : subgraph) {
// Find the node at the path ...
@@ -1012,7 +1399,7 @@
Node<Payload, PropertyPayload> node =
cache.findNodeRelativeTo(this, relativePath);
if (!node.isLoaded()) {
// Update the persistent information ...
- cache.nodeOperations.update(persistentNode, node);
+ cache.nodeOperations.materialize(persistentNode, node);
}
}
}
@@ -1023,7 +1410,7 @@
*/
protected final void unload() {
assert !isStale();
- assert !changed;
+ assert status == Status.UNCHANGED;
assert !changedBelow;
if (!isLoaded()) return;
cache.recordUnloaded(this);
@@ -1084,8 +1471,8 @@
protected final void refreshPhase2( RefreshState<Payload, PropertyPayload>
refreshState,
Results persistentInfoForRefreshedNodes ) {
assert !isStale();
- if (this.changed) {
- // There's nothing to do ...
+ if (this.status != Status.UNCHANGED) {
+ // There are changes, so nothing to do ...
return;
}
if (refreshState.requiresRefresh(this)) {
@@ -1121,15 +1508,15 @@
return;
}
// This node can be unloaded (since it has no changes and isn't above a
node with changes) ...
- unload();
+ if (!this.changedBelow) unload();
}
/**
* Define the persistent child information that this node is to be populated
with. This method does not cause the node's
* information to be read from the store.
* <p>
- * This method is intended to be called by the {@link
GraphSession.Operations#update(org.jboss.dna.graph.Node, Node)}, and
- * should not be called by other components.
+ * This method is intended to be called by the {@link
GraphSession.Operations#materialize(org.jboss.dna.graph.Node, Node)}
+ * , and should not be called by other components.
* </p>
*
* @param children the children for this node; may not be null
@@ -1177,11 +1564,14 @@
protected void updateLocation( Path.Segment segment ) {
assert !isStale();
Path newPath = null;
+ Path currentPath = getPath();
if (segment != null) {
+ if (segment.equals(currentPath.getLastSegment())) return;
// Recompute the path based upon the parent path ...
Path parentPath = getParent().getPath();
newPath = cache.pathFactory.create(parentPath, segment);
} else {
+ if (this.isRoot()) return;
// This must be the root ...
newPath = cache.pathFactory.createRootPath();
assert this.isRoot();
@@ -1190,7 +1580,7 @@
if (newLocation != this.location) {
Location oldLocation = this.location;
this.location = newLocation;
- cache.nodeOperations.updateLocation(this, oldLocation);
+ cache.nodeOperations.postUpdateLocation(this, oldLocation);
}
if (isLoaded() && childrenByName != cache.NO_CHILDREN) {
@@ -1206,19 +1596,61 @@
}
}
- protected void synchronize( List<Location> actualChildren ) {
- if (!isLoaded()) return;
- for (Location actualChild : actualChildren) {
- Path.Segment actualSegment = actualChild.getPath().getLastSegment();
- Node<Payload, PropertyPayload> existingChild =
parent.getChild(actualSegment);
- if (existingChild == null) {
- // The child doesn't exist yet ...
- NodeId nodeId = cache.idFactory.create();
- Node<Payload, PropertyPayload> newChild =
cache.createNode(this, nodeId, actualChild);
- parent.childrenByName.put(actualSegment.getName(), newChild);
+ /**
+ * This method is used to adjust the existing children by adding a child that was
recently added to the persistent store
+ * (via clone or copy). The new child will appear at the end of the existing
children, but before any children that were
+ * added to, moved into, created under this parent.
+ *
+ * @param newChild the new child that was added
+ */
+ protected void synchronizeWithNewlyPersistedNode( Location newChild ) {
+ if (!this.isLoaded()) return;
+ Path childPath = newChild.getPath();
+ Name childName = childPath.getLastSegment().getName();
+ if (this.childrenByName.isEmpty()) {
+ // Just have to add the child ...
+ this.childrenByName = Multimaps.newLinkedListMultimap();
+ if (childPath.getLastSegment().hasIndex()) {
+ // The child has a SNS index, but this is an only child ...
+ newChild =
newChild.with(cache.pathFactory.create(childPath.getParent(), childName));
}
+ Node<Payload, PropertyPayload> child = cache.createNode(this,
cache.idFactory.create(), newChild);
+ this.childrenByName.put(childName, child);
+ return;
}
+ // Unfortunately, there is no efficient way to insert into the multi-map, so
we need to recreate it ...
+ ListMultimap<Name, Node<Payload, PropertyPayload>> children =
Multimaps.newLinkedListMultimap();
+ boolean added = false;
+ for (Node<Payload, PropertyPayload> child :
this.childrenByName.values()) {
+ if (!added && child.isNew()) {
+ // Add the new child here ...
+ Node<Payload, PropertyPayload> newChildNode =
cache.createNode(this, cache.idFactory.create(), newChild);
+ children.put(childName, newChildNode);
+ added = true;
+ }
+ children.put(child.getName(), child);
+ }
+ if (!added) {
+ Node<Payload, PropertyPayload> newChildNode =
cache.createNode(this, cache.idFactory.create(), newChild);
+ children.put(childName, newChildNode);
+ }
+
+ // Replace the children ...
+ this.childrenByName = children;
+
+ // Adjust the SNS indexes for those children with the same name as
'childToBeMoved' ...
+ List<Node<Payload, PropertyPayload>> childrenWithName =
childrenByName.get(childName);
+ int snsIndex = 1;
+ for (Node<Payload, PropertyPayload> sns : childrenWithName) {
+ if (sns.getSegment().getIndex() != snsIndex) {
+ // The SNS index is not correct, so fix it and update the location
...
+ Path.Segment newSegment = cache.pathFactory.createSegment(childName,
snsIndex);
+ sns.updateLocation(newSegment);
+ sns.markAsChanged();
+ }
+ ++snsIndex;
+ }
}
/**
@@ -1228,11 +1660,21 @@
* @return true if there are changes in the specified scope, or false otherwise
*/
public final boolean isChanged( boolean recursive ) {
- assert !isStale();
- return recursive ? this.changed || this.changedBelow : this.changed;
+ if (this.status == Status.UNCHANGED) return recursive &&
this.changedBelow;
+ return true;
}
/**
+ * Determine whether this node has been created since the last save. If this
method returns true, then by definition the
+ * parent node will be marked as having {@link #isChanged(boolean) changed}.
+ *
+ * @return true if this node is new, or false otherwise
+ */
+ public final boolean isNew() {
+ return this.status == Status.NEW;
+ }
+
+ /**
* This method determines whether this node, or any nodes below it, contain
changes that depend on nodes that are outside
* of this branch.
*
@@ -1295,8 +1737,8 @@
*/
public void clearChanges() {
assert !isStale();
- if (this.changed) {
- this.changed = false;
+ if (this.status != Status.UNCHANGED) {
+ this.status = Status.UNCHANGED;
this.changedBelow = false;
unload();
} else {
@@ -1317,13 +1759,33 @@
* Mark this node as having changes.
*
* @see #clearChanges()
+ * @see #markAsNew()
*/
public final void markAsChanged() {
assert !isStale();
- this.changed = true;
+ if (this.status == Status.NEW) return;
+ this.status = Status.CHANGED;
if (this.parent != null) this.parent.markAsChangedBelow();
}
+ public final void markAsCopied() {
+ assert !isStale();
+ this.status = Status.COPIED;
+ if (this.parent != null) this.parent.markAsChangedBelow();
+ }
+
+ /**
+ * Mark this node has having been created and not yet saved.
+ *
+ * @see #clearChanges()
+ * @see #markAsChanged()
+ */
+ public final void markAsNew() {
+ assert !isStale();
+ this.status = Status.NEW;
+ if (this.parent != null) this.parent.markAsChanged();
+ }
+
protected final void markAsChangedBelow() {
if (!this.changedBelow) {
this.changedBelow = true;
@@ -1378,15 +1840,25 @@
* @param newNodeName the new name for the node, or null if the node should keep
the same name
* @param useBatch true if this operation should be performed using the
session's current batch operation and executed
* upon {@link GraphSession#save()}, or false if the move should be
performed immediately
+ * @throws ValidationException if the supplied parent node is a decendant of this
node
* @throws RepositorySourceException if the parent node is to be loaded but a
problem is encountered while doing so
* @throws IllegalArgumentException if this is the root node
+ * @throws AccessControlException if the caller does not have the permission to
perform the operation
*/
protected void moveTo( Node<Payload, PropertyPayload> parent,
Name newNodeName,
boolean useBatch ) {
final Node<Payload, PropertyPayload> child = this;
assert !parent.isStale();
- assert child.parent != this;
+ // Make sure the parent is not a decendant of the child ...
+ if (parent.isAtOrBelow(child)) {
+ String path = getPath().getString(cache.context.getNamespaceRegistry());
+ String parentPath =
parent.getPath().getString(cache.context.getNamespaceRegistry());
+ String workspaceName = cache.workspaceName;
+ String msg = GraphI18n.unableToMoveNodeToBeChildOfDecendent.text(path,
parentPath, workspaceName);
+ throw new ValidationException(msg);
+ }
+
assert !child.isRoot();
if (newNodeName == null) newNodeName = getName();
@@ -1395,13 +1867,9 @@
cache.authorizer.checkPermissions(child.getPath().getParent(),
Action.REMOVE);
parent.load();
- if (parent.childrenByName == cache.NO_CHILDREN) {
- parent.childrenByName = Multimaps.newLinkedListMultimap();
- }
- Name childName = child.getName();
- List<Node<Payload, PropertyPayload>> currentChildren =
parent.childrenByName.get(childName);
- currentChildren.add(child);
- parent.markAsChanged();
+
+ cache.nodeOperations.preMove(child, parent);
+
// Remove the child from it's existing parent ...
final Node<Payload, PropertyPayload> oldParent = child.parent;
// Record the operation ...
@@ -1418,25 +1886,46 @@
cache.store.move(child.getLocation()).as(newNodeName).into(parent.getLocation());
}
}
- cache.recordMove(child, oldParent, parent);
+ // Remove the child from the current location (even if its the same node;
there's cleanup to do) ...
child.remove();
- // Set the new parent to this node ...
+ // Now add the child ...
+ if (parent.childrenByName == cache.NO_CHILDREN) {
+ parent.childrenByName = Multimaps.newLinkedListMultimap();
+ }
+ parent.childrenByName.put(newNodeName, child);
child.parent = parent;
+ parent.markAsChanged();
// Update the new child with the correct location ...
- Path.Segment segment = cache.pathFactory.createSegment(childName,
currentChildren.size());
+ int snsIndex = parent.childrenByName.get(newNodeName).size();
+ Path.Segment segment = cache.pathFactory.createSegment(newNodeName,
snsIndex);
child.updateLocation(segment);
+ cache.recordMove(child, oldParent, parent);
+
+ cache.nodeOperations.postMove(child, oldParent);
}
/**
+ * Rename this node to have a different name.
+ *
+ * @param newNodeName
+ */
+ public void rename( Name newNodeName ) {
+ moveTo(this.parent, newNodeName, true);
+ }
+
+ /**
* Copy this node (and all nodes below it) and place the copy under the supplied
parent location. The new copy will be
* appended to any existing children of the supplied parent node, and will be
given the appropriate same-name-sibling
- * index.
+ * index. This method may not be called on the root node.
*
* @param parent the new parent for the new copy; may not be null
* @throws RepositorySourceException if the parent node is to be loaded but a
problem is encountered while doing so
- * @throws IllegalArgumentException if this is the root node
+ * @throws IllegalArgumentException if the parent is null, or if this is the root
node
+ * @throws AccessControlException if the caller does not have the permission to
perform the operation
*/
public void copyTo( Node<Payload, PropertyPayload> parent ) {
+ CheckArg.isNotNull(parent, "parent");
+ CheckArg.isEquals(this.isRoot(), "this.isRoot()", false,
"false");
final Node<Payload, PropertyPayload> child = this;
assert !parent.isStale();
assert child.parent != this;
@@ -1450,17 +1939,24 @@
if (parent.childrenByName == cache.NO_CHILDREN) {
parent.childrenByName = Multimaps.newLinkedListMultimap();
}
+
+ cache.nodeOperations.preCopy(this, parent);
+
Name childName = child.getName();
// Figure out the name and SNS of the new copy ...
List<Node<Payload, PropertyPayload>> currentChildren =
parent.childrenByName.get(childName);
- Location copyLocation =
Location.create(cache.pathFactory.create(parent.getPath(), childName,
currentChildren.size()));
+ Location copyLocation =
Location.create(cache.pathFactory.create(parent.getPath(),
+ childName,
+
currentChildren.size() + 1));
// Perform the copy ...
cache.operations.copy(child.getLocation()).to(copyLocation);
// Add the child to the parent ...
- cache.createNode(parent, cache.idFactory.create(), copyLocation);
- parent.markAsChanged();
+ Node<Payload, PropertyPayload> copy = cache.createNode(parent,
cache.idFactory.create(), copyLocation);
+ copy.markAsCopied(); // marks parent as changed
+
+ cache.nodeOperations.postCopy(this, copy);
}
/**
@@ -1477,6 +1973,68 @@
}
/**
+ * Move the specified child to be located immediately before the other supplied
node.
+ *
+ * @param childToBeMoved the path segment specifying the child that is to be
moved
+ * @param before the path segment of the node before which the {@code
childToBeMoved} should be placed, or null if the
+ * child should be moved to the end
+ * @throws PathNotFoundException if the <code>childToBeMoved</code>
or <code>before</code> segments do not specify an
+ * existing child
+ * @throws IllegalArgumentException if either segment is null or does not specify
an existing node
+ */
+ public void orderChildBefore( Path.Segment childToBeMoved,
+ Path.Segment before ) throws PathNotFoundException
{
+ CheckArg.isNotNull(childToBeMoved, "childToBeMoved");
+
+ // Check authorization ...
+ cache.authorizer.checkPermissions(getPath(), Action.REMOVE);
+ cache.authorizer.checkPermissions(getPath(), Action.ADD_NODE);
+
+ // Find the node to be moved ...
+ Node<Payload, PropertyPayload> nodeToBeMoved =
getChild(childToBeMoved);
+ Node<Payload, PropertyPayload> beforeNode = before != null ?
getChild(before) : null;
+
+ if (beforeNode == null) {
+ // Moving the node into its parent will remove it from its current spot
in the child list and re-add it to the end
+ cache.operations.move(nodeToBeMoved.getLocation()).into(this.location);
+ } else {
+ // Record the move ...
+
cache.operations.move(nodeToBeMoved.getLocation()).before(beforeNode.getLocation());
+ }
+
+ // Unfortunately, there is no efficient way to insert into the multi-map, so
we need to recreate it ...
+ ListMultimap<Name, Node<Payload, PropertyPayload>> children =
Multimaps.newLinkedListMultimap();
+ for (Node<Payload, PropertyPayload> child : childrenByName.values()) {
+ if (child == nodeToBeMoved) continue;
+ if (before != null && child.getSegment().equals(before)) {
+ children.put(nodeToBeMoved.getName(), nodeToBeMoved);
+ }
+ children.put(child.getName(), child);
+ }
+ if (before == null) {
+ children.put(nodeToBeMoved.getName(), nodeToBeMoved);
+ }
+
+ // Replace the children ...
+ this.childrenByName = children;
+ this.markAsChanged();
+
+ // Adjust the SNS indexes for those children with the same name as
'childToBeMoved' ...
+ Name movedName = nodeToBeMoved.getName();
+ List<Node<Payload, PropertyPayload>> childrenWithName =
childrenByName.get(movedName);
+ int snsIndex = 1;
+ for (Node<Payload, PropertyPayload> sns : childrenWithName) {
+ if (sns.getSegment().getIndex() != snsIndex) {
+ // The SNS index is not correct, so fix it and update the location
...
+ Path.Segment newSegment = cache.pathFactory.createSegment(movedName,
snsIndex);
+ sns.updateLocation(newSegment);
+ sns.markAsChanged();
+ }
+ ++snsIndex;
+ }
+ }
+
+ /**
* Remove this node from it's parent. Note that locations are
<i>not</i> updated, since they will be updated if this node
* is added to a different parent. However, the locations of same-name-siblings
under the parent <i>are</i> updated.
*/
@@ -1487,6 +2045,7 @@
assert this.parent.childrenByName != null;
assert this.parent.childrenByName != cache.NO_CHILDREN;
this.parent.markAsChanged();
+ this.markAsChanged();
Name name = getName();
List<Node<Payload, PropertyPayload>> childrenWithSameName =
this.parent.childrenByName.get(name);
this.parent = null;
@@ -1514,15 +2073,21 @@
/**
* Remove this node from it's parent and destroy it's contents. The
location of sibling nodes with the same name will be
* updated, and the node and all nodes below it will be destroyed and removed
from the cache.
+ *
+ * @throws AccessControlException if the caller does not have the permission to
perform the operation
*/
public void destroy() {
assert !isStale();
// Check authorization ...
cache.authorizer.checkPermissions(getPath(), Action.REMOVE);
+
+ final Node<Payload, PropertyPayload> parent = this.parent;
+ cache.nodeOperations.preRemoveChild(parent, this);
// Remove the node from its parent ...
remove();
// This node was successfully removed, so now remove it from the cache ...
cache.recordDelete(this);
+ cache.nodeOperations.postRemoveChild(parent, this);
}
public final boolean isRoot() {
@@ -1549,7 +2114,7 @@
*
* @return the parent node
*/
- public final Node<Payload, PropertyPayload> getParent() {
+ public Node<Payload, PropertyPayload> getParent() {
assert !isStale();
return parent;
}
@@ -1566,7 +2131,7 @@
*
* @return the name; never null
*/
- public final Name getName() {
+ public Name getName() {
return location.getPath().getLastSegment().getName();
}
@@ -1598,6 +2163,161 @@
}
/**
+ * Create a new child node with the supplied name. The same-name-sibling index
will be determined based upon the existing
+ * children.
+ *
+ * @param name the name of the new child node
+ * @return the new child node
+ * @throws IllegalArgumentException if the name is null
+ * @throws RepositorySourceException if this node must be loaded but doing so
results in a problem
+ */
+ public Node<Payload, PropertyPayload> createChild( Name name ) {
+ CheckArg.isNotNull(name, "name");
+ return doCreateChild(name, null, null);
+ }
+
+ /**
+ * Create a new child node with the supplied name and one initial property. The
same-name-sibling index will be determined
+ * based upon the existing children.
+ *
+ * @param name the name of the new child node
+ * @param property a property for the new node
+ * @return the new child node
+ * @throws IllegalArgumentException if the name or identification property is
null
+ * @throws RepositorySourceException if this node must be loaded but doing so
results in a problem
+ */
+ public Node<Payload, PropertyPayload> createChild( Name name,
+ Property property ) {
+ CheckArg.isNotNull(name, "name");
+ CheckArg.isNotNull(property, "property");
+ return doCreateChild(name, property, null);
+ }
+
+ /**
+ * Create a new child node with the supplied name and multiple initial
properties. The same-name-sibling index will be
+ * determined based upon the existing children.
+ *
+ * @param name the name of the new child node
+ * @param firstProperty the first identification property for the new node
+ * @param remainingProperties the remaining identification properties for the new
node
+ * @return the new child node
+ * @throws IllegalArgumentException if the name or properties are null
+ * @throws ValidationException if the new node is not valid as a child
+ * @throws RepositorySourceException if this node must be loaded but doing so
results in a problem
+ */
+ public Node<Payload, PropertyPayload> createChild( Name name,
+ Property firstProperty,
+ Property...
remainingProperties ) {
+ CheckArg.isNotNull(name, "name");
+ CheckArg.isNotNull(firstProperty, "firstProperty");
+ return doCreateChild(name, firstProperty, remainingProperties);
+ }
+
+ private Node<Payload, PropertyPayload> doCreateChild( Name name,
+ Property firstProperty,
+ Property[]
remainingProperties ) throws ValidationException {
+ assert !isStale();
+
+ // Check permission here ...
+ Path path = getPath();
+ cache.authorizer.checkPermissions(path, Action.ADD_NODE);
+
+ // Now load if required ...
+ load();
+
+ // Figure out the name and SNS of the new copy ...
+ List<Node<Payload, PropertyPayload>> currentChildren =
childrenByName.get(name);
+ Path newPath = cache.pathFactory.create(path, name, currentChildren.size() +
1);
+ Location newChild = Location.create(newPath);
+
+ // Create the properties ...
+ Map<Name, PropertyInfo<PropertyPayload>> newProperties = new
HashMap<Name, PropertyInfo<PropertyPayload>>();
+ if (firstProperty != null) {
+ PropertyInfo<PropertyPayload> info = new
PropertyInfo<PropertyPayload>(firstProperty, firstProperty.isMultiple(),
+
Status.NEW, null);
+ newProperties.put(info.getName(), info);
+ if (remainingProperties != null) {
+ for (Property property : remainingProperties) {
+ PropertyInfo<PropertyPayload> info2 = new
PropertyInfo<PropertyPayload>(property, property.isMultiple(),
+
Status.NEW, null);
+ newProperties.put(info2.getName(), info2);
+ }
+ }
+ }
+
+ // Notify before the addition ...
+ cache.nodeOperations.preCreateChild(this, newPath.getLastSegment(),
newProperties);
+
+ // Record the current state before any changes ...
+ Status statusBefore = this.status;
+ boolean changedBelowBefore = this.changedBelow;
+
+ // Add the child to the parent ...
+ Node<Payload, PropertyPayload> child = cache.createNode(this,
cache.idFactory.create(), newChild);
+ child.markAsNew(); // marks parent as changed
+ if (childrenByName == cache.NO_CHILDREN) {
+ childrenByName = Multimaps.newLinkedListMultimap();
+ }
+ childrenByName.put(name, child);
+
+ // Set the properties on the new node, but in a private backdoor way ...
+ assert child.properties == null;
+ child.properties = newProperties;
+
+ try {
+ // The node has been changed, so try notifying before we record the
creation (which can't be undone) ...
+ cache.nodeOperations.postCreateChild(this, child, child.properties);
+
+ // Notification was fine, so now do the create ...
+ Graph.Create<Graph.Batch> create =
cache.operations.create(newChild.getPath());
+ if (!child.properties.isEmpty()) {
+ // Process the property infos (in case some were added during the
pre- or post- operations ...
+ for (PropertyInfo<PropertyPayload> property :
child.properties.values()) {
+ create.with(property.getProperty());
+ }
+ }
+ create.and();
+ } catch (ValidationException e) {
+ // Clean up the children ...
+ if (childrenByName.size() == 1) {
+ childrenByName = cache.NO_CHILDREN;
+ } else {
+ childrenByName.remove(child.getName(), child);
+ }
+ this.status = statusBefore;
+ this.changedBelow = changedBelowBefore;
+ throw e;
+ }
+ return child;
+ }
+
+ /**
+ * Determine whether this node has a child with the supplied name and SNS index.
+ *
+ * @param segment the segment of the child
+ * @return true if there is a child, or false if there is no such child
+ * @throws RepositorySourceException if there is a problem loading this
node's information from the store
+ */
+ public boolean hasChild( Path.Segment segment ) {
+ return hasChild(segment.getName(), segment.getIndex());
+ }
+
+ /**
+ * Determine whether this node has a child with the supplied name and SNS index.
+ *
+ * @param name the name of the child
+ * @param sns the same-name-sibling index; must be 1 or more
+ * @return true if there is a child, or false if there is no such child
+ * @throws RepositorySourceException if there is a problem loading this
node's information from the store
+ */
+ public boolean hasChild( Name name,
+ int sns ) {
+ load();
+ List<Node<Payload, PropertyPayload>> children =
childrenByName.get(name); // never null
+ return children.size() >= sns; // SNS is 1-based, index is 0-based
+ }
+
+ /**
* Get the child with the supplied segment.
*
* @param segment the segment of the child
@@ -1727,28 +2447,34 @@
* @param isMultiValued true if the property is multi-valued
* @param payload the optional payload for this property; may be null
* @return the previous information for the property, or null if there was no
previous property
+ * @throws AccessControlException if the caller does not have the permission to
perform the operation
*/
public PropertyInfo<PropertyPayload> setProperty( Property property,
boolean isMultiValued,
PropertyPayload payload ) {
+ assert !isStale();
+ cache.authorizer.checkPermissions(getPath(), Action.SET_PROPERTY);
+
load();
- cache.authorizer.checkPermissions(getPath(), Action.SET_PROPERTY);
+ if (properties == cache.NO_PROPERTIES) {
+ properties = new HashMap<Name,
PropertyInfo<PropertyPayload>>();
+ }
+
Name name = property.getName();
PropertyInfo<PropertyPayload> previous = properties.get(name);
- PropertyId id = null;
- PropertyStatus status = null;
+ Status status = null;
if (previous != null) {
- id = previous.getPropertyId();
status = previous.getStatus(); // keep NEW or CHANGED status, but
UNCHANGED -> CHANGED
- if (status == PropertyStatus.UNCHANGED) status = PropertyStatus.CHANGED;
+ if (status == Status.UNCHANGED) status = Status.CHANGED;
} else {
- id = new PropertyId(getNodeId(), name);
- status = PropertyStatus.NEW;
+ status = Status.NEW;
}
- PropertyInfo<PropertyPayload> info = new
PropertyInfo<PropertyPayload>(id, property, isMultiValued, status, payload);
+ PropertyInfo<PropertyPayload> info = new
PropertyInfo<PropertyPayload>(property, isMultiValued, status, payload);
+ cache.nodeOperations.preSetProperty(this, property.getName(), info);
properties.put(name, info);
cache.operations.set(property).on(location);
markAsChanged();
+ cache.nodeOperations.postSetProperty(this, property.getName(), previous);
return previous;
}
@@ -1759,10 +2485,16 @@
* @return the previous information for the property, or null if there was no
previous property
*/
public PropertyInfo<PropertyPayload> removeProperty( Name name ) {
+ assert !isStale();
+ cache.authorizer.checkPermissions(getPath(), Action.REMOVE);
+
load();
+ if (!properties.containsKey(name)) return null;
+ cache.nodeOperations.preRemoveProperty(this, name);
PropertyInfo<PropertyPayload> results = properties.remove(name);
markAsChanged();
cache.operations.remove(name).on(location);
+ cache.nodeOperations.postRemoveProperty(this, name, results);
return results;
}
@@ -1809,6 +2541,7 @@
* @return payload
*/
public Payload getPayload() {
+ load();
return payload;
}
@@ -1840,6 +2573,7 @@
if (obj == this) return true;
if (obj instanceof Node) {
Node<Payload, PropertyPayload> that = (Node<Payload,
PropertyPayload>)obj;
+ if (this.isStale() || that.isStale()) return false;
if (!this.nodeId.equals(that.nodeId)) return false;
return this.location.equals(that.location);
}
@@ -1938,10 +2672,10 @@
Node<Payload, PropertyPayload> node = changedNodes.poll();
// Visit this node ...
boolean visitChildren = true;
- if (node.changed) {
+ if (node.isChanged(false)) {
visitChildren = visitor.visit(node);
}
- if (visitChildren && node.changedBelow) {
+ if (visitChildren && node.isChanged(true)) {
// Visit the children ...
int index = -1;
Iterator<Node<Payload, PropertyPayload>> iter =
node.getChildren().iterator();
@@ -1977,29 +2711,26 @@
}
}
- public static enum PropertyStatus {
+ public static enum Status {
NEW,
CHANGED,
- UNCHANGED;
+ UNCHANGED,
+ COPIED;
}
@Immutable
public static final class PropertyInfo<PropertyPayload> {
- private final PropertyId propertyId;
private final Property property;
- private final PropertyStatus status;
+ private final Status status;
private final boolean multiValued;
private final PropertyPayload payload;
- protected PropertyInfo( PropertyId propertyId,
- Property property,
- boolean multiValued,
- PropertyStatus status,
- PropertyPayload payload ) {
- assert propertyId != null;
+ public PropertyInfo( Property property,
+ boolean multiValued,
+ Status status,
+ PropertyPayload payload ) {
assert property != null;
assert status != null;
- this.propertyId = propertyId;
this.property = property;
this.status = status;
this.multiValued = multiValued;
@@ -2011,17 +2742,35 @@
*
* @return the current status; never null
*/
- public PropertyStatus getStatus() {
+ public Status getStatus() {
return status;
}
/**
+ * Determine whether this property has been modified since it was last saved.
+ *
+ * @return true if the {@link #getStatus() status} is {@link Status#CHANGED
changed}
+ */
+ public boolean isModified() {
+ return status != Status.UNCHANGED && status != Status.NEW;
+ }
+
+ /**
+ * Determine whether this property has been created since the last save.
+ *
+ * @return true if the {@link #getStatus() status} is {@link Status#NEW new}
+ */
+ public boolean isNew() {
+ return status == Status.NEW;
+ }
+
+ /**
* Get the name of the property.
*
* @return the propert name; never null
*/
public Name getName() {
- return propertyId.getPropertyName();
+ return property.getName();
}
/**
@@ -2034,15 +2783,6 @@
}
/**
- * Get the identifier for this property.
- *
- * @return the property identifier; never null
- */
- public PropertyId getPropertyId() {
- return propertyId;
- }
-
- /**
* Get the payload for this property.
*
* @return the payload; may be null if there is no payload
@@ -2067,7 +2807,7 @@
*/
@Override
public int hashCode() {
- return propertyId.hashCode();
+ return getName().hashCode();
}
/**
@@ -2080,7 +2820,7 @@
if (obj == this) return true;
if (obj instanceof PropertyInfo) {
PropertyInfo<?> that = (PropertyInfo<?>)obj;
- return propertyId.equals(that.getPropertyId());
+ return getName().equals(that.getName());
}
return false;
}
@@ -2093,7 +2833,7 @@
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
- sb.append(propertyId);
+ sb.append(getName());
if (payload != null) sb.append(payload);
if (property.isSingle()) {
sb.append(" with value ");
@@ -2148,7 +2888,7 @@
* @param node the node that should be loaded (if it is not already)
*/
protected void load( Node<Payload, PropertyPayload> node ) {
- if (node != null && !node.isLoaded()) {
+ if (node != null && !node.isLoaded() && !node.isNew()) {
nodesToLoad.add(node);
batch.read(node.getLocation());
}
@@ -2168,7 +2908,7 @@
// Now load all of the children into the correct node ...
for (Node<Payload, PropertyPayload> childToBeRead : nodesToLoad) {
org.jboss.dna.graph.Node persistentNode =
results.getNode(childToBeRead.getLocation());
- nodeOperations.update(persistentNode, childToBeRead);
+ nodeOperations.materialize(persistentNode, childToBeRead);
finishNodeAfterLoading(childToBeRead);
}
}
@@ -2488,75 +3228,4 @@
}
}
- /**
- * An immutable identifier for a property on a node, used within the {@link
GraphSession}.
- */
- @Immutable
- public final static class PropertyId {
- private final NodeId nodeId;
- private final Name propertyName;
- private final int hc;
-
- public PropertyId( NodeId nodeId,
- Name propertyName ) {
- this.nodeId = nodeId;
- this.propertyName = propertyName;
- this.hc = HashCode.compute(this.nodeId, this.propertyName);
- }
-
- /**
- * Get the identifier of the node on which the property exists.
- *
- * @return the node identifier; never null
- */
- public NodeId getNodeId() {
- return nodeId;
- }
-
- /**
- * Get the name of the property.
- *
- * @return the property name; never null
- */
- public Name getPropertyName() {
- return propertyName;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode() {
- return hc;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals( Object obj ) {
- if (obj == this) return true;
- if (obj instanceof PropertyId) {
- PropertyId that = (PropertyId)obj;
- if (this.hc != that.hc) return false;
- if (!this.nodeId.equals(that.nodeId)) return false;
- return this.propertyName.equals(that.propertyName);
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- return this.nodeId.toString() + '@' + this.propertyName.toString();
- }
- }
}
Modified: trunk/dna-graph/src/main/resources/org/jboss/dna/graph/GraphI18n.properties
===================================================================
--- trunk/dna-graph/src/main/resources/org/jboss/dna/graph/GraphI18n.properties 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-graph/src/main/resources/org/jboss/dna/graph/GraphI18n.properties 2009-07-09
16:26:04 UTC (rev 1082)
@@ -111,4 +111,7 @@
# Session
unableToRefreshBranchBecauseChangesDependOnChangesToNodesOutsideOfBranch = Unable to
refresh "{0}" in workspace "{1}" because it contains changes that
depend on changes to nodes outside of this branch
unableToSaveBranchBecauseChangesDependOnChangesToNodesOutsideOfBranch = Unable to save
"{0}" in workspace "{1}" because it contains changes that depend on
changes to nodes outside of this branch
+unableToSaveNodeThatWasCreatedSincePreviousSave = Unable to save node "{0}" in
workspace "{1}" because it was created since the last save
nodeHasAlreadyBeenRemovedFromThisSession = Node "{0}" in workspace "{1}
has already been removed from this session
+unableToMoveNodeToBeChildOfDecendent = Node "{0}" in workspace "{2}"
cannot be moved under a decendant node ("{1}")
+childNotFound = Child "{0}" could not be found under "{1}" in
workspace "{2}"
Deleted: trunk/dna-graph/src/test/java/org/jboss/dna/graph/session/GraphCacheTest.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/session/GraphCacheTest.java 2009-07-09
16:23:09 UTC (rev 1081)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/session/GraphCacheTest.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -1,574 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
- * is licensed to you 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.
- *
- * JBoss DNA 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.session;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNot.not;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.Graph;
-import org.jboss.dna.graph.connector.RepositoryConnection;
-import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
-import org.jboss.dna.graph.connector.RepositorySourceException;
-import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.Path;
-import org.jboss.dna.graph.property.PathFactory;
-import org.jboss.dna.graph.property.Property;
-import org.jboss.dna.graph.session.GraphSession.Node;
-import org.jboss.dna.graph.session.GraphSession.Operations;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- *
- */
-public class GraphCacheTest {
-
- protected ExecutionContext context;
- protected InMemoryRepositorySource source;
- private Graph store;
- private GraphSession<Object, Object> cache;
- private PathFactory pathFactory;
- protected int numberOfConnections;
-
- @Before
- public void beforeEach() throws Exception {
- context = new ExecutionContext();
- pathFactory = context.getValueFactories().getPathFactory();
- source = new InMemoryRepositorySource();
- source.setName("store");
- // Use a connection factory so we can count the number of connections that were
made
- RepositoryConnectionFactory connectionFactory = new RepositoryConnectionFactory()
{
- public RepositoryConnection createConnection( String sourceName ) throws
RepositorySourceException {
- if (source.getName().equals(sourceName)) {
- ++numberOfConnections;
- return source.getConnection();
- }
- return null;
- }
- };
- store = Graph.create(source.getName(), connectionFactory, context);
-
- // Load the store with content ...
-
store.importXmlFrom(getClass().getClassLoader().getResourceAsStream("cars.xml")).into("/");
- numberOfConnections = 0; // reset the number of connections
-
- Operations<Object, Object> nodeOps = null; // use default
- String workspaceName = null; // use current
- cache = new GraphSession<Object, Object>(store, workspaceName, nodeOps);
- }
-
- @Test
- public void shouldHaveRootNodeWithCorrectNodeIdAndLocation() {
- Node<Object, Object> node = cache.getRoot();
- assertThat(node, is(notNullValue()));
- assertThat(node.getNodeId(), is(notNullValue()));
- assertThat(node.getLocation(), is(notNullValue()));
- assertNoMoreConnectionsUsed();
- assertNoChanges();
- }
-
- @Test
- public void shouldNotHaveAutomaticallyLoadedRootNode() {
- assertThat(cache.getRoot().isLoaded(), is(false));
- assertNoMoreConnectionsUsed();
- assertNoChanges();
- }
-
- @Test
- public void shouldHaveRootNodeWithChildren() {
- Node<Object, Object> node = cache.getRoot();
- assertChildren(node, "Cars");
- assertConnectionsUsed(1);
- assertNoChanges();
- }
-
- @Test
- public void shouldHaveNoExpirationIfSourceDoesNotHaveCachePolicy() {
- Node<Object, Object> node = cache.getRoot();
- node.load();
- assertThat(node.getExpirationTimeInMillis(), is(Long.MAX_VALUE));
- assertConnectionsUsed(1);
- assertNoChanges();
- }
-
- @Test
- public void shouldAutomaticallyLoadNodesWhenNavigatingToChildren() {
- Node<Object, Object> root = cache.getRoot();
- assertThat(root.isLoaded(), is(false));
- assertChildren(root, "Cars"); // causes loading of the root node
- assertThat(root.isLoaded(), is(true));
- assertConnectionsUsed(1);
-
- Node<Object, Object> cars = root.getChildren().iterator().next(); // only
one child
- assertThat(cars.isLoaded(), is(false));
- assertChildren(cars, "Hybrid", "Sports", "Luxury",
"Utility");
- assertConnectionsUsed(1);
- assertThat(cars.isLoaded(), is(true));
- assertThat(cars.getParent(), is(sameInstance(root)));
-
- Node<Object, Object> sports = cars.getChild(segment("Sports"));
- assertThat(sports.isLoaded(), is(false));
- assertChildren(sports, "Aston Martin DB9", "Infiniti G37");
- assertConnectionsUsed(1);
- assertThat(sports.isLoaded(), is(true));
- assertThat(sports.getParent(), is(sameInstance(cars)));
-
- Node<Object, Object> g37 = sports.getChild(segment("Infiniti
G37"));
- assertThat(g37.isLoaded(), is(false));
- assertChildren(g37);
- assertConnectionsUsed(1);
- assertThat(g37.isLoaded(), is(true));
- assertThat(g37.isLeaf(), is(true));
- assertThat(g37.getParent(), is(sameInstance(sports)));
-
- // Try another branch ...
- Node<Object, Object> utility =
cars.getChild(segment("Utility"));
- assertThat(utility.isLoaded(), is(false));
- assertChildren(utility, "Land Rover LR2", "Land Rover LR3",
"Hummer H3", "Ford F-150");
- assertConnectionsUsed(1);
- assertThat(utility.isLoaded(), is(true));
- assertThat(utility.getParent(), is(sameInstance(cars)));
-
- Node<Object, Object> lr3 = utility.getChild(segment("Land Rover
LR3"));
- assertThat(lr3.isLoaded(), is(false));
- assertChildren(lr3);
- assertConnectionsUsed(1);
- assertThat(lr3.isLoaded(), is(true));
- assertThat(lr3.isLeaf(), is(true));
- assertThat(lr3.getParent(), is(sameInstance(utility)));
-
- assertNoMoreConnectionsUsed();
- assertNoChanges();
- }
-
- @Test
- public void shouldFindNodesByPath() {
- Node<Object, Object> g37 =
cache.findNodeWith(path("/Cars/Sports/Infiniti G37")); // loads the node and all
parents
- assertConnectionsUsed(1);
- assertThat(g37.isLoaded(), is(true));
- assertChildren(g37);
- assertThat(g37.isLoaded(), is(true));
- assertThat(g37.isLeaf(), is(true));
-
- Node<Object, Object> sports = g37.getParent();
- assertThat(sports.isLoaded(), is(true));
- assertChildren(sports, "Aston Martin DB9", "Infiniti G37");
-
- Node<Object, Object> cars = sports.getParent();
- assertThat(cars.isLoaded(), is(true));
- assertChildren(cars, "Hybrid", "Sports", "Luxury",
"Utility");
-
- Node<Object, Object> root = cars.getParent();
- assertThat(root, is(sameInstance(cache.getRoot())));
- assertThat(root.isLoaded(), is(true));
- assertChildren(root, "Cars"); // causes loading of the root node
-
- assertNoMoreConnectionsUsed();
-
- // Try another branch that should not be loaded...
- Node<Object, Object> utility =
cars.getChild(segment("Utility"));
- assertThat(utility.isLoaded(), is(false));
- assertChildren(utility, "Land Rover LR2", "Land Rover LR3",
"Hummer H3", "Ford F-150");
- assertConnectionsUsed(1);
- assertThat(utility.isLoaded(), is(true));
- assertThat(utility.getParent(), is(sameInstance(cars)));
-
- assertNoMoreConnectionsUsed();
- assertNoChanges();
- }
-
- @Test
- public void shouldFindNodesById() {
- cache.findNodeWith(path("/Cars/Sports/Infiniti G37")); // loads the
node and all parents
- assertConnectionsUsed(1); // "Utility" was found because it is child of
"Cars" loaded when "Sports" was loaded
-
- cache.getRoot().onCachedNodes(new GraphSession.NodeVisitor<Object,
Object>() {
- @SuppressWarnings( "synthetic-access" )
- @Override
- public boolean visit( Node<Object, Object> node ) {
- assertThat(cache.findNodeWith(node.getNodeId(), null),
is(sameInstance(node)));
- return true;
- }
- });
- }
-
- @Test
- public void shouldFindNodesByLocation() {
- cache.findNodeWith(path("/Cars/Sports/Infiniti G37")); // loads the
node and all parents
- assertConnectionsUsed(1); // "Utility" was found because it is child of
"Cars" loaded when "Sports" was loaded
-
- cache.getRoot().onCachedNodes(new GraphSession.NodeVisitor<Object,
Object>() {
- @SuppressWarnings( "synthetic-access" )
- @Override
- public boolean visit( Node<Object, Object> node ) {
- assertThat(cache.findNodeWith(null, node.getLocation().getPath()),
is(sameInstance(node)));
- return true;
- }
- });
- }
-
- @Test
- public void shouldFindNodesByIdAfterClearing() {
- Node<Object, Object> g37 =
cache.findNodeWith(path("/Cars/Sports/Infiniti G37")); // loads the node and all
parents
- assertConnectionsUsed(1);
- assertThat(g37.isLoaded(), is(true));
- assertChildren(g37);
- assertThat(g37.isLoaded(), is(true));
- assertThat(g37.isLeaf(), is(true));
-
- Node<Object, Object> sports = g37.getParent();
- Node<Object, Object> cars = sports.getParent();
- Node<Object, Object> root = cars.getParent();
-
- assertNoMoreConnectionsUsed();
-
- cache.getRoot().unload();
-
- Node<Object, Object> g37_b = cache.findNodeWith(g37.getNodeId(),
g37.getPath());
- assertConnectionsUsed(1);
-
- Node<Object, Object> sports_b = g37_b.getParent();
- Node<Object, Object> cars_b = sports_b.getParent();
- Node<Object, Object> root_b = cars_b.getParent();
- assertThat(g37_b, is(not(sameInstance(g37))));
- assertThat(sports_b, is(not(sameInstance(sports))));
- assertThat(cars_b, is(not(sameInstance(cars))));
- assertThat(root_b, is(sameInstance(root)));
- assertThat(g37_b.isLeaf(), is(true));
- assertChildren(sports_b, "Aston Martin DB9", "Infiniti
G37");
- assertChildren(cars_b, "Hybrid", "Sports",
"Luxury", "Utility");
- assertChildren(root_b, "Cars");
-
- assertNoMoreConnectionsUsed();
- assertNoChanges();
- }
-
- @Test
- public void shouldMoveBranchAndRefresh() {
- Node<Object, Object> sports =
cache.findNodeWith(path("/Cars/Sports"));
- Node<Object, Object> utility =
cache.findNodeWith(path("/Cars/Utility"));
- assertConnectionsUsed(1); // "Utility" was found because it is child of
"Cars" loaded when "Sports" was loaded
-
- sports.moveTo(utility);
- assertConnectionsUsed(1); // "Utility" was not fully loaded before
- assertNoMoreConnectionsUsed();
-
- Node<Object, Object> cars = cache.findNodeWith(path("/Cars"));
-
- for (int i = 0; i != 3; ++i) {
- assertChildren(cars, "Hybrid", "Luxury",
"Utility");
- assertChildren(utility, "Land Rover LR2", "Land Rover
LR3", "Hummer H3", "Ford F-150", "Sports");
- assertThat(sports.getParent(), is(utility));
- assertThat(utility.getParent(), is(cars));
-
- // Ensure that the changes were recorded appropriately ...
- assertThat(cars.isChanged(false), is(true));
- assertThat(sports.isChanged(false), is(false));
- assertThat(utility.isChanged(false), is(true));
- assertThat(cache.hasPendingChanges(), is(true));
- assertThat(cache.changeDependencies.size(), is(1));
- assertThat(cache.changeDependencies.get(sports.getNodeId()).getMovedFrom(),
is(cars.getNodeId()));
- assertThat(cache.operations.isExecuteRequired(), is(true));
-
- if (i == 0) {
- // 1st time: Refreshing "Utility" shouldn't work because
"/Cars" was involved in the same move ...
- try {
- cache.refresh(utility, false);
- fail("Expected exception from the call to refresh");
- } catch (InvalidStateException e) {
- // expected ...
- }
- } else if (i == 1) {
- // 2nd time: refresh "/Cars" but keep the changes ...
- cache.refresh(cars, true);
- } else if (i == 2) {
- // 3rd time:
- cache.refresh(cars, false);
- }
- }
-
- // Now the state should be back to the original representation, but we need to
refind the nodes ...
- sports = cache.findNodeWith(path("/Cars/Sports"));
- utility = cache.findNodeWith(path("/Cars/Utility"));
- cars = cache.findNodeWith(path("/Cars"));
-
- assertChildren(cars, "Hybrid", "Sports", "Luxury",
"Utility");
- assertChildren(utility, "Land Rover LR2", "Land Rover LR3",
"Hummer H3", "Ford F-150");
- assertThat(sports.getParent(), is(cars));
- assertThat(utility.getParent(), is(cars));
-
- // Now there should be no changes ...
- assertNoChanges();
- System.out.println(cache.root.getSnapshot(false));
- }
-
- @Test
- public void shouldMoveBranchAndSaveBranch() {
- Node<Object, Object> sports =
cache.findNodeWith(path("/Cars/Sports"));
- Node<Object, Object> utility =
cache.findNodeWith(path("/Cars/Utility"));
- assertConnectionsUsed(1); // "Utility" was found because it is child of
"Cars" loaded when "Sports" was loaded
-
- sports.moveTo(utility);
- assertConnectionsUsed(1); // "Utility" was not fully loaded before
- assertNoMoreConnectionsUsed();
-
- Node<Object, Object> cars = cache.findNodeWith(path("/Cars"));
- Node<Object, Object> root = cache.getRoot();
-
- for (int i = 0; i != 2; ++i) {
- assertChildren(cars, "Hybrid", "Luxury",
"Utility");
- assertChildren(utility, "Land Rover LR2", "Land Rover
LR3", "Hummer H3", "Ford F-150", "Sports");
- assertThat(sports.getParent(), is(utility));
- assertThat(utility.getParent(), is(cars));
-
- // Ensure that the changes were recorded appropriately ...
- assertThat(cars.isChanged(false), is(true));
- assertThat(sports.isChanged(false), is(false));
- assertThat(utility.isChanged(false), is(true));
- assertThat(cache.hasPendingChanges(), is(true));
- assertThat(cache.changeDependencies.size(), is(1));
- assertThat(cache.changeDependencies.get(sports.getNodeId()).getMovedFrom(),
is(cars.getNodeId()));
- assertThat(cache.operations.isExecuteRequired(), is(true));
-
- if (i == 0) {
- // 1st time: Saving "Utility" shouldn't work because
"/Cars" was involved in the same move ...
- try {
- cache.save(utility);
- fail("Expected exception from the call to save");
- } catch (InvalidStateException e) {
- // expected ...
- }
- } else if (i == 1) {
- // 2nd time: Save "/Cars" but keep the changes ...
- assertConnectionsUsed(0);
- cache.save(cars);
- assertConnectionsUsed(2); // 1 to load children required by validation, 1
to perform save
- }
- // i=2 do nothing
- }
-
- // The affected nodes should now be stale ...
- assertThat(sports.isStale(), is(true));
- assertThat(utility.isStale(), is(true));
- assertThat(cars.isStale(), is(false)); // not stale because it was unloaded
- assertThat(cars.isLoaded(), is(false));
- assertThat(root.isStale(), is(false)); // not touched during saves
-
- // Now the state should reflect our changes, but we need to refind the nodes ...
- sports = cache.findNodeWith(path("/Cars/Utility/Sports"));
- assertConnectionsUsed(1);
- utility = cache.findNodeWith(path("/Cars/Utility"));
- assertNoMoreConnectionsUsed();
-
- assertChildren(cars, "Hybrid", "Luxury",
"Utility");
- assertChildren(utility, "Land Rover LR2", "Land Rover LR3",
"Hummer H3", "Ford F-150", "Sports");
- assertThat(sports.getParent(), is(utility));
- assertThat(utility.getParent(), is(cars));
-
- // Now there should be no changes ...
- assertNoChanges();
-
- System.out.println(cache.root.getSnapshot(false));
- }
-
- @Test
- public void shouldMoveBranchAndSaveAll() {
- Node<Object, Object> sports =
cache.findNodeWith(path("/Cars/Sports"));
- Node<Object, Object> utility =
cache.findNodeWith(path("/Cars/Utility"));
- assertConnectionsUsed(1); // "Utility" was found because it is child of
"Cars" loaded when "Sports" was loaded
-
- sports.moveTo(utility);
- assertConnectionsUsed(1); // "Utility" was not fully loaded before
- assertNoMoreConnectionsUsed();
-
- Node<Object, Object> cars = cache.findNodeWith(path("/Cars"));
- Node<Object, Object> root = cache.getRoot();
-
- assertChildren(cars, "Hybrid", "Luxury",
"Utility");
- assertChildren(utility, "Land Rover LR2", "Land Rover LR3",
"Hummer H3", "Ford F-150", "Sports");
- assertThat(sports.getParent(), is(utility));
- assertThat(utility.getParent(), is(cars));
-
- // Ensure that the changes were recorded appropriately ...
- assertThat(cars.isChanged(false), is(true));
- assertThat(sports.isChanged(false), is(false));
- assertThat(utility.isChanged(false), is(true));
- assertThat(cache.hasPendingChanges(), is(true));
- assertThat(cache.changeDependencies.size(), is(1));
- assertThat(cache.changeDependencies.get(sports.getNodeId()).getMovedFrom(),
is(cars.getNodeId()));
- assertThat(cache.operations.isExecuteRequired(), is(true));
-
- // Save the changes ...
- assertConnectionsUsed(0);
- cache.save();
- assertConnectionsUsed(2); // 1 to load children required by validation, 1 to
perform save
-
- // The affected nodes should now be stale ...
- assertThat(sports.isStale(), is(true));
- assertThat(utility.isStale(), is(true));
- assertThat(cars.isStale(), is(false)); // not stale because it was unloaded
- assertThat(cars.isLoaded(), is(false));
- assertThat(root.isStale(), is(false)); // not touched during saves
-
- // Now the state should reflect our changes, but we need to refind the nodes ...
- sports = cache.findNodeWith(path("/Cars/Utility/Sports"));
- assertConnectionsUsed(1);
- utility = cache.findNodeWith(path("/Cars/Utility"));
- assertNoMoreConnectionsUsed();
-
- assertChildren(cars, "Hybrid", "Luxury",
"Utility");
- assertChildren(utility, "Land Rover LR2", "Land Rover LR3",
"Hummer H3", "Ford F-150", "Sports");
- assertThat(sports.getParent(), is(utility));
- assertThat(utility.getParent(), is(cars));
-
- // Now there should be no changes ...
- assertNoChanges();
-
- // System.out.println(cache.root.getSnapshot(false));
- }
-
- @Test
- public void shouldLoadSubgraphs() {
- cache.setDepthForLoadingNodes(4);
- Node<Object, Object> cars = cache.findNodeWith(path("/Cars")); //
loads the node and all parents
- assertChildren(cars, "Hybrid", "Sports", "Luxury",
"Utility");
- assertConnectionsUsed(1);
-
- Node<Object, Object> sports =
cache.findNodeWith(path("/Cars/Sports"));
- Node<Object, Object> g37 =
cache.findNodeWith(path("/Cars/Sports/Infiniti G37"));
- Node<Object, Object> db9 = cache.findNodeWith(path("/Cars/Sports/Aston
Martin DB9"));
- assertConnectionsUsed(0); // should have been loaded with sports subgraph
-
- assertThat(sports.isLoaded(), is(true));
- assertThat(g37.isLoaded(), is(true));
- assertThat(db9.isLoaded(), is(true));
- assertChildren(sports, "Aston Martin DB9", "Infiniti G37");
- assertChildren(g37);
- assertChildren(db9);
-
- assertNoMoreConnectionsUsed();
- assertNoChanges();
- }
-
- @Test
- public void shouldMarkAsChangedWhenSettingProperties() {
- Node<Object, Object> g37 =
cache.findNodeWith(path("/Cars/Sports/Infiniti G37"));
- assertThat(g37.isChanged(false), is(false));
-
- // Set the new property ...
- Property newProperty = createProperty("something",
"value1");
- g37.setProperty(newProperty, false, null);
- assertThat(g37.isChanged(false), is(true));
- assertThat(cache.getRoot().isChanged(true), is(true));
-
- // Save the changes ...
- cache.save();
- }
-
- @Test
- public void shouldClearPropertyChangesWhenRefreshing() {
- Node<Object, Object> g37 =
cache.findNodeWith(path("/Cars/Sports/Infiniti G37"));
- assertThat(g37.isChanged(false), is(false));
-
- // Set the new property ...
- Property newProperty = createProperty("something",
"value1");
- g37.setProperty(newProperty, false, null);
- assertThat(g37.isChanged(false), is(true));
- assertThat(cache.getRoot().isChanged(true), is(true));
-
- // Refresh the changes ...
- cache.refresh(g37, false);
-
- assertThat(g37.isChanged(true), is(false));
- assertThat(cache.getRoot().isChanged(true), is(false));
- assertNoChanges();
- }
-
- protected void assertChildren( Node<Object, Object> node,
- String... childNames ) {
- assertThat(node.getChildrenCount(), is(childNames.length));
- List<Path.Segment> segments = new LinkedList<Path.Segment>();
- for (String childName : childNames) {
- segments.add(pathFactory.createSegment(childName));
- }
- Iterator<Path.Segment> expectedIter = segments.iterator();
- Iterator<Node<Object, Object>> actualIter =
node.getChildren().iterator();
- while (expectedIter.hasNext() && actualIter.hasNext()) {
- Node<Object, Object> actualNode = actualIter.next();
- Path actualPath = actualNode.getPath();
- Path.Segment actualSegment = actualPath.getLastSegment();
- Path.Segment expectedSegment = expectedIter.next();
- assertThat(actualSegment, is(expectedSegment));
- }
- assertThat(expectedIter.hasNext(), is(false));
- assertThat(actualIter.hasNext(), is(false));
- }
-
- protected Name name( String name ) {
- return context.getValueFactories().getNameFactory().create(name);
- }
-
- protected Path.Segment segment( String segment ) {
- return context.getValueFactories().getPathFactory().createSegment(segment);
- }
-
- protected Path path( String path ) {
- return context.getValueFactories().getPathFactory().create(path);
- }
-
- protected Property createProperty( String name,
- Object... values ) {
- return context.getPropertyFactory().create(name(name), values);
- }
-
- protected void assertChildrenNotLoaded( Node<Object, Object> node ) {
- for (Node<Object, Object> child : node.getChildren()) {
- assertThat(child.isLoaded(), is(false));
- }
- }
-
- protected void assertNoChanges() {
- assertThat(cache.hasPendingChanges(), is(false));
- assertThat(cache.changeDependencies.isEmpty(), is(true));
- assertThat(cache.operations.isExecuteRequired(), is(false));
- }
-
- protected void assertNoMoreConnectionsUsed() {
- assertThat(numberOfConnections, is(0));
- }
-
- protected void assertConnectionsUsed( int number ) {
- assertThat(numberOfConnections, is(number));
- numberOfConnections = 0;
- }
-
-}
Copied: trunk/dna-graph/src/test/java/org/jboss/dna/graph/session/GraphSessionTest.java
(from rev 1081,
trunk/dna-graph/src/test/java/org/jboss/dna/graph/session/GraphCacheTest.java)
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/session/GraphSessionTest.java
(rev 0)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/session/GraphSessionTest.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -0,0 +1,752 @@
+/*
+ * JBoss DNA (
http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you 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.
+ *
+ * JBoss DNA 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.session;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import org.jboss.dna.common.statistic.Stopwatch;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.RepositorySourceException;
+import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.session.GraphSession.Node;
+import org.jboss.dna.graph.session.GraphSession.Operations;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class GraphSessionTest {
+
+ private static final Stopwatch LOADING_STOPWATCH = new Stopwatch();
+
+ protected ExecutionContext context;
+ protected InMemoryRepositorySource source;
+ private Graph store;
+ private GraphSession<Object, Object> cache;
+ private PathFactory pathFactory;
+ protected int numberOfConnections;
+
+ @Before
+ public void beforeEach() throws Exception {
+ context = new ExecutionContext();
+ pathFactory = context.getValueFactories().getPathFactory();
+ source = new InMemoryRepositorySource();
+ source.setName("store");
+ // Use a connection factory so we can count the number of connections that were
made
+ RepositoryConnectionFactory connectionFactory = new RepositoryConnectionFactory()
{
+ public RepositoryConnection createConnection( String sourceName ) throws
RepositorySourceException {
+ if (source.getName().equals(sourceName)) {
+ ++numberOfConnections;
+ return source.getConnection();
+ }
+ return null;
+ }
+ };
+ store = Graph.create(source.getName(), connectionFactory, context);
+
+ // Load the store with content ...
+ LOADING_STOPWATCH.start();
+
store.importXmlFrom(getClass().getClassLoader().getResourceAsStream("cars.xml")).into("/");
+ LOADING_STOPWATCH.stop();
+ numberOfConnections = 0; // reset the number of connections
+
+ Operations<Object, Object> nodeOps = null; // use default
+ String workspaceName = null; // use current
+ cache = new GraphSession<Object, Object>(store, workspaceName, nodeOps);
+ }
+
+ @AfterClass
+ public static void afterAll() {
+ System.out.println(LOADING_STOPWATCH);
+ }
+
+ @Test
+ public void shouldHaveRootNodeWithCorrectNodeIdAndLocation() {
+ Node<Object, Object> node = cache.getRoot();
+ assertThat(node, is(notNullValue()));
+ assertThat(node.getNodeId(), is(notNullValue()));
+ assertThat(node.getLocation(), is(notNullValue()));
+ assertNoMoreConnectionsUsed();
+ assertNoChanges();
+ }
+
+ @Test
+ public void shouldNotHaveAutomaticallyLoadedRootNode() {
+ assertThat(cache.getRoot().isLoaded(), is(false));
+ assertNoMoreConnectionsUsed();
+ assertNoChanges();
+ }
+
+ @Test
+ public void shouldHaveRootNodeWithChildren() {
+ Node<Object, Object> node = cache.getRoot();
+ assertChildren(node, "Cars");
+ assertConnectionsUsed(1);
+ assertNoChanges();
+ }
+
+ @Test
+ public void shouldHaveNoExpirationIfSourceDoesNotHaveCachePolicy() {
+ Node<Object, Object> node = cache.getRoot();
+ node.load();
+ assertThat(node.getExpirationTimeInMillis(), is(Long.MAX_VALUE));
+ assertConnectionsUsed(1);
+ assertNoChanges();
+ }
+
+ @Test
+ public void shouldAutomaticallyLoadNodesWhenNavigatingToChildren() {
+ Node<Object, Object> root = cache.getRoot();
+ assertThat(root.isLoaded(), is(false));
+ assertChildren(root, "Cars"); // causes loading of the root node
+ assertThat(root.isLoaded(), is(true));
+ assertConnectionsUsed(1);
+
+ Node<Object, Object> cars = root.getChildren().iterator().next(); // only
one child
+ assertThat(cars.isLoaded(), is(false));
+ assertChildren(cars, "Hybrid", "Sports", "Luxury",
"Utility");
+ assertConnectionsUsed(1);
+ assertThat(cars.isLoaded(), is(true));
+ assertThat(cars.getParent(), is(sameInstance(root)));
+
+ Node<Object, Object> sports = cars.getChild(segment("Sports"));
+ assertThat(sports.isLoaded(), is(false));
+ assertChildren(sports, "Aston Martin DB9", "Infiniti G37");
+ assertConnectionsUsed(1);
+ assertThat(sports.isLoaded(), is(true));
+ assertThat(sports.getParent(), is(sameInstance(cars)));
+
+ Node<Object, Object> g37 = sports.getChild(segment("Infiniti
G37"));
+ assertThat(g37.isLoaded(), is(false));
+ assertChildren(g37);
+ assertConnectionsUsed(1);
+ assertThat(g37.isLoaded(), is(true));
+ assertThat(g37.isLeaf(), is(true));
+ assertThat(g37.getParent(), is(sameInstance(sports)));
+
+ // Try another branch ...
+ Node<Object, Object> utility =
cars.getChild(segment("Utility"));
+ assertThat(utility.isLoaded(), is(false));
+ assertChildren(utility, "Land Rover LR2", "Land Rover LR3",
"Hummer H3", "Ford F-150");
+ assertConnectionsUsed(1);
+ assertThat(utility.isLoaded(), is(true));
+ assertThat(utility.getParent(), is(sameInstance(cars)));
+
+ Node<Object, Object> lr3 = utility.getChild(segment("Land Rover
LR3"));
+ assertThat(lr3.isLoaded(), is(false));
+ assertChildren(lr3);
+ assertConnectionsUsed(1);
+ assertThat(lr3.isLoaded(), is(true));
+ assertThat(lr3.isLeaf(), is(true));
+ assertThat(lr3.getParent(), is(sameInstance(utility)));
+
+ assertNoMoreConnectionsUsed();
+ assertNoChanges();
+ }
+
+ @Test
+ public void shouldFindNodesByPath() {
+ Node<Object, Object> g37 =
cache.findNodeWith(path("/Cars/Sports/Infiniti G37")); // loads the node and all
parents
+ assertConnectionsUsed(1);
+ assertThat(g37.isLoaded(), is(true));
+ assertChildren(g37);
+ assertThat(g37.isLoaded(), is(true));
+ assertThat(g37.isLeaf(), is(true));
+
+ Node<Object, Object> sports = g37.getParent();
+ assertThat(sports.isLoaded(), is(true));
+ assertChildren(sports, "Aston Martin DB9", "Infiniti G37");
+
+ Node<Object, Object> cars = sports.getParent();
+ assertThat(cars.isLoaded(), is(true));
+ assertChildren(cars, "Hybrid", "Sports", "Luxury",
"Utility");
+
+ Node<Object, Object> root = cars.getParent();
+ assertThat(root, is(sameInstance(cache.getRoot())));
+ assertThat(root.isLoaded(), is(true));
+ assertChildren(root, "Cars"); // causes loading of the root node
+
+ assertNoMoreConnectionsUsed();
+
+ // Try another branch that should not be loaded...
+ Node<Object, Object> utility =
cars.getChild(segment("Utility"));
+ assertThat(utility.isLoaded(), is(false));
+ assertChildren(utility, "Land Rover LR2", "Land Rover LR3",
"Hummer H3", "Ford F-150");
+ assertConnectionsUsed(1);
+ assertThat(utility.isLoaded(), is(true));
+ assertThat(utility.getParent(), is(sameInstance(cars)));
+
+ assertNoMoreConnectionsUsed();
+ assertNoChanges();
+ }
+
+ @Test
+ public void shouldFindNodesById() {
+ cache.findNodeWith(path("/Cars/Sports/Infiniti G37")); // loads the
node and all parents
+ assertConnectionsUsed(1); // "Utility" was found because it is child of
"Cars" loaded when "Sports" was loaded
+
+ cache.getRoot().onCachedNodes(new GraphSession.NodeVisitor<Object,
Object>() {
+ @SuppressWarnings( "synthetic-access" )
+ @Override
+ public boolean visit( Node<Object, Object> node ) {
+ assertThat(cache.findNodeWith(node.getNodeId(), null),
is(sameInstance(node)));
+ return true;
+ }
+ });
+ }
+
+ @Test
+ public void shouldFindNodesByLocation() {
+ cache.findNodeWith(path("/Cars/Sports/Infiniti G37")); // loads the
node and all parents
+ assertConnectionsUsed(1); // "Utility" was found because it is child of
"Cars" loaded when "Sports" was loaded
+
+ cache.getRoot().onCachedNodes(new GraphSession.NodeVisitor<Object,
Object>() {
+ @SuppressWarnings( "synthetic-access" )
+ @Override
+ public boolean visit( Node<Object, Object> node ) {
+ assertThat(cache.findNodeWith(null, node.getLocation().getPath()),
is(sameInstance(node)));
+ return true;
+ }
+ });
+ }
+
+ @Test
+ public void shouldFindNodesByIdAfterClearing() {
+ Node<Object, Object> g37 =
cache.findNodeWith(path("/Cars/Sports/Infiniti G37")); // loads the node and all
parents
+ assertConnectionsUsed(1);
+ assertThat(g37.isLoaded(), is(true));
+ assertChildren(g37);
+ assertThat(g37.isLoaded(), is(true));
+ assertThat(g37.isLeaf(), is(true));
+
+ Node<Object, Object> sports = g37.getParent();
+ Node<Object, Object> cars = sports.getParent();
+ Node<Object, Object> root = cars.getParent();
+
+ assertNoMoreConnectionsUsed();
+
+ cache.getRoot().unload();
+
+ Node<Object, Object> g37_b = cache.findNodeWith(g37.getNodeId(),
g37.getPath());
+ assertConnectionsUsed(1);
+
+ Node<Object, Object> sports_b = g37_b.getParent();
+ Node<Object, Object> cars_b = sports_b.getParent();
+ Node<Object, Object> root_b = cars_b.getParent();
+ assertThat(g37_b, is(not(sameInstance(g37))));
+ assertThat(sports_b, is(not(sameInstance(sports))));
+ assertThat(cars_b, is(not(sameInstance(cars))));
+ assertThat(root_b, is(sameInstance(root)));
+ assertThat(g37_b.isLeaf(), is(true));
+ assertChildren(sports_b, "Aston Martin DB9", "Infiniti
G37");
+ assertChildren(cars_b, "Hybrid", "Sports",
"Luxury", "Utility");
+ assertChildren(root_b, "Cars");
+
+ assertNoMoreConnectionsUsed();
+ assertNoChanges();
+ }
+
+ @Test
+ public void shouldMoveBranchAndRefresh() {
+ Node<Object, Object> sports =
cache.findNodeWith(path("/Cars/Sports"));
+ Node<Object, Object> utility =
cache.findNodeWith(path("/Cars/Utility"));
+ assertConnectionsUsed(1); // "Utility" was found because it is child of
"Cars" loaded when "Sports" was loaded
+
+ sports.moveTo(utility);
+ assertConnectionsUsed(1); // "Utility" was not fully loaded before
+ assertNoMoreConnectionsUsed();
+
+ Node<Object, Object> cars = cache.findNodeWith(path("/Cars"));
+
+ for (int i = 0; i != 3; ++i) {
+ assertChildren(cars, "Hybrid", "Luxury",
"Utility");
+ assertChildren(utility, "Land Rover LR2", "Land Rover
LR3", "Hummer H3", "Ford F-150", "Sports");
+ assertThat(sports.getParent(), is(utility));
+ assertThat(utility.getParent(), is(cars));
+
+ // Ensure that the changes were recorded appropriately ...
+ assertThat(cars.isChanged(false), is(true)); // 'sports' removed as
child
+ assertThat(utility.isChanged(false), is(true)); // 'sports' added as
child
+ assertThat(sports.isChanged(false), is(true)); // path has changed
+ assertThat(cache.hasPendingChanges(), is(true));
+ assertThat(cache.changeDependencies.size(), is(1));
+ assertThat(cache.changeDependencies.get(sports.getNodeId()).getMovedFrom(),
is(cars.getNodeId()));
+ assertThat(cache.operations.isExecuteRequired(), is(true));
+
+ if (i == 0) {
+ // 1st time: Refreshing "Utility" shouldn't work because
"/Cars" was involved in the same move ...
+ try {
+ cache.refresh(utility, false);
+ fail("Expected exception from the call to refresh");
+ } catch (InvalidStateException e) {
+ // expected ...
+ }
+ } else if (i == 1) {
+ // 2nd time: refresh "/Cars" but keep the changes ...
+ cache.refresh(cars, true);
+ } else if (i == 2) {
+ // 3rd time:
+ cache.refresh(cars, false);
+ }
+ }
+
+ // Now the state should be back to the original representation, but we need to
refind the nodes ...
+ sports = cache.findNodeWith(path("/Cars/Sports"));
+ utility = cache.findNodeWith(path("/Cars/Utility"));
+ cars = cache.findNodeWith(path("/Cars"));
+
+ assertChildren(cars, "Hybrid", "Sports", "Luxury",
"Utility");
+ assertChildren(utility, "Land Rover LR2", "Land Rover LR3",
"Hummer H3", "Ford F-150");
+ assertThat(sports.getParent(), is(cars));
+ assertThat(utility.getParent(), is(cars));
+
+ // Now there should be no changes ...
+ assertNoChanges();
+ System.out.println(cache.root.getSnapshot(false));
+ }
+
+ @Test
+ public void shouldMoveBranchAndSaveBranch() {
+ Node<Object, Object> sports =
cache.findNodeWith(path("/Cars/Sports"));
+ Node<Object, Object> utility =
cache.findNodeWith(path("/Cars/Utility"));
+ assertConnectionsUsed(1); // "Utility" was found because it is child of
"Cars" loaded when "Sports" was loaded
+
+ sports.moveTo(utility);
+ assertConnectionsUsed(1); // "Utility" was not fully loaded before
+ assertNoMoreConnectionsUsed();
+
+ Node<Object, Object> cars = cache.findNodeWith(path("/Cars"));
+ Node<Object, Object> root = cache.getRoot();
+
+ for (int i = 0; i != 2; ++i) {
+ assertChildren(cars, "Hybrid", "Luxury",
"Utility");
+ assertChildren(utility, "Land Rover LR2", "Land Rover
LR3", "Hummer H3", "Ford F-150", "Sports");
+ assertThat(sports.getParent(), is(utility));
+ assertThat(utility.getParent(), is(cars));
+
+ // Ensure that the changes were recorded appropriately ...
+ assertThat(cars.isChanged(false), is(true)); // 'sports' removed as
child
+ assertThat(utility.isChanged(false), is(true)); // 'sports' added as
child
+ assertThat(sports.isChanged(false), is(true)); // path has changed
+ assertThat(cache.hasPendingChanges(), is(true));
+ assertThat(cache.changeDependencies.size(), is(1));
+ assertThat(cache.changeDependencies.get(sports.getNodeId()).getMovedFrom(),
is(cars.getNodeId()));
+ assertThat(cache.operations.isExecuteRequired(), is(true));
+
+ if (i == 0) {
+ // 1st time: Saving "Utility" shouldn't work because
"/Cars" was involved in the same move ...
+ try {
+ cache.save(utility);
+ fail("Expected exception from the call to save");
+ } catch (InvalidStateException e) {
+ // expected ...
+ }
+ } else if (i == 1) {
+ // 2nd time: Save "/Cars" but keep the changes ...
+ assertConnectionsUsed(0);
+ cache.save(cars);
+ assertConnectionsUsed(2); // 1 to load children required by validation, 1
to perform save
+ }
+ // i=2 do nothing
+ }
+
+ // The affected nodes should now be stale ...
+ assertThat(sports.isStale(), is(true));
+ assertThat(utility.isStale(), is(true));
+ assertThat(cars.isStale(), is(false)); // not stale because it was unloaded
+ assertThat(cars.isLoaded(), is(false));
+ assertThat(root.isStale(), is(false)); // not touched during saves
+
+ // Now the state should reflect our changes, but we need to refind the nodes ...
+ sports = cache.findNodeWith(path("/Cars/Utility/Sports"));
+ assertConnectionsUsed(1);
+ utility = cache.findNodeWith(path("/Cars/Utility"));
+ assertNoMoreConnectionsUsed();
+
+ assertChildren(cars, "Hybrid", "Luxury",
"Utility");
+ assertChildren(utility, "Land Rover LR2", "Land Rover LR3",
"Hummer H3", "Ford F-150", "Sports");
+ assertThat(sports.getParent(), is(utility));
+ assertThat(utility.getParent(), is(cars));
+
+ // Now there should be no changes ...
+ assertNoChanges();
+
+ System.out.println(cache.root.getSnapshot(false));
+ }
+
+ @Test
+ public void shouldMoveBranchAndSaveAll() {
+ Node<Object, Object> sports =
cache.findNodeWith(path("/Cars/Sports"));
+ Node<Object, Object> utility =
cache.findNodeWith(path("/Cars/Utility"));
+ assertConnectionsUsed(1); // "Utility" was found because it is child of
"Cars" loaded when "Sports" was loaded
+
+ sports.moveTo(utility);
+ assertConnectionsUsed(1); // "Utility" was not fully loaded before
+ assertNoMoreConnectionsUsed();
+
+ Node<Object, Object> cars = cache.findNodeWith(path("/Cars"));
+ Node<Object, Object> root = cache.getRoot();
+
+ assertChildren(cars, "Hybrid", "Luxury",
"Utility");
+ assertChildren(utility, "Land Rover LR2", "Land Rover LR3",
"Hummer H3", "Ford F-150", "Sports");
+ assertThat(sports.getParent(), is(utility));
+ assertThat(utility.getParent(), is(cars));
+
+ // Ensure that the changes were recorded appropriately ...
+ assertThat(cars.isChanged(false), is(true)); // 'sports' removed as
child
+ assertThat(utility.isChanged(false), is(true)); // 'sports' added as
child
+ assertThat(sports.isChanged(false), is(true)); // path has changed
+ assertThat(cache.hasPendingChanges(), is(true));
+ assertThat(cache.changeDependencies.size(), is(1));
+ assertThat(cache.changeDependencies.get(sports.getNodeId()).getMovedFrom(),
is(cars.getNodeId()));
+ assertThat(cache.operations.isExecuteRequired(), is(true));
+
+ // Save the changes ...
+ assertConnectionsUsed(0);
+ cache.save();
+ assertConnectionsUsed(2); // 1 to load children required by validation, 1 to
perform save
+
+ // The affected nodes should now be stale ...
+ assertThat(sports.isStale(), is(true));
+ assertThat(utility.isStale(), is(true));
+ assertThat(cars.isStale(), is(false)); // not stale because it was unloaded
+ assertThat(cars.isLoaded(), is(false));
+ assertThat(root.isStale(), is(false)); // not touched during saves
+
+ // Now the state should reflect our changes, but we need to refind the nodes ...
+ sports = cache.findNodeWith(path("/Cars/Utility/Sports"));
+ assertConnectionsUsed(1);
+ utility = cache.findNodeWith(path("/Cars/Utility"));
+ assertNoMoreConnectionsUsed();
+
+ assertChildren(cars, "Hybrid", "Luxury",
"Utility");
+ assertChildren(utility, "Land Rover LR2", "Land Rover LR3",
"Hummer H3", "Ford F-150", "Sports");
+ assertThat(sports.getParent(), is(utility));
+ assertThat(utility.getParent(), is(cars));
+
+ // Now there should be no changes ...
+ assertNoChanges();
+
+ // System.out.println(cache.root.getSnapshot(false));
+ }
+
+ @Test
+ public void shouldRenameNodeByRemovingAndAddingAtEndOfChildren() {
+ Node<Object, Object> sports =
cache.findNodeWith(path("/Cars/Sports"));
+ assertConnectionsUsed(1); // "Utility" was found because it is child of
"Cars" loaded when "Sports" was loaded
+
+ sports.rename(name("non-sports")); // "Sports" was already
loaded, as was "Cars"
+ assertNoMoreConnectionsUsed();
+
+ Node<Object, Object> cars = cache.findNodeWith(path("/Cars"));
+
+ assertChildren(cars, "Hybrid", "Luxury", "Utility",
"non-sports");
+ assertThat(sports.getParent(), is(cars));
+
+ // Ensure that the changes were recorded appropriately ...
+ assertThat(cars.isChanged(false), is(true)); // 'sports' renamed as
child
+ assertThat(sports.isChanged(false), is(true)); // path has changed
+ assertThat(cache.hasPendingChanges(), is(true));
+ assertThat(cache.operations.isExecuteRequired(), is(true));
+
+ // Save "/Cars" but keep the changes ...
+ assertConnectionsUsed(0);
+ cache.save(cars);
+ assertConnectionsUsed(2); // 1 to load children required by validation, 1 to
perform save
+
+ // Now the state should reflect our changes, but we need to refind the nodes ...
+ Node<Object, Object> nonSports =
cache.findNodeWith(path("/Cars/non-sports"));
+ assertConnectionsUsed(1);
+ assertNoMoreConnectionsUsed();
+
+ assertChildren(cars, "Hybrid", "Luxury", "Utility",
"non-sports");
+ assertThat(nonSports.getParent(), is(cars));
+
+ // Now there should be no changes ...
+ assertNoChanges();
+
+ System.out.println(cache.root.getSnapshot(false));
+ }
+
+ @Test
+ public void
shouldRenameNodeByRemovingAndAddingAtEndOfChildrenEvenWithSameNameSiblings() {
+ Node<Object, Object> sports =
cache.findNodeWith(path("/Cars/Sports"));
+ assertConnectionsUsed(1); // "Utility" was found because it is child of
"Cars" loaded when "Sports" was loaded
+
+ sports.rename(name("Utility")); // "Sports" was already
loaded, as was "Cars"
+ assertNoMoreConnectionsUsed();
+
+ Node<Object, Object> cars = cache.findNodeWith(path("/Cars"));
+
+ assertChildren(cars, "Hybrid", "Luxury", "Utility",
"Utility[2]");
+ assertThat(sports.getParent(), is(cars));
+
+ // Ensure that the changes were recorded appropriately ...
+ assertThat(cars.isChanged(false), is(true)); // 'sports' renamed as
child
+ assertThat(sports.isChanged(false), is(true)); // path has changed
+ assertThat(cache.hasPendingChanges(), is(true));
+ assertThat(cache.operations.isExecuteRequired(), is(true));
+
+ // Save "/Cars" but keep the changes ...
+ assertConnectionsUsed(0);
+ cache.save(cars);
+ assertConnectionsUsed(2); // 1 to load children required by validation, 1 to
perform save
+
+ // Now the state should reflect our changes, but we need to refind the nodes ...
+ Node<Object, Object> utility2 =
cache.findNodeWith(path("/Cars/Utility[2]"));
+ assertConnectionsUsed(1);
+ assertNoMoreConnectionsUsed();
+
+ assertChildren(cars, "Hybrid", "Luxury", "Utility",
"Utility[2]");
+ assertThat(utility2.getParent(), is(cars));
+
+ // Now there should be no changes ...
+ assertNoChanges();
+
+ System.out.println(cache.root.getSnapshot(false));
+ }
+
+ @Test
+ public void shouldReorderChildWithNoSnsIndexes() {
+ Node<Object, Object> sports =
cache.findNodeWith(path("/Cars/Sports"));
+ Node<Object, Object> utility =
cache.findNodeWith(path("/Cars/Utility"));
+ Node<Object, Object> cars = cache.findNodeWith(path("/Cars"));
+ assertConnectionsUsed(1); // "Utility" was found because it is child of
"Cars" loaded when "Sports" was loaded
+
+ cars.orderChildBefore(utility.getSegment(), sports.getSegment());
+ assertNoMoreConnectionsUsed();
+
+ Node<Object, Object> root = cache.getRoot();
+
+ assertChildren(cars, "Hybrid", "Utility", "Sports",
"Luxury");
+ assertThat(sports.getParent(), is(cars));
+ assertThat(utility.getParent(), is(cars));
+
+ // Save the changes ...
+ assertConnectionsUsed(0);
+ cache.save();
+ assertConnectionsUsed(2); // 1 to load children required by validation, 1 to
perform save
+
+ // The affected nodes should now be stale ...
+ assertThat(sports.isStale(), is(true));
+ assertThat(utility.isStale(), is(true));
+ assertThat(cars.isStale(), is(false)); // not stale because it was unloaded
+ assertThat(cars.isLoaded(), is(false));
+ assertThat(root.isStale(), is(false)); // not touched during saves
+
+ // Now the state should reflect our changes ...
+ assertChildren(cars, "Hybrid", "Utility", "Sports",
"Luxury");
+
+ // Now there should be no changes ...
+ assertNoChanges();
+ }
+
+ @Test
+ public void shouldReorderChildWithSnsIndexes() {
+ Node<Object, Object> sports =
cache.findNodeWith(path("/Cars/Sports"));
+ Node<Object, Object> cars = cache.findNodeWith(path("/Cars"));
+ assertConnectionsUsed(1); // "Utility" was found because it is child of
"Cars" loaded when "Sports" was loaded
+
+ Node<Object, Object> exp1 =
cars.createChild(name("Experimental"));
+ Node<Object, Object> exp2 =
cars.createChild(name("Experimental"));
+ Node<Object, Object> exp3 =
cars.createChild(name("Experimental"));
+ assertThat(cache.hasPendingChanges(), is(true));
+ assertThat(exp1.getSegment().getIndex(), is(1));
+ assertThat(exp2.getSegment().getIndex(), is(2));
+ assertThat(exp3.getSegment().getIndex(), is(3));
+ assertChildren(cars, "Hybrid", "Sports", "Luxury",
"Utility", "Experimental", "Experimental[2]",
"Experimental[3]");
+
+ cars.orderChildBefore(exp3.getSegment(), sports.getSegment());
+ assertNoMoreConnectionsUsed();
+
+ assertThat(exp1.getSegment().getIndex(), is(2));
+ assertThat(exp2.getSegment().getIndex(), is(3));
+ assertThat(exp3.getSegment().getIndex(), is(1));
+ assertChildren(cars, "Hybrid", "Experimental",
"Sports", "Luxury", "Utility", "Experimental[2]",
"Experimental[3]");
+
+ // Save the changes ...
+ assertConnectionsUsed(0);
+ cache.save();
+ assertConnectionsUsed(2); // 1 to load children required by validation, 1 to
perform save
+
+ // Now the state should reflect our changes ...
+ assertChildren(cars, "Hybrid", "Experimental",
"Sports", "Luxury", "Utility", "Experimental[2]",
"Experimental[3]");
+
+ // Now there should be no changes ...
+ assertNoChanges();
+ }
+
+ @Test
+ public void shouldLoadSubgraphs() {
+ cache.setDepthForLoadingNodes(4);
+ Node<Object, Object> cars = cache.findNodeWith(path("/Cars")); //
loads the node and all parents
+ assertChildren(cars, "Hybrid", "Sports", "Luxury",
"Utility");
+ assertConnectionsUsed(1);
+
+ Node<Object, Object> sports =
cache.findNodeWith(path("/Cars/Sports"));
+ Node<Object, Object> g37 =
cache.findNodeWith(path("/Cars/Sports/Infiniti G37"));
+ Node<Object, Object> db9 = cache.findNodeWith(path("/Cars/Sports/Aston
Martin DB9"));
+ assertConnectionsUsed(0); // should have been loaded with sports subgraph
+
+ assertThat(sports.isLoaded(), is(true));
+ assertThat(g37.isLoaded(), is(true));
+ assertThat(db9.isLoaded(), is(true));
+ assertChildren(sports, "Aston Martin DB9", "Infiniti G37");
+ assertChildren(g37);
+ assertChildren(db9);
+
+ assertNoMoreConnectionsUsed();
+ assertNoChanges();
+ }
+
+ @Test
+ public void shouldMarkAsChangedWhenSettingProperties() {
+ Node<Object, Object> g37 =
cache.findNodeWith(path("/Cars/Sports/Infiniti G37"));
+ assertThat(g37.isChanged(false), is(false));
+
+ // Set the new property ...
+ Property newProperty = createProperty("something",
"value1");
+ g37.setProperty(newProperty, false, null);
+ assertThat(g37.isChanged(false), is(true));
+ assertThat(cache.getRoot().isChanged(true), is(true));
+
+ // Save the changes ...
+ cache.save();
+ }
+
+ @Test
+ public void shouldClearPropertyChangesWhenRefreshing() {
+ Node<Object, Object> g37 =
cache.findNodeWith(path("/Cars/Sports/Infiniti G37"));
+ assertThat(g37.isChanged(false), is(false));
+
+ // Set the new property ...
+ Property newProperty = createProperty("something",
"value1");
+ g37.setProperty(newProperty, false, null);
+ assertThat(g37.isChanged(false), is(true));
+ assertThat(cache.getRoot().isChanged(true), is(true));
+
+ // Refresh the changes ...
+ cache.refresh(g37, false);
+
+ assertThat(g37.isChanged(true), is(false));
+ assertThat(cache.getRoot().isChanged(true), is(false));
+ assertNoChanges();
+ }
+
+ @Test
+ public void shouldCreateChildren() {
+ Node<Object, Object> cars = cache.findNodeWith(path("/Cars")); //
loads the node and all parents
+ assertChildren(cars, "Hybrid", "Sports", "Luxury",
"Utility");
+ assertConnectionsUsed(1);
+
+ Node<Object, Object> experimental =
cars.createChild(name("Experimental"));
+ assertThat(experimental.getParent(), is(sameInstance(cars)));
+ assertChildren(cars, "Hybrid", "Sports", "Luxury",
"Utility", "Experimental");
+ assertThat(cars.isChanged(false), is(true));
+ assertThat(experimental.isNew(), is(true));
+ assertNoMoreConnectionsUsed();
+
+ Node<Object, Object> experimental2 =
cars.createChild(name("Experimental"));
+ assertThat(experimental2.getParent(), is(sameInstance(cars)));
+ assertChildren(cars, "Hybrid", "Sports", "Luxury",
"Utility", "Experimental[1]", "Experimental[2]");
+ assertThat(cars.isChanged(false), is(true));
+ assertThat(experimental2.isNew(), is(true));
+ assertNoMoreConnectionsUsed();
+ }
+
+ protected void assertChildren( Node<Object, Object> node,
+ String... childNames ) {
+ assertThat(node.getChildrenCount(), is(childNames.length));
+ List<Path.Segment> segments = new LinkedList<Path.Segment>();
+ for (String childName : childNames) {
+ segments.add(pathFactory.createSegment(childName));
+ }
+ Iterator<Path.Segment> expectedIter = segments.iterator();
+ Iterator<Node<Object, Object>> actualIter =
node.getChildren().iterator();
+ while (expectedIter.hasNext() && actualIter.hasNext()) {
+ Node<Object, Object> actualNode = actualIter.next();
+ Path actualPath = actualNode.getPath();
+ Path.Segment actualSegment = actualPath.getLastSegment();
+ Path.Segment expectedSegment = expectedIter.next();
+ assertThat(actualSegment, is(expectedSegment));
+ }
+ assertThat(expectedIter.hasNext(), is(false));
+ assertThat(actualIter.hasNext(), is(false));
+ }
+
+ protected Name name( String name ) {
+ return context.getValueFactories().getNameFactory().create(name);
+ }
+
+ protected Path.Segment segment( String segment ) {
+ return context.getValueFactories().getPathFactory().createSegment(segment);
+ }
+
+ protected Path path( String path ) {
+ return context.getValueFactories().getPathFactory().create(path);
+ }
+
+ protected Property createProperty( String name,
+ Object... values ) {
+ return context.getPropertyFactory().create(name(name), values);
+ }
+
+ protected void assertChildrenNotLoaded( Node<Object, Object> node ) {
+ for (Node<Object, Object> child : node.getChildren()) {
+ assertThat(child.isLoaded(), is(false));
+ }
+ }
+
+ protected void assertNoChanges() {
+ assertThat(cache.hasPendingChanges(), is(false));
+ assertThat(cache.changeDependencies.isEmpty(), is(true));
+ assertThat(cache.operations.isExecuteRequired(), is(false));
+ }
+
+ protected void assertNoMoreConnectionsUsed() {
+ assertThat(numberOfConnections, is(0));
+ }
+
+ protected void assertConnectionsUsed( int number ) {
+ assertThat(numberOfConnections, is(number));
+ numberOfConnections = 0;
+ }
+
+}
Property changes on:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/session/GraphSessionTest.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-07-09 16:23:09
UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-07-09 16:26:04
UTC (rev 1082)
@@ -24,7 +24,6 @@
package org.jboss.dna.jcr;
import java.io.InputStream;
-import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
@@ -43,7 +42,6 @@
import javax.jcr.ItemNotFoundException;
import javax.jcr.ItemVisitor;
import javax.jcr.NoSuchWorkspaceException;
-import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
@@ -66,7 +64,8 @@
import net.jcip.annotations.Immutable;
import org.jboss.dna.common.i18n.I18n;
import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.connector.RepositorySourceException;
import org.jboss.dna.graph.property.Binary;
import org.jboss.dna.graph.property.DateTime;
import org.jboss.dna.graph.property.Name;
@@ -74,81 +73,80 @@
import org.jboss.dna.graph.property.Path;
import org.jboss.dna.graph.property.PathFactory;
import org.jboss.dna.graph.property.ValueFactories;
+import org.jboss.dna.graph.session.GraphSession.Node;
+import org.jboss.dna.graph.session.GraphSession.NodeId;
+import org.jboss.dna.graph.session.GraphSession.PropertyInfo;
+import org.jboss.dna.jcr.SessionCache.JcrNodePayload;
+import org.jboss.dna.jcr.SessionCache.JcrPropertyPayload;
import org.jboss.dna.jcr.SessionCache.NodeEditor;
-import org.jboss.dna.jcr.cache.ChildNode;
-import org.jboss.dna.jcr.cache.Children;
-import org.jboss.dna.jcr.cache.NodeInfo;
/**
- * An abstract implementation of the JCR {@link Node} interface. Instances of this class
are created and managed by the
- * {@link SessionCache}. Each instance references the {@link NodeInfo node information}
also managed by the SessionCache, and
- * finds and operates against this information with each method call.
+ * An abstract implementation of the JCR {@link javax.jcr.Node} interface. Instances of
this class are created and managed by the
+ * {@link SessionCache}. Each instance indirectly references the {@link javax.jcr.Node
node information} also managed by the
+ * SessionCache, and finds and operates against this information with each method call.
*/
@Immutable
-abstract class AbstractJcrNode extends AbstractJcrItem implements Node {
+abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node {
private static final NodeType[] EMPTY_NODE_TYPES = new NodeType[] {};
- protected final UUID nodeUuid;
+ protected final NodeId nodeId;
+ protected final Location location;
AbstractJcrNode( SessionCache cache,
- UUID nodeUuid ) {
+ NodeId nodeId,
+ Location location ) {
super(cache);
- this.nodeUuid = nodeUuid;
+ this.nodeId = nodeId;
+ this.location = location;
}
abstract boolean isRoot();
public abstract AbstractJcrNode getParent() throws ItemNotFoundException,
RepositoryException;
- final UUID internalUuid() {
- return nodeUuid;
+ final NodeId internalId() {
+ return nodeId;
}
final Name name() throws RepositoryException {
- return cache.getNameOf(nodeUuid);
+ return nodeInfo().getName();
}
- final NodeInfo nodeInfo() throws ItemNotFoundException, RepositoryException {
- return cache.findNodeInfo(nodeUuid);
+ final Path.Segment segment() throws RepositoryException {
+ return nodeInfo().getSegment();
}
+ final Node<JcrNodePayload, JcrPropertyPayload> nodeInfo()
+ throws ItemNotFoundException, AccessDeniedException, RepositoryException {
+ return cache.findNode(nodeId, location.getPath());
+ }
+
final NodeEditor editorForParent() throws RepositoryException {
try {
- return cache.getEditorFor(nodeInfo().getParent());
+ Node<JcrNodePayload, JcrPropertyPayload> parent =
nodeInfo().getParent();
+ return cache.getEditorFor(parent);
} catch (ItemNotFoundException err) {
- String msg = JcrI18n.nodeHasAlreadyBeenRemovedFromThisSession.text(nodeUuid,
cache.workspaceName());
+ String msg = JcrI18n.nodeHasAlreadyBeenRemovedFromThisSession.text(nodeId,
cache.workspaceName());
throw new RepositoryException(msg);
} catch (InvalidItemStateException err) {
- String msg = JcrI18n.nodeHasAlreadyBeenRemovedFromThisSession.text(nodeUuid,
cache.workspaceName());
+ String msg = JcrI18n.nodeHasAlreadyBeenRemovedFromThisSession.text(nodeId,
cache.workspaceName());
throw new RepositoryException(msg);
}
}
final NodeEditor editor() throws RepositoryException {
try {
- return cache.getEditorFor(nodeUuid);
+ return cache.getEditorFor(nodeId, location.getPath());
} catch (ItemNotFoundException err) {
- String msg = JcrI18n.nodeHasAlreadyBeenRemovedFromThisSession.text(nodeUuid,
cache.workspaceName());
+ String msg = JcrI18n.nodeHasAlreadyBeenRemovedFromThisSession.text(nodeId,
cache.workspaceName());
throw new RepositoryException(msg);
} catch (InvalidItemStateException err) {
- String msg = JcrI18n.nodeHasAlreadyBeenRemovedFromThisSession.text(nodeUuid,
cache.workspaceName());
+ String msg = JcrI18n.nodeHasAlreadyBeenRemovedFromThisSession.text(nodeId,
cache.workspaceName());
throw new RepositoryException(msg);
}
}
- final NodeEditor editorFor( Graph.Batch operations ) throws RepositoryException {
- try {
- return cache.getEditorFor(nodeUuid, operations);
- } catch (ItemNotFoundException err) {
- String msg = JcrI18n.nodeHasAlreadyBeenRemovedFromThisSession.text(nodeUuid,
cache.workspaceName());
- throw new RepositoryException(msg);
- } catch (InvalidItemStateException err) {
- String msg = JcrI18n.nodeHasAlreadyBeenRemovedFromThisSession.text(nodeUuid,
cache.workspaceName());
- throw new RepositoryException(msg);
- }
- }
-
final JcrValue valueFrom( int propertyType,
Object value ) {
return new JcrValue(cache.factories(), cache, propertyType, value);
@@ -166,7 +164,7 @@
return new JcrValue(factories, cache, PropertyType.DATE, binary);
}
- final JcrValue valueFrom( Node value ) throws
UnsupportedRepositoryOperationException, RepositoryException {
+ final JcrValue valueFrom( javax.jcr.Node value ) throws
UnsupportedRepositoryOperationException, RepositoryException {
ValueFactories factories = cache.factories();
String uuid = factories.getStringFactory().create(value.getUUID());
return new JcrValue(factories, cache, PropertyType.REFERENCE, uuid);
@@ -188,21 +186,31 @@
@Override
Path path() throws RepositoryException {
- return cache.getPathFor(nodeInfo());
+ // Don't use the path in the location, since it may no longer be valid
+ return nodeInfo().getPath();
}
+ boolean isReferenceable() throws RepositoryException {
+ return isNodeType(JcrMixLexicon.REFERENCEABLE);
+ }
+
/**
* {@inheritDoc}
*
* @see javax.jcr.Node#getUUID()
*/
- public final String getUUID() throws RepositoryException {
+ public String getUUID() throws RepositoryException {
// Return "jcr:uuid" only if node is referenceable
- String referenceableTypeName =
JcrMixLexicon.REFERENCEABLE.getString(namespaces());
- if (!isNodeType(referenceableTypeName)) {
+ if (!isReferenceable()) {
throw new UnsupportedRepositoryOperationException();
}
- return nodeUuid.toString();
+ PropertyInfo<JcrPropertyPayload> uuidProp =
nodeInfo().getProperty(JcrLexicon.UUID);
+ if (uuidProp == null) {
+ uuidProp = nodeInfo().getProperty(DnaLexicon.UUID);
+ }
+ assert uuidProp != null;
+ assert !uuidProp.getProperty().isEmpty();
+ return
context().getValueFactories().getStringFactory().create(uuidProp.getProperty().getFirstValue());
}
/**
@@ -222,19 +230,30 @@
* @see javax.jcr.Node#isNodeType(java.lang.String)
*/
public boolean isNodeType( String nodeTypeName ) throws RepositoryException {
- NodeType nodeType = getPrimaryNodeType();
+ return isNodeType(nameFrom(nodeTypeName));
+ }
+ /**
+ * Determine whether this node's primary type or any of the mixins are or extend
the node type with the supplied name. This
+ * method is semantically equivalent to but slightly more efficient than the {@link
#isNodeType(String) equivalent in the JCR
+ * API}, especially when the node type name is already a {@link Name} object.
+ *
+ * @param nodeTypeName the name of the node type
+ * @return true if this node is of the node type given by the supplied name, or false
otherwise
+ * @throws RepositoryException if there is an exception
+ */
+ public final boolean isNodeType( Name nodeTypeName ) throws RepositoryException {
+ JcrNodeType nodeType = getPrimaryNodeType();
if (nodeType.isNodeType(nodeTypeName)) {
return true;
}
-
- NodeType[] mixinNodeTypes = getMixinNodeTypes();
- for (int i = 0; i < mixinNodeTypes.length; i++) {
- if (mixinNodeTypes[i].isNodeType(nodeTypeName)) {
+ JcrNodeTypeManager nodeTypes = session().nodeTypeManager();
+ for (Name mixinTypeName : getMixinTypeNames()) {
+ JcrNodeType mixinType = nodeTypes.getNodeType(mixinTypeName);
+ if (mixinType.isNodeType(nodeTypeName)) {
return true;
}
}
-
return false;
}
@@ -244,7 +263,7 @@
* @see javax.jcr.Node#getDefinition()
*/
public NodeDefinition getDefinition() throws RepositoryException {
- NodeDefinitionId definitionId = nodeInfo().getDefinitionId();
+ NodeDefinitionId definitionId = nodeInfo().getPayload().getDefinitionId();
return session().nodeTypeManager().getNodeDefinition(definitionId);
}
@@ -254,12 +273,11 @@
* @see javax.jcr.Node#getPrimaryNodeType()
*/
public JcrNodeType getPrimaryNodeType() throws RepositoryException {
- Name primaryTypeName = nodeInfo().getPrimaryTypeName();
- return session().nodeTypeManager().getNodeType(primaryTypeName);
+ return session().nodeTypeManager().getNodeType(getPrimaryTypeName());
}
Name getPrimaryTypeName() throws RepositoryException {
- return nodeInfo().getPrimaryTypeName();
+ return nodeInfo().getPayload().getPrimaryTypeName();
}
/**
@@ -281,7 +299,7 @@
}
List<Name> getMixinTypeNames() throws RepositoryException {
- return nodeInfo().getMixinTypeNames();
+ return nodeInfo().getPayload().getMixinTypeNames();
}
/**
@@ -306,7 +324,7 @@
getPath(),
cache.workspaceName()));
}
- return cache.findJcrItem(nodeUuid, primaryItemPath);
+ return cache.findJcrItem(nodeId, location.getPath(), primaryItemPath);
} catch (ValueFormatException error) {
I18n msg = JcrI18n.primaryItemNameForPrimaryTypeIsNotValid;
throw new ItemNotFoundException(msg.text(primaryType.getName(),
@@ -331,9 +349,22 @@
@Override
public boolean isSame( Item otherItem ) throws RepositoryException {
CheckArg.isNotNull(otherItem, "otherItem");
- if (super.isSame(otherItem) && otherItem instanceof Node) {
+ if (super.isSame(otherItem) && otherItem instanceof javax.jcr.Node) {
if (otherItem instanceof AbstractJcrNode) {
- return
internalUuid().equals(((AbstractJcrNode)otherItem).internalUuid());
+ AbstractJcrNode that = (AbstractJcrNode)otherItem;
+ if (this.isReferenceable() && that.isReferenceable()) {
+ // Both are referenceable, so compare the UUIDs ...
+ return getUUID().equals(((AbstractJcrNode)otherItem).getUUID());
+ }
+
+ // One or both are not referenceable, so find the nearest ancestor that
is referenceable.
+ // The correspondence identifier (per Section 4.10.2 of JSR-170, version
1.0.1) for a
+ // non-referenceable node is the pair of the UUID of the nearest
referenceable ancestor and
+ // the relative path from that referenceable ancestor. Per Section 6.2.8,
two non-referenceable
+ // nodes are the same if they have the same correspondence identifier.
+ CorrespondenceId thisId = this.getCorrespondenceId();
+ CorrespondenceId thatId = that.getCorrespondenceId();
+ return thisId.equals(thatId);
}
// If not our implementation, let the other item figure out whether we are
the same.
return otherItem.isSame(this);
@@ -341,13 +372,31 @@
return false;
}
+ public CorrespondenceId getCorrespondenceId() throws RepositoryException {
+ if (this.isReferenceable()) return new CorrespondenceId(getUUID());
+ assert !this.isRoot(); // the root must be referenceable
+
+ // Find the nearest ancestor that is referenceable ...
+ Path currentPath = path();
+ AbstractJcrNode node = this.getParent();
+ int beginIndex = currentPath.size() - 1;
+ while (!node.isRoot() && !node.isReferenceable()) {
+ node = node.getParent();
+ --beginIndex;
+ }
+ // Get the relative path from the ancestor to this node ...
+ Path relativePath = currentPath.relativeTo(node.path());
+ assert !relativePath.isAbsolute();
+ return new CorrespondenceId(node.getUUID(), relativePath);
+ }
+
/**
* {@inheritDoc}
*
* @see javax.jcr.Node#hasProperties()
*/
public final boolean hasProperties() throws RepositoryException {
- return nodeInfo().hasProperties();
+ return nodeInfo().getPropertyCount() > 0;
}
/**
@@ -369,16 +418,20 @@
if (relativePath.equals(".")) return false;
if (relativePath.equals("..")) return false;
// Otherwise it should be a property on this node ...
- return cache.findPropertyInfo(new PropertyId(nodeUuid, nameFrom(relativePath)))
!= null;
+ return nodeInfo().getProperty(nameFrom(relativePath)) != null;
}
+ public final boolean hasProperty( Name name ) throws RepositoryException {
+ return nodeInfo().getProperty(name) != null;
+ }
+
/**
* {@inheritDoc}
*
* @see javax.jcr.Node#getProperties()
*/
public final PropertyIterator getProperties() throws RepositoryException {
- return new JcrPropertyIterator(cache.findJcrPropertiesFor(nodeUuid));
+ return new JcrPropertyIterator(cache.findJcrPropertiesFor(nodeId,
location.getPath()));
}
/**
@@ -390,7 +443,7 @@
CheckArg.isNotNull(namePattern, "namePattern");
namePattern = namePattern.trim();
if (namePattern.length() == 0) return new JcrEmptyPropertyIterator();
- Collection<AbstractJcrProperty> properties =
cache.findJcrPropertiesFor(nodeUuid);
+ Collection<AbstractJcrProperty> properties =
cache.findJcrPropertiesFor(nodeId, location.getPath());
if ("*".equals(namePattern)) return new
JcrPropertyIterator(properties);
// Figure out the patterns for each of the different disjunctions in the supplied
pattern ...
@@ -433,7 +486,7 @@
if (true) throw new UnsupportedOperationException();
// This implementation is just wrong.
// Iterate through the properties to see which ones have a REFERENCE type ...
- Collection<AbstractJcrProperty> properties =
cache.findJcrPropertiesFor(nodeUuid);
+ Collection<AbstractJcrProperty> properties =
cache.findJcrPropertiesFor(nodeId, location.getPath());
Collection<AbstractJcrProperty> references = new
LinkedList<AbstractJcrProperty>();
Iterator<AbstractJcrProperty> iter = properties.iterator();
while (iter.hasNext()) {
@@ -452,7 +505,7 @@
* @throws RepositoryException if there is an error finding the property with the
supplied name
*/
public final Property getProperty( Name propertyName ) throws RepositoryException {
- return cache.findJcrProperty(new PropertyId(nodeUuid, propertyName));
+ return cache.findJcrProperty(nodeId, location.getPath(), propertyName);
}
/**
@@ -468,19 +521,30 @@
// Not a relative path ...
throw new
IllegalArgumentException(JcrI18n.invalidPathParameter.text(relativePath,
"relativePath"));
}
+ Name propertyName = null;
if (indexOfFirstSlash != -1) {
// We know it's a relative path with more than one segment ...
Path path = pathFrom(relativePath).getNormalizedPath();
- AbstractJcrItem item = cache.findJcrItem(nodeUuid, path);
- if (item instanceof Property) {
- return (Property)item;
+ if (path.size() > 1) {
+ try {
+ AbstractJcrItem item = cache.findJcrItem(nodeId, location.getPath(),
path);
+ if (item instanceof Property) {
+ return (Property)item;
+ }
+ } catch (ItemNotFoundException e) {
+ I18n msg = JcrI18n.propertyNotFoundAtPathRelativeToReferenceNode;
+ throw new PathNotFoundException(msg.text(relativePath, getPath(),
cache.workspaceName()));
+ }
+ I18n msg = JcrI18n.propertyNotFoundAtPathRelativeToReferenceNode;
+ throw new PathNotFoundException(msg.text(relativePath, getPath(),
cache.workspaceName()));
}
- I18n msg = JcrI18n.propertyNotFoundAtPathRelativeToReferenceNode;
- throw new PathNotFoundException(msg.text(relativePath, getPath(),
cache.workspaceName()));
+ propertyName = path.getLastSegment().getName();
+ } else {
+ propertyName = nameFrom(relativePath);
}
// It's just a name, so look for it directly ...
- Property property = getProperty(nameFrom(relativePath));
- if (property != null) return property;
+ Property result = getProperty(propertyName);
+ if (result != null) return result;
I18n msg = JcrI18n.pathNotFoundRelativeTo;
throw new PathNotFoundException(msg.text(relativePath, getPath(),
cache.workspaceName()));
}
@@ -503,16 +567,19 @@
if (indexOfFirstSlash != -1) {
Path path = pathFrom(relativePath).getNormalizedPath();
try {
- AbstractJcrNode item = cache.findJcrNode(nodeUuid, path);
+ AbstractJcrNode item = cache.findJcrNode(nodeId, location.getPath(),
path);
return item != null;
} catch (PathNotFoundException e) {
return false;
}
}
// It's just a name, so look for a child ...
- Path.Segment segment = segmentFrom(relativePath);
- ChildNode child = nodeInfo().getChildren().getChild(segment);
- return child != null;
+ try {
+ Path.Segment segment = segmentFrom(relativePath);
+ return nodeInfo().getChild(segment) != null;
+ } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
+ return false;
+ }
}
/**
@@ -521,7 +588,7 @@
* @see javax.jcr.Node#hasNodes()
*/
public final boolean hasNodes() throws RepositoryException {
- return nodeInfo().getChildren().size() > 0;
+ return nodeInfo().getChildrenCount() > 0;
}
/**
@@ -530,7 +597,7 @@
* @throws IllegalArgumentException if <code>relativePath</code> is empty
or <code>null</code>.
* @see javax.jcr.Node#getNode(java.lang.String)
*/
- public final Node getNode( String relativePath ) throws RepositoryException {
+ public final javax.jcr.Node getNode( String relativePath ) throws RepositoryException
{
CheckArg.isNotEmpty(relativePath, "relativePath");
if (relativePath.equals(".")) return this;
if (relativePath.equals("..")) return this.getParent();
@@ -539,24 +606,36 @@
// Not a relative path ...
throw new
IllegalArgumentException(JcrI18n.invalidPathParameter.text(relativePath,
"relativePath"));
}
+ Path.Segment segment = null;
if (indexOfFirstSlash != -1) {
// We know it's a relative path with more than one segment ...
Path path = pathFrom(relativePath).getNormalizedPath();
- AbstractJcrItem item = cache.findJcrItem(nodeUuid, path);
- if (item instanceof Node) {
- return (Node)item;
+ if (path.size() == 1) {
+ if (path.getLastSegment().isSelfReference()) return this;
+ if (path.getLastSegment().isParentReference()) return this.getParent();
}
- I18n msg = JcrI18n.nodeNotFoundAtPathRelativeToReferenceNode;
- throw new PathNotFoundException(msg.text(relativePath, getPath(),
cache.workspaceName()));
+ // We know it's a resolved relative path with more than one segment ...
+ if (path.size() > 1) {
+ AbstractJcrItem item = cache.findJcrNode(nodeId, location.getPath(),
path);
+ if (item instanceof javax.jcr.Node) {
+ return (javax.jcr.Node)item;
+ }
+ I18n msg = JcrI18n.nodeNotFoundAtPathRelativeToReferenceNode;
+ throw new PathNotFoundException(msg.text(relativePath, getPath(),
cache.workspaceName()));
+ }
+ segment = path.getLastSegment();
+ } else {
+ segment = segmentFrom(relativePath);
}
// It's just a name, so look for a child ...
- Path.Segment segment = segmentFrom(relativePath);
- ChildNode child = nodeInfo().getChildren().getChild(segment);
- if (child != null) {
- return cache.findJcrNode(child.getUuid());
+ try {
+ return nodeInfo().getChild(segment).getPayload().getJcrNode();
+ } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
+ String msg = JcrI18n.childNotFoundUnderNode.text(segment, getPath(),
cache.workspaceName());
+ throw new PathNotFoundException(msg);
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getLocalizedMessage(), e);
}
- String msg = JcrI18n.childNotFoundUnderNode.text(segment, getPath(),
cache.workspaceName());
- throw new PathNotFoundException(msg);
}
/**
@@ -565,11 +644,15 @@
* @see javax.jcr.Node#getNodes()
*/
public final NodeIterator getNodes() throws RepositoryException {
- Children children = nodeInfo().getChildren();
- if (children.size() == 0) {
+ int childCount = nodeInfo().getChildrenCount();
+ if (childCount == 0) {
return new JcrEmptyNodeIterator();
}
- return new JcrChildNodeIterator(cache, children, children.size());
+ List<AbstractJcrNode> matchingChildren = new
LinkedList<AbstractJcrNode>();
+ for (Node<JcrNodePayload, JcrPropertyPayload> child :
nodeInfo().getChildren()) {
+ matchingChildren.add(child.getPayload().getJcrNode());
+ }
+ return new JcrChildNodeIterator(matchingChildren, childCount);
}
/**
@@ -585,11 +668,10 @@
List<Object> patterns = createPatternsFor(namePattern);
// Implementing exact-matching only for now to prototype types as properties
- Children children = nodeInfo().getChildren();
- List<ChildNode> matchingChildren = new LinkedList<ChildNode>();
+ List<AbstractJcrNode> matchingChildren = new
LinkedList<AbstractJcrNode>();
NamespaceRegistry registry = namespaces();
boolean foundMatch = false;
- for (ChildNode child : children) {
+ for (Node<JcrNodePayload, JcrPropertyPayload> child :
nodeInfo().getChildren()) {
String childName = child.getName().getString(registry);
for (Object patternOrMatch : patterns) {
if (patternOrMatch instanceof Pattern) {
@@ -601,12 +683,12 @@
}
if (foundMatch) {
foundMatch = false;
- matchingChildren.add(child);
+ matchingChildren.add(child.getPayload().getJcrNode());
break;
}
}
}
- return new JcrChildNodeIterator(cache, matchingChildren,
matchingChildren.size());
+ return new JcrChildNodeIterator(matchingChildren, matchingChildren.size());
}
/**
@@ -685,8 +767,10 @@
// Check for any existing properties based on residual definitions that conflict
//
------------------------------------------------------------------------------
for (JcrPropertyDefinition propertyDefinition :
mixinCandidateType.propertyDefinitions()) {
- AbstractJcrProperty existingProp = cache.findJcrProperty(new
PropertyId(nodeUuid,
-
propertyDefinition.getInternalName()));
+ if (!hasProperty(propertyDefinition.getInternalName())) continue;
+ AbstractJcrProperty existingProp = cache.findJcrProperty(nodeId,
+ location.getPath(),
+
propertyDefinition.getInternalName());
if (existingProp != null) {
if (propertyDefinition.isMultiple()) {
if
(!propertyDefinition.canCastToTypeAndSatisfyConstraints(existingProp.getValues())) {
@@ -710,14 +794,12 @@
for (Name nodeName : mixinChildNodeNames) {
// Need to figure out if the child node requires an SNS definition
- int snsCount =
nodeInfo().getChildren().getCountOfSameNameSiblingsWithName(nodeName);
-
- for (Iterator<ChildNode> iter =
nodeInfo().getChildren().getChildren(nodeName); iter.hasNext();) {
- AbstractJcrNode childNode = cache.findJcrNode(iter.next().getUuid());
+ int snsCount = nodeInfo().getChildrenCount(nodeName);
+ for (Node<JcrNodePayload, JcrPropertyPayload> child :
nodeInfo().getChildren(nodeName)) {
JcrNodeDefinition match =
this.cache.nodeTypes().findChildNodeDefinition(mixinCandidateType.getInternalName(),
Collections.<Name>emptyList(),
nodeName,
-
childNode.getPrimaryNodeType().getInternalName(),
+
child.getPayload().getPrimaryTypeName(),
snsCount,
false);
@@ -860,7 +942,7 @@
for (NodeIterator iter = getNodes(); iter.hasNext();) {
AbstractJcrNode node = (AbstractJcrNode)iter.nextNode();
Name childNodeName = cache.nameFactory.create(node.getName());
- int snsCount =
node.nodeInfo().getChildren().getCountOfSameNameSiblingsWithName(childNodeName);
+ int snsCount = node.nodeInfo().getChildrenCount(childNodeName);
if (mixinName.equals(node.getDefinition().getDeclaringNodeType().getName()))
{
// Only the residual definition would work - if there were any other
definition for this name,
// the mixin type would not have been added due to the conflict
@@ -877,8 +959,7 @@
}
}
- cache.findJcrProperty(editor().setProperty(JcrLexicon.MIXIN_TYPES,
newMixinValues, PropertyType.NAME, false));
-
+ editor().setProperty(JcrLexicon.MIXIN_TYPES, newMixinValues, PropertyType.NAME,
false);
}
/**
@@ -886,10 +967,10 @@
*
* @see javax.jcr.Node#addNode(java.lang.String)
*/
- public final Node addNode( String relPath )
+ public final javax.jcr.Node addNode( String relPath )
throws ItemExistsException, PathNotFoundException, VersionException,
ConstraintViolationException, LockException,
RepositoryException {
- return addNode(relPath, null);
+ return addNode(relPath, null, null);
}
/**
@@ -897,8 +978,8 @@
*
* @see javax.jcr.Node#addNode(java.lang.String, java.lang.String)
*/
- public final Node addNode( String relPath,
- String primaryNodeTypeName )
+ public final javax.jcr.Node addNode( String relPath,
+ String primaryNodeTypeName )
throws ItemExistsException, PathNotFoundException, VersionException,
ConstraintViolationException, LockException,
RepositoryException {
return this.addNode(relPath, primaryNodeTypeName, null);
@@ -940,17 +1021,17 @@
if (path.getLastSegment().getIndex() > 1 || relPath.endsWith("]"))
{
throw new RepositoryException(JcrI18n.invalidPathParameter.text(relPath,
"relPath"));
}
- if (path.size() != 1) {
+ if (path.size() > 1) {
// The only segment in the path is the child name ...
- NodeInfo parentInfo = null;
Path parentPath = path.getParent();
try {
- parentInfo = cache.findNodeInfo(nodeUuid, parentPath); // throws
PathNotFoundException
- editor = cache.getEditorFor(parentInfo.getUuid());
- } catch (PathNotFoundException e) {
+ // Find the parent node ...
+ Node<JcrNodePayload, JcrPropertyPayload> parentOfNewNode =
cache.findNode(nodeId, location.getPath(), parentPath);
+ editor = cache.getEditorFor(parentOfNewNode);
+ } catch (RepositoryException e) {
// We're going to throw an exception ... the question is which one
...
try {
- NodeInfo grandparentInfo;
+ Node<JcrNodePayload, JcrPropertyPayload> grandparent;
if (parentPath.size() > 1) {
// Per the TCK, if relPath references a property, then we have to
throw a ConstraintViolationException
// So, if we can't find the parent, try for the parent's
parent and see if the last segment of the
@@ -959,12 +1040,13 @@
Path grandparentPath = parentPath.getParent();
assert grandparentPath != null;
- grandparentInfo = cache.findNodeInfo(nodeUuid, grandparentPath);
// throws PathNotFoundException
+ grandparent = cache.findNode(nodeId, location.getPath(),
grandparentPath); // throws
+ // PathNotFoundException
} else {
- grandparentInfo = this.nodeInfo();
+ grandparent = this.nodeInfo();
}
- if
(grandparentInfo.getProperty(parentPath.getLastSegment().getName()) != null) {
+ if (grandparent.getProperty(parentPath.getLastSegment().getName()) !=
null) {
// Need to throw a ConstraintViolationException since the request
was to add a child to
// a property ...
throw new
ConstraintViolationException(JcrI18n.invalidPathParameter.text(relPath,
"relPath"));
@@ -994,13 +1076,11 @@
}
// Create the child ...
- ChildNode child = editor.createChild(childName, desiredUuid,
childPrimaryTypeName);
- return cache.findJcrNode(child.getUuid());
+ return editor.createChild(childName, desiredUuid, childPrimaryTypeName);
}
protected final Property removeExistingValuedProperty( String name ) throws
ConstraintViolationException, RepositoryException {
- PropertyId id = new PropertyId(nodeUuid, nameFrom(name));
- AbstractJcrProperty property = cache.findJcrProperty(id);
+ AbstractJcrProperty property = cache.findJcrProperty(nodeId, location.getPath(),
nameFrom(name));
if (property != null) {
property.remove();
return property;
@@ -1017,7 +1097,7 @@
public final Property setProperty( String name,
boolean value )
throws ValueFormatException, VersionException, LockException,
ConstraintViolationException, RepositoryException {
- return cache.findJcrProperty(editor().setProperty(nameFrom(name),
valueFrom(PropertyType.BOOLEAN, value)));
+ return editor().setProperty(nameFrom(name), valueFrom(PropertyType.BOOLEAN,
value));
}
/**
@@ -1033,7 +1113,7 @@
return removeExistingValuedProperty(name);
}
- return cache.findJcrProperty(editor().setProperty(nameFrom(name),
valueFrom(value)));
+ return editor().setProperty(nameFrom(name), valueFrom(value));
}
/**
@@ -1044,7 +1124,7 @@
public final Property setProperty( String name,
double value )
throws ValueFormatException, VersionException, LockException,
ConstraintViolationException, RepositoryException {
- return cache.findJcrProperty(editor().setProperty(nameFrom(name),
valueFrom(PropertyType.DOUBLE, value)));
+ return editor().setProperty(nameFrom(name), valueFrom(PropertyType.DOUBLE,
value));
}
/**
@@ -1059,7 +1139,7 @@
return removeExistingValuedProperty(name);
}
- return cache.findJcrProperty(editor().setProperty(nameFrom(name),
valueFrom(value)));
+ return editor().setProperty(nameFrom(name), valueFrom(value));
}
/**
@@ -1070,7 +1150,7 @@
public final Property setProperty( String name,
long value )
throws ValueFormatException, VersionException, LockException,
ConstraintViolationException, RepositoryException {
- return cache.findJcrProperty(editor().setProperty(nameFrom(name),
valueFrom(PropertyType.LONG, value)));
+ return editor().setProperty(nameFrom(name), valueFrom(PropertyType.LONG,
value));
}
/**
@@ -1079,13 +1159,13 @@
* @see javax.jcr.Node#setProperty(java.lang.String, javax.jcr.Node)
*/
public final Property setProperty( String name,
- Node value )
+ javax.jcr.Node value )
throws ValueFormatException, VersionException, LockException,
ConstraintViolationException, RepositoryException {
if (value == null) {
return removeExistingValuedProperty(name);
}
- return cache.findJcrProperty(editor().setProperty(nameFrom(name),
valueFrom(value)));
+ return editor().setProperty(nameFrom(name), valueFrom(value));
}
/**
@@ -1100,7 +1180,7 @@
return removeExistingValuedProperty(name);
}
- return cache.findJcrProperty(editor().setProperty(nameFrom(name),
valueFrom(PropertyType.STRING, value)));
+ return editor().setProperty(nameFrom(name), valueFrom(PropertyType.STRING,
value));
}
/**
@@ -1116,7 +1196,7 @@
return removeExistingValuedProperty(name);
}
- return cache.findJcrProperty(editor().setProperty(nameFrom(name), valueFrom(type,
value)));
+ return editor().setProperty(nameFrom(name), valueFrom(type, value));
}
/**
@@ -1131,9 +1211,7 @@
return removeExistingValuedProperty(name);
}
- return cache.findJcrProperty(editor().setProperty(nameFrom(name),
- valuesFrom(PropertyType.STRING,
values),
- PropertyType.UNDEFINED));
+ return editor().setProperty(nameFrom(name), valuesFrom(PropertyType.STRING,
values), PropertyType.UNDEFINED);
}
/**
@@ -1149,7 +1227,7 @@
return removeExistingValuedProperty(name);
}
- return cache.findJcrProperty(editor().setProperty(nameFrom(name),
valuesFrom(type, values), PropertyType.UNDEFINED));
+ return editor().setProperty(nameFrom(name), valuesFrom(type, values),
PropertyType.UNDEFINED);
}
/**
@@ -1164,7 +1242,7 @@
return removeExistingValuedProperty(name);
}
- return cache.findJcrProperty(editor().setProperty(nameFrom(name),
(JcrValue)value));
+ return editor().setProperty(nameFrom(name), (JcrValue)value);
}
/**
@@ -1180,7 +1258,7 @@
return removeExistingValuedProperty(name);
}
- return cache.findJcrProperty(editor().setProperty(nameFrom(name),
((JcrValue)value).asType(type)));
+ return editor().setProperty(nameFrom(name), ((JcrValue)value).asType(type));
}
/**
@@ -1214,7 +1292,7 @@
}
// Set the value, perhaps to an empty array ...
- return cache.findJcrProperty(editor().setProperty(nameFrom(name), values,
type));
+ return editor().setProperty(nameFrom(name), values, type);
}
/**
@@ -1305,7 +1383,9 @@
*/
public final boolean isModified() {
try {
- return nodeInfo().isModified();
+ Node<JcrNodePayload, JcrPropertyPayload> node = nodeInfo();
+ // Considered modified if *not* new but changed
+ return !node.isNew() && node.isChanged(true);
} catch (RepositoryException re) {
throw new IllegalStateException(re);
}
@@ -1356,68 +1436,41 @@
}
/**
- * Obtain the corresponding node path from the supplied workspace name.
+ * {@inheritDoc}
*
- * @param workspaceName
- * @return the path of the corresponding node in the supplied workspace
- * @throws NoSuchWorkspaceException if the workspace does not exist
- * @throws ItemNotFoundException if there is no corresponding node in the supplied
workspace
- * @throws RepositoryException if there is another problem
+ * @see javax.jcr.Node#getCorrespondingNodePath(java.lang.String)
*/
- final Path correspondingNodePathFrom( String workspaceName )
+ public final String getCorrespondingNodePath( String workspaceName )
throws NoSuchWorkspaceException, ItemNotFoundException, RepositoryException {
-
- assert workspaceName != null;
-
+ CheckArg.isNotNull(workspaceName, "workspace name");
NamespaceRegistry namespaces = this.context().getNamespaceRegistry();
+ // Find the closest ancestor (including this node) that is referenceable ...
AbstractJcrNode referenceableRoot = this;
while
(!referenceableRoot.isNodeType(JcrMixLexicon.REFERENCEABLE.getString(namespaces))) {
referenceableRoot = referenceableRoot.getParent();
}
- UUID uuid = referenceableRoot.internalUuid();
+ // Find the relative path from the nearest referenceable node to this node (or
null if this node is referenceable) ...
Path relativePath = path().equals(referenceableRoot.path()) ? null :
path().relativeTo(referenceableRoot.path());
-
- Path correspondingPath = this.cache.getPathFor(workspaceName, uuid,
relativePath);
-
- try {
- this.session().checkPermission(workspaceName, correspondingPath,
"read");
- } catch (AccessControlException ace) {
- throw new AccessDeniedException(ace);
- }
-
- return correspondingPath;
+ UUID uuid = UUID.fromString(referenceableRoot.getUUID());
+ return this.cache.getPathForCorrespondingNode(workspaceName, uuid,
relativePath).getString(namespaces);
}
/**
* {@inheritDoc}
*
- * @see javax.jcr.Node#getCorrespondingNodePath(java.lang.String)
- */
- public final String getCorrespondingNodePath( String workspaceName )
- throws NoSuchWorkspaceException, ItemNotFoundException, RepositoryException {
-
- CheckArg.isNotNull(workspaceName, "workspace name");
- return correspondingNodePathFrom(workspaceName).getString(this.namespaces());
- }
-
- /**
- * {@inheritDoc}
- *
* @see javax.jcr.Node#update(java.lang.String)
*/
public final void update( String srcWorkspaceName ) throws NoSuchWorkspaceException,
RepositoryException {
CheckArg.isNotNull(srcWorkspaceName, "workspace name");
- Path correspondingPath;
-
if (session().hasPendingChanges()) {
throw new InvalidItemStateException(JcrI18n.noPendingChangesAllowed.text());
}
try {
- correspondingPath = correspondingNodePathFrom(srcWorkspaceName);
+ getCorrespondingNodePath(srcWorkspaceName);
} catch (ItemNotFoundException infe) {
return;
}
@@ -1507,27 +1560,23 @@
}
PathFactory pathFactory = this.cache.pathFactory();
-
Path srcPath = pathFactory.create(srcChildRelPath);
- ChildNode source;
-
if (srcPath.isAbsolute() || srcPath.size() != 1) {
throw new ItemNotFoundException();
}
// getLastSegment should return the only segment, since we verified that size()
== 1
Path.Segment sourceSegment = srcPath.getLastSegment();
- source = nodeInfo().getChildren().getChild(sourceSegment);
- if (source == null) {
+ try {
+ nodeInfo().getChild(sourceSegment);
+ } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
String workspaceName = this.cache.session().getWorkspace().getName();
throw new ItemNotFoundException(JcrI18n.pathNotFound.text(srcPath,
workspaceName));
}
- Path destPath = null;
Path.Segment destSegment = null;
- ChildNode destination = null;
if (destChildRelPath != null) {
- destPath = pathFactory.create(destChildRelPath);
+ Path destPath = pathFactory.create(destChildRelPath);
if (destPath.isAbsolute() || destPath.size() != 1) {
throw new ItemNotFoundException();
}
@@ -1535,15 +1584,15 @@
destSegment = destPath.getLastSegment();
// getLastSegment should return the only segment, since we verified that
size() == 1
- destination = nodeInfo().getChildren().getChild(destSegment);
- if (destination == null) {
+ try {
+ nodeInfo().getChild(destSegment);
+ } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
String workspaceName = this.cache.session().getWorkspace().getName();
throw new ItemNotFoundException(JcrI18n.pathNotFound.text(destPath,
workspaceName));
}
}
this.editor().orderChildBefore(sourceSegment, destSegment);
-
}
protected static List<Object> createPatternsFor( String namePattern ) throws
RepositoryException {
@@ -1609,7 +1658,7 @@
* @see javax.jcr.Item#refresh(boolean)
*/
public void refresh( boolean keepChanges ) throws RepositoryException {
- this.cache.refresh(this.nodeUuid, keepChanges);
+ this.cache.refresh(this.nodeId, keepChanges);
}
/**
@@ -1618,7 +1667,7 @@
* @see javax.jcr.Item#save()
*/
public void save() throws RepositoryException {
- cache.save(nodeUuid);
+ cache.save(nodeId, location.getPath());
}
@Override
@@ -1636,4 +1685,20 @@
return re.getMessage();
}
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof AbstractJcrNode) {
+ AbstractJcrNode that = (AbstractJcrNode)obj;
+ if (this.cache != that.cache) return false;
+ return this.location.equals(that.location);
+ }
+ return false;
+ }
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -39,26 +39,31 @@
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.session.GraphSession.PropertyInfo;
+import org.jboss.dna.jcr.SessionCache.JcrPropertyPayload;
import org.jboss.dna.jcr.SessionCache.NodeEditor;
-import org.jboss.dna.jcr.cache.PropertyInfo;
/**
* @author jverhaeg
*/
@NotThreadSafe
-abstract class AbstractJcrProperty extends AbstractJcrItem implements Property {
+abstract class AbstractJcrProperty extends AbstractJcrItem implements Property,
Comparable<Property> {
- protected final PropertyId propertyId;
+ protected final AbstractJcrNode node;
+ protected final Name name;
AbstractJcrProperty( SessionCache cache,
- PropertyId propertyId ) {
+ AbstractJcrNode node,
+ Name name ) {
super(cache);
- assert propertyId != null;
- this.propertyId = propertyId;
+ assert node != null;
+ assert name != null;
+ this.node = node;
+ this.name = name;
}
final NodeEditor editor() throws ItemNotFoundException, InvalidItemStateException,
RepositoryException {
- return cache.getEditorFor(propertyId.getNodeId());
+ return node.editor();
}
abstract boolean isMultiple();
@@ -74,20 +79,24 @@
visitor.visit(this);
}
- final PropertyInfo propertyInfo() throws PathNotFoundException, RepositoryException
{
- return cache.findPropertyInfo(propertyId);
+ final PropertyInfo<JcrPropertyPayload> propertyInfo() throws
PathNotFoundException, RepositoryException {
+ return node.nodeInfo().getProperty(name);
}
- final Name name() throws RepositoryException {
- return propertyInfo().getPropertyName();
+ final Name name() {
+ return name;
}
+ final JcrPropertyPayload payload() throws RepositoryException {
+ return propertyInfo().getPayload();
+ }
+
final org.jboss.dna.graph.property.Property property() throws RepositoryException {
return propertyInfo().getProperty();
}
JcrValue createValue( Object value ) throws RepositoryException {
- return new JcrValue(context().getValueFactories(), this.cache,
propertyInfo().getPropertyType(), value);
+ return new JcrValue(context().getValueFactories(), this.cache,
payload().getPropertyType(), value);
}
final JcrValue createValue( Object value,
@@ -97,7 +106,7 @@
@Override
Path path() throws RepositoryException {
- return cache.getPathFor(propertyInfo());
+ return context().getValueFactories().getPathFactory().create(node.path(), name);
}
/**
@@ -106,7 +115,7 @@
* @see javax.jcr.Property#getType()
*/
public int getType() throws RepositoryException {
- return propertyInfo().getPropertyType();
+ return payload().getPropertyType();
}
/**
@@ -115,9 +124,7 @@
* @see javax.jcr.Property#getDefinition()
*/
public final PropertyDefinition getDefinition() throws RepositoryException {
- PropertyInfo info = propertyInfo();
- PropertyDefinitionId definitionId = info.getDefinitionId();
- return cache.session().nodeTypeManager().getPropertyDefinition(definitionId);
+ return
cache.session().nodeTypeManager().getPropertyDefinition(payload().getPropertyDefinitionId());
}
/**
@@ -129,8 +136,8 @@
*
* @see javax.jcr.Item#getName()
*/
- public final String getName() throws RepositoryException {
- return propertyInfo().getPropertyName().getString(namespaces());
+ public final String getName() {
+ return name.getString(namespaces());
}
/**
@@ -138,8 +145,8 @@
*
* @see javax.jcr.Item#getParent()
*/
- public final Node getParent() throws RepositoryException {
- return cache.findJcrNode(propertyId.getNodeId());
+ public final Node getParent() {
+ return node;
}
/**
@@ -148,7 +155,7 @@
* @see javax.jcr.Item#getPath()
*/
public final String getPath() throws RepositoryException {
- return cache.getPathFor(propertyInfo()).getString(namespaces());
+ return path().getString(namespaces());
}
/**
@@ -159,8 +166,7 @@
public final boolean isModified() {
try {
return propertyInfo().isModified();
- }
- catch (RepositoryException re) {
+ } catch (RepositoryException re) {
throw new IllegalStateException(re);
}
}
@@ -173,8 +179,7 @@
public final boolean isNew() {
try {
return propertyInfo().isNew();
- }
- catch (RepositoryException re) {
+ } catch (RepositoryException re) {
throw new IllegalStateException(re);
}
}
@@ -222,7 +227,7 @@
* @see javax.jcr.Item#remove()
*/
public void remove() throws VersionException, LockException,
ConstraintViolationException, RepositoryException {
- editor().removeProperty(propertyId.getPropertyName());
+ editor().removeProperty(name);
}
/**
@@ -234,4 +239,18 @@
public void save() {
throw new UnsupportedOperationException();
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo( Property that ) {
+ if (that == this) return 0;
+ try {
+ return this.getName().compareTo(that.getName());
+ } catch (RepositoryException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
Added: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/CorrespondenceId.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/CorrespondenceId.java
(rev 0)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/CorrespondenceId.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -0,0 +1,102 @@
+/*
+ * JBoss DNA (
http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you 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.
+ *
+ * JBoss DNA 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.jcr;
+
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.common.util.HashCode;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.basic.BasicPath;
+
+/**
+ * A correspondence identifier is defined to be the pair of the UUID of the nearest
referenceable ancestor and the relative path
+ * from that referenceable ancestor to the node of interest. If any node is a
referenceable node, then the correspondence
+ * identifier is just the UUID of the node. Per Section 4.10.2 of JSR-170, version
1.0.1.
+ * <p>
+ * Note that per Section 6.2.8, two non-referenceable nodes are the same if they have the
same correspondence identifier.
+ * </p>
+ */
+@Immutable
+public class CorrespondenceId {
+
+ private static final Path NO_PATH = BasicPath.SELF_PATH;
+
+ private final String referenceableId;
+ private final Path relativePath;
+ private final int hc;
+
+ public CorrespondenceId( String referenceableId ) {
+ this(referenceableId, NO_PATH);
+ }
+
+ public CorrespondenceId( String referenceableId,
+ Path relativePath ) {
+ CheckArg.isNotNull(referenceableId, "referenceableId");
+ CheckArg.isNotNull(relativePath, "relativePath");
+ assert !relativePath.isAbsolute();
+ this.referenceableId = referenceableId;
+ this.relativePath = relativePath;
+ this.hc = HashCode.compute(this.referenceableId, this.relativePath);
+ }
+
+ /**
+ * @return referenceableId
+ */
+ public String getReferenceableId() {
+ return referenceableId;
+ }
+
+ /**
+ * @return relativePath
+ */
+ public Path getRelativePath() {
+ return relativePath;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return hc;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof CorrespondenceId) {
+ CorrespondenceId that = (CorrespondenceId)obj;
+ return this.referenceableId.equals(that.referenceableId) &&
this.relativePath.equals(that.relativePath);
+ }
+ return false;
+ }
+
+}
Property changes on: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/CorrespondenceId.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrChildNodeIterator.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrChildNodeIterator.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrChildNodeIterator.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -24,29 +24,22 @@
package org.jboss.dna.jcr;
import java.util.Iterator;
-import javax.jcr.Node;
import javax.jcr.NodeIterator;
-import javax.jcr.RepositoryException;
import net.jcip.annotations.Immutable;
import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.jcr.cache.ChildNode;
/**
*/
@Immutable
final class JcrChildNodeIterator implements NodeIterator {
- private final SessionCache cache;
- private final Iterator<ChildNode> iterator;
+ private final Iterator<AbstractJcrNode> iterator;
private int ndx;
private int size;
- JcrChildNodeIterator( SessionCache cache,
- Iterable<ChildNode> children,
+ JcrChildNodeIterator( Iterable<AbstractJcrNode> children,
int size ) {
- assert cache != null;
assert children != null;
- this.cache = cache;
iterator = children.iterator();
this.size = size;
}
@@ -92,14 +85,10 @@
*
* @see javax.jcr.NodeIterator#nextNode()
*/
- public Node nextNode() {
- ChildNode child = iterator.next();
+ public javax.jcr.Node nextNode() {
+ AbstractJcrNode child = iterator.next();
ndx++;
- try {
- return cache.findJcrNode(child.getUuid());
- } catch (RepositoryException error) {
- throw new RuntimeException(error);
- }
+ return child;
}
/**
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -29,15 +29,12 @@
import java.util.List;
import java.util.Map;
import java.util.Stack;
-import java.util.UUID;
import javax.jcr.ImportUUIDBehavior;
-import javax.jcr.ItemExistsException;
import javax.jcr.PathNotFoundException;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFormatException;
-import javax.jcr.nodetype.ConstraintViolationException;
import net.jcip.annotations.NotThreadSafe;
import org.jboss.dna.common.text.TextDecoder;
import org.jboss.dna.common.text.XmlNameEncoder;
@@ -303,57 +300,58 @@
}
private void addNodeIfPending() throws SAXException {
- if (currentNodeName != null) {
- try {
- AbstractJcrNode parentNode = parentStack.peek();
-
- UUID uuid = null;
- List<Value> rawUuid = currentProps.get(uuidName);
-
- if (rawUuid != null) {
- assert rawUuid.size() == 1;
- uuid = UUID.fromString(rawUuid.get(0).getString());
- }
-
- String typeName =
currentProps.get(primaryTypeName).get(0).getString();
- AbstractJcrNode newNode =
cache().findJcrNode(parentNode.editorFor(operations()).createChild(nameFor(currentNodeName),
-
uuid,
-
nameFor(typeName)).getUuid());
-
- for (Map.Entry<String, List<Value>> entry :
currentProps.entrySet()) {
- if (entry.getKey().equals(primaryTypeName)) {
- continue;
- }
-
- if (entry.getKey().equals(mixinTypesName)) {
- for (Value value : entry.getValue()) {
- JcrNodeType mixinType =
session.workspace().nodeTypeManager().getNodeType(nameFor(value.getString()));
- newNode.editorFor(operations()).addMixin(mixinType);
- }
- continue;
- }
-
- if (entry.getKey().equals(uuidName)) {
- continue;
- }
-
- List<Value> values = entry.getValue();
-
- if (values.size() == 1) {
-
newNode.editorFor(operations()).setProperty(nameFor(entry.getKey()),
(JcrValue)values.get(0));
- } else {
-
newNode.editorFor(operations()).setProperty(nameFor(entry.getKey()),
-
values.toArray(new Value[values.size()]),
-
PropertyType.UNDEFINED);
- }
- }
-
- parentStack.push(newNode);
- currentProps.clear();
- } catch (RepositoryException re) {
- throw new EnclosingSAXException(re);
- }
- }
+ // if (currentNodeName != null) {
+ // try {
+ // AbstractJcrNode parentNode = parentStack.peek();
+ //
+ // UUID uuid = null;
+ // List<Value> rawUuid = currentProps.get(uuidName);
+ //
+ // if (rawUuid != null) {
+ // assert rawUuid.size() == 1;
+ // uuid = UUID.fromString(rawUuid.get(0).getString());
+ // }
+ //
+ // String typeName = currentProps.get(primaryTypeName).get(0).getString();
+ // AbstractJcrNode newNode =
+ //
cache().findJcrNode(parentNode.editorFor(operations()).createChild(nameFor(currentNodeName),
+ // uuid,
+ // nameFor(typeName)).getUuid());
+ //
+ // for (Map.Entry<String, List<Value>> entry :
currentProps.entrySet()) {
+ // if (entry.getKey().equals(primaryTypeName)) {
+ // continue;
+ // }
+ //
+ // if (entry.getKey().equals(mixinTypesName)) {
+ // for (Value value : entry.getValue()) {
+ // JcrNodeType mixinType =
session.workspace().nodeTypeManager().getNodeType(nameFor(value.getString()));
+ // newNode.editorFor(operations()).addMixin(mixinType);
+ // }
+ // continue;
+ // }
+ //
+ // if (entry.getKey().equals(uuidName)) {
+ // continue;
+ // }
+ //
+ // List<Value> values = entry.getValue();
+ //
+ // if (values.size() == 1) {
+ // newNode.editorFor(operations()).setProperty(nameFor(entry.getKey()),
(JcrValue)values.get(0));
+ // } else {
+ // newNode.editorFor(operations()).setProperty(nameFor(entry.getKey()),
+ // values.toArray(new Value[values.size()]),
+ // PropertyType.UNDEFINED);
+ // }
+ // }
+ //
+ // parentStack.push(newNode);
+ // currentProps.clear();
+ // } catch (RepositoryException re) {
+ // throw new EnclosingSAXException(re);
+ // }
+ // }
}
@Override
@@ -371,8 +369,9 @@
ByteArrayInputStream is = new
ByteArrayInputStream(Base64.decode(s, Base64.URL_SAFE));
currentProps.get(currentPropName).add(session.getValueFactory().createValue(is));
} else {
-
currentProps.get(currentPropName).add(session.getValueFactory().createValue(SYSTEM_VIEW_NAME_DECODER.decode(s),
-
currentPropType));
+ currentProps.get(currentPropName).add(session.getValueFactory()
+
.createValue(SYSTEM_VIEW_NAME_DECODER.decode(s),
+
currentPropType));
}
} catch (RepositoryException re) {
throw new EnclosingSAXException(re);
@@ -418,70 +417,70 @@
String localName,
String name,
Attributes atts ) throws SAXException {
- try {
- String primaryTypeName =
atts.getValue(JcrContentHandler.this.primaryTypeName);
- String rawUuid = atts.getValue(uuidName);
- UUID uuid = (rawUuid != null ? UUID.fromString(rawUuid) : null);
- AbstractJcrNode parentNode = parentStack.peek();
+ // try {
+ // String primaryTypeName =
atts.getValue(JcrContentHandler.this.primaryTypeName);
+ // String rawUuid = atts.getValue(uuidName);
+ // UUID uuid = (rawUuid != null ? UUID.fromString(rawUuid) : null);
+ // AbstractJcrNode parentNode = parentStack.peek();
+ //
+ // if (uuid != null) {
+ // AbstractJcrNode existingNodeWithUuid =
(AbstractJcrNode)session.getNodeByUUID(rawUuid);
+ // if (existingNodeWithUuid != null) {
+ // switch (uuidBehavior) {
+ // case ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING:
+ // parentNode = existingNodeWithUuid.getParent();
+ // parentNode.editorFor(operations()).destroyChild(uuid);
+ // break;
+ // case ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW:
+ // uuid = UUID.randomUUID();
+ // break;
+ // case ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING:
+ // if
(existingNodeWithUuid.path().isAtOrAbove(parentStack.firstElement().path())) {
+ // throw new ConstraintViolationException();
+ // }
+ // AbstractJcrNode temp = existingNodeWithUuid.getParent();
+ // temp.editorFor(operations()).destroyChild(uuid);
+ // break;
+ // case ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW:
+ // throw new ItemExistsException();
+ // }
+ // }
+ // }
+ //
+ // name = DOCUMENT_VIEW_NAME_DECODER.decode(name);
+ // AbstractJcrNode currentNode =
cache().findJcrNode(parentNode.editorFor(operations()).createChild(nameFor(name),
+ // uuid,
+ // nameFor(primaryTypeName)).getUuid());
+ //
+ // for (int i = 0; i < atts.getLength(); i++) {
+ // if (JcrContentHandler.this.primaryTypeName.equals(atts.getQName(i))) {
+ // continue;
+ // }
+ //
+ // if (mixinTypesName.equals(atts.getQName(i))) {
+ // JcrNodeType mixinType =
session.workspace().nodeTypeManager().getNodeType(nameFor(atts.getValue(i)));
+ // currentNode.editorFor(operations()).addMixin(mixinType);
+ // continue;
+ // }
+ //
+ // if (uuidName.equals(atts.getQName(i))) {
+ // continue;
+ // }
+ //
+ // // We may want to use the workspace context here so that we only use the
permanent namespace mappings
+ // // Name propName =
session.executionContext.getValueFactories().getNameFactory().create(atts.getQName(i));
+ // // String value = DOCUMENT_VIEW_NAME_DECODER.decode(atts.getValue(i));
+ // String value = atts.getValue(i);
+ // String propertyName =
DOCUMENT_VIEW_NAME_DECODER.decode(atts.getQName(i));
+ // currentNode.editorFor(operations()).setProperty(nameFor(propertyName),
+ // (JcrValue)valueFor(value, PropertyType.STRING));
+ // }
+ //
+ // parentStack.push(currentNode);
+ // } catch (RepositoryException re) {
+ // throw new EnclosingSAXException(re);
+ // }
- if (uuid != null) {
- AbstractJcrNode existingNodeWithUuid =
(AbstractJcrNode)session.getNodeByUUID(rawUuid);
- if (existingNodeWithUuid != null) {
- switch (uuidBehavior) {
- case
ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING:
- parentNode = existingNodeWithUuid.getParent();
- parentNode.editorFor(operations()).destroyChild(uuid);
- break;
- case ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW:
- uuid = UUID.randomUUID();
- break;
- case
ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING:
- if
(existingNodeWithUuid.path().isAtOrAbove(parentStack.firstElement().path())) {
- throw new ConstraintViolationException();
- }
- AbstractJcrNode temp = existingNodeWithUuid.getParent();
- temp.editorFor(operations()).destroyChild(uuid);
- break;
- case ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW:
- throw new ItemExistsException();
- }
- }
- }
-
- name = DOCUMENT_VIEW_NAME_DECODER.decode(name);
- AbstractJcrNode currentNode =
cache().findJcrNode(parentNode.editorFor(operations()).createChild(nameFor(name),
-
uuid,
-
nameFor(primaryTypeName)).getUuid());
-
- for (int i = 0; i < atts.getLength(); i++) {
- if (JcrContentHandler.this.primaryTypeName.equals(atts.getQName(i)))
{
- continue;
- }
-
- if (mixinTypesName.equals(atts.getQName(i))) {
- JcrNodeType mixinType =
session.workspace().nodeTypeManager().getNodeType(nameFor(atts.getValue(i)));
- currentNode.editorFor(operations()).addMixin(mixinType);
- continue;
- }
-
- if (uuidName.equals(atts.getQName(i))) {
- continue;
- }
-
- // We may want to use the workspace context here so that we only use
the permanent namespace mappings
- // Name propName =
session.executionContext.getValueFactories().getNameFactory().create(atts.getQName(i));
- // String value =
DOCUMENT_VIEW_NAME_DECODER.decode(atts.getValue(i));
- String value = atts.getValue(i);
- String propertyName =
DOCUMENT_VIEW_NAME_DECODER.decode(atts.getQName(i));
-
currentNode.editorFor(operations()).setProperty(nameFor(propertyName),
-
(JcrValue)valueFor(value, PropertyType.STRING));
- }
-
- parentStack.push(currentNode);
- } catch (RepositoryException re) {
- throw new EnclosingSAXException(re);
- }
-
}
@Override
@@ -500,19 +499,20 @@
public void characters( char[] ch,
int start,
int length ) throws SAXException {
- try {
- AbstractJcrNode parentNode = parentStack.peek();
- AbstractJcrNode currentNode =
cache().findJcrNode(parentNode.editorFor(operations()).createChild(JcrLexicon.XMLTEXT,
-
null,
-
JcrNtLexicon.UNSTRUCTURED).getUuid());
-
- String s = new String(ch, start, length);
-
currentNode.editorFor(operations()).setProperty(JcrLexicon.XMLCHARACTERS,
- (JcrValue)valueFor(s,
PropertyType.STRING));
-
- } catch (RepositoryException re) {
- throw new EnclosingSAXException(re);
- }
+ // try {
+ // AbstractJcrNode parentNode = parentStack.peek();
+ // AbstractJcrNode currentNode =
+ //
cache().findJcrNode(parentNode.editorFor(operations()).createChild(JcrLexicon.XMLTEXT,
+ // null,
+ // JcrNtLexicon.UNSTRUCTURED).getUuid());
+ //
+ // String s = new String(ch, start, length);
+ // currentNode.editorFor(operations()).setProperty(JcrLexicon.XMLCHARACTERS,
+ // (JcrValue)valueFor(s, PropertyType.STRING));
+ //
+ // } catch (RepositoryException re) {
+ // throw new EnclosingSAXException(re);
+ // }
}
}
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java 2009-07-09 16:23:09 UTC
(rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java 2009-07-09 16:26:04 UTC
(rev 1082)
@@ -47,7 +47,7 @@
public static I18n fileDoesNotExist;
public static I18n rootNodeHasNoParent;
-
+
public static I18n noNamespaceWithPrefix;
public static I18n noNamespaceWithUri;
public static I18n unableToChangeTheDefaultNamespace;
@@ -87,7 +87,8 @@
public static I18n unableToSaveNodeThatWasCreatedSincePreviousSave;
public static I18n unableToSetMultiValuedPropertyUsingSingleValue;
public static I18n unableToSetSingleValuedPropertyUsingMultipleValues;
- public static I18n
unableToRefreshBranchSinceAtLeastOneNodeMovedToParentOutsideOfBranch;
+ public static I18n
unableToRefreshBranchBecauseChangesDependOnChangesToNodesOutsideOfBranch;
+ public static I18n
unableToSaveBranchBecauseChangesDependOnChangesToNodesOutsideOfBranch;
public static I18n allPropertyValuesMustHaveSameType;
public static I18n cannotRemoveNodeFromClone;
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -37,6 +37,7 @@
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.version.VersionException;
import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.Property;
/**
@@ -48,8 +49,9 @@
static final JcrValue[] EMPTY_VALUES = new JcrValue[] {};
JcrMultiValueProperty( SessionCache cache,
- PropertyId propertyId ) {
- super(cache, propertyId);
+ AbstractJcrNode node,
+ Name name ) {
+ super(cache, node, name);
}
/**
@@ -191,10 +193,10 @@
for (int i = 0; i < values.length; i++) {
// Force a conversion as per SetValueValueFormatExceptionTest in JR TCK
- if (values[i] != null) ((JcrValue) values[i]).asType(this.getType());
+ if (values[i] != null) ((JcrValue)values[i]).asType(this.getType());
}
-
-
cache.getEditorFor(propertyId.getNodeId()).setProperty(propertyId.getPropertyName(),
values, PropertyType.UNDEFINED);
+
+ editor().setProperty(name(), values, PropertyType.UNDEFINED);
}
/**
@@ -228,7 +230,7 @@
jcrValues = EMPTY_VALUES;
}
-
cache.getEditorFor(propertyId.getNodeId()).setProperty(propertyId.getPropertyName(),
jcrValues, this.getType());
+ editor().setProperty(name(), jcrValues, this.getType());
}
/**
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNode.java 2009-07-09 16:23:09 UTC
(rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNode.java 2009-07-09 16:26:04 UTC
(rev 1082)
@@ -23,10 +23,11 @@
*/
package org.jboss.dna.jcr;
-import java.util.UUID;
import javax.jcr.ItemNotFoundException;
import javax.jcr.RepositoryException;
import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.session.GraphSession.NodeId;
/**
*
@@ -35,8 +36,9 @@
final class JcrNode extends AbstractJcrNode {
JcrNode( SessionCache cache,
- UUID nodeUuid ) {
- super(cache, nodeUuid);
+ NodeId nodeId,
+ Location location ) {
+ super(cache, nodeId, location);
}
/**
@@ -55,7 +57,7 @@
* @see javax.jcr.Node#getIndex()
*/
public int getIndex() throws RepositoryException {
- return cache.getSnsIndexOf(nodeUuid);
+ return segment().getIndex();
}
/**
@@ -64,7 +66,7 @@
* @see javax.jcr.Item#getName()
*/
public String getName() throws RepositoryException {
- return cache.getNameOf(nodeUuid).getString(namespaces());
+ return name().getString(namespaces());
}
/**
@@ -74,7 +76,7 @@
*/
@Override
public AbstractJcrNode getParent() throws ItemNotFoundException, RepositoryException
{
- return cache.findJcrNode(nodeInfo().getParent());
+ return nodeInfo().getParent().getPayload().getJcrNode();
}
/**
@@ -83,7 +85,7 @@
* @see javax.jcr.Item#getPath()
*/
public String getPath() throws RepositoryException {
- return cache.getPathFor(nodeUuid).getString(namespaces());
+ return nodeInfo().getPath().getString(namespaces());
}
/**
@@ -92,6 +94,6 @@
* @see javax.jcr.Item#remove()
*/
public void remove() throws RepositoryException {
- editorForParent().destroyChild(nodeUuid);
+ editorForParent().destroyChild(nodeInfo());
}
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java 2009-07-09 16:23:09 UTC
(rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java 2009-07-09 16:26:04 UTC
(rev 1082)
@@ -490,7 +490,22 @@
return this.thisAndAllSupertypesNames.contains(nodeTypeName);
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
@Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof NodeType) {
+ NodeType that = (NodeType)obj;
+ return this.getName().equals(that.getName());
+ }
+ return false;
+ }
+
+ @Override
public String toString() {
return getName();
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -32,6 +32,7 @@
import javax.jcr.nodetype.PropertyDefinition;
import net.jcip.annotations.Immutable;
import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.property.Binary;
import org.jboss.dna.graph.property.DateTime;
import org.jboss.dna.graph.property.Name;
@@ -310,7 +311,7 @@
throw new IllegalStateException("Invalid property type: " +
type);
}
}
-
+
@Override
public int hashCode() {
return getId().toString().hashCode();
@@ -327,7 +328,6 @@
} else if (!id.equals(other.id)) return false;
return true;
}
-
/**
* Interface that encapsulates a reusable method that can test values to determine if
they match a specific list of
@@ -564,7 +564,7 @@
Node node = null;
try {
UUID uuid = cache.factories().getUuidFactory().create(jcrValue.value());
- node = cache.findJcrNode(uuid);
+ node = cache.findJcrNode(Location.create(uuid));
} catch (RepositoryException re) {
return false;
}
@@ -608,7 +608,12 @@
JcrValue jcrValue = (JcrValue)value;
// Need to use the session execution context to handle the remaps
- Name name =
jcrValue.sessionCache().session().getExecutionContext().getValueFactories().getNameFactory().create(jcrValue.value());
+ Name name = jcrValue.sessionCache()
+ .session()
+ .getExecutionContext()
+ .getValueFactories()
+ .getNameFactory()
+ .create(jcrValue.value());
for (int i = 0; i < constraints.length; i++) {
if (constraints[i].equals(name)) {
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRootNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRootNode.java 2009-07-09 16:23:09 UTC
(rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRootNode.java 2009-07-09 16:26:04 UTC
(rev 1082)
@@ -23,12 +23,13 @@
*/
package org.jboss.dna.jcr;
-import java.util.UUID;
import javax.jcr.Item;
import javax.jcr.ItemNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.ConstraintViolationException;
import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.session.GraphSession.NodeId;
/**
* @author jverhaeg
@@ -37,8 +38,9 @@
final class JcrRootNode extends AbstractJcrNode {
JcrRootNode( SessionCache cache,
- UUID nodeUuid ) {
- super(cache, nodeUuid);
+ NodeId nodeId,
+ Location location ) {
+ super(cache, nodeId, location);
}
/**
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-07-09 16:23:09 UTC
(rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-07-09 16:26:04 UTC
(rev 1082)
@@ -53,10 +53,10 @@
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.SecurityContext;
import org.jboss.dna.graph.property.Binary;
import org.jboss.dna.graph.property.DateTime;
-import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.NamespaceRegistry;
import org.jboss.dna.graph.property.Path;
import org.jboss.dna.graph.property.PathFactory;
@@ -480,14 +480,11 @@
if (path.getLastSegment().hasIndex()) {
return getNode(path);
}
- // We can't tell from the name, so try a node first ...
+ // We can't tell from the name, so ask for an item ...
try {
- return getNode(path);
- } catch (PathNotFoundException e) {
- // A node was not found, so look for a node using the parent as the
node's path ...
- Path parentPath = path.getParent();
- Name propertyName = path.getLastSegment().getName();
- return
getNode(parentPath).getProperty(propertyName.getString(namespaces()));
+ return cache.findJcrItem(null, rootPath, path.relativeTo(rootPath));
+ } catch (ItemNotFoundException e) {
+ throw new PathNotFoundException(e.getMessage(), e);
}
}
@@ -511,7 +508,11 @@
*/
AbstractJcrNode getNode( Path path ) throws RepositoryException,
PathNotFoundException {
if (path.isRoot()) return cache.findJcrRootNode();
- return cache.findJcrNode(null, path.relativeTo(rootPath));
+ try {
+ return cache.findJcrNode(null, path);
+ } catch (ItemNotFoundException e) {
+ throw new PathNotFoundException(e.getMessage());
+ }
}
/**
@@ -520,7 +521,7 @@
* @see javax.jcr.Session#getNodeByUUID(java.lang.String)
*/
public Node getNodeByUUID( String uuid ) throws ItemNotFoundException,
RepositoryException {
- return cache.findJcrNode(UUID.fromString(uuid));
+ return cache.findJcrNode(Location.create(UUID.fromString(uuid)));
}
/**
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSingleValueProperty.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSingleValueProperty.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSingleValueProperty.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -34,7 +34,9 @@
import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.version.VersionException;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.property.Binary;
+import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.Reference;
import org.jboss.dna.graph.property.ValueFactories;
@@ -44,8 +46,9 @@
final class JcrSingleValueProperty extends AbstractJcrProperty {
JcrSingleValueProperty( SessionCache cache,
- PropertyId propertyId ) {
- super(cache, propertyId);
+ AbstractJcrNode node,
+ Name name ) {
+ super(cache, node, name);
}
/**
@@ -139,7 +142,7 @@
ValueFactories factories = context().getValueFactories();
Reference dnaReference =
factories.getReferenceFactory().create(property().getFirstValue());
UUID uuid = factories.getUuidFactory().create(dnaReference);
- return cache.findJcrNode(uuid);
+ return cache.findJcrNode(Location.create(uuid));
} catch (org.jboss.dna.graph.property.ValueFormatException e) {
throw new ValueFormatException(e.getMessage(), e);
}
@@ -194,16 +197,16 @@
// Force a conversion as per SetValueValueFormatExceptionTest in JR TCK
jcrValue.asType(this.getType());
-
-
cache.getEditorFor(propertyId.getNodeId()).setProperty(propertyId.getPropertyName(),
jcrValue);
+
+ editor().setProperty(name(), jcrValue);
return;
}
if (value == null) {
// Then we're to delete the property ...
-
cache.getEditorFor(propertyId.getNodeId()).removeProperty(propertyId.getPropertyName());
+ editor().removeProperty(name());
return;
}
-
+
// We have to convert from one Value implementation to ours ...
switch (value.getType()) {
case PropertyType.STRING:
@@ -241,7 +244,7 @@
protected void setValue( JcrValue jcrValue )
throws ValueFormatException, VersionException, LockException,
ConstraintViolationException, RepositoryException {
assert jcrValue != null;
-
cache.getEditorFor(propertyId.getNodeId()).setProperty(propertyId.getPropertyName(),
jcrValue);
+ editor().setProperty(name(), jcrValue);
}
/**
@@ -327,11 +330,11 @@
this.remove();
return;
}
-
+
if
(!value.isNodeType(JcrMixLexicon.REFERENCEABLE.getString(this.context().getNamespaceRegistry())))
{
throw new ValueFormatException(JcrI18n.nodeNotReferenceable.text());
}
-
+
String uuid = value.getUUID();
setValue(createValue(uuid, PropertyType.REFERENCE).asType(this.getType()));
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java 2009-07-09 16:23:09
UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java 2009-07-09 16:26:04
UTC (rev 1082)
@@ -26,11 +26,8 @@
import java.io.IOException;
import java.io.InputStream;
import java.security.AccessControlException;
-import java.util.HashSet;
-import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
-import java.util.UUID;
import javax.jcr.AccessDeniedException;
import javax.jcr.InvalidSerializedDataException;
import javax.jcr.ItemExistsException;
@@ -53,26 +50,24 @@
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
-import org.jboss.dna.graph.Subgraph;
-import org.jboss.dna.graph.SubgraphNode;
import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
import org.jboss.dna.graph.connector.RepositorySource;
import org.jboss.dna.graph.connector.RepositorySourceException;
import org.jboss.dna.graph.connector.UuidAlreadyExistsException;
import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.NameFactory;
import org.jboss.dna.graph.property.Path;
import org.jboss.dna.graph.property.PathFactory;
import org.jboss.dna.graph.property.Property;
import org.jboss.dna.graph.property.PropertyFactory;
-import org.jboss.dna.graph.property.UuidFactory;
import org.jboss.dna.graph.property.ValueFormatException;
import org.jboss.dna.graph.property.basic.GraphNamespaceRegistry;
-import org.jboss.dna.graph.request.ReadBranchRequest;
+import org.jboss.dna.graph.request.InvalidWorkspaceException;
+import org.jboss.dna.graph.session.GraphSession.Node;
import org.jboss.dna.jcr.JcrContentHandler.EnclosingSAXException;
import org.jboss.dna.jcr.JcrContentHandler.SaveMode;
import org.jboss.dna.jcr.JcrRepository.Option;
-import org.jboss.dna.jcr.cache.NodeInfo;
+import org.jboss.dna.jcr.SessionCache.JcrNodePayload;
+import org.jboss.dna.jcr.SessionCache.JcrPropertyPayload;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
@@ -312,134 +307,31 @@
}
try {
- this.session.checkPermission(destPath.getParent(), "add_node");
+ // Use the session to verify that the node location has a definition and is
valid with the new cloned child.
+ // This also performs the check permission for reading the parent ...
+ Name newNodeName = destPath.getLastSegment().getName();
+ SessionCache cache = this.session.cache();
+ Node<JcrNodePayload, JcrPropertyPayload> parent = cache.findNode(null,
destPath.getParent());
+ cache.findBestNodeDefinition(parent, newNodeName,
parent.getPayload().getPrimaryTypeName());
+
+ // Now perform the clone, using the direct (non-session) method ...
+ cache.graphSession().immediateClone(srcPath, srcWorkspace, destPath,
removeExisting);
+ } catch (ItemNotFoundException e) {
+ // The destination path was not found ...
+ throw new PathNotFoundException(e.getLocalizedMessage(), e);
+ } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
+ throw new PathNotFoundException(e.getLocalizedMessage(), e);
+ } catch (UuidAlreadyExistsException e) {
+ throw new ItemExistsException(e.getLocalizedMessage(), e);
+ } catch (InvalidWorkspaceException e) {
+ throw new NoSuchWorkspaceException(e.getLocalizedMessage(), e);
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getLocalizedMessage(), e);
} catch (AccessControlException ace) {
throw new AccessDeniedException(ace);
}
-
- clone(srcWorkspace, srcPath, destPath, removeExisting, false);
}
- void clone( String srcWorkspace,
- Path srcPath,
- Path destPath,
- boolean removeExisting,
- boolean destPathIncludesSegment )
- throws ConstraintViolationException, VersionException, AccessDeniedException,
PathNotFoundException, ItemExistsException,
- LockException, RepositoryException {
-
- /*
- * Make sure that the node has a definition at the new location
- */
- SessionCache cache = this.session.cache();
- NodeInfo cacheParent = cache.findNodeInfo(null, destPath.getParent());
-
- // Skip the cache and load the latest parent info directly from the graph
- NodeInfo parent = cache.loadFromGraph(null, cacheParent.getUuid());
- Name newNodeName = destPath.getLastSegment().getName();
- String parentPath =
destPath.getParent().getString(this.context.getNamespaceRegistry());
-
- Subgraph sourceTree = null;
- // This will check for a definition and throw a ConstraintViolationException or
ItemExistsException if none is found
- graph.useWorkspace(srcWorkspace);
- Property primaryTypeProp;
- Property uuidProp;
- try {
- Map<Name, Property> props;
-
- if (removeExisting) {
- sourceTree =
graph.getSubgraphOfDepth(ReadBranchRequest.NO_MAXIMUM_DEPTH).at(srcPath);
- props = sourceTree.getRoot().getPropertiesByName();
- } else {
- props = graph.getNodeAt(srcPath).getPropertiesByName();
- }
- primaryTypeProp = props.get(JcrLexicon.PRIMARY_TYPE);
- uuidProp = props.get(DnaLexicon.UUID);
- } catch (org.jboss.dna.graph.property.PathNotFoundException pnfe) {
- String srcAbsPath = srcPath.getString(this.context.getNamespaceRegistry());
- throw new PathNotFoundException(JcrI18n.itemNotFoundAtPath.text(srcAbsPath,
srcWorkspace));
- } finally {
- graph.useWorkspace(this.name);
- }
-
- assert primaryTypeProp != null : "Cannot have a node in a JCR repository
with no jcr:primaryType property";
- assert uuidProp != null : "Cannot have a node in a JCR repository with no
UUID";
-
- NameFactory nameFactory = this.context.getValueFactories().getNameFactory();
- this.session.cache().findBestNodeDefinition(parent,
- parentPath,
- newNodeName,
-
nameFactory.create(primaryTypeProp.getFirstValue()));
-
- if (removeExisting) {
- assert sourceTree != null;
-
- // Find all of the UUIDS in the source tree
- UuidFactory uuidFactory = context().getValueFactories().getUuidFactory();
- PathFactory pathFactory = context().getValueFactories().getPathFactory();
-
- Set<UUID> sourceUuids = new HashSet<UUID>();
- LinkedList<SubgraphNode> nodesToVisit = new
LinkedList<SubgraphNode>();
- nodesToVisit.addFirst(sourceTree.getRoot());
-
- while (!nodesToVisit.isEmpty()) {
- SubgraphNode node = nodesToVisit.removeFirst();
-
- UUID uuid =
uuidFactory.create(node.getProperty(DnaLexicon.UUID).getFirstValue().toString());
- if (uuid != null) {
- sourceUuids.add(uuid);
- }
- for (Path.Segment childSegment : node.getChildrenSegments()) {
-
nodesToVisit.add(node.getNode(pathFactory.createRelativePath(childSegment)));
- }
- }
-
- // See if the nodes exist in the current workspace outside of the current
tree
- for (UUID uuid : sourceUuids) {
- NodeInfo nodeInfo = null;
- try {
- nodeInfo = session.cache().findNodeInfo(uuid);
- } catch (ItemNotFoundException infe) {
- continue;
- }
- assert nodeInfo != null;
-
- NodeDefinitionId nodeDefnId = nodeInfo.getDefinitionId();
-
- JcrNodeType nodeType =
nodeTypeManager.getNodeType(nodeDefnId.getNodeTypeName());
- JcrNodeDefinition nodeDefn = nodeType.childNodeDefinition(nodeDefnId);
- if (nodeDefn.isMandatory()) {
- // We can't just remove a mandatory node... unless its parent
will be removed too!
- String path =
session.cache().getPathFor(nodeInfo).getString(context().getNamespaceRegistry());
- throw new
ConstraintViolationException(JcrI18n.cannotRemoveNodeFromClone.text(path, uuid));
-
- }
- }
-
- if (destPathIncludesSegment) {
-
graph.clone(srcPath).fromWorkspace(srcWorkspace).as(destPath.getLastSegment()).into(destPath.getParent()).replacingExistingNodesWithSameUuids();
- } else {
-
graph.clone(srcPath).fromWorkspace(srcWorkspace).as(newNodeName).into(destPath.getParent()).replacingExistingNodesWithSameUuids();
- }
- } else {
- try {
- if (destPathIncludesSegment) {
-
graph.clone(srcPath).fromWorkspace(srcWorkspace).as(destPath.getLastSegment()).into(destPath.getParent()).replacingExistingNodesWithSameUuids();
- } else {
-
graph.clone(srcPath).fromWorkspace(srcWorkspace).as(newNodeName).into(destPath.getParent()).failingIfAnyUuidsMatch();
- }
-
- } catch (UuidAlreadyExistsException uaee) {
- throw new ItemExistsException(uaee.getMessage());
- }
- }
-
- assert uuidProp.getFirstValue() instanceof UUID;
- // Load the node that we just copied
- cache.compensateForWorkspaceChildChange(cacheParent.getUuid(), null,
(UUID)uuidProp.getFirstValue(), newNodeName);
-
- }
-
/**
* {@inheritDoc}
*
@@ -489,54 +381,29 @@
}
try {
- this.session.checkPermission(destPath.getParent(), "add_node");
+ // Use the session to verify that the node location has a definition and is
valid with the new cloned child.
+ // This also performs the check permission for reading the parent ...
+ Name newNodeName = destPath.getLastSegment().getName();
+ SessionCache cache = this.session.cache();
+ Node<JcrNodePayload, JcrPropertyPayload> parent = cache.findNode(null,
destPath.getParent());
+ cache.findBestNodeDefinition(parent, newNodeName,
parent.getPayload().getPrimaryTypeName());
+
+ // Now perform the clone, using the direct (non-session) method ...
+ cache.graphSession().immediateCopy(srcPath, srcWorkspace, destPath);
+ } catch (ItemNotFoundException e) {
+ // The destination path was not found ...
+ throw new PathNotFoundException(e.getLocalizedMessage(), e);
+ } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
+ throw new PathNotFoundException(e.getLocalizedMessage(), e);
+ } catch (UuidAlreadyExistsException e) {
+ throw new ItemExistsException(e.getLocalizedMessage(), e);
+ } catch (InvalidWorkspaceException e) {
+ throw new NoSuchWorkspaceException(e.getLocalizedMessage(), e);
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getLocalizedMessage(), e);
} catch (AccessControlException ace) {
throw new AccessDeniedException(ace);
}
-
- /*
- * Make sure that the node has a definition at the new location
- */
- SessionCache cache = this.session.cache();
- NodeInfo cacheParent = cache.findNodeInfo(null, destPath.getParent());
-
- // Skip the cache and load the latest parent info directly from the graph
- NodeInfo parent = cache.loadFromGraph(destPath.getParent(),
cacheParent.getUuid());
- Name newNodeName = destPath.getLastSegment().getName();
- String parentPath =
destPath.getParent().getString(this.context.getNamespaceRegistry());
-
- // This will check for a definition and throw a ConstraintViolationException or
ItemExistsException if none is found
- graph.useWorkspace(srcWorkspace);
-
- Property primaryTypeProp;
- Property uuidProp;
- try {
- Map<Name, Property> props =
graph.getNodeAt(srcPath).getPropertiesByName();
- primaryTypeProp = props.get(JcrLexicon.PRIMARY_TYPE);
- uuidProp = props.get(DnaLexicon.UUID);
- } catch (org.jboss.dna.graph.property.PathNotFoundException pnfe) {
- throw new PathNotFoundException(JcrI18n.itemNotFoundAtPath.text(srcAbsPath,
srcWorkspace));
- } finally {
- graph.useWorkspace(this.name);
- }
-
- assert primaryTypeProp != null : "Cannot have a node in a JCR repository
with no jcr:primaryType property";
- assert uuidProp != null : "Cannot have a node in a JCR repository with no
UUID";
-
- NameFactory nameFactory = this.context.getValueFactories().getNameFactory();
- this.session.cache().findBestNodeDefinition(parent,
- parentPath,
- newNodeName,
-
nameFactory.create(primaryTypeProp.getFirstValue()));
-
- // Perform the copy operation, but use the "to" form (not the
"into", which takes the parent) ...
- graph.copy(srcPath).fromWorkspace(srcWorkspace).to(destPath);
-
- // Load the node that we just copied
- cache.compensateForWorkspaceChildChange(cacheParent.getUuid(),
- null,
-
UUID.fromString(uuidProp.getFirstValue().toString()),
- newNodeName);
}
/**
@@ -621,31 +488,38 @@
}
try {
- this.session.checkPermission(srcAbsPath.substring(0,
srcAbsPath.lastIndexOf('/')), "remove");
- this.session.checkPermission(destAbsPath, "add_node");
+ // Use the session to verify that the node location has a definition and is
valid with the new cloned child.
+ // This also performs the check permission for reading the parent ...
+ Name newNodeName = destPath.getLastSegment().getName();
+ SessionCache cache = this.session.cache();
+ Node<JcrNodePayload, JcrPropertyPayload> newParent =
cache.findNode(null, destPath.getParent());
+ cache.findBestNodeDefinition(newParent, newNodeName,
newParent.getPayload().getPrimaryTypeName());
+
+ // Now perform the clone, using the direct (non-session) method ...
+ cache.graphSession().immediateMove(srcPath, destPath);
} catch (AccessControlException ace) {
throw new AccessDeniedException(ace);
}
- /*
- * Make sure that the node has a definition at the new location
- */
- SessionCache cache = this.session.cache();
- NodeInfo nodeInfo = cache.findNodeInfo(null, srcPath);
- NodeInfo cacheParent = cache.findNodeInfo(null, destPath.getParent());
- NodeInfo oldParent = cache.findNodeInfo(null, srcPath.getParent());
-
- // Skip the cache and load the latest parent info directly from the graph
- NodeInfo parent = cache.loadFromGraph(destPath.getParent(),
cacheParent.getUuid());
- Name newNodeName = destPath.getLastSegment().getName();
- String parentPath =
destPath.getParent().getString(this.context.getNamespaceRegistry());
-
- // This will check for a definition and throw a ConstraintViolationException or
ItemExistsException if none is found
- cache.findBestNodeDefinition(parent, parentPath, newNodeName,
nodeInfo.getPrimaryTypeName());
-
- // Perform the copy operation, but use the "to" form (not the
"into", which takes the parent) ...
- graph.move(srcPath).as(newNodeName).into(destPath.getParent());
- cache.compensateForWorkspaceChildChange(cacheParent.getUuid(),
oldParent.getUuid(), nodeInfo.getUuid(), newNodeName);
+ // /*
+ // * Make sure that the node has a definition at the new location
+ // */
+ // SessionCache cache = this.session.cache();
+ // NodeInfo nodeInfo = cache.findNodeInfo(null, srcPath);
+ // NodeInfo cacheParent = cache.findNodeInfo(null, destPath.getParent());
+ // NodeInfo oldParent = cache.findNodeInfo(null, srcPath.getParent());
+ //
+ // // Skip the cache and load the latest parent info directly from the graph
+ // NodeInfo parent = cache.loadFromGraph(destPath.getParent(),
cacheParent.getUuid());
+ // Name newNodeName = destPath.getLastSegment().getName();
+ // String parentPath =
destPath.getParent().getString(this.context.getNamespaceRegistry());
+ //
+ // // This will check for a definition and throw a ConstraintViolationException
or ItemExistsException if none is found
+ // cache.findBestNodeDefinition(parent, parentPath, newNodeName,
nodeInfo.getPrimaryTypeName());
+ //
+ // // Perform the copy operation, but use the "to" form (not the
"into", which takes the parent) ...
+ // graph.move(srcPath).as(newNodeName).into(destPath.getParent());
+ // cache.compensateForWorkspaceChildChange(cacheParent.getUuid(),
oldParent.getUuid(), nodeInfo.getUuid(), newNodeName);
}
/**
Deleted: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/PropertyId.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/PropertyId.java 2009-07-09 16:23:09 UTC
(rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/PropertyId.java 2009-07-09 16:26:04 UTC
(rev 1082)
@@ -1,111 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you 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.
- *
- * JBoss DNA 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.jcr;
-
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.util.HashCode;
-import org.jboss.dna.graph.property.Name;
-
-/**
- * An immutable identifier for a property, often used to reference information a property
held within the {@link SessionCache}.
- */
-@Immutable
-public final class PropertyId {
-
- private final UUID nodeId;
- private final Name propertyName;
- private final int hc;
-
- /**
- * Create a new property identifier.
- *
- * @param nodeId the UUID of the node that owns the property being reference; may not
be null
- * @param propertyName the name of the property being referenced; may not be null
- */
- public PropertyId( UUID nodeId,
- Name propertyName ) {
- assert nodeId != null;
- assert propertyName != null;
- this.nodeId = nodeId;
- this.propertyName = propertyName;
- this.hc = HashCode.compute(this.nodeId, this.propertyName);
- }
-
- /**
- * Get the UUID of the node that owns the property.
- *
- * @return the node's UUID; never null
- */
- public UUID getNodeId() {
- return nodeId;
- }
-
- /**
- * Get the name of the property.
- *
- * @return the property name; never null
- */
- public Name getPropertyName() {
- return propertyName;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode() {
- return hc;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals( Object obj ) {
- if (obj == this) return true;
- if (obj instanceof PropertyId) {
- PropertyId that = (PropertyId)obj;
- if (this.hc != that.hc) return false;
- if (!this.nodeId.equals(that.nodeId)) return false;
- return this.propertyName.equals(that.propertyName);
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- return this.nodeId.toString() + '@' + this.propertyName.toString();
- }
-
-}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-07-09 16:23:09
UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-07-09 16:26:04
UTC (rev 1082)
@@ -23,19 +23,17 @@
*/
package org.jboss.dna.jcr;
+import java.lang.ref.SoftReference;
import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Queue;
import java.util.Set;
-import java.util.Stack;
import java.util.UUID;
import javax.jcr.AccessDeniedException;
import javax.jcr.InvalidItemStateException;
@@ -43,7 +41,6 @@
import javax.jcr.ItemExistsException;
import javax.jcr.ItemNotFoundException;
import javax.jcr.NoSuchWorkspaceException;
-import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
@@ -51,16 +48,15 @@
import javax.jcr.Value;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
-import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.PropertyDefinition;
+import net.jcip.annotations.Immutable;
import net.jcip.annotations.ThreadSafe;
import org.jboss.dna.common.i18n.I18n;
import org.jboss.dna.common.util.Logger;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.Results;
import org.jboss.dna.graph.connector.RepositorySourceException;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.NameFactory;
@@ -72,22 +68,14 @@
import org.jboss.dna.graph.property.ValueFactories;
import org.jboss.dna.graph.property.ValueFactory;
import org.jboss.dna.graph.property.ValueFormatException;
-import org.jboss.dna.graph.request.BatchRequestBuilder;
-import org.jboss.dna.graph.request.ChangeRequest;
-import org.jboss.dna.graph.request.CreateNodeRequest;
import org.jboss.dna.graph.request.InvalidWorkspaceException;
-import org.jboss.dna.graph.request.Request;
-import org.jboss.dna.jcr.cache.ChangedNodeInfo;
-import org.jboss.dna.jcr.cache.ChildNode;
-import org.jboss.dna.jcr.cache.Children;
-import org.jboss.dna.jcr.cache.EmptyChildren;
-import org.jboss.dna.jcr.cache.ImmutableChildren;
-import org.jboss.dna.jcr.cache.ImmutableNodeInfo;
-import org.jboss.dna.jcr.cache.NewNodeInfo;
-import org.jboss.dna.jcr.cache.NodeInfo;
-import org.jboss.dna.jcr.cache.PropertyInfo;
-import com.google.common.base.ReferenceType;
-import com.google.common.collect.ReferenceMap;
+import org.jboss.dna.graph.session.GraphSession;
+import org.jboss.dna.graph.session.InvalidStateException;
+import org.jboss.dna.graph.session.ValidationException;
+import org.jboss.dna.graph.session.GraphSession.Node;
+import org.jboss.dna.graph.session.GraphSession.NodeId;
+import org.jboss.dna.graph.session.GraphSession.PropertyInfo;
+import org.jboss.dna.graph.session.GraphSession.Status;
/**
* The class that manages the session's information that has been locally-cached
after reading from the underlying {@link Graph
@@ -132,9 +120,9 @@
* Hidden flag that controls whether properties that appear on DNA nodes but not
allowed by the node type or mixins should be
* included anyway. This is currently {@value} .
*/
- private static final boolean INCLUDE_PROPERTIES_NOT_ALLOWED_BY_NODE_TYPE_OR_MIXINS =
true;
+ protected static final boolean INCLUDE_PROPERTIES_NOT_ALLOWED_BY_NODE_TYPE_OR_MIXINS
= true;
- private static final Set<Name> EMPTY_NAMES = Collections.emptySet();
+ protected static final Set<Name> EMPTY_NAMES = Collections.emptySet();
private final JcrSession session;
private final String workspaceName;
@@ -146,24 +134,13 @@
protected final NamespaceRegistry namespaces;
protected final PropertyFactory propertyFactory;
private final Graph store;
- private final Name defaultPrimaryTypeName;
- private final Property defaultPrimaryTypeProperty;
+ protected final Name defaultPrimaryTypeName;
+ protected final Property defaultPrimaryTypeProperty;
protected final Path rootPath;
protected final Name residualName;
- private UUID root;
- private final ReferenceMap<UUID, AbstractJcrNode> jcrNodes;
- private final ReferenceMap<PropertyId, AbstractJcrProperty> jcrProperties;
+ private GraphSession<JcrNodePayload, JcrPropertyPayload> graphSession;
- protected final HashMap<UUID, ImmutableNodeInfo> cachedNodes;
- protected final HashMap<UUID, ChangedNodeInfo> changedNodes;
- protected final HashMap<UUID, NodeInfo> deletedNodes;
- protected final Map<UUID, Path> pathCache;
-
- private LinkedList<Request> requests;
- private BatchRequestBuilder requestBuilder;
- protected Graph.Batch operations;
-
public SessionCache( JcrSession session,
String workspaceName,
ExecutionContext context,
@@ -188,18 +165,13 @@
this.rootPath = pathFactory.createRootPath();
this.residualName = nameFactory.create(JcrNodeType.RESIDUAL_ITEM_NAME);
- this.jcrNodes = new ReferenceMap<UUID,
AbstractJcrNode>(ReferenceType.STRONG, ReferenceType.SOFT);
- this.jcrProperties = new ReferenceMap<PropertyId,
AbstractJcrProperty>(ReferenceType.STRONG, ReferenceType.SOFT);
+ // Create the graph session, customized for JCR ...
+ this.graphSession = new GraphSession<JcrNodePayload,
JcrPropertyPayload>(this.store, this.workspaceName,
+ new
JcrNodeOperations(), new JcrAuthorizer());
+ }
- this.cachedNodes = new HashMap<UUID, ImmutableNodeInfo>();
- this.changedNodes = new HashMap<UUID, ChangedNodeInfo>();
- this.deletedNodes = new HashMap<UUID, NodeInfo>();
- this.pathCache = new HashMap<UUID, Path>();
-
- // Create the batch operations ...
- this.requests = new LinkedList<Request>();
- this.requestBuilder = new BatchRequestBuilder(this.requests);
- this.operations = this.store.batch(this.requestBuilder);
+ final GraphSession<JcrNodePayload, JcrPropertyPayload> graphSession() {
+ return graphSession;
}
JcrSession session() {
@@ -211,7 +183,7 @@
}
String sourceName() {
- return session.sourceName();
+ return store.getSourceName();
}
ExecutionContext context() {
@@ -234,21 +206,36 @@
return session.nodeTypeManager();
}
- /**
- * Checks whether the current session has the appropriate permissions to perform the
given action.
- *
- * @param node the node on which the action will be performed
- * @param action the name of the action to perform, should be "add_node",
"remove", or "set_property"
- * @throws AccessDeniedException if the current session does not have the requisite
privileges to perform this task
- * @throws RepositoryException if any other error occurs
- */
- protected void checkPermission( NodeInfo node,
- String action ) throws AccessDeniedException,
RepositoryException {
- try {
- this.session.checkPermission(SessionCache.this.getPathFor(node), action);
- } catch (AccessControlException ace) {
- throw new AccessDeniedException(ace);
+ final String readable( Name name ) {
+ return name.getString(namespaces);
+ }
+
+ final String readable( Path.Segment segment ) {
+ return segment.getString(namespaces);
+ }
+
+ final String readable( Path path ) {
+ return path.getString(namespaces);
+ }
+
+ final String readable( Location location ) {
+ return location.getString(namespaces);
+ }
+
+ final String readable( Iterable<Name> names ) {
+ StringBuilder sb = new StringBuilder();
+ sb.append('[');
+ boolean first = true;
+ for (Name name : names) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append(", ");
+ }
+ sb.append(name.getString(namespaces));
}
+ sb.append(']');
+ return sb.toString();
}
/**
@@ -257,7 +244,7 @@
* @return true if there are pending changes, or false if there is currently no
changes
*/
boolean hasPendingChanges() {
- return operations.isExecuteRequired();
+ return graphSession.hasPendingChanges();
}
/**
@@ -269,24 +256,7 @@
* @param keepChanges indicates whether changed nodes should be kept or refreshed
from the repository.
*/
public void refresh( boolean keepChanges ) {
- if (keepChanges) {
- // Keep the pending operations
- Set<UUID> retainedSet = new
HashSet<UUID>(this.changedNodes.size() + this.deletedNodes.size());
- retainedSet.addAll(this.changedNodes.keySet());
- retainedSet.addAll(this.deletedNodes.keySet());
-
- // Removed any cached nodes not already in the changed or deleted set
- this.cachedNodes.keySet().retainAll(retainedSet);
- this.jcrNodes.keySet().retainAll(retainedSet);
- } else {
- // Throw out the old pending operations
- this.requests.clear();
- this.changedNodes.clear();
- this.cachedNodes.clear();
- this.deletedNodes.clear();
- this.jcrNodes.clear();
- }
-
+ graphSession.refresh(keepChanges);
}
/**
@@ -295,238 +265,28 @@
* If {@code keepChanges == true}, modified nodes will not have their state
refreshed.
* </p>
*
- * @param nodeUuid the UUID of the node that is to be saved; may not be null
+ * @param nodeId the identifier of the node that is to be saved; may not be null
* @param keepChanges indicates whether changed nodes should be kept or refreshed
from the repository.
+ * @throws InvalidItemStateException if the node being refreshed no longer exists
* @throws RepositoryException if any error resulting while saving the changes to the
repository
*/
- public void refresh( UUID nodeUuid,
- boolean keepChanges ) throws RepositoryException {
- assert nodeUuid != null;
- // If the node being refreshed is the root node, then it's more efficient to
refresh the whole workspace ...
- if (this.root.equals(nodeUuid)) {
- refresh(keepChanges);
- return;
+ public void refresh( NodeId nodeId,
+ boolean keepChanges ) throws InvalidItemStateException,
RepositoryException {
+ assert nodeId != null;
+ try {
+ Node<JcrNodePayload, JcrPropertyPayload> node =
graphSession.findNodeWith(nodeId);
+ graphSession.refresh(node, keepChanges);
+ } catch (InvalidStateException e) {
+ throw new InvalidItemStateException(e.getLocalizedMessage());
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getLocalizedMessage());
}
-
- // Build the set of affected node UUIDs
- Set<UUID> nodesUnderBranch = new HashSet<UUID>();
- Stack<UUID> nodesToVisit = new Stack<UUID>();
- Set<UUID> nodesRemovedFromBranch = new HashSet<UUID>();
-
- nodesToVisit.add(nodeUuid);
- while (!nodesToVisit.isEmpty()) {
- UUID uuid = nodesToVisit.pop();
- nodesUnderBranch.add(uuid);
-
- NodeInfo nodeInfo = null;
- ChangedNodeInfo changedInfo = this.changedNodes.get(uuid);
- if (changedInfo != null) {
- Collection<UUID> removedNodes =
changedInfo.getUuidsForRemovedChildren();
- nodesToVisit.addAll(removedNodes);
- nodesRemovedFromBranch.addAll(removedNodes);
- nodeInfo = changedInfo;
- } else {
- nodeInfo = this.cachedNodes.get(uuid);
- }
- if (nodeInfo != null) {
- for (ChildNode childNode : nodeInfo.getChildren()) {
- nodesToVisit.add(childNode.getUuid());
- }
- }
- }
-
- if (!nodesRemovedFromBranch.isEmpty()) {
- // Skip any nodes that were moved from one parent to another within this
branch ...
- nodesRemovedFromBranch.removeAll(nodesUnderBranch);
- // Skip any nodes that were actually deleted (not moved)...
- nodesRemovedFromBranch.removeAll(this.deletedNodes.keySet());
- if (!nodesRemovedFromBranch.isEmpty()) {
- // There was at least one node that was moved from this branch to another
parent outside this branch
- Path path = getPathFor(nodeUuid);
- String msg =
JcrI18n.unableToRefreshBranchSinceAtLeastOneNodeMovedToParentOutsideOfBranch.text(path,
-
workspaceName());
- throw new RepositoryException(msg);
- }
- }
-
- // Find the path of the given node ...
- Path path = getPathFor(nodeUuid);
-
- if (keepChanges) {
- // Keep the pending operations
- for (UUID uuid : nodesUnderBranch) {
- // getPathFor can (and will) add entries to cachedNodes - hence the
existence of nodesToCheck
- if (getPathFor(uuid).isDecendantOf(path)) {
- if (!this.changedNodes.containsKey(uuid) &&
!this.deletedNodes.containsKey(uuid)) {
- this.cachedNodes.remove(uuid);
- }
- }
- }
- } else {
- this.cachedNodes.keySet().removeAll(nodesUnderBranch);
- this.changedNodes.keySet().removeAll(nodesUnderBranch);
- this.deletedNodes.keySet().removeAll(nodesUnderBranch);
- this.jcrNodes.keySet().removeAll(nodesUnderBranch);
-
- // Throw out the old pending operations
- if (operations.isExecuteRequired()) {
-
- // Make sure the builder has finished all the requests ...
- this.requestBuilder.finishPendingRequest();
-
- // Remove all of the enqueued requests for this branch ...
- for (Iterator<Request> iter = this.requests.iterator();
iter.hasNext();) {
- Request request = iter.next();
- assert request instanceof ChangeRequest;
- ChangeRequest change = (ChangeRequest)request;
- if (change.changes(workspaceName, path)) {
- iter.remove();
- }
- }
- }
- }
-
}
/**
- * Checks that the child items of the node are consistent with the definitions
required by the node's primary type and mixin
- * types (if any).
- * <p>
- * This method first checks that all of the child nodes and properties for the node
have definitions based on the current
- * primary and mixin node types for the node as held in the node type registry. The
method then checks that all mandatory (and
- * non-protected) items are populated.
- * </p>
- *
- * @param nodeUuid the UUID of the node to check
- * @param checkSns if true indicates that this method should distinguish between
child nodes that have no matching definition
- * and child nodes that would have a definition that would match if it allowed
same-name siblings. This flag determines
- * which exception type should be thrown in that case.
- * @throws ItemExistsException if checkSns is true and there is no definition that
allows same-name siblings for one of the
- * node's child nodes and the node already has a child node with the
given name
- * @throws ConstraintViolationException if one of the node's properties or child
nodes does not have a matching definition for
- * the name and type among the node's primary and mixin types; this
should only occur if type definitions have been
- * modified since the node was loaded or modified.
- * @throws RepositoryException if any other error occurs
- */
- private void checkAgainstTypeDefinitions( UUID nodeUuid,
- boolean checkSns )
- throws ConstraintViolationException, ItemExistsException, RepositoryException {
-
- assert nodeUuid != null;
-
- if (this.deletedNodes.containsKey(nodeUuid)) {
- nodeUuid = this.deletedNodes.get(nodeUuid).getParent();
- }
-
- NodeInfo nodeInfo = findNodeInfo(nodeUuid);
- AbstractJcrNode node = findJcrNode(nodeUuid);
-
- Name primaryTypeName = node.getPrimaryTypeName();
- List<Name> mixinTypeNames = node.getMixinTypeNames();
- Set<JcrNodeDefinition> satisfiedChildNodes = new
HashSet<JcrNodeDefinition>();
- Set<JcrPropertyDefinition> satisfiedProperties = new
HashSet<JcrPropertyDefinition>();
-
- for (AbstractJcrProperty property : findJcrPropertiesFor(nodeUuid)) {
- JcrPropertyDefinition definition =
findBestPropertyDefintion(primaryTypeName,
- mixinTypeNames,
-
property.property(),
-
property.getType(),
-
property.property().isSingle(),
- false);
- if (definition == null) {
- throw new
ConstraintViolationException(JcrI18n.noDefinition.text("property",
-
property.getName(),
-
node.getPath(),
-
primaryTypeName,
-
mixinTypeNames));
- }
-
- satisfiedProperties.add(definition);
- }
-
- Children children = nodeInfo.getChildren();
- for (ChildNode child : children) {
- int snsCount = children.getCountOfSameNameSiblingsWithName(child.getName());
- NodeInfo childInfo = findNodeInfo(child.getUuid());
- JcrNodeDefinition definition =
nodeTypes().findChildNodeDefinition(primaryTypeName,
-
mixinTypeNames,
-
child.getName(),
-
childInfo.getPrimaryTypeName(),
- snsCount,
- false);
- if (definition == null) {
- if (checkSns && snsCount > 1) {
- definition = nodeTypes().findChildNodeDefinition(primaryTypeName,
- mixinTypeNames,
- child.getName(),
-
childInfo.getPrimaryTypeName(),
- 1,
- false);
-
- if (definition != null) {
- throw new
ItemExistsException(JcrI18n.noSnsDefinition.text(child.getName(),
-
node.getPath(),
-
primaryTypeName,
-
mixinTypeNames));
- }
- }
- throw new
ConstraintViolationException(JcrI18n.noDefinition.text("child node",
-
child.getName(),
-
node.getPath(),
-
primaryTypeName,
-
mixinTypeNames));
- }
- satisfiedChildNodes.add(definition);
- }
-
- JcrNodeType primaryType = nodeTypes().getNodeType(primaryTypeName);
- for (JcrPropertyDefinition definition : primaryType.getPropertyDefinitions()) {
- if (definition.isMandatory() && !definition.isProtected() &&
!satisfiedProperties.contains(definition)) {
- throw new
ConstraintViolationException(JcrI18n.noDefinition.text("property",
-
definition.getName(),
-
node.getPath(),
-
primaryTypeName,
-
mixinTypeNames));
- }
- }
- for (JcrNodeDefinition definition : primaryType.getChildNodeDefinitions()) {
- if (definition.isMandatory() && !definition.isProtected() &&
!satisfiedChildNodes.contains(definition)) {
- throw new
ConstraintViolationException(JcrI18n.noDefinition.text("child node",
-
definition.getName(),
-
node.getPath(),
-
primaryTypeName,
-
mixinTypeNames));
- }
- }
-
- for (Name mixinTypeName : mixinTypeNames) {
- JcrNodeType mixinType = nodeTypes().getNodeType(mixinTypeName);
- for (JcrPropertyDefinition definition : mixinType.getPropertyDefinitions())
{
- if (definition.isMandatory() && !definition.isProtected()
&& !satisfiedProperties.contains(definition)) {
- throw new
ConstraintViolationException(JcrI18n.noDefinition.text("child node",
-
definition.getName(),
-
node.getPath(),
-
primaryTypeName,
-
mixinTypeNames));
- }
- }
- for (JcrNodeDefinition definition : mixinType.getChildNodeDefinitions()) {
- if (definition.isMandatory() && !definition.isProtected()
&& !satisfiedChildNodes.contains(definition)) {
- throw new
ConstraintViolationException(JcrI18n.noDefinition.text("child node",
-
definition.getName(),
-
node.getPath(),
-
primaryTypeName,
-
mixinTypeNames));
- }
- }
-
- }
- }
-
- /**
* Find the best definition for the child node with the given name on the node with
the given UUID.
*
- * @param nodeUuid the parent node; may not be null
+ * @param parent the parent node; may not be null
* @param newNodeName the name of the potential new child node; may not be null
* @param newNodePrimaryTypeName the primary type of the potential new child node;
may not be null
* @return the definition that best fits the new node name and type
@@ -536,48 +296,18 @@
* mixin types
* @throws RepositoryException if any other error occurs
*/
- protected JcrNodeDefinition findBestNodeDefinition( UUID nodeUuid,
+ protected JcrNodeDefinition findBestNodeDefinition( Node<JcrNodePayload,
JcrPropertyPayload> parent,
Name newNodeName,
Name newNodePrimaryTypeName )
throws ItemExistsException, ConstraintViolationException, RepositoryException {
- assert (nodeUuid != null);
- assert (newNodeName != null);
+ assert parent != null;
+ assert newNodeName != null;
- NodeInfo nodeInfo = findNodeInfo(nodeUuid);
- AbstractJcrNode node = findJcrNode(nodeUuid);
+ Name primaryTypeName = parent.getPayload().getPrimaryTypeName();
+ List<Name> mixinTypeNames = parent.getPayload().getMixinTypeNames();
- return findBestNodeDefinition(nodeInfo, node.getPath(), newNodeName,
newNodePrimaryTypeName);
- }
-
- /**
- * Find the best definition for the child node with the given name on the node with
the given UUID.
- *
- * @param parentInfo the parent node's info; may not be null
- * @param parentPath the path to the parent node; may not be null
- * @param newNodeName the name of the potential new child node; may not be null
- * @param newNodePrimaryTypeName the primary type of the potential new child node;
may not be null
- * @return the definition that best fits the new node name and type
- * @throws ItemExistsException if there is no definition that allows same-name
siblings for the name and type and the parent
- * node already has a child node with the given name
- * @throws ConstraintViolationException if there is no definition for the name and
type among the parent node's primary and
- * mixin types
- * @throws RepositoryException if any other error occurs
- */
- protected JcrNodeDefinition findBestNodeDefinition( NodeInfo parentInfo,
- String parentPath,
- Name newNodeName,
- Name newNodePrimaryTypeName )
- throws ItemExistsException, ConstraintViolationException, RepositoryException {
- assert (parentInfo != null);
- assert (parentPath != null);
- assert (newNodeName != null);
-
- Name primaryTypeName = parentInfo.getPrimaryTypeName();
- List<Name> mixinTypeNames = parentInfo.getMixinTypeNames();
-
- Children children = parentInfo.getChildren();
// Need to add one to speculate that this node will be added
- int snsCount = children.getCountOfSameNameSiblingsWithName(newNodeName) + 1;
+ int snsCount = parent.getChildrenCount(newNodeName) + 1;
JcrNodeDefinition definition =
nodeTypes().findChildNodeDefinition(primaryTypeName,
mixinTypeNames,
newNodeName,
@@ -594,302 +324,271 @@
true);
if (definition != null) {
- throw new
ItemExistsException(JcrI18n.noSnsDefinition.text(newNodeName,
-
parentPath,
-
primaryTypeName,
-
mixinTypeNames));
+ throw new
ItemExistsException(JcrI18n.noSnsDefinition.text(readable(newNodeName),
+
readable(parent.getPath()),
+
readable(primaryTypeName),
+
readable(mixinTypeNames)));
}
}
throw new ConstraintViolationException(JcrI18n.noDefinition.text("child
node",
-
newNodeName,
- parentPath,
-
primaryTypeName,
-
mixinTypeNames));
+
readable(newNodeName),
+
readable(parent.getPath()),
+
readable(primaryTypeName),
+
readable(mixinTypeNames)));
}
return definition;
}
/**
- * The JCR specification assumes that reading a node into the session does not imply
reading the relationship between the node
- * and its children into the session. As a performance optimization, DNA eagerly
loads the list of child names and UUIDs (but
- * not the child nodes themselves). This creates an issue when direct writes are
performed through the workspace. The act of
- * modifying a node is assumed to imply loading its children, but we must load the
node in order to modify it.
- * <p>
- * This method provides a way to signal that a child should be added to one parent
and, optionally, removed from another. The
- * cache of loaded nodes and the cache of changed nodes are modified accordingly, but
no additional graph requests are
- * batched.
- * </p>
+ * Save any changes that have been accumulated by this session.
*
- * @param newParentUuid the UUID of the node to which the child is to be moved; may
not be null
- * @param oldParentUuid the UUID of the parent node from which the child was moved;
may not be null
- * @param child the UUID of the child node that was moved or copied; may not be null
- * @param childName the new name of the child node; may not be null
- * @throws RepositoryException if an error occurs
+ * @throws IllegalArgumentException if the identifier and path are both node
+ * @throws ItemNotFoundException if a node with the supplied identifier and path
could not be found
+ * @throws AccessDeniedException if the caller does not have privilege to perform the
operation
+ * @throws ConstraintViolationException if there was a constraint violation
+ * @throws RepositoryException if any error resulting while saving the changes to the
repository
*/
- public void compensateForWorkspaceChildChange( UUID newParentUuid,
- UUID oldParentUuid,
- UUID child,
- Name childName ) throws
RepositoryException {
- assert newParentUuid != null;
- assert child != null;
- assert childName != null;
-
- ChangedNodeInfo changedNode = this.changedNodes.get(newParentUuid);
- if (changedNode != null) {
- // This adds the child to the changed node, but doesn't generate a
corresponding pending request
- // avoiding a challenge later.
- changedNode.addChild(childName, child, this.pathFactory);
-
- } else {
- this.cachedNodes.remove(newParentUuid);
+ public void save() throws ItemNotFoundException, AccessDeniedException,
ConstraintViolationException, RepositoryException {
+ try {
+ graphSession.save();
+ } catch (ValidationException e) {
+ throw new ConstraintViolationException(e.getLocalizedMessage(),
e.getCause());
+ } catch (InvalidStateException e) {
+ throw new InvalidItemStateException(e.getLocalizedMessage(), e.getCause());
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getLocalizedMessage(), e.getCause());
+ } catch (AccessControlException e) {
+ throw new AccessDeniedException(e.getMessage(), e.getCause());
}
-
- if (oldParentUuid != null) {
- changedNode = this.changedNodes.get(oldParentUuid);
- if (changedNode != null) {
- changedNode.removeChild(child, this.pathFactory);
- } else {
- this.cachedNodes.remove(newParentUuid);
- }
- }
}
/**
- * Save any changes that have been accumulated by this session.
+ * Save any changes to the identified node or its descendants. The supplied node may
not have been deleted or created in this
+ * session since the last save operation.
*
+ * @param nodeId the identifier of the node that is to be saved; may not be null
+ * @param absolutePath the absolute path to the node; may not be null
+ * @throws IllegalArgumentException if the identifier and path are both node
+ * @throws ItemNotFoundException if a node with the supplied identifier and path
could not be found
+ * @throws AccessDeniedException if the caller does not have privilege to perform the
operation
+ * @throws ConstraintViolationException if there was a constraint violation
* @throws RepositoryException if any error resulting while saving the changes to the
repository
*/
- public void save() throws RepositoryException {
- if (operations.isExecuteRequired()) {
- for (UUID changedUuid : this.changedNodes.keySet()) {
- checkAgainstTypeDefinitions(changedUuid, false);
- }
-
- // Execute the batched operations ...
- try {
- operations.execute();
- } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
- throw new InvalidItemStateException(e.getLocalizedMessage(), e);
- } catch (RuntimeException e) {
- throw new RepositoryException(e.getLocalizedMessage(), e);
- }
-
- // Create a new batch for future operations ...
- // LinkedList<Request> oldRequests = this.requests;
- this.requests = new LinkedList<Request>();
- this.requestBuilder = new BatchRequestBuilder(this.requests);
- operations = store.batch(this.requestBuilder);
-
- // Remove all the cached items that have been changed or deleted ...
- for (UUID changedUuid : changedNodes.keySet()) {
- cachedNodes.remove(changedUuid);
- }
- for (UUID changedUuid : deletedNodes.keySet()) {
- cachedNodes.remove(changedUuid);
- }
- // Remove all the changed and deleted infos ...
- changedNodes.clear();
- deletedNodes.clear();
+ public void save( NodeId nodeId,
+ Path absolutePath )
+ throws ItemNotFoundException, AccessDeniedException,
ConstraintViolationException, RepositoryException {
+ assert nodeId != null;
+ try {
+ Node<JcrNodePayload, JcrPropertyPayload> node =
graphSession.findNodeWith(nodeId, absolutePath);
+ assert node != null;
+ graphSession.save(node);
+ } catch (ValidationException e) {
+ throw new ConstraintViolationException(e.getLocalizedMessage(),
e.getCause());
+ } catch (InvalidStateException e) {
+ throw new InvalidItemStateException(e.getLocalizedMessage(), e.getCause());
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getLocalizedMessage(), e.getCause());
+ } catch (AccessControlException e) {
+ throw new AccessDeniedException(e.getMessage(), e.getCause());
}
}
/**
- * Save any changes to the identified node or its descendants. The supplied node may
not have been deleted or created in this
- * session since the last save operation.
+ * Find the session's node for the given identifier and path.
*
- * @param nodeUuid the UUID of the node that is to be saved; may not be null
- * @throws RepositoryException if any error resulting while saving the changes to the
repository
+ * @param id the identifier for the node
+ * @param absolutePath the absolute path to the node; may not be null
+ * @return the existing node implementation
+ * @throws IllegalArgumentException if the identifier and path are both node
+ * @throws ItemNotFoundException if a node with the supplied identifier and path
could not be found
+ * @throws AccessDeniedException if the caller does not have privilege to read the
node
+ * @throws RepositoryException if an error resulting in finding this node in the
repository
*/
- public void save( UUID nodeUuid ) throws RepositoryException {
- assert nodeUuid != null;
- if (deletedNodes.containsKey(nodeUuid)) {
- // This node was deleted in this session ...
- throw new
InvalidItemStateException(JcrI18n.nodeHasAlreadyBeenRemovedFromThisSession.text(nodeUuid,
workspaceName()));
+ public Node<JcrNodePayload, JcrPropertyPayload> findNode( NodeId id,
+ Path absolutePath )
+ throws ItemNotFoundException, AccessDeniedException, RepositoryException {
+ try {
+ return graphSession.findNodeWith(id, absolutePath);
+ } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
+ throw new ItemNotFoundException(e.getMessage(), e.getCause());
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getMessage(), e.getCause());
+ } catch (AccessControlException e) {
+ throw new AccessDeniedException(e.getMessage(), e.getCause());
}
+ }
- // The node must not have been created since the last save ...
- if (!cachedNodes.containsKey(nodeUuid)) {
- // It is not cached, which means it WAS created ...
- Path path = getPathFor(nodeUuid);
- throw new
RepositoryException(JcrI18n.unableToSaveNodeThatWasCreatedSincePreviousSave.text(path,
workspaceName()));
+ /**
+ * Find the session's node for the given identifier and path.
+ *
+ * @param from the identifier of the reference node; may be null if the root node is
to be used as the reference
+ * @param fromAbsolutePath the absolute path of the reference node; may not be null
+ * @param relativePath the relative (but normalized) path from the reference node,
but which may be an absolute (and
+ * normalized) path only when the reference node is the root node; may not be
null
+ * @return the existing node implementation
+ * @throws IllegalArgumentException if the identifier and path are both node
+ * @throws ItemNotFoundException if a node with the supplied identifier and path
could not be found
+ * @throws PathNotFoundException if the node given by the relative path does not
exist
+ * @throws AccessDeniedException if the caller does not have privilege to read the
node
+ * @throws RepositoryException if an error resulting in finding this node in the
repository
+ */
+ public Node<JcrNodePayload, JcrPropertyPayload> findNode( NodeId from,
+ Path fromAbsolutePath,
+ Path relativePath )
+ throws PathNotFoundException, ItemNotFoundException, AccessDeniedException,
RepositoryException {
+ // Find the reference node ...
+ Node<JcrNodePayload, JcrPropertyPayload> referenceNode = findNode(from,
fromAbsolutePath);
+ try {
+ return graphSession.findNodeRelativeTo(referenceNode, relativePath);
+ } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
+ throw new PathNotFoundException(e.getMessage(), e.getCause());
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getMessage(), e.getCause());
+ } catch (AccessControlException e) {
+ throw new AccessDeniedException(e.getMessage(), e.getCause());
}
-
- if (operations.isExecuteRequired()) {
- // Find the path of the given node ...
- Path path = getPathFor(nodeUuid);
-
- // Make sure the builder has finished all the requests ...
- this.requestBuilder.finishPendingRequest();
-
- // Remove all of the enqueued requests for this branch ...
- LinkedList<Request> branchRequests = new LinkedList<Request>();
- LinkedList<Request> nonBranchRequests = new
LinkedList<Request>();
- Set<UUID> branchUuids = new HashSet<UUID>();
- for (Request request : this.requests) {
- assert request instanceof ChangeRequest;
- ChangeRequest change = (ChangeRequest)request;
- if (change.changes(workspaceName, path)) {
- branchRequests.add(request);
- // Record the UUID of the node being saved now ...
- UUID changedUuid = null;
- if (change instanceof CreateNodeRequest) {
- // We want the parent UUID ...
- changedUuid = ((CreateNodeRequest)change).under().getUuid();
- } else {
- changedUuid = change.changedLocation().getUuid();
- }
- assert changedUuid != null;
- branchUuids.add(changedUuid);
- } else {
- nonBranchRequests.add(request);
- }
- }
-
- if (branchRequests.isEmpty()) {
- // None of the changes affected the branch given by the node ...
- return;
- }
-
- /*
- * branchUuids contains all the roots of the changes, but there may be
further changes under the roots (e.g., a
- * newly created node will have it's parent's UUID in branchUuids,
but not the new node's uuid.
- */
- Set<UUID> uuidsUnderBranch = new HashSet<UUID>();
- LinkedList<UUID> peersToCheck = new LinkedList<UUID>();
-
- for (UUID changedUuid : branchUuids) {
- checkAgainstTypeDefinitions(changedUuid, false);
- }
-
- for (UUID branchUuid : branchUuids) {
- uuidsUnderBranch.add(branchUuid);
- ChangedNodeInfo changedNode = changedNodes.get(branchUuid);
- if (changedNode != null) {
- for (ChildNode childNode : changedNode.getChildren()) {
- uuidsUnderBranch.add(childNode.getUuid());
- }
-
- Collection<UUID> peers = changedNode.getPeers();
- if (peers != null) peersToCheck.addAll(peers);
- }
-
- }
-
- /*
- * Need to check that any peers in a Session.move operation are both in the
save
- */
- for (UUID peerUuid : peersToCheck) {
- if (!uuidsUnderBranch.contains(peerUuid)) {
- throw new ConstraintViolationException();
- }
- }
-
- // Now execute the branch ...
- Graph.Batch branchBatch = store.batch(new
BatchRequestBuilder(branchRequests));
- try {
- branchBatch.execute();
-
- // Still have non-branch related requests that we haven't executed
...
- this.requests = nonBranchRequests;
- this.requestBuilder = new BatchRequestBuilder(this.requests);
- this.operations = store.batch(this.requestBuilder);
-
- // Remove all the cached, changed or deleted items that were just saved
...
- cachedNodes.keySet().removeAll(uuidsUnderBranch);
- changedNodes.keySet().removeAll(uuidsUnderBranch);
- deletedNodes.keySet().removeAll(uuidsUnderBranch);
- } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
- throw new InvalidItemStateException(e.getLocalizedMessage(), e);
- } catch (RuntimeException e) {
- throw new RepositoryException(e.getLocalizedMessage(), e);
- }
- }
}
+ /**
+ * Find the root node associated with this workspace.
+ *
+ * @return the root node; never null
+ * @throws RepositoryException if an error resulting in finding this node in the
repository
+ */
public JcrRootNode findJcrRootNode() throws RepositoryException {
- return (JcrRootNode)findJcrNode(findNodeInfoForRoot().getUuid());
+ return (JcrRootNode)graphSession.getRoot().getPayload().getJcrNode();
}
/**
- * Find the JCR {@link JcrNode Node implementation} for the given UUID.
+ * Find the JCR {@link JcrNode Node implementation} for the given identifier and
path.
*
- * @param uuid the node's UUID
+ * @param location the location of the node
* @return the existing node implementation
- * @throws ItemNotFoundException if a node with the supplied UUID could not be found
+ * @throws IllegalArgumentException if the identifier and path are both node
+ * @throws ItemNotFoundException if a node with the supplied identifier and path
could not be found
+ * @throws AccessDeniedException if the caller does not have privilege to read the
node
* @throws RepositoryException if an error resulting in finding this node in the
repository
*/
- public AbstractJcrNode findJcrNode( UUID uuid ) throws ItemNotFoundException,
RepositoryException {
- AbstractJcrNode node = jcrNodes.get(uuid);
- if (node != null) return node;
+ public AbstractJcrNode findJcrNode( Location location )
+ throws ItemNotFoundException, AccessDeniedException, RepositoryException {
+ try {
+ return graphSession.findNodeWith(location).getPayload().getJcrNode();
+ } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
+ throw new ItemNotFoundException(e.getMessage(), e.getCause());
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getMessage(), e.getCause());
+ } catch (AccessControlException e) {
+ throw new AccessDeniedException(e.getMessage(), e.getCause());
+ }
+ }
- // An existing JCR Node object was not found, so we'll have to create it by
finding the underlying
- // NodeInfo for the node (from the changed state or the cache) ...
- NodeInfo info = findNodeInfo(uuid);
- assert info != null;
-
- // Create the appropriate JCR Node object ...
- return createAndCacheJcrNodeFor(info);
+ /**
+ * Find the JCR {@link JcrNode Node implementation} for the given identifier and
path.
+ *
+ * @param id the identifier for the node
+ * @param absolutePath the absolute path to the node; may not be null
+ * @return the existing node implementation
+ * @throws IllegalArgumentException if the identifier and path are both node
+ * @throws ItemNotFoundException if a node with the supplied identifier and path
could not be found
+ * @throws AccessDeniedException if the caller does not have privilege to read the
node
+ * @throws RepositoryException if an error resulting in finding this node in the
repository
+ */
+ public AbstractJcrNode findJcrNode( NodeId id,
+ Path absolutePath )
+ throws ItemNotFoundException, AccessDeniedException, RepositoryException {
+ return findNode(id, absolutePath).getPayload().getJcrNode();
}
/**
* Find the JCR {@link AbstractJcrNode Node implementation} for the node given by the
UUID of a reference node and a relative
* path from the reference node. The relative path should already have been {@link
Path#getNormalizedPath() normalized}.
*
- * @param uuidOfReferenceNode the UUID of the reference node; may be null if the root
node is to be used as the reference
+ * @param from the identifier of the reference node; may be null if the root node is
to be used as the reference
+ * @param fromAbsolutePath the absolute path of the reference node; may not be null
* @param relativePath the relative (but normalized) path from the reference node,
but which may be an absolute (and
* normalized) path only when the reference node is the root node; may not be
null
* @return the information for the referenced node; never null
- * @throws ItemNotFoundException if the reference node with the supplied UUID does
not exist
+ * @throws ItemNotFoundException if the reference node with the supplied identifier
and path does not exist
* @throws PathNotFoundException if the node given by the relative path does not
exist
- * @throws InvalidItemStateException if the node with the UUID has been deleted in
this session
+ * @throws InvalidItemStateException if the reference node has been deleted in this
session
+ * @throws AccessDeniedException if the caller does not have privilege to read the
reference or result node
* @throws RepositoryException if any other error occurs while reading information
from the repository
- * @see #findNodeInfoForRoot()
*/
- public AbstractJcrNode findJcrNode( UUID uuidOfReferenceNode,
+ public AbstractJcrNode findJcrNode( NodeId from,
+ Path fromAbsolutePath,
Path relativePath )
- throws PathNotFoundException, InvalidItemStateException, RepositoryException {
- // An existing JCR Node object was not found, so we'll have to create it by
finding the underlying
- // NodeInfo for the node (from the changed state or the cache) ...
- NodeInfo info = findNodeInfo(uuidOfReferenceNode, relativePath);
- assert info != null;
-
- // Look for an existing node ...
- AbstractJcrNode node = jcrNodes.get(info.getUuid());
- if (node != null) return node;
-
- // Create the appropriate JCR Node object ...
- return createAndCacheJcrNodeFor(info);
+ throws ItemNotFoundException, PathNotFoundException, InvalidItemStateException,
AccessDeniedException,
+ RepositoryException {
+ // Find the reference node ...
+ Node<JcrNodePayload, JcrPropertyPayload> referenceNode = findNode(from,
fromAbsolutePath);
+ try {
+ // Find the reference node ...
+ return graphSession.findNodeRelativeTo(referenceNode,
relativePath).getPayload().getJcrNode();
+ } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
+ throw new PathNotFoundException(e.getMessage(), e.getCause());
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getMessage(), e.getCause());
+ } catch (AccessControlException e) {
+ throw new AccessDeniedException(e.getMessage(), e.getCause());
+ }
}
- public AbstractJcrProperty findJcrProperty( PropertyId propertyId ) throws
PathNotFoundException, RepositoryException {
- AbstractJcrProperty property = jcrProperties.get(propertyId);
- if (property != null) return property;
-
- // An existing JCR Property object was not found, so we'll have to create it
by finding the underlying
- // NodeInfo for the property's parent (from the changed state or the cache)
...
- PropertyInfo info = findPropertyInfo(propertyId); // throws PathNotFoundException
if node not there
- if (info == null) return null; // no such property on this node
-
- // Skip all internal properties ...
- if (info.getPropertyName().getNamespaceUri().equals(DnaIntLexicon.Namespace.URI))
return null;
-
- // Now create the appropriate JCR Property object ...
- return createAndCacheJcrPropertyFor(info);
+ /**
+ * Find the JCR {@link javax.jcr.Property} with the givenname on the node with the
supplied ID and/or at the absolute path.
+ *
+ * @param id the identifier of the node, or null if the path should be used
+ * @param absolutePath the absolute path to the node; should not be null
+ * @param propertyName the property name; may not be null
+ * @return the property, or null if there is no such property
+ * @throws PathNotFoundException if the node does not exist
+ * @throws AccessDeniedException if the caller cannot read the property
+ * @throws RepositoryException if there is a problem reading the node and/or
property
+ */
+ public AbstractJcrProperty findJcrProperty( NodeId id,
+ Path absolutePath,
+ Name propertyName )
+ throws PathNotFoundException, AccessDeniedException, RepositoryException {
+ // Find the node that owns the property ...
+ Node<JcrNodePayload, JcrPropertyPayload> node = findNode(id,
absolutePath);
+ PropertyInfo<JcrPropertyPayload> propertyInfo =
node.getProperty(propertyName);
+ if (propertyInfo != null) {
+ return propertyInfo.getPayload().getJcrProperty();
+ }
+ return null;
}
- public Collection<AbstractJcrProperty> findJcrPropertiesFor( UUID nodeUuid )
- throws ItemNotFoundException, RepositoryException {
- NodeInfo info = findNodeInfo(nodeUuid);
- Set<Name> propertyNames = info.getPropertyNames();
- Collection<AbstractJcrProperty> result = new
ArrayList<AbstractJcrProperty>(propertyNames.size());
- for (Name propertyName : propertyNames) {
- if (!propertyName.getNamespaceUri().equals(DnaIntLexicon.Namespace.URI)) {
- result.add(findJcrProperty(new PropertyId(nodeUuid, propertyName)));
+ /**
+ * Find the properties for the node given by the supplied identifier and/or path.
+ *
+ * @param id the identifier of the node, or null if the path should be used
+ * @param absolutePath the absolute path to the node; should not be null
+ * @return an immutable snapshot of the properties in the node
+ * @throws PathNotFoundException if the node does not exist
+ * @throws AccessDeniedException if the caller cannot read the property
+ * @throws RepositoryException if there is a problem reading the node and/or
property
+ */
+ public Collection<AbstractJcrProperty> findJcrPropertiesFor( NodeId id,
+ Path absolutePath )
+ throws PathNotFoundException, AccessDeniedException, RepositoryException {
+ try {
+ Node<JcrNodePayload, JcrPropertyPayload> node =
graphSession.findNodeWith(id, absolutePath);
+ Collection<AbstractJcrProperty> result = new
ArrayList<AbstractJcrProperty>(node.getPropertyCount());
+ for
(org.jboss.dna.graph.session.GraphSession.PropertyInfo<JcrPropertyPayload> property
: node.getProperties()) {
+ Name propertyName = property.getName();
+ if (!propertyName.getNamespaceUri().equals(DnaIntLexicon.Namespace.URI))
{
+ result.add(property.getPayload().getJcrProperty());
+ }
}
+ return result;
+ } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
+ throw new PathNotFoundException(e.getMessage(), e.getCause());
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getMessage(), e.getCause());
+ } catch (AccessControlException e) {
+ throw new AccessDeniedException(e.getMessage(), e.getCause());
}
- return result;
}
/**
@@ -897,7 +596,9 @@
* a relative path from the reference node to the desired item. The relative path
should already have been
* {@link Path#getNormalizedPath() normalized}.
*
- * @param uuidOfReferenceNode the UUID of the reference node; may be null if the root
node is to be used as the reference
+ * @param from the identifier of the reference node; may be null if the root node is
to be used as the reference
+ * @param fromAbsolutePath the absolute path of the reference node; may be null if
the root node is to be used as the
+ * reference
* @param relativePath the relative (but normalized) path from the reference node to
the desired item, but which may be an
* absolute (and normalized) path only when the reference node is the root
node; may not be null
* @return the information for the referenced item; never null
@@ -905,21 +606,23 @@
* supplied relative path does not exist
* @throws InvalidItemStateException if the node with the UUID has been deleted in
this session
* @throws RepositoryException if any other error occurs while reading information
from the repository
- * @see #findNodeInfoForRoot()
*/
- public AbstractJcrItem findJcrItem( UUID uuidOfReferenceNode,
+ public AbstractJcrItem findJcrItem( NodeId from,
+ Path fromAbsolutePath,
Path relativePath )
throws ItemNotFoundException, InvalidItemStateException, RepositoryException {
+ if (from == null && fromAbsolutePath == null) {
+ from = graphSession.getRoot().getNodeId();
+ }
// A pathological case is an empty relative path ...
if (relativePath.size() == 0) {
- return findJcrNode(uuidOfReferenceNode);
+ return findJcrNode(from, fromAbsolutePath);
}
if (relativePath.size() == 1) {
Path.Segment segment = relativePath.getLastSegment();
- if (segment.isSelfReference()) return findJcrNode(uuidOfReferenceNode);
+ if (segment.isSelfReference()) return findJcrNode(from, fromAbsolutePath);
if (segment.isParentReference()) {
- NodeInfo referencedNode = findNodeInfo(uuidOfReferenceNode);
- return findJcrNode(referencedNode.getParent());
+ return findJcrNode(from, fromAbsolutePath, relativePath);
}
}
@@ -927,115 +630,168 @@
Path.Segment lastSegment = relativePath.getLastSegment();
if (lastSegment.getIndex() > 1) {
// Only nodes can have SNS index (but an index of 1 is the default)...
- return findJcrNode(uuidOfReferenceNode);
+ return findJcrNode(from, fromAbsolutePath);
}
- NodeInfo parent = null;
- if (relativePath.size() == 1) {
- // The referenced node must be the parent ...
- parent = findNodeInfo(uuidOfReferenceNode);
- } else {
- // We know that the parent of the referenced item should be a node (if the
path is right) ...
- parent = findNodeInfo(uuidOfReferenceNode, relativePath.getParent());
+ Node<JcrNodePayload, JcrPropertyPayload> fromNode = null;
+ Node<JcrNodePayload, JcrPropertyPayload> parent = null;
+ try {
+ fromNode = graphSession.findNodeWith(from, fromAbsolutePath);
+ if (from == null) from = fromNode.getNodeId();
+ assert from != null;
+ if (relativePath.size() == 1) {
+ // The referenced node must be the parent ...
+ parent = fromNode;
+ } else {
+ // We know that the parent of the referenced item should be a node (if
the path is right) ...
+ parent = graphSession.findNodeRelativeTo(fromNode,
relativePath.getParent());
+ }
+ } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
+ throw new ItemNotFoundException(e.getMessage(), e.getCause());
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getMessage(), e.getCause());
+ } catch (AccessControlException e) {
+ throw new AccessDeniedException(e.getMessage(), e.getCause());
}
// JSR-170 doesn't allow children and proeprties to have the same name, but
this is relaxed in JSR-283.
// But JSR-283 Section 3.3.4 states "The method Session.getItem will return
the item at the specified path
// if there is only one such item, if there is both a node and a property at the
specified path, getItem
// will return the node." Therefore, look for a child first ...
- ChildNode child = parent.getChildren().getChild(lastSegment);
- if (child != null) {
- return findJcrNode(child.getUuid());
+ if (parent.hasChild(lastSegment)) {
+ // There is a child!
+ Node<JcrNodePayload, JcrPropertyPayload> child =
parent.getChild(lastSegment);
+ return child.getPayload().getJcrNode();
}
// Otherwise it should be a property ...
- PropertyInfo propertyInfo = parent.getProperty(lastSegment.getName());
+ org.jboss.dna.graph.session.GraphSession.PropertyInfo<JcrPropertyPayload>
propertyInfo = parent.getProperty(lastSegment.getName());
if (propertyInfo != null) {
- return findJcrProperty(propertyInfo.getPropertyId());
+ return propertyInfo.getPayload().getJcrProperty();
}
// It was not found, so prepare a good exception message ...
String msg = null;
- if (findNodeInfoForRoot().getUuid().equals(uuidOfReferenceNode)) {
+ if (from.equals(graphSession.getRoot().getNodeId())) {
// The reference node was the root, so use this fact to convert the path to
an absolute path in the message
Path absolutePath = rootPath.resolve(relativePath);
- msg = JcrI18n.itemNotFoundAtPath.text(absolutePath, workspaceName);
+ msg = JcrI18n.itemNotFoundAtPath.text(readable(absolutePath),
workspaceName);
} else {
// Find the path of the reference node ...
- Path referenceNodePath = getPathFor(uuidOfReferenceNode);
- msg = JcrI18n.itemNotFoundAtPathRelativeToReferenceNode.text(relativePath,
referenceNodePath, workspaceName);
+ Path referenceNodePath = fromNode.getPath();
+ msg =
JcrI18n.itemNotFoundAtPathRelativeToReferenceNode.text(readable(relativePath),
+
readable(referenceNodePath),
+ workspaceName);
}
throw new ItemNotFoundException(msg);
}
/**
* Obtain an {@link NodeEditor editor} that can be used to manipulate the properties
or children on the node identified by the
- * supplied UUID. The node must exist prior to this call, either as a node that
exists in the workspace or as a node that was
- * created within this session but not yet persisted to the workspace. This method
returns an editor that batches all changes
- * in transient storage from where they can be persisted to the repository by {@link
javax.jcr.Session#save() saving the
- * session} or by {@link javax.jcr.Item#save() saving an ancestor}.
+ * supplied identifier and path. The node must exist prior to this call, either as a
node that exists in the workspace or as a
+ * node that was created within this session but not yet persisted to the workspace.
This method returns an editor that
+ * batches all changes in transient storage from where they can be persisted to the
repository by
+ * {@link javax.jcr.Session#save() saving the session} or by {@link
javax.jcr.Item#save() saving an ancestor}.
*
- * @param uuid the UUID of the node that is to be changed; may not be null and must
represent an <i>existing</i> node
+ * @param node the node
* @return the editor; never null
- * @throws ItemNotFoundException if no such node could be found in the session or
workspace
- * @throws InvalidItemStateException if the item has been marked for deletion within
this session
- * @throws RepositoryException if any other error occurs while reading information
from the repository
*/
- public NodeEditor getEditorFor( UUID uuid ) throws ItemNotFoundException,
InvalidItemStateException, RepositoryException {
- return getEditorFor(uuid, this.operations);
+ public NodeEditor getEditorFor( Node<JcrNodePayload, JcrPropertyPayload> node )
{
+ return new NodeEditor(node);
}
/**
* Obtain an {@link NodeEditor editor} that can be used to manipulate the properties
or children on the node identified by the
- * supplied UUID. The node must exist prior to this call, either as a node that
exists in the workspace or as a node that was
- * created within this session but not yet persisted to the workspace.
+ * supplied identifier and path. The node must exist prior to this call, either as a
node that exists in the workspace or as a
+ * node that was created within this session but not yet persisted to the workspace.
This method returns an editor that
+ * batches all changes in transient storage from where they can be persisted to the
repository by
+ * {@link javax.jcr.Session#save() saving the session} or by {@link
javax.jcr.Item#save() saving an ancestor}.
*
- * @param uuid the UUID of the node that is to be changed; may not be null and must
represent an <i>existing</i> node
- * @param operationsBatch the {@link Graph.Batch} to use for batching operations.
This should be populated for direct
- * persistence (q.v. section 7.1.3.7 of the JCR 1.0.1 specification) and
should be null to use session-based
- * persistence.
+ * @param id the identifier for the node
+ * @param absolutePath the absolute path to the node; may not be null
* @return the editor; never null
* @throws ItemNotFoundException if no such node could be found in the session or
workspace
+ * @throws AccessDeniedException if the caller does not have privilege to read the
reference or result node
* @throws InvalidItemStateException if the item has been marked for deletion within
this session
* @throws RepositoryException if any other error occurs while reading information
from the repository
*/
- public NodeEditor getEditorFor( UUID uuid,
- Graph.Batch operationsBatch )
- throws ItemNotFoundException, InvalidItemStateException, RepositoryException {
- // See if we already have something in the changed nodes ...
- ChangedNodeInfo info = changedNodes.get(uuid);
- Location currentLocation = null;
- if (info == null) {
- // Or in the cache ...
- NodeInfo cached = cachedNodes.get(uuid);
- if (cached == null) {
- cached = loadFromGraph(null, uuid);
+ public NodeEditor getEditorFor( NodeId id,
+ Path absolutePath )
+ throws ItemNotFoundException, AccessDeniedException, InvalidItemStateException,
RepositoryException {
+ Node<JcrNodePayload, JcrPropertyPayload> node =
this.graphSession.findNodeWith(id, absolutePath);
+ return new NodeEditor(node);
+ }
+
+ /**
+ * Returns the absolute path of the node in the specified workspace that corresponds
to this node.
+ * <p>
+ * The corresponding node is defined as the node in srcWorkspace with the same UUID
as this node or, if this node has no UUID,
+ * the same path relative to the nearest ancestor that does have a UUID, or the root
node, whichever comes first. This is
+ * qualified by the requirement that referencable nodes only correspond with other
referencables and non-referenceables with
+ * other non-referenceables.
+ * </p>
+ *
+ * @param workspaceName the name of the workspace
+ * @param uuid the UUID of the corresponding node, or the UUID of the closest
ancestor that is referenceable
+ * @param relativePath the relative path from the referenceable node, or null if the
supplied UUID identifies the
+ * corresponding node
+ * @return the absolute path to the corresponding node in the workspace; never null
+ * @throws NoSuchWorkspaceException if the specified workspace does not exist
+ * @throws ItemNotFoundException if no corresponding node exists
+ * @throws AccessDeniedException if the current session does not have sufficient
rights to perform this operation
+ * @throws RepositoryException if another exception occurs
+ */
+ Path getPathForCorrespondingNode( String workspaceName,
+ UUID uuid,
+ Path relativePath )
+ throws NoSuchWorkspaceException, AccessDeniedException, ItemNotFoundException,
RepositoryException {
+ assert workspaceName != null;
+ assert uuid != null || relativePath != null;
+
+ try {
+ try {
+ store.useWorkspace(workspaceName);
+ } catch (InvalidWorkspaceException iwe) {
+ throw new
NoSuchWorkspaceException(JcrI18n.workspaceNameIsInvalid.text(store.getSourceName(),
workspaceName));
}
- // Now put into the changed nodes ...
- info = new ChangedNodeInfo(cached);
- changedNodes.put(uuid, info);
- currentLocation = info.getOriginalLocation();
- } else {
- // compute the current location ...
- currentLocation = Location.create(getPathFor(info), uuid);
+ org.jboss.dna.graph.Node node;
+ if (uuid != null) {
+ node = store.getNodeAt(uuid);
+
+ if (relativePath != null) {
+ Path nodePath = node.getLocation().getPath();
+ Path absolutePath = relativePath.resolveAgainst(nodePath);
+ node = store.getNodeAt(absolutePath);
+ }
+
+ } else {
+ Path absolutePath =
pathFactory.createAbsolutePath(relativePath.getSegmentsList());
+ node = store.getNodeAt(absolutePath);
+ }
+ assert node != null;
+
+ Path path = node.getLocation().getPath();
+ try {
+ this.session().checkPermission(workspaceName, path, "read");
+ } catch (AccessControlException ace) {
+ throw new AccessDeniedException(ace);
+ }
+ return path;
+ } catch (org.jboss.dna.graph.property.PathNotFoundException pnfe) {
+ throw new ItemNotFoundException(pnfe);
+ } finally {
+ store.useWorkspace(this.workspaceName);
}
- return new NodeEditor(info, currentLocation, operationsBatch == null ?
this.operations : operationsBatch);
}
/**
* An interface used to manipulate a node's properties and children.
*/
public final class NodeEditor {
- private final ChangedNodeInfo node;
- private final Location currentLocation;
- private final Graph.Batch operations;
+ private final Node<JcrNodePayload, JcrPropertyPayload> node;
- protected NodeEditor( ChangedNodeInfo node,
- Location currentLocation,
- Graph.Batch operations ) {
+ protected NodeEditor( Node<JcrNodePayload, JcrPropertyPayload> node ) {
this.node = node;
- this.currentLocation = currentLocation;
- this.operations = operations;
}
/**
@@ -1052,20 +808,17 @@
boolean isMultiple )
throws javax.jcr.ValueFormatException, RepositoryException {
// Check for existing single-valued property - can't set multiple values
on single-valued property
- PropertyInfo propInfo = this.node.getProperty(propertyName);
+ PropertyInfo<JcrPropertyPayload> propInfo =
this.node.getProperty(propertyName);
if (propInfo != null && propInfo.isMultiValued() != isMultiple) {
- NamespaceRegistry namespaces = SessionCache.this.namespaces;
String workspaceName = SessionCache.this.workspaceName();
+ String propName = readable(propertyName);
+ String path = readable(node.getPath());
if (isMultiple) {
I18n msg =
JcrI18n.unableToSetSingleValuedPropertyUsingMultipleValues;
- throw new
javax.jcr.ValueFormatException(msg.text(propertyName.getString(namespaces),
-
getPathFor(this.node).getString(namespaces),
- workspaceName));
+ throw new javax.jcr.ValueFormatException(msg.text(propName, path,
workspaceName));
}
I18n msg = JcrI18n.unableToSetMultiValuedPropertyUsingSingleValue;
- throw new
javax.jcr.ValueFormatException(msg.text(propertyName.getString(namespaces),
-
getPathFor(this.node).getString(namespaces),
- workspaceName));
+ throw new javax.jcr.ValueFormatException(msg.text(propName, path,
workspaceName));
}
}
@@ -1076,14 +829,14 @@
*
* @param name the property name; may not be null
* @param value the new property values; may not be null
- * @return the identifier for the property; never null
+ * @return the JCR property object for the property; never null
* @throws ConstraintViolationException if the property could not be set because
of a node type constraint or property
* definition constraint
* @throws AccessDeniedException if the current session does not have the
requisite privileges to perform this task
* @throws RepositoryException if any other error occurs
*/
- public PropertyId setProperty( Name name,
- JcrValue value )
+ public AbstractJcrProperty setProperty( Name name,
+ JcrValue value )
throws AccessDeniedException, ConstraintViolationException,
RepositoryException {
return setProperty(name, value, true);
}
@@ -1096,35 +849,30 @@
* @param name the property name; may not be null
* @param value the new property values; may not be null
* @param skipProtected indicates whether protected property definitions should
be ignored
- * @return the identifier for the property; never null
+ * @return the JCR property object for the property; never null
* @throws ConstraintViolationException if the property could not be set because
of a node type constraint or property
* definition constraint
* @throws AccessDeniedException if the current session does not have the
requisite privileges to perform this task
* @throws RepositoryException if any other error occurs
*/
- public PropertyId setProperty( Name name,
- JcrValue value,
- boolean skipProtected )
+ public AbstractJcrProperty setProperty( Name name,
+ JcrValue value,
+ boolean skipProtected )
throws AccessDeniedException, ConstraintViolationException,
RepositoryException {
assert name != null;
assert value != null;
- SessionCache.this.checkPermission(node,
JcrSession.JCR_SET_PROPERTY_PERMISSION);
+ checkCardinalityOfExistingProperty(name, false);
JcrPropertyDefinition definition = null;
- PropertyId id = null;
- checkCardinalityOfExistingProperty(name, false);
-
// Look for an existing property ...
- PropertyInfo existing = node.getProperty(name);
+ PropertyInfo<JcrPropertyPayload> existing = node.getProperty(name);
if (existing != null) {
- // Reuse the existing ID ...
- id = existing.getPropertyId();
// We're replacing an existing property, but we still need to check
that the property definition
// (still) defines a type. So, find the property definition for the
existing property ...
- definition =
nodeTypes().getPropertyDefinition(existing.getDefinitionId());
+ definition =
nodeTypes().getPropertyDefinition(existing.getPayload().getPropertyDefinitionId());
if (definition != null) {
// The definition's require type must match the value's ...
@@ -1137,14 +885,12 @@
if (!definition.satisfiesConstraints(value)) definition = null;
}
}
- } else {
- // This is a new property, so create a new ID ...
- id = new PropertyId(node.getUuid(), name);
}
+ JcrNodePayload payload = node.getPayload();
if (definition == null) {
// Look for a definition ...
- definition =
nodeTypes().findPropertyDefinition(node.getPrimaryTypeName(),
-
node.getMixinTypeNames(),
+ definition =
nodeTypes().findPropertyDefinition(payload.getPrimaryTypeName(),
+
payload.getMixinTypeNames(),
name,
value,
true,
@@ -1167,14 +913,30 @@
}
Property dnaProp = propertyFactory.create(name, objValue);
- // Create the property info ...
- PropertyInfo newProperty = new PropertyInfo(id, definition.getId(),
propertyType, dnaProp, definition.isMultiple(),
- existing == null, existing !=
null);
-
- // Finally update the cached information and record the change ...
- node.setProperty(newProperty, factories());
- operations.set(dnaProp).on(currentLocation);
- return newProperty.getPropertyId();
+ try {
+ // Create (or reuse) the JCR Property object ...
+ AbstractJcrProperty jcrProp = null;
+ if (existing != null) {
+ jcrProp = existing.getPayload().getJcrProperty();
+ } else {
+ AbstractJcrNode jcrNode = payload.getJcrNode();
+ if (definition.isMultiple()) {
+ jcrProp = new JcrMultiValueProperty(SessionCache.this, jcrNode,
dnaProp.getName());
+ } else {
+ jcrProp = new JcrSingleValueProperty(SessionCache.this, jcrNode,
dnaProp.getName());
+ }
+ }
+ assert jcrProp != null;
+ JcrPropertyPayload propPayload = new
JcrPropertyPayload(definition.getId(), propertyType, jcrProp);
+ node.setProperty(dnaProp, definition.isMultiple(), propPayload);
+ return jcrProp;
+ } catch (ValidationException e) {
+ throw new ConstraintViolationException(e.getMessage(), e.getCause());
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getMessage(), e.getCause());
+ } catch (AccessControlException e) {
+ throw new AccessDeniedException(e.getMessage(), e.getCause());
+ }
}
/**
@@ -1188,16 +950,16 @@
* @param values new property values, all of which must have the same {@link
Value#getType() property type}; may not be
* null but may be empty
* @param valueType
- * @return the identifier for the property; never null
+ * @return the JCR property object for the property; never null
* @throws ConstraintViolationException if the property could not be set because
of a node type constraint or property
* definition constraint
* @throws javax.jcr.ValueFormatException
* @throws AccessDeniedException if the current session does not have the
requisite privileges to perform this task
* @throws RepositoryException if any other error occurs
*/
- public PropertyId setProperty( Name name,
- Value[] values,
- int valueType )
+ public AbstractJcrProperty setProperty( Name name,
+ Value[] values,
+ int valueType )
throws AccessDeniedException, ConstraintViolationException,
RepositoryException, javax.jcr.ValueFormatException {
return setProperty(name, values, valueType, true);
}
@@ -1212,22 +974,21 @@
* @param skipProtected if true, attempts to set protected properties will fail.
If false, attempts to set protected
* properties will be allowed.
* @param valueType
- * @return the identifier for the property; never null
+ * @return the JCR property object for the property; never null
* @throws ConstraintViolationException if the property could not be set because
of a node type constraint or property
* definition constraint
* @throws javax.jcr.ValueFormatException
* @throws AccessDeniedException if the current session does not have the
requisite privileges to perform this task
* @throws RepositoryException if any other error occurs
*/
- public PropertyId setProperty( Name name,
- Value[] values,
- int valueType,
- boolean skipProtected )
+ public AbstractJcrProperty setProperty( Name name,
+ Value[] values,
+ int valueType,
+ boolean skipProtected )
throws AccessDeniedException, ConstraintViolationException,
RepositoryException, javax.jcr.ValueFormatException {
assert name != null;
assert values != null;
- SessionCache.this.checkPermission(node,
JcrSession.JCR_SET_PROPERTY_PERMISSION);
checkCardinalityOfExistingProperty(name, true);
int len = values.length;
@@ -1254,10 +1015,9 @@
sb.append(']');
String propType = PropertyType.nameFromValue(expectedType);
I18n msg = JcrI18n.allPropertyValuesMustHaveSameType;
- NamespaceRegistry namespaces = SessionCache.this.namespaces;
- String path = getPathFor(node.getUuid()).getString(namespaces);
+ String path = readable(node.getPath());
String workspaceName = SessionCache.this.workspaceName();
- throw new javax.jcr.ValueFormatException(msg.text(name, values,
propType, path, workspaceName));
+ throw new javax.jcr.ValueFormatException(msg.text(readable(name),
values, propType, path, workspaceName));
}
if (value.getType() != valueType && valueType !=
PropertyType.UNDEFINED) {
value = ((JcrValue)value).asType(valueType);
@@ -1273,17 +1033,13 @@
int numValues = newValues.length;
JcrPropertyDefinition definition = null;
- PropertyId id = null;
// Look for an existing property ...
- PropertyInfo existing = node.getProperty(name);
+ PropertyInfo<JcrPropertyPayload> existing = node.getProperty(name);
if (existing != null) {
- // Reuse the existing ID ...
- id = existing.getPropertyId();
-
// We're replacing an existing property, but we still need to check
that the property definition
// (still) defines a type. So, find the property definition for the
existing property ...
- definition =
nodeTypes().getPropertyDefinition(existing.getDefinitionId());
+ definition =
nodeTypes().getPropertyDefinition(existing.getPayload().getPropertyDefinitionId());
if (definition != null) {
// The definition's require type must match the value's ...
@@ -1302,14 +1058,12 @@
}
}
}
- } else {
- // This is a new property, so create a new ID ...
- id = new PropertyId(node.getUuid(), name);
}
+ JcrNodePayload payload = node.getPayload();
if (definition == null) {
// Look for a definition ...
- definition =
nodeTypes().findPropertyDefinition(node.getPrimaryTypeName(),
-
node.getMixinTypeNames(),
+ definition =
nodeTypes().findPropertyDefinition(payload.getPrimaryTypeName(),
+
payload.getMixinTypeNames(),
name,
newValues,
skipProtected);
@@ -1338,31 +1092,30 @@
}
Property dnaProp = propertyFactory.create(name, objValues);
- // Create the property info ...
- PropertyInfo newProperty = new PropertyInfo(id, definition.getId(),
propertyType, dnaProp, definition.isMultiple(),
- existing == null, existing !=
null);
-
- // Finally update the cached information and record the change ...
- node.setProperty(newProperty, factories());
- operations.set(dnaProp).on(currentLocation);
-
- // If there is a single value, we need to record that this property is
actually a multi-valued property definition ...
- if (numValues == 1) {
- if (node.setSingleMultiProperty(name)) {
- Set<Name> names = node.getSingleMultiPropertyNames();
- // Added this property name to the set, so record the change ...
- PropertyInfo singleMulti =
createSingleMultiplePropertyInfo(node.getUuid(),
-
node.getPrimaryTypeName(),
-
node.getMixinTypeNames(),
- names);
- node.setProperty(singleMulti, factories());
- operations.set(singleMulti.getProperty()).on(currentLocation);
+ try {
+ // Create (or reuse) the JCR Property object ...
+ AbstractJcrProperty jcrProp = null;
+ if (existing != null) {
+ jcrProp = existing.getPayload().getJcrProperty();
+ } else {
+ AbstractJcrNode jcrNode = payload.getJcrNode();
+ if (definition.isMultiple()) {
+ jcrProp = new JcrMultiValueProperty(SessionCache.this, jcrNode,
dnaProp.getName());
+ } else {
+ jcrProp = new JcrSingleValueProperty(SessionCache.this, jcrNode,
dnaProp.getName());
+ }
}
- } else {
- removeSingleMultiProperty(node, name);
+ assert jcrProp != null;
+ JcrPropertyPayload propPayload = new
JcrPropertyPayload(definition.getId(), propertyType, jcrProp);
+ node.setProperty(dnaProp, definition.isMultiple(), propPayload);
+ return jcrProp;
+ } catch (ValidationException e) {
+ throw new ConstraintViolationException(e.getMessage(), e.getCause());
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getMessage(), e.getCause());
+ } catch (AccessControlException e) {
+ throw new AccessDeniedException(e.getMessage(), e.getCause());
}
-
- return newProperty.getPropertyId();
}
/**
@@ -1374,63 +1127,37 @@
* @throws RepositoryException if any other error occurs
*/
public boolean removeProperty( Name name ) throws AccessDeniedException,
RepositoryException {
- SessionCache.this.checkPermission(node, JcrSession.JCR_REMOVE_PERMISSION);
-
- PropertyInfo info = node.removeProperty(name);
- if (info != null) {
- operations.remove(name).on(currentLocation);
- // Is this named in the single-multi property names? ...
- removeSingleMultiProperty(node, name);
- return true;
+ try {
+ return node.removeProperty(name) != null;
+ } catch (ValidationException e) {
+ throw new ConstraintViolationException(e.getMessage(), e.getCause());
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getMessage(), e.getCause());
+ } catch (AccessControlException e) {
+ throw new AccessDeniedException(e.getMessage(), e.getCause());
}
- return false;
}
- private void removeSingleMultiProperty( ChangedNodeInfo node,
- Name propertyName ) {
- if (node.removeSingleMultiProperty(propertyName)) {
- Set<Name> names = node.getSingleMultiPropertyNames();
- if (names == null || names.isEmpty()) {
- node.removeProperty(DnaIntLexicon.MULTI_VALUED_PROPERTIES);
-
operations.remove(DnaIntLexicon.MULTI_VALUED_PROPERTIES).on(currentLocation);
- } else {
- // Added this property name to the set, so record the change ...
- PropertyInfo singleMulti =
createSingleMultiplePropertyInfo(node.getUuid(),
-
node.getPrimaryTypeName(),
-
node.getMixinTypeNames(),
- names);
- node.setProperty(singleMulti, factories());
- operations.set(singleMulti.getProperty()).on(currentLocation);
- }
- }
- }
-
+ /**
+ * Move the specified child to be located immediately before the other supplied
node.
+ *
+ * @param childToBeMoved the path segment specifying the child that is to be
moved
+ * @param before the path segment of the node before which the {@code
childToBeMoved} should be placed, or null if the
+ * node should be moved to the end
+ * @throws IllegalArgumentException if either segment is null or does not specify
an existing node
+ * @throws AccessDeniedException if the current session does not have the
requisite permissions to remove this property
+ * @throws RepositoryException if any other error occurs
+ */
public void orderChildBefore( Path.Segment childToBeMoved,
- Path.Segment before ) {
- // Clear the path cache ...
- SessionCache.this.pathCache.clear();
-
- PathFactory pathFactory = SessionCache.this.pathFactory;
- Path thisPath = this.currentLocation.getPath();
- UUID fromUuid = this.node.getChildren().getChild(childToBeMoved).getUuid();
- Location fromLocation = Location.create(pathFactory.create(thisPath,
childToBeMoved), fromUuid);
-
- Children children = this.node.getChildren();
- ChildNode nodeToBeMoved = children.getChild(childToBeMoved);
- this.node.removeChild(nodeToBeMoved.getUuid(), pathFactory);
-
- if (before == null) {
- this.node.addChild(nodeToBeMoved.getName(), nodeToBeMoved.getUuid(),
pathFactory);
- // Moving the node into its parent will remove it from its current spot
in the child list and re-add it to the end
- operations.move(fromLocation).into(this.currentLocation);
-
- } else {
- Path beforePath = pathFactory.create(thisPath, before);
- UUID beforeUuid = this.node.getChildren().getChild(before).getUuid();
- Location beforeLocation = Location.create(beforePath, beforeUuid);
-
- this.node.addChild(nodeToBeMoved.getName(), before,
nodeToBeMoved.getUuid(), pathFactory);
- operations.move(fromLocation).before(beforeLocation);
+ Path.Segment before ) throws AccessDeniedException,
RepositoryException {
+ try {
+ node.orderChildBefore(childToBeMoved, before);
+ } catch (ValidationException e) {
+ throw new ConstraintViolationException(e.getMessage(), e.getCause());
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getMessage(), e.getCause());
+ } catch (AccessControlException e) {
+ throw new AccessDeniedException(e.getMessage(), e.getCause());
}
}
@@ -1440,133 +1167,127 @@
*
* @param child the UUID of the existing node; may not be null
* @param newNodeName
- * @return the representation of the newly-added child, which includes the {@link
ChildNode#getSnsIndex()
- * same-name-sibling index}
+ * @return the newly-added child in its location under the new parent; never
null
* @throws ItemNotFoundException if the specified child node could be found in
the session or workspace
* @throws InvalidItemStateException if the specified child has been marked for
deletion within this session
* @throws ConstraintViolationException if moving the node into this node
violates this node's definition
* @throws RepositoryException if any other error occurs while reading
information from the repository
*/
- public ChildNode moveToBeChild( AbstractJcrNode child,
- Name newNodeName )
+ public Node<JcrNodePayload, JcrPropertyPayload> moveToBeChild(
AbstractJcrNode child,
+ Name newNodeName
)
throws ItemNotFoundException, InvalidItemStateException,
ConstraintViolationException, RepositoryException {
- UUID nodeUuid = child.nodeUuid;
- if (nodeUuid.equals(node.getUuid()) || isAncestor(nodeUuid)) {
- Path pathOfNode = getPathFor(nodeUuid);
- Path thisPath = currentLocation.getPath();
- String msg =
JcrI18n.unableToMoveNodeToBeChildOfDecendent.text(pathOfNode, thisPath, workspaceName());
+ // Look up the child and verify that the child can move into this node ...
+ Node<JcrNodePayload, JcrPropertyPayload> existingChild =
findNode(child.nodeId, child.location.getPath());
+ if (existingChild.equals(node) || node.isAtOrBelow(existingChild)) {
+ String pathOfChild = readable(existingChild.getPath());
+ String thisPath = readable(node.getPath());
+ String msg =
JcrI18n.unableToMoveNodeToBeChildOfDecendent.text(pathOfChild, thisPath,
workspaceName());
throw new RepositoryException(msg);
}
- // Is the node already a child?
- boolean nameDoesNotChange = newNodeName == null ||
newNodeName.equals(child.path().getLastSegment());
- ChildNode existingChild = node.getChildren().getChild(nodeUuid);
- if (existingChild != null && nameDoesNotChange) return
existingChild;
+ // Find the best node definition for the child in the new parent, or throw an
exception if there is none ...
+ JcrNodeDefinition defn = findBestNodeDefinition(node, newNodeName,
child.getPrimaryTypeName());
- JcrNodeDefinition definition = findBestNodeDefinition(node.getUuid(),
newNodeName, child.getPrimaryTypeName());
+ try {
+ // Perform the move ...
+ existingChild.moveTo(node, newNodeName);
- // Get an editor for the child (in its current location) and one for its
parent ...
- NodeEditor newChildEditor = getEditorFor(nodeUuid);
+ NodeDefinitionId existingChildDefinitionId =
existingChild.getPayload().getDefinitionId();
+ if (defn.getId().equals(existingChildDefinitionId)) {
+ // The node definition changed, so try to set the property ...
+ NodeEditor newChildEditor = getEditorFor(existingChild);
+ try {
+ JcrValue value = new JcrValue(factories(), SessionCache.this,
PropertyType.STRING, defn.getId()
+
.getString());
+ newChildEditor.setProperty(DnaIntLexicon.NODE_DEFINITON, value);
+ } catch (ConstraintViolationException e) {
+ // We can't set this property on the node (according to the
node definition).
+ // But we still want the node info to have the correct node
definition.
+ // When it is reloaded into a cache (after being persisted), the
correct node definition
+ // will be computed again ...
+
existingChild.setPayload(existingChild.getPayload().with(defn.getId()));
- if (!definition.getId().equals(node.getDefinitionId())) {
- // The node definition changed, so try to set the property ...
- try {
- JcrValue value = new JcrValue(factories(), SessionCache.this,
PropertyType.STRING,
- definition.getId().getString());
- newChildEditor.setProperty(DnaIntLexicon.NODE_DEFINITON, value);
- } catch (ConstraintViolationException e) {
- // We can't set this property on the node (according to the node
definition).
- // But we still want the node info to have the correct node
definition.
- // When it is reloaded into a cache (after being persisted), the
correct node definition
- // will be computed again ...
- node.setDefinitionId(definition.getId());
-
- // And remove the property from the info ...
- newChildEditor.removeProperty(DnaIntLexicon.NODE_DEFINITON);
+ // And remove the property from the info ...
+ newChildEditor.removeProperty(DnaIntLexicon.NODE_DEFINITON);
+ }
}
+ return existingChild;
+ } catch (ValidationException e) {
+ throw new ConstraintViolationException(e.getMessage(), e.getCause());
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getMessage(), e.getCause());
+ } catch (AccessControlException e) {
+ throw new AccessDeniedException(e.getMessage(), e.getCause());
}
-
- // Clear the path cache ...
- SessionCache.this.pathCache.clear();
-
- // Remove the node from the current parent and add it to this ...
- ChangedNodeInfo newChildInfo = newChildEditor.node;
- UUID existingParent = newChildInfo.getParent();
-
- ChangedNodeInfo existingParentInfo = getEditorFor(existingParent).node;
- existingChild = existingParentInfo.removeChild(nodeUuid, pathFactory);
- ChildNode newChild = node.addChild(newNodeName, existingChild.getUuid(),
pathFactory);
-
- // Set the child's changed representation to point to this node as its
parent ...
- newChildInfo.setParent(node.getUuid());
-
- // Set up the peer relationship between the two nodes that must be saved
together
- node.addPeer(existingParent);
- existingParentInfo.addPeer(node.getUuid());
-
- // Set up the peer relationship between the two nodes that must be saved
together
- node.addPeer(existingParent);
- existingParentInfo.addPeer(node.getUuid());
-
- // Now, record the operation to do this ...
- if (nameDoesNotChange) {
- operations.move(newChildEditor.currentLocation).into(currentLocation);
- } else {
-
operations.move(newChildEditor.currentLocation).as(newNodeName).into(currentLocation);
- }
-
- return newChild;
}
public void addMixin( JcrNodeType mixinCandidateType ) throws
javax.jcr.ValueFormatException, RepositoryException {
- PropertyInfo existingMixinProperty =
node.getProperty(JcrLexicon.MIXIN_TYPES);
+ try {
+ PropertyInfo<JcrPropertyPayload> existingMixinProperty =
node.getProperty(JcrLexicon.MIXIN_TYPES);
- // getProperty(JcrLexicon.MIXIN_TYPES);
- Value[] existingMixinValues;
- if (existingMixinProperty != null) {
- existingMixinValues =
findJcrProperty(existingMixinProperty.getPropertyId()).getValues();
- } else {
- existingMixinValues = new Value[0];
- }
+ // getProperty(JcrLexicon.MIXIN_TYPES);
+ Value[] existingMixinValues;
+ if (existingMixinProperty != null) {
+ existingMixinValues =
existingMixinProperty.getPayload().getJcrProperty().getValues();
+ } else {
+ existingMixinValues = new Value[0];
+ }
- Value[] newMixinValues = new Value[existingMixinValues.length + 1];
- System.arraycopy(existingMixinValues, 0, newMixinValues, 0,
existingMixinValues.length);
- newMixinValues[newMixinValues.length - 1] = new JcrValue(factories(),
SessionCache.this, PropertyType.NAME,
-
mixinCandidateType.getInternalName());
+ Value[] newMixinValues = new Value[existingMixinValues.length + 1];
+ System.arraycopy(existingMixinValues, 0, newMixinValues, 0,
existingMixinValues.length);
+ newMixinValues[newMixinValues.length - 1] = new JcrValue(factories(),
SessionCache.this, PropertyType.NAME,
+
mixinCandidateType.getInternalName());
- findJcrProperty(setProperty(JcrLexicon.MIXIN_TYPES, newMixinValues,
PropertyType.NAME, false));
+ setProperty(JcrLexicon.MIXIN_TYPES, newMixinValues, PropertyType.NAME,
false);
- //
------------------------------------------------------------------------------
- // Create any auto-created properties/nodes from new type
- //
------------------------------------------------------------------------------
+ //
------------------------------------------------------------------------------
+ // Create any auto-created properties/nodes from new type
+ //
------------------------------------------------------------------------------
- for (JcrPropertyDefinition propertyDefinition :
mixinCandidateType.propertyDefinitions()) {
- if (propertyDefinition.isAutoCreated() &&
!propertyDefinition.isProtected()) {
- if (null == findJcrProperty(new PropertyId(node.getUuid(),
propertyDefinition.getInternalName()))) {
- assert propertyDefinition.getDefaultValues() != null;
- if (propertyDefinition.isMultiple()) {
- setProperty(propertyDefinition.getInternalName(),
- propertyDefinition.getDefaultValues(),
- propertyDefinition.getRequiredType());
- } else {
- assert propertyDefinition.getDefaultValues().length == 1;
- setProperty(propertyDefinition.getInternalName(),
(JcrValue)propertyDefinition.getDefaultValues()[0]);
+ for (JcrPropertyDefinition propertyDefinition :
mixinCandidateType.propertyDefinitions()) {
+ if (propertyDefinition.isAutoCreated() &&
!propertyDefinition.isProtected()) {
+ PropertyInfo<JcrPropertyPayload> autoCreatedProp =
node.getProperty(propertyDefinition.getInternalName());
+ if (autoCreatedProp == null) {
+ // We have to 'auto-create' the property ...
+ assert propertyDefinition.getDefaultValues() != null;
+ if (propertyDefinition.isMultiple()) {
+ setProperty(propertyDefinition.getInternalName(),
+ propertyDefinition.getDefaultValues(),
+ propertyDefinition.getRequiredType());
+ } else {
+ assert propertyDefinition.getDefaultValues().length ==
1;
+ setProperty(propertyDefinition.getInternalName(),
+
(JcrValue)propertyDefinition.getDefaultValues()[0]);
+ }
}
}
}
- }
- for (JcrNodeDefinition nodeDefinition :
mixinCandidateType.childNodeDefinitions()) {
- if (nodeDefinition.isAutoCreated() &&
!nodeDefinition.isProtected()) {
- Name nodeName = nodeDefinition.getInternalName();
- if (!node.getChildren().getChildren(nodeName).hasNext()) {
- assert nodeDefinition.getDefaultPrimaryType() != null;
- createChild(nodeName, (UUID)null,
((JcrNodeType)nodeDefinition.getDefaultPrimaryType()).getInternalName());
+ for (JcrNodeDefinition nodeDefinition :
mixinCandidateType.childNodeDefinitions()) {
+ if (nodeDefinition.isAutoCreated() &&
!nodeDefinition.isProtected()) {
+ Name nodeName = nodeDefinition.getInternalName();
+ if (node.getChildrenCount(nodeName) == 0) {
+ assert nodeDefinition.getDefaultPrimaryType() != null;
+ createChild(nodeName,
+ (UUID)null,
+
((JcrNodeType)nodeDefinition.getDefaultPrimaryType()).getInternalName());
+ }
}
}
- }
+ if
(JcrMixLexicon.REFERENCEABLE.equals(mixinCandidateType.getInternalName())) {
+ // This node is now referenceable, so make sure there is a UUID
property ...
+ UUID uuid = node.getLocation().getUuid();
+ if (uuid == null) uuid = UUID.randomUUID();
+ JcrValue value = new JcrValue(factories(), SessionCache.this,
PropertyType.STRING, uuid);
+ setProperty(JcrLexicon.UUID, value, false);
+ }
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getMessage(), e.getCause());
+ } catch (AccessControlException e) {
+ throw new AccessDeniedException(e.getMessage(), e.getCause());
+ }
}
/**
@@ -1575,190 +1296,133 @@
* @param name the name for the new child; may not be null
* @param desiredUuid the desired UUID, or null if the UUID for the child should
be generated automatically
* @param primaryTypeName the name of the primary type for the new node
- * @return the representation of the newly-created child, which includes the
{@link ChildNode#getSnsIndex()
- * same-name-sibling index}
+ * @return the representation of the newly-created child
* @throws InvalidItemStateException if the specified child has been marked for
deletion within this session
* @throws ConstraintViolationException if moving the node into this node
violates this node's definition
* @throws NoSuchNodeTypeException if the node type for the primary type could
not be found
* @throws AccessDeniedException if the current session does not have the
requisite privileges to perform this task
* @throws RepositoryException if any other error occurs while reading
information from the repository
*/
- public ChildNode createChild( Name name,
- UUID desiredUuid,
- Name primaryTypeName )
+ public JcrNode createChild( Name name,
+ UUID desiredUuid,
+ Name primaryTypeName )
throws InvalidItemStateException, ConstraintViolationException,
AccessDeniedException, RepositoryException {
- SessionCache.this.checkPermission(node, JcrSession.JCR_ADD_NODE_PERMISSION);
-
if (desiredUuid == null) desiredUuid = UUID.randomUUID();
+ try {
- // Verify that this node accepts a child of the supplied name (given any
existing SNS nodes) ...
- int numSns = node.getChildren().getCountOfSameNameSiblingsWithName(name) +
1;
- JcrNodeDefinition definition =
nodeTypes().findChildNodeDefinition(node.getPrimaryTypeName(),
-
node.getMixinTypeNames(),
- name,
-
primaryTypeName,
- numSns,
- true);
- // Make sure there was a valid child node definition ...
- if (definition == null) {
+ // Verify that this node accepts a child of the supplied name (given any
existing SNS nodes) ...
+ int numSns = node.getChildrenCount(name) + 1;
+ JcrNodePayload payload = node.getPayload();
+ JcrNodeDefinition definition =
nodeTypes().findChildNodeDefinition(payload.getPrimaryTypeName(),
+
payload.getMixinTypeNames(),
+ name,
+
primaryTypeName,
+
numSns,
+
true);
+ // Make sure there was a valid child node definition ...
+ if (definition == null) {
- // Check if the definition would have worked with less SNS
- definition =
nodeTypes().findChildNodeDefinition(node.getPrimaryTypeName(),
-
node.getMixinTypeNames(),
- name,
- primaryTypeName,
- numSns - 1,
- true);
- if (definition != null) {
- // Only failed because there was no SNS definition - throw
ItemExistsException per 7.1.4 of 1.0.1 spec
- Path pathForChild = pathFactory.create(getPathFor(node), name, numSns
+ 1);
- String msg = JcrI18n.noSnsDefinitionForNode.text(pathForChild,
workspaceName());
- throw new ItemExistsException(msg);
+ // Check if the definition would have worked with less SNS
+ definition =
nodeTypes().findChildNodeDefinition(payload.getPrimaryTypeName(),
+
payload.getMixinTypeNames(),
+ name,
+ primaryTypeName,
+ numSns - 1,
+ true);
+ if (definition != null) {
+ // Only failed because there was no SNS definition - throw
ItemExistsException per 7.1.4 of 1.0.1 spec
+ Path pathForChild = pathFactory.create(node.getPath(), name,
numSns + 1);
+ String msg = JcrI18n.noSnsDefinitionForNode.text(pathForChild,
workspaceName());
+ throw new ItemExistsException(msg);
+ }
+ // Didn't work for other reasons - throw
ConstraintViolationException
+ Path pathForChild = pathFactory.create(node.getPath(), name, numSns +
1);
+ String msg =
JcrI18n.nodeDefinitionCouldNotBeDeterminedForNode.text(pathForChild,
+
workspaceName(),
+
sourceName());
+ throw new ConstraintViolationException(msg);
}
- // Didn't work for other reasons - throw
ConstraintViolationException
- Path pathForChild = pathFactory.create(getPathFor(node), name, numSns +
1);
- String msg =
JcrI18n.nodeDefinitionCouldNotBeDeterminedForNode.text(pathForChild, workspaceName());
- throw new ConstraintViolationException(msg);
- }
- // Find the primary type ...
- JcrNodeType primaryType = null;
- if (primaryTypeName != null) {
- primaryType = nodeTypes().getNodeType(primaryTypeName);
- if (primaryType == null) {
- Path pathForChild = pathFactory.create(getPathFor(node), name, numSns
+ 1);
- I18n msg =
JcrI18n.unableToCreateNodeWithPrimaryTypeThatDoesNotExist;
- throw new NoSuchNodeTypeException(msg.text(primaryTypeName,
pathForChild, workspaceName()));
+ // Find the primary type ...
+ JcrNodeType primaryType = null;
+ if (primaryTypeName != null) {
+ primaryType = nodeTypes().getNodeType(primaryTypeName);
+ if (primaryType == null) {
+ Path pathForChild = pathFactory.create(node.getPath(), name,
numSns + 1);
+ I18n msg =
JcrI18n.unableToCreateNodeWithPrimaryTypeThatDoesNotExist;
+ throw new NoSuchNodeTypeException(msg.text(primaryTypeName,
pathForChild, workspaceName()));
+ }
+ } else {
+ primaryType = (JcrNodeType)definition.getDefaultPrimaryType();
+ if (primaryType == null) {
+ // There is no default primary type ...
+ Path pathForChild = pathFactory.create(node.getPath(), name,
numSns + 1);
+ I18n msg =
JcrI18n.unableToCreateNodeWithNoDefaultPrimaryTypeOnChildNodeDefinition;
+ String nodeTypeName =
definition.getDeclaringNodeType().getName();
+ throw new NoSuchNodeTypeException(msg.text(definition.getName(),
+ nodeTypeName,
+ pathForChild,
+ workspaceName()));
+ }
}
- } else {
- primaryType = (JcrNodeType)definition.getDefaultPrimaryType();
- if (primaryType == null) {
- // There is no default primary type ...
- Path pathForChild = pathFactory.create(getPathFor(node), name, numSns
+ 1);
- I18n msg =
JcrI18n.unableToCreateNodeWithNoDefaultPrimaryTypeOnChildNodeDefinition;
- String nodeTypeName = definition.getDeclaringNodeType().getName();
- throw new NoSuchNodeTypeException(msg.text(definition.getName(),
nodeTypeName, pathForChild, workspaceName()));
- }
- }
- primaryTypeName = primaryType.getInternalName();
+ primaryTypeName = primaryType.getInternalName();
- ChildNode result = node.addChild(name, desiredUuid, pathFactory);
+ // ---------------------------------------------------------
+ // Now create the child node representation in the cache ...
+ // ---------------------------------------------------------
- // ---------------------------------------------------------
- // Now create the child node representation in the cache ...
- // ---------------------------------------------------------
- Path newPath = pathFactory.create(currentLocation.getPath(),
result.getSegment());
- Location location = Location.create(newPath, desiredUuid);
+ // Create the initial properties ...
+ Property primaryTypeProp =
propertyFactory.create(JcrLexicon.PRIMARY_TYPE, primaryTypeName);
+ Property nodeDefinitionProp =
propertyFactory.create(DnaIntLexicon.NODE_DEFINITON, definition.getId().getString());
+ List<Name> mixinTypeNames = null;
- // Create the properties ...
- Map<Name, PropertyInfo> properties = new HashMap<Name,
PropertyInfo>();
- Property primaryTypeProp = propertyFactory.create(JcrLexicon.PRIMARY_TYPE,
primaryTypeName);
- Property nodeDefinitionProp =
propertyFactory.create(DnaIntLexicon.NODE_DEFINITON, definition.getId().getString());
-
- // Now add the "jcr:uuid" property if and only if referenceable
...
- if (primaryType.isNodeType(JcrMixLexicon.REFERENCEABLE)) {
- if (desiredUuid == null) {
- desiredUuid = UUID.randomUUID();
+ // Now add the "jcr:uuid" property if and only if referenceable
...
+ Node<JcrNodePayload, JcrPropertyPayload> result = null;
+ if (primaryType.isNodeType(JcrMixLexicon.REFERENCEABLE)) {
+ if (desiredUuid == null) {
+ desiredUuid = UUID.randomUUID();
+ }
+ Property uuidProperty = propertyFactory.create(JcrLexicon.UUID,
desiredUuid);
+ result = node.createChild(name, uuidProperty, primaryTypeProp,
nodeDefinitionProp);
+ } else {
+ result = node.createChild(name, primaryTypeProp,
nodeDefinitionProp);
}
-
- // We know that this property is single-valued
- JcrValue value = new JcrValue(factories(), SessionCache.this,
PropertyType.STRING, desiredUuid.toString());
- PropertyDefinition propertyDefinition =
nodeTypes().findPropertyDefinition(primaryTypeName,
-
Collections.<Name>emptyList(),
-
JcrLexicon.UUID,
-
value,
-
false,
-
false);
- PropertyId propId = new PropertyId(desiredUuid, JcrLexicon.UUID);
- JcrPropertyDefinition defn = (JcrPropertyDefinition)propertyDefinition;
- org.jboss.dna.graph.property.Property uuidProperty =
propertyFactory.create(JcrLexicon.UUID, desiredUuid);
- PropertyInfo propInfo = new PropertyInfo(propId, defn.getId(),
PropertyType.STRING, uuidProperty,
- defn.isMultiple(), true,
false);
- properties.put(JcrLexicon.UUID, propInfo);
+ // Now create the payload ...
+ JcrNodePayload newPayload = new JcrNodePayload(SessionCache.this, result,
primaryTypeName, mixinTypeNames,
+ definition.getId());
+ result.setPayload(newPayload);
+ // Finally, return the jcr node ...
+ assert result.getPayload() == newPayload;
+ return (JcrNode)newPayload.getJcrNode();
+ } catch (ValidationException e) {
+ throw new ConstraintViolationException(e.getMessage(), e.getCause());
+ } catch (RepositorySourceException e) {
+ throw new RepositoryException(e.getMessage(), e.getCause());
+ } catch (AccessControlException e) {
+ throw new AccessDeniedException(e.getMessage(), e.getCause());
}
-
- // Create the property info for the "jcr:primaryType" child
property ...
- JcrPropertyDefinition primaryTypeDefn =
findBestPropertyDefintion(node.getPrimaryTypeName(),
-
node.getMixinTypeNames(),
-
primaryTypeProp,
-
PropertyType.NAME,
- true,
- false);
- PropertyDefinitionId primaryTypeDefinitionId = primaryTypeDefn.getId();
- PropertyInfo primaryTypeInfo = new PropertyInfo(new PropertyId(desiredUuid,
primaryTypeProp.getName()),
- primaryTypeDefinitionId,
PropertyType.NAME, primaryTypeProp, false,
- true, false);
- properties.put(primaryTypeProp.getName(), primaryTypeInfo);
-
- // Create the property info for the "dna:nodeDefinition" child
property ...
- JcrPropertyDefinition nodeDefnDefn =
findBestPropertyDefintion(node.getPrimaryTypeName(),
-
node.getMixinTypeNames(),
-
nodeDefinitionProp,
-
PropertyType.STRING,
- true,
- false);
-
- if (nodeDefnDefn != null) {
- PropertyDefinitionId nodeDefnDefinitionId = nodeDefnDefn.getId();
- PropertyInfo nodeDefinitionInfo = new PropertyInfo(new
PropertyId(desiredUuid, nodeDefinitionProp.getName()),
- nodeDefnDefinitionId,
PropertyType.STRING, nodeDefinitionProp,
- false, true, false);
- properties.put(nodeDefinitionProp.getName(), nodeDefinitionInfo);
- }
- assert nodeDefnDefn != null &&
nodeDefnDefn.getInternalName().equals(DnaIntLexicon.NODE_DEFINITON);
-
- // Now create the child node info, putting it in the changed map (and not the
cache map!) ...
- NewNodeInfo newInfo = new NewNodeInfo(location, primaryTypeName,
definition.getId(), node.getUuid(), properties);
- changedNodes.put(desiredUuid, newInfo);
-
- // ---------------------------------------
- // Now record the changes to the store ...
- // ---------------------------------------
- Graph.Create<Graph.Batch> create =
operations.createUnder(currentLocation).nodeNamed(name).with(desiredUuid).with(primaryTypeProp);
- // if (nodeDefnDefn != null) {
- create = create.with(nodeDefinitionProp);
- // }
- create.and();
- return result;
}
/**
* Destroy the child node with the supplied UUID and all nodes that exist below
it, including any nodes that were created
* and haven't been persisted.
*
- * @param nodeUuid the UUID of the child node; may not be null
+ * @param child the child node; may not be null
* @throws AccessDeniedException if the current session does not have the
requisite privileges to perform this task
* @throws RepositoryException if any other error occurs
* @return true if the child was successfully removed, or false if the node did
not exist as a child
*/
- public boolean destroyChild( UUID nodeUuid ) throws AccessDeniedException,
RepositoryException {
- SessionCache.this.checkPermission(node, JcrSession.JCR_REMOVE_PERMISSION);
-
- ChildNode deleted = node.removeChild(nodeUuid, pathFactory);
-
- if (deleted != null) {
- // Recursively mark the cached/changed information as deleted ...
- deleteNodeInfos(nodeUuid);
-
- // Now make the request to the source ...
- Path childPath = pathFactory.create(currentLocation.getPath(),
deleted.getSegment());
- Location locationOfChild = Location.create(childPath, nodeUuid);
- operations.delete(locationOfChild);
- return true;
+ public boolean destroyChild( Node<JcrNodePayload, JcrPropertyPayload> child
)
+ throws AccessDeniedException, RepositoryException {
+ if (!child.getParent().equals(node)) return false;
+ try {
+ child.destroy();
+ } catch (AccessControlException e) {
+ throw new AccessDeniedException(e.getMessage(), e.getCause());
}
- return false;
+ return true;
}
-
- protected boolean isAncestor( UUID uuid ) throws ItemNotFoundException,
InvalidItemStateException, RepositoryException {
- UUID ancestor = node.getParent();
- while (ancestor != null) {
- if (ancestor.equals(uuid)) return true;
- NodeInfo info = findNodeInfo(ancestor);
- ancestor = info.getParent();
- }
- return false;
- }
}
/**
@@ -1817,806 +1481,1130 @@
return null;
}
- /**
- * Utility method that creates and caches the appropriate kind of AbstractJcrNode
implementation for node given by the
- * supplied information.
- *
- * @param info the information for the node; may not be null
- * @return the <i>new</i> instance of the {@link Node}; never null
- */
- private AbstractJcrNode createAndCacheJcrNodeFor( NodeInfo info ) {
- UUID uuid = info.getUuid();
- Location location = info.getOriginalLocation();
- NodeDefinitionId nodeDefinitionId = info.getDefinitionId();
- JcrNodeDefinition definition = nodeTypes().getNodeDefinition(nodeDefinitionId);
- assert definition != null;
+ // Path getPathFor( String workspaceName,
+ // UUID uuid,
+ // Path relativePath ) throws NoSuchWorkspaceException, ItemNotFoundException,
RepositoryException {
+ // assert workspaceName != null;
+ // assert uuid != null || relativePath != null;
+ //
+ // Graph graph = operations.getGraph();
+ // try {
+ // graph.useWorkspace(workspaceName);
+ // } catch (InvalidWorkspaceException iwe) {
+ // throw new
NoSuchWorkspaceException(JcrI18n.workspaceNameIsInvalid.text(graph.getSourceName(),
workspaceName));
+ // }
+ //
+ // try {
+ // org.jboss.dna.graph.Node node;
+ // if (uuid != null) {
+ // node = graph.getNodeAt(uuid);
+ //
+ // if (relativePath != null) {
+ // Path nodePath = node.getLocation().getPath();
+ // Path absolutePath = relativePath.resolveAgainst(nodePath);
+ // node = graph.getNodeAt(absolutePath);
+ // }
+ //
+ // } else {
+ // Path absolutePath =
pathFactory.createAbsolutePath(relativePath.getSegmentsList());
+ // node = graph.getNodeAt(absolutePath);
+ // }
+ // assert node != null;
+ //
+ // return node.getLocation().getPath();
+ // } catch (org.jboss.dna.graph.property.PathNotFoundException pnfe) {
+ // throw new ItemNotFoundException(pnfe);
+ // } finally {
+ // graph.useWorkspace(this.workspaceName);
+ // }
+ //
+ // }
+ //
+ // Path getPathFor( UUID uuid ) throws ItemNotFoundException,
InvalidItemStateException, RepositoryException {
+ // if (uuid.equals(root)) return rootPath;
+ // return getPathFor(findNodeInfo(uuid));
+ // }
+ //
+ // Path getPathFor( NodeInfo info ) throws ItemNotFoundException,
InvalidItemStateException, RepositoryException {
+ // if (info == null) {
+ // return pathFactory.createRootPath();
+ // }
+ // UUID uuid = info.getUuid();
+ // if (uuid.equals(root)) return rootPath;
+ //
+ // // This isn't the root node ...
+ // Path result = pathCache.get(uuid);
+ // if (result == null) {
+ // // We need to build a path using the parent path ...
+ // UUID parent = info.getParent();
+ // if (parent == null) {
+ // // Then this node is the root ...
+ // root = info.getUuid();
+ // result = rootPath;
+ // } else {
+ // NodeInfo parentInfo = findNodeInfo(parent);
+ // Path parentPath = getPathFor(parentInfo);
+ // ChildNode child = parentInfo.getChildren().getChild(info.getUuid());
+ // result = pathFactory.create(parentPath, child.getSegment());
+ // }
+ // pathCache.put(uuid, result);
+ // }
+ // assert result != null;
+ // return result;
+ // }
+ //
+ // Path getPathFor( PropertyInfo propertyInfo ) throws ItemNotFoundException,
RepositoryException {
+ // Path nodePath = getPathFor(propertyInfo.getNodeUuid());
+ // return pathFactory.create(nodePath, propertyInfo.getPropertyName());
+ // }
+ //
+ // Path getPathFor( PropertyId propertyId ) throws ItemNotFoundException,
RepositoryException {
+ // return getPathFor(findPropertyInfo(propertyId));
+ // }
+ //
+ // protected Name getNameOf( UUID nodeUuid ) throws ItemNotFoundException,
InvalidItemStateException, RepositoryException {
+ // findNodeInfoForRoot();
+ // if (nodeUuid == root) return nameFactory.create("");
+ // // Get the parent ...
+ // NodeInfo info = findNodeInfo(nodeUuid);
+ // NodeInfo parent = findNodeInfo(info.getParent());
+ // ChildNode child = parent.getChildren().getChild(info.getUuid());
+ // return child.getName();
+ // }
+ //
+ // protected int getSnsIndexOf( UUID nodeUuid ) throws ItemNotFoundException,
InvalidItemStateException, RepositoryException {
+ // findNodeInfoForRoot();
+ // if (nodeUuid == root) return 1;
+ // // Get the parent ...
+ // NodeInfo info = findNodeInfo(nodeUuid);
+ // NodeInfo parent = findNodeInfo(info.getParent());
+ // ChildNode child = parent.getChildren().getChild(info.getUuid());
+ // return child.getSnsIndex();
+ // }
+ //
+ // /**
+ // * Load from the underlying repository graph the information for the node with the
supplied UUID. This method returns the
+ // * information for the requested node (after placing it in the cache), but this
method may (at its discretion) also load and
+ // * cache information for other nodes.
+ // * <p>
+ // * Note that this method does not check the cache before loading from the
repository graph.
+ // * </p>
+ // *
+ // * @param path the path of the node, if known; may be null only if the UUID is
supplied
+ // * @param uuid the UUID of the node, if known; may be null only if the path is
supplied
+ // * @return the information for the node
+ // * @throws ItemNotFoundException if the node does not exist in the repository
+ // * @throws RepositoryException if there was an error obtaining this information
from the repository
+ // */
+ // protected ImmutableNodeInfo loadFromGraph( Path path,
+ // UUID uuid ) throws ItemNotFoundException, RepositoryException {
+ // // Load the node information from the store ...
+ // try {
+ // // See if there is a path for this uuid ...
+ // Location location = Location.create(path, uuid);
+ // org.jboss.dna.graph.Node node = store.getNodeAt(location);
+ // ImmutableNodeInfo info = createNodeInfoFrom(node, null);
+ // this.cachedNodes.put(info.getUuid(), info);
+ // return info;
+ // } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
+ // throw new ItemNotFoundException(JcrI18n.itemNotFoundWithUuid.text(uuid,
workspaceName, e.getLocalizedMessage()));
+ // } catch (RepositorySourceException e) {
+ // throw new RepositoryException(
+ // JcrI18n.errorWhileFindingNodeWithUuid.text(uuid, workspaceName,
e.getLocalizedMessage()),
+ // e);
+ // }
+ // }
+ //
+ // /**
+ // * Load from the underlying repository graph the information for the node with the
supplied UUID. This method returns the
+ // * information for the requested node (after placing it in the cache), but this
method may (at its discretion) also load and
+ // * cache information for other nodes.
+ // * <p>
+ // * Note that this method does not check the cache before loading from the
repository graph.
+ // * </p>
+ // *
+ // * @param path the path to the node; may not be null
+ // * @param parentInfo the parent information; may be null if not known
+ // * @return the information for the node
+ // * @throws PathNotFoundException if the node does not exist in the repository
+ // * @throws RepositoryException if there was an error obtaining this information
from the repository
+ // */
+ // protected ImmutableNodeInfo loadFromGraph( Path path,
+ // NodeInfo parentInfo ) throws PathNotFoundException, RepositoryException {
+ // // Load the node information from the store ...
+ // try {
+ // org.jboss.dna.graph.Node node = store.getNodeAt(path);
+ // ImmutableNodeInfo info = createNodeInfoFrom(node, parentInfo);
+ // this.cachedNodes.put(info.getUuid(), info);
+ // return info;
+ // } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
+ // throw new PathNotFoundException(JcrI18n.pathNotFound.text(path, workspaceName));
+ // } catch (RepositorySourceException e) {
+ // throw new RepositoryException(JcrI18n.errorWhileFindingNodeWithPath.text(path,
workspaceName));
+ // }
+ // }
- // Need to determine if this is the root node ...
- if (location.getPath().isRoot()) {
- // It is a root node ...
- JcrRootNode node = new JcrRootNode(this, uuid);
- jcrNodes.put(uuid, node);
- root = uuid;
- return node;
+ // /**
+ // * Create the {@link NodeInfo} object given the DNA graph node and the parent node
information (if it is available).
+ // *
+ // * @param graphNode the DNA graph node; may not be null
+ // * @param parentInfo the information for the parent node, or null if the supplied
graph node represents the root node, or if
+ // * the parent information is not known
+ // * @return the node information; never null
+ // * @throws RepositoryException if there is an error determining the child {@link
NodeDefinition} for the supplied node,
+ // * preventing the node information from being constructed
+ // */
+ // private ImmutableNodeInfo createNodeInfoFrom( org.jboss.dna.graph.Node graphNode,
+ // NodeInfo parentInfo ) throws RepositoryException {
+ // // Now get the DNA node's UUID and find the DNA property containing the UUID
...
+ // Location location = graphNode.getLocation();
+ // UUID uuid = location.getUuid();
+ // org.jboss.dna.graph.property.Property uuidProperty = null;
+ // if (uuid != null) {
+ // // Check for an identification property ...
+ // uuidProperty = location.getIdProperty(JcrLexicon.UUID);
+ // if (uuidProperty == null) {
+ // uuidProperty = propertyFactory.create(JcrLexicon.UUID, uuid);
+ // }
+ // }
+ // if (uuidProperty == null) {
+ // uuidProperty = graphNode.getProperty(JcrLexicon.UUID);
+ // if (uuidProperty != null) {
+ // // Grab the first 'good' UUID value ...
+ // for (Object uuidValue : uuidProperty) {
+ // try {
+ // uuid = factories.getUuidFactory().create(uuidValue);
+ // break;
+ // } catch (ValueFormatException e) {
+ // // Ignore; just continue with the next property value
+ // }
+ // }
+ // }
+ // if (uuid == null) {
+ // // Look for the DNA UUID property ...
+ // org.jboss.dna.graph.property.Property dnaUuidProperty =
graphNode.getProperty(DnaLexicon.UUID);
+ // if (dnaUuidProperty != null) {
+ // // Grab the first 'good' UUID value ...
+ // for (Object uuidValue : dnaUuidProperty) {
+ // try {
+ // uuid = factories.getUuidFactory().create(uuidValue);
+ // break;
+ // } catch (ValueFormatException e) {
+ // // Ignore; just continue with the next property value
+ // }
+ // }
+ // }
+ // }
+ // }
+ // if (uuid == null) uuid = UUID.randomUUID();
+ // if (uuidProperty == null) uuidProperty = propertyFactory.create(JcrLexicon.UUID,
uuid);
+ //
+ // // Either the UUID is not known, or there was no node. Either way, we have to
create the node ...
+ // if (uuid == null) uuid = UUID.randomUUID();
+ //
+ // // Look for the primary type of the node ...
+ // Map<Name, Property> graphProperties = graphNode.getPropertiesByName();
+ // final boolean isRoot = location.getPath().isRoot();
+ // Name primaryTypeName = null;
+ // org.jboss.dna.graph.property.Property primaryTypeProperty =
graphNode.getProperty(JcrLexicon.PRIMARY_TYPE);
+ // if (primaryTypeProperty != null && !primaryTypeProperty.isEmpty()) {
+ // try {
+ // primaryTypeName =
factories.getNameFactory().create(primaryTypeProperty.getFirstValue());
+ // } catch (ValueFormatException e) {
+ // // use the default ...
+ // }
+ // }
+ // if (primaryTypeName == null) {
+ // // We have to have a primary type, so use the default ...
+ // if (isRoot) {
+ // primaryTypeName = DnaLexicon.ROOT;
+ // primaryTypeProperty = propertyFactory.create(JcrLexicon.PRIMARY_TYPE,
primaryTypeName);
+ // } else {
+ // primaryTypeName = defaultPrimaryTypeName;
+ // primaryTypeProperty = defaultPrimaryTypeProperty;
+ // }
+ // // We have to add this property to the graph node...
+ // graphProperties = new HashMap<Name, Property>(graphProperties);
+ // graphProperties.put(primaryTypeProperty.getName(), primaryTypeProperty);
+ // }
+ // assert primaryTypeProperty != null;
+ // assert primaryTypeProperty.isEmpty() == false;
+ //
+ // // Look for a node definition stored on the node ...
+ // JcrNodeDefinition definition = null;
+ // org.jboss.dna.graph.property.Property nodeDefnProperty =
graphProperties.get(DnaIntLexicon.NODE_DEFINITON);
+ // if (nodeDefnProperty != null && !nodeDefnProperty.isEmpty()) {
+ // String nodeDefinitionString =
stringFactory.create(nodeDefnProperty.getFirstValue());
+ // NodeDefinitionId id = NodeDefinitionId.fromString(nodeDefinitionString,
nameFactory);
+ // definition = nodeTypes().getNodeDefinition(id);
+ // }
+ // // Figure out the node definition for this node ...
+ // if (isRoot) {
+ // if (definition == null) definition = nodeTypes().getRootNodeDefinition();
+ // } else {
+ // // We need the parent ...
+ // Path path = location.getPath();
+ // if (parentInfo == null) {
+ // Path parentPath = path.getParent();
+ // parentInfo = findNodeInfo(null, parentPath.getNormalizedPath());
+ // }
+ // if (definition == null) {
+ // Name childName = path.getLastSegment().getName();
+ // int numExistingChildrenWithSameName =
parentInfo.getChildren().getCountOfSameNameSiblingsWithName(childName);
+ // definition = nodeTypes().findChildNodeDefinition(parentInfo.getPrimaryTypeName(),
+ // parentInfo.getMixinTypeNames(),
+ // childName,
+ // primaryTypeName,
+ // numExistingChildrenWithSameName,
+ // false);
+ // }
+ // if (definition == null) {
+ // String msg = JcrI18n.nodeDefinitionCouldNotBeDeterminedForNode.text(path,
workspaceName);
+ // throw new RepositorySourceException(sourceName(), msg);
+ // }
+ // }
+ //
+ // // ------------------------------------------------------
+ // // Set the node's properties ...
+ // // ------------------------------------------------------
+ // boolean referenceable = false;
+ //
+ // // Start with the primary type ...
+ // JcrNodeType primaryType = nodeTypes().getNodeType(primaryTypeName);
+ // if (primaryType == null) {
+ // Path path = location.getPath();
+ // String msg =
JcrI18n.missingNodeTypeForExistingNode.text(primaryTypeName.getString(namespaces), path,
workspaceName);
+ // throw new RepositorySourceException(sourceName(), msg);
+ // }
+ // if (primaryType.isNodeType(JcrMixLexicon.REFERENCEABLE)) referenceable = true;
+ //
+ // // The process the mixin types ...
+ // Property mixinTypesProperty = graphProperties.get(JcrLexicon.MIXIN_TYPES);
+ // List<Name> mixinTypeNames = null;
+ // if (mixinTypesProperty != null && !mixinTypesProperty.isEmpty()) {
+ // for (Object mixinTypeValue : mixinTypesProperty) {
+ // Name mixinTypeName = nameFactory.create(mixinTypeValue);
+ // if (mixinTypeNames == null) mixinTypeNames = new LinkedList<Name>();
+ // mixinTypeNames.add(mixinTypeName);
+ // JcrNodeType mixinType = nodeTypes().getNodeType(mixinTypeName);
+ // if (mixinType == null) continue;
+ // if (!referenceable && mixinType.isNodeType(JcrMixLexicon.REFERENCEABLE))
referenceable = true;
+ // }
+ // }
+ //
+ // // Create the set of multi-valued property names ...
+ // Set<Name> multiValuedPropertyNames = EMPTY_NAMES;
+ // Set<Name> newSingleMultiPropertyNames = null;
+ // Property multiValuedPropNamesProp =
graphProperties.get(DnaIntLexicon.MULTI_VALUED_PROPERTIES);
+ // if (multiValuedPropNamesProp != null &&
!multiValuedPropNamesProp.isEmpty()) {
+ // multiValuedPropertyNames = getSingleMultiPropertyNames(multiValuedPropNamesProp,
location.getPath(), uuid);
+ // }
+ //
+ // // Now create the JCR property object wrappers around the other properties ...
+ // Map<Name, PropertyInfo> props = new HashMap<Name, PropertyInfo>();
+ // for (Property dnaProp : graphProperties.values()) {
+ // Name name = dnaProp.getName();
+ //
+ // // Is this is single-valued property?
+ // boolean isSingle = dnaProp.isSingle();
+ // // Make sure that this isn't a multi-valued property with one value ...
+ // if (isSingle && multiValuedPropertyNames.contains(name)) isSingle =
false;
+ //
+ // // Figure out the JCR property type for this property ...
+ // int propertyType = PropertyTypeUtil.jcrPropertyTypeFor(dnaProp);
+ // PropertyDefinition propertyDefinition =
findBestPropertyDefintion(primaryTypeName,
+ // mixinTypeNames,
+ // dnaProp,
+ // propertyType,
+ // isSingle,
+ // false);
+ //
+ // // If there still is no property type defined ...
+ // if (propertyDefinition == null &&
INCLUDE_PROPERTIES_NOT_ALLOWED_BY_NODE_TYPE_OR_MIXINS) {
+ // // We can use the "nt:unstructured" property definitions for any
property ...
+ // NodeType unstructured = nodeTypes().getNodeType(JcrNtLexicon.UNSTRUCTURED);
+ // for (PropertyDefinition anyDefinition :
unstructured.getDeclaredPropertyDefinitions()) {
+ // if (anyDefinition.isMultiple()) {
+ // propertyDefinition = anyDefinition;
+ // break;
+ // }
+ // }
+ // }
+ // if (propertyDefinition == null) {
+ // // We're supposed to skip this property (since we don't have a definition
for it) ...
+ // continue;
+ // }
+ //
+ // // Figure out if this is a multi-valued property ...
+ // boolean isMultiple = propertyDefinition.isMultiple();
+ // if (!isMultiple && dnaProp.isEmpty()) {
+ // // Only multi-valued properties can have no values; so if not multi-valued, then
skip ...
+ // continue;
+ // }
+ //
+ // // Update the list of single-valued multi-property names ...
+ // if (isMultiple && isSingle) {
+ // if (newSingleMultiPropertyNames == null) newSingleMultiPropertyNames = new
HashSet<Name>();
+ // newSingleMultiPropertyNames.add(name);
+ // }
+ //
+ // // Figure out the property type ...
+ // int definitionType = propertyDefinition.getRequiredType();
+ // if (definitionType != PropertyType.UNDEFINED) {
+ // propertyType = definitionType;
+ // }
+ //
+ // // Record the property in the node information ...
+ // PropertyId propId = new PropertyId(uuid, name);
+ // JcrPropertyDefinition defn = (JcrPropertyDefinition)propertyDefinition;
+ // PropertyInfo propInfo = new PropertyInfo(propId, defn.getId(), propertyType,
dnaProp, defn.isMultiple(), false, false);
+ // props.put(name, propInfo);
+ // }
+ //
+ // // Now add the "jcr:uuid" property if and only if referenceable ...
+ // if (referenceable) {
+ // // We know that this property is single-valued
+ // JcrValue value = new JcrValue(factories(), this, PropertyType.STRING, uuid);
+ // PropertyDefinition propertyDefinition =
nodeTypes().findPropertyDefinition(primaryTypeName,
+ // mixinTypeNames,
+ // JcrLexicon.UUID,
+ // value,
+ // false,
+ // false);
+ // PropertyId propId = new PropertyId(uuid, JcrLexicon.UUID);
+ // JcrPropertyDefinition defn = (JcrPropertyDefinition)propertyDefinition;
+ // PropertyInfo propInfo = new PropertyInfo(propId, defn.getId(),
PropertyType.STRING, uuidProperty, defn.isMultiple(),
+ // false, false);
+ // props.put(JcrLexicon.UUID, propInfo);
+ // } else {
+ // // Make sure there is NOT a "jcr:uuid" property ...
+ // props.remove(JcrLexicon.UUID);
+ // }
+ // // Make sure the "dna:uuid" property did not get in there ...
+ // props.remove(DnaLexicon.UUID);
+ //
+ // // Make sure the single-valued multi-property names are stored as a property ...
+ // if (newSingleMultiPropertyNames != null) {
+ // PropertyInfo info = createSingleMultiplePropertyInfo(uuid,
+ // primaryTypeName,
+ // mixinTypeNames,
+ // newSingleMultiPropertyNames);
+ // props.put(info.getPropertyName(), info);
+ // }
+ //
+ // // Create the node information ...
+ // UUID parentUuid = parentInfo != null ? parentInfo.getUuid() : null;
+ // List<Location> locations = graphNode.getChildren();
+ // Children children = locations.isEmpty() ? new EmptyChildren(parentUuid) : new
ImmutableChildren(parentUuid, locations);
+ // props = Collections.unmodifiableMap(props);
+ // return new ImmutableNodeInfo(location, primaryTypeName, mixinTypeNames,
definition.getId(), parentUuid, children, props);
+ // }
+ //
+ protected final void updateSingleMultipleProperty( Node<JcrNodePayload,
JcrPropertyPayload> node,
+ Name singleMultiPropertyName,
+ boolean add ) {
+ PropertyInfo<JcrPropertyPayload> existing =
node.getProperty(DnaIntLexicon.MULTI_VALUED_PROPERTIES);
+ Set<Name> singleMultiPropertyNames = null;
+ if (existing != null) {
+ singleMultiPropertyNames = new HashSet<Name>();
+ // Grab the existing values ...
+ for (Object value : existing.getProperty()) {
+ singleMultiPropertyNames.add(nameFactory().create(value));
+ }
+ if (add) singleMultiPropertyNames.add(singleMultiPropertyName);
+ else singleMultiPropertyNames.remove(singleMultiPropertyName);
+ } else {
+ if (add) {
+ singleMultiPropertyNames =
Collections.singleton(singleMultiPropertyName);
+ } else {
+ // supposed to remove the property name, but there isn't a property,
so just return
+ return;
+ }
}
- // It is not a root node ...
- JcrNode node = new JcrNode(this, uuid);
- assert !uuid.equals(root);
- jcrNodes.put(uuid, node);
- return node;
- }
-
- /**
- * Utility method that creates and caches the appropriate kind of AbstractJcrProperty
implementation for property given by the
- * supplied information.
- *
- * @param info the information for the property; may not be null
- * @return the <i>new</i> instance of the {@link Property}; never null
- */
- private AbstractJcrProperty createAndCacheJcrPropertyFor( PropertyInfo info ) {
- boolean multiValued = info.isMultiValued();
- JcrPropertyDefinition definition =
nodeTypes().getPropertyDefinition(info.getDefinitionId());
- assert definition != null;
- if (multiValued) {
- return new JcrMultiValueProperty(this, info.getPropertyId());
+ if (singleMultiPropertyNames.isEmpty()) {
+ // Remove the property ...
+ assert existing != null;
+ node.removeProperty(existing.getName());
+ return;
}
- return new JcrSingleValueProperty(this, info.getPropertyId());
+ PropertyInfo<JcrPropertyPayload> property =
createSingleMultipleProperty(node.getPayload(),
+
existing,
+
singleMultiPropertyNames);
+ node.setProperty(property.getProperty(), property.isMultiValued(),
property.getPayload());
}
- /**
- * Find the information for the node given by the UUID of the node. This is often the
fastest way to find information,
- * especially after the information has been cached. Note, however, that this method
first checks the cache, and if the
- * information is not in the cache, the information is read from the repository.
- *
- * @param uuid the UUID for the node; may not be null
- * @return the information for the node with the supplied UUID, or null if the
information is not in the cache
- * @throws AccessDeniedException if the node cannot be accessed
- * @throws ItemNotFoundException if there is no node with the supplied UUID
- * @throws InvalidItemStateException if the node with the UUID has been deleted in
this session
- * @throws RepositoryException if any other error occurs while reading information
from the repository
- * @see #findNodeInfoInCache(UUID)
- * @see #findNodeInfo(UUID, Path)
- * @see #findNodeInfoForRoot()
- */
- NodeInfo findNodeInfo( UUID uuid )
- throws AccessDeniedException, ItemNotFoundException, InvalidItemStateException,
RepositoryException {
- assert uuid != null;
- // See if we already have something in the cache ...
- NodeInfo info = findNodeInfoInCache(uuid);
- if (info == null) {
- // Nope, so go ahead and load it ...
- info = loadFromGraph(null, uuid);
+ protected PropertyInfo<JcrPropertyPayload> createSingleMultipleProperty(
JcrNodePayload nodePayload,
+
PropertyInfo<JcrPropertyPayload> existing,
+
Set<Name> singleMultiPropertyNames ) {
+ int number = singleMultiPropertyNames.size();
+ // Otherwise, we have to set/update the property ...
+ String[] names = new String[number];
+ JcrValue[] values = new JcrValue[number];
+ if (number == 1) {
+ String str =
singleMultiPropertyNames.iterator().next().getString(namespaces);
+ names[0] = str;
+ values[0] = new JcrValue(factories(), this, PropertyType.STRING, str);
+ } else {
+ int index = 0;
+ for (Name name : singleMultiPropertyNames) {
+ String str = name.getString(namespaces);
+ names[index] = str;
+ values[index] = new JcrValue(factories(), this, PropertyType.STRING,
str);
+ ++index;
+ }
}
- SessionCache.this.checkPermission(info, JcrSession.JCR_READ_PERMISSION);
-
- return info;
+ JcrPropertyDefinition definition =
nodeTypes().findPropertyDefinition(nodePayload.getPrimaryTypeName(),
+
nodePayload.getMixinTypeNames(),
+
DnaIntLexicon.MULTI_VALUED_PROPERTIES,
+ values,
+ false);
+ Property dnaProp = propertyFactory.create(DnaIntLexicon.MULTI_VALUED_PROPERTIES,
singleMultiPropertyNames.iterator());
+ return createPropertyInfo(nodePayload, dnaProp, definition, PropertyType.STRING,
existing);
}
- /**
- * Find the information for the node given by the UUID of the node. This is often the
fastest way to find information,
- * especially after the information has been cached. Note, however, that this method
only checks the cache.
- *
- * @param uuid the UUID for the node; may not be null
- * @return the information for the node with the supplied UUID, or null if the
information is not in the cache
- * @see #findNodeInfo(UUID)
- * @see #findNodeInfo(UUID, Path)
- * @see #findNodeInfoForRoot()
- * @throws InvalidItemStateException if the node with the UUID has been deleted in
this session
- */
- NodeInfo findNodeInfoInCache( UUID uuid ) throws InvalidItemStateException {
- // See if we already have something in the changed nodes ...
- NodeInfo info = changedNodes.get(uuid);
- if (info == null) {
- // Or in the cache ...
- info = cachedNodes.get(uuid);
- if (info == null) {
- // Finally check if the node was deleted ...
- if (deletedNodes.containsKey(uuid)) {
- throw new InvalidItemStateException();
- }
+ protected final PropertyInfo<JcrPropertyPayload> createPropertyInfo(
JcrNodePayload nodePayload,
+ Property
dnaProp,
+
JcrPropertyDefinition definition,
+ int
propertyType,
+
PropertyInfo<JcrPropertyPayload> existing ) {
+ // Create (or reuse) the JCR Property object ...
+ AbstractJcrProperty jcrProp = null;
+ if (existing != null) {
+ jcrProp = existing.getPayload().getJcrProperty();
+ } else {
+ AbstractJcrNode jcrNode = nodePayload.getJcrNode();
+ if (definition.isMultiple()) {
+ jcrProp = new JcrMultiValueProperty(SessionCache.this, jcrNode,
dnaProp.getName());
+ } else {
+ jcrProp = new JcrSingleValueProperty(SessionCache.this, jcrNode,
dnaProp.getName());
}
}
- return info;
- }
+ assert jcrProp != null;
+ JcrPropertyPayload propPayload = new JcrPropertyPayload(definition.getId(),
propertyType, jcrProp);
+ Status status = existing != null ? Status.CHANGED : Status.NEW;
+ return new GraphSession.PropertyInfo<JcrPropertyPayload>(dnaProp,
definition.isMultiple(), status, propPayload);
- /**
- * Find the information for the root node. Generally, this returns information
that's in the cache, except for the first time
- * the root node is needed.
- *
- * @return the node information
- * @throws RepositoryException if there is an error while obtaining the information
from the repository
- */
- NodeInfo findNodeInfoForRoot() throws RepositoryException {
- if (root == null) {
- // We haven't found the root yet ...
- NodeInfo info = loadFromGraph(this.rootPath, (NodeInfo)null);
- root = info.getUuid();
- this.jcrNodes.put(root, new JcrRootNode(this, root));
- return info;
- }
- return findNodeInfo(root);
}
- /**
- * Find the information for the node given by the UUID of a reference node and a
relative path from the reference node.
- *
- * @param node the reference node; may be null if the root node is to be used as the
reference
- * @param relativePath the relative path from the reference node, but which may be an
absolute path only when the reference
- * node is the root node; may not be null
- * @return the information for the referenced node; never null
- * @throws ItemNotFoundException if the reference node with the supplied UUID does
not exist
- * @throws PathNotFoundException if the node given by the relative path does not
exist
- * @throws InvalidItemStateException if the node with the UUID has been deleted in
this session
- * @throws RepositoryException if any other error occurs while reading information
from the repository
- * @see #findNodeInfoForRoot()
- */
- NodeInfo findNodeInfo( UUID node,
- Path relativePath )
- throws ItemNotFoundException, InvalidItemStateException, PathNotFoundException,
RepositoryException {
- // The relative path must be normalized ...
- assert relativePath.isNormalized();
-
- // Find the node from which we're starting ...
- NodeInfo fromInfo = null;
- if (node == null) {
- // This is only valid when the path is relative to the root (or it's an
absolute path)
- fromInfo = findNodeInfoForRoot();
- node = fromInfo.getUuid();
- } else {
- fromInfo = findNodeInfo(node);
- assert relativePath.isAbsolute() ? node == root : true;
- }
- if (relativePath.isAbsolute()) {
- relativePath = relativePath.relativeTo(this.rootPath);
- }
-
- // If the relative path is of zero-length ...
- if (relativePath.size() == 0) {
- SessionCache.this.checkPermission(fromInfo, JcrSession.JCR_READ_PERMISSION);
- return fromInfo;
- }
- // Or it is of length 1 but it is a self reference ...
- if (relativePath.size() == 1 &&
relativePath.getLastSegment().isSelfReference()) {
- SessionCache.this.checkPermission(fromInfo, JcrSession.JCR_READ_PERMISSION);
- return fromInfo;
- }
-
- // TODO: This could be more efficient than always walking the path. For example,
we could
- // maintain a cache of paths. Right now, we are walking as much of the path as we
can,
- // but as soon as we reach the bottom-most cached/changed node, we need to read
the rest
- // from the graph. We are figuring out all of the remaining nodes and read them
from
- // the graph in one batch operation, so that part is pretty good.
-
- // Now, walk the path to find the nodes, being sure to look for changed
information ...
- NodeInfo info = fromInfo;
- Iterator<Path.Segment> pathsIter = relativePath.iterator();
- while (pathsIter.hasNext()) {
- Path.Segment child = pathsIter.next();
- if (child.isParentReference()) {
- // Walk up ...
- UUID parentUuid = info.getParent();
- if (parentUuid == null) {
- assert info.getUuid() == findNodeInfoForRoot().getUuid();
- String msg = JcrI18n.errorWhileFindingNodeWithPath.text(relativePath,
workspaceName);
- throw new PathNotFoundException(msg);
+ @Immutable
+ final class JcrNodeOperations extends GraphSession.NodeOperations<JcrNodePayload,
JcrPropertyPayload> {
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.session.GraphSession.Operations#materialize(org.jboss.dna.graph.Node,
+ * org.jboss.dna.graph.session.GraphSession.Node)
+ */
+ @Override
+ public void materialize( org.jboss.dna.graph.Node persistentNode,
+ Node<JcrNodePayload, JcrPropertyPayload> node ) {
+ // Now get the DNA node's UUID and find the DNA property containing the
UUID ...
+ Location location = node.getLocation();
+ UUID uuid = location.getUuid();
+ org.jboss.dna.graph.property.Property uuidProperty = null;
+ if (uuid != null) {
+ // Check for an identification property ...
+ uuidProperty = location.getIdProperty(JcrLexicon.UUID);
+ if (uuidProperty == null) {
+ uuidProperty = propertyFactory.create(JcrLexicon.UUID, uuid);
}
- info = findNodeInfo(parentUuid);
- } else {
- // Walk down ...
- // Note that once we start walking down, a normalized path should never
have any more parent
- // or self references
- ChildNode childNodeInfo = info.getChildren().getChild(child);
- if (childNodeInfo == null) {
- // The node (no longer?) exists, so compute the
- Path fromPath = getPathFor(fromInfo);
- String msg = JcrI18n.pathNotFoundRelativeTo.text(relativePath,
fromPath, workspaceName);
- throw new PathNotFoundException(msg);
+ }
+ if (uuidProperty == null) {
+
org.jboss.dna.graph.session.GraphSession.PropertyInfo<JcrPropertyPayload> uuidInfo =
node.getProperty(JcrLexicon.UUID);
+ if (uuidInfo != null) {
+ uuidProperty = uuidInfo.getProperty();
}
- // See if we already have something in the changed nodes ...
- UUID uuid = childNodeInfo.getUuid();
- NodeInfo childInfo = changedNodes.get(uuid);
- if (childInfo == null) {
- // Or in the cache ...
- childInfo = cachedNodes.get(uuid);
- if (childInfo == null) {
- // At this point, we've reached the bottom of the nodes that
we have locally.
- // Get the actual location of the last 'info', since all
paths will be relative to it...
- Location actualLocation = info.getOriginalLocation();
- Path actualPath = actualLocation.getPath();
- Path nextPath = pathFactory.create(actualPath, child);
- if (pathsIter.hasNext()) {
- // There are multiple remaining paths, so load them all in
one batch operation,
- // starting at the top-most path (the one we're currently
at)...
- List<Path> pathsInBatch = new
LinkedList<Path>();
- Results batchResults = null;
+ if (uuidProperty != null) {
+ // Grab the first 'good' UUID value ...
+ for (Object uuidValue : uuidProperty) {
+ try {
+ uuid = factories.getUuidFactory().create(uuidValue);
+ break;
+ } catch (ValueFormatException e) {
+ // Ignore; just continue with the next property value
+ }
+ }
+ }
+ if (uuid == null) {
+ // Look for the DNA UUID property ...
+ uuidInfo = node.getProperty(DnaLexicon.UUID);
+ if (uuidInfo != null) {
+ uuidProperty = uuidInfo.getProperty();
+ }
+ if (uuidProperty != null) {
+ // Grab the first 'good' UUID value ...
+ for (Object uuidValue : uuidProperty) {
try {
- Graph.Batch batch = store.batch();
- batch.read(nextPath);
- pathsInBatch.add(nextPath);
- while (pathsIter.hasNext()) {
- child = pathsIter.next();
- nextPath = pathFactory.create(nextPath, child);
- batch.read(nextPath);
- pathsInBatch.add(nextPath);
- }
- batchResults = batch.execute();
- } catch (org.jboss.dna.graph.property.PathNotFoundException
e) {
- Path fromPath = getPathFor(fromInfo);
- throw new
PathNotFoundException(JcrI18n.pathNotFoundRelativeTo.text(relativePath,
-
fromPath,
-
workspaceName));
- } catch (RepositorySourceException e) {
- throw new
RepositoryException(JcrI18n.errorWhileFindingNodeWithUuid.text(uuid,
-
workspaceName,
-
e.getLocalizedMessage()));
+ uuid = factories.getUuidFactory().create(uuidValue);
+ break;
+ } catch (ValueFormatException e) {
+ // Ignore; just continue with the next property value
}
- // Now process all of the nodes that we loaded, again
starting at the top and going down ...
- for (Path batchPath : pathsInBatch) {
- org.jboss.dna.graph.Node dnaNode =
batchResults.getNode(batchPath);
- ImmutableNodeInfo originalChildInfo =
createNodeInfoFrom(dnaNode, info);
- this.cachedNodes.put(originalChildInfo.getUuid(),
originalChildInfo);
- childInfo = originalChildInfo;
- info = originalChildInfo;
- }
- } else {
- // This is the last path, so do it a little more efficiently
than above ...
- childInfo = loadFromGraph(nextPath, info);
- info = childInfo;
}
- } else {
- info = childInfo;
}
+ }
+ }
+ if (uuid == null) uuid = UUID.randomUUID();
+ if (uuidProperty == null) uuidProperty =
propertyFactory.create(JcrLexicon.UUID, uuid);
+
+ // Look for the primary type of the node ...
+ Map<Name, Property> graphProperties =
persistentNode.getPropertiesByName();
+ final boolean isRoot = location.getPath().isRoot();
+ Name primaryTypeName = null;
+ org.jboss.dna.graph.property.Property primaryTypeProperty =
graphProperties.get(JcrLexicon.PRIMARY_TYPE);
+ if (primaryTypeProperty != null && !primaryTypeProperty.isEmpty()) {
+ try {
+ primaryTypeName =
factories.getNameFactory().create(primaryTypeProperty.getFirstValue());
+ } catch (ValueFormatException e) {
+ // use the default ...
+ }
+ }
+ if (primaryTypeName == null) {
+ // We have to have a primary type, so use the default ...
+ if (isRoot) {
+ primaryTypeName = DnaLexicon.ROOT;
+ primaryTypeProperty = propertyFactory.create(JcrLexicon.PRIMARY_TYPE,
primaryTypeName);
} else {
- info = childInfo;
+ primaryTypeName = defaultPrimaryTypeName;
+ primaryTypeProperty = defaultPrimaryTypeProperty;
}
+ // We have to add this property to the graph node...
+ graphProperties = new HashMap<Name, Property>(graphProperties);
+ graphProperties.put(primaryTypeProperty.getName(), primaryTypeProperty);
}
- }
- SessionCache.this.checkPermission(info, JcrSession.JCR_READ_PERMISSION);
- return info;
- }
+ assert primaryTypeProperty != null;
+ assert primaryTypeProperty.isEmpty() == false;
- /**
- * Find the property information with the given identifier. If the property is not
yet loaded into the cache, the node (and
- * its properties) will be read from the repository.
- *
- * @param propertyId the identifier for the property; may not be null
- * @return the property information, or null if the node does not contain the
specified property
- * @throws PathNotFoundException if the node containing this property does not exist
- * @throws InvalidItemStateException if the node with the UUID has been deleted in
this session
- * @throws RepositoryException if there is an error while obtaining the information
- */
- PropertyInfo findPropertyInfo( PropertyId propertyId )
- throws PathNotFoundException, InvalidItemStateException, RepositoryException {
- NodeInfo info = findNodeInfo(propertyId.getNodeId());
- return info.getProperty(propertyId.getPropertyName());
- }
+ // Look for a node definition stored on the node ...
+ JcrNodeDefinition definition = null;
+ org.jboss.dna.graph.property.Property nodeDefnProperty =
graphProperties.get(DnaIntLexicon.NODE_DEFINITON);
+ if (nodeDefnProperty != null && !nodeDefnProperty.isEmpty()) {
+ String nodeDefinitionString =
stringFactory.create(nodeDefnProperty.getFirstValue());
+ NodeDefinitionId id = NodeDefinitionId.fromString(nodeDefinitionString,
nameFactory);
+ definition = nodeTypes().getNodeDefinition(id);
+ }
+ // Figure out the node definition for this node ...
+ if (definition == null) {
+ if (isRoot) {
+ try {
+ definition = nodeTypes().getRootNodeDefinition();
+ } catch (RepositoryException e) {
+ // Shouldn't really happen ...
+ throw new ValidationException(e.getMessage(), e);
+ }
+ } else {
+ Name childName = node.getName();
+ Node<JcrNodePayload, JcrPropertyPayload> parent =
node.getParent();
+ JcrNodePayload parentInfo = parent.getPayload();
+ int numExistingChildrenWithSameName =
parent.getChildrenCount(childName);
+ // The children include this node, so we need to subtract one from
the count so that the
+ // number of existing children is either 0 (if there are no other SNS
nodes) or 1+
+ // (if there are at least 2 SNS nodes)
+ --numExistingChildrenWithSameName;
+ definition =
nodeTypes().findChildNodeDefinition(parentInfo.getPrimaryTypeName(),
+
parentInfo.getMixinTypeNames(),
+ childName,
+ primaryTypeName,
+
numExistingChildrenWithSameName,
+ false);
+ }
+ }
+ if (definition == null) {
+ String msg =
JcrI18n.nodeDefinitionCouldNotBeDeterminedForNode.text(readable(node.getPath()),
+
workspaceName(),
+
sourceName());
+ throw new ValidationException(msg);
+ }
- Path getPathFor( String workspaceName,
- UUID uuid,
- Path relativePath ) throws NoSuchWorkspaceException,
ItemNotFoundException, RepositoryException {
- assert workspaceName != null;
- assert uuid != null || relativePath != null;
+ // ------------------------------------------------------
+ // Set the node's properties ...
+ // ------------------------------------------------------
+ boolean referenceable = false;
- Graph graph = operations.getGraph();
- try {
- graph.useWorkspace(workspaceName);
- } catch (InvalidWorkspaceException iwe) {
- throw new
NoSuchWorkspaceException(JcrI18n.workspaceNameIsInvalid.text(graph.getSourceName(),
workspaceName));
- }
+ // Start with the primary type ...
+ JcrNodeType primaryType = nodeTypes().getNodeType(primaryTypeName);
+ if (primaryType == null) {
+ Path path = location.getPath();
+ String msg =
JcrI18n.missingNodeTypeForExistingNode.text(readable(primaryTypeName),
+ readable(path),
+
workspaceName(),
+ sourceName());
+ throw new ValidationException(msg);
+ }
+ if (primaryType.isNodeType(JcrMixLexicon.REFERENCEABLE)) referenceable =
true;
- try {
- org.jboss.dna.graph.Node node;
- if (uuid != null) {
- node = graph.getNodeAt(uuid);
-
- if (relativePath != null) {
- Path nodePath = node.getLocation().getPath();
- Path absolutePath = relativePath.resolveAgainst(nodePath);
- node = graph.getNodeAt(absolutePath);
+ // The process the mixin types ...
+ Property mixinTypesProperty = graphProperties.get(JcrLexicon.MIXIN_TYPES);
+ List<Name> mixinTypeNames = null;
+ if (mixinTypesProperty != null && !mixinTypesProperty.isEmpty()) {
+ for (Object mixinTypeValue : mixinTypesProperty) {
+ Name mixinTypeName = nameFactory.create(mixinTypeValue);
+ if (mixinTypeNames == null) mixinTypeNames = new
LinkedList<Name>();
+ mixinTypeNames.add(mixinTypeName);
+ JcrNodeType mixinType = nodeTypes().getNodeType(mixinTypeName);
+ if (mixinType == null) continue;
+ if (!referenceable &&
mixinType.isNodeType(JcrMixLexicon.REFERENCEABLE)) referenceable = true;
}
+ }
- } else {
- Path absolutePath =
pathFactory.createAbsolutePath(relativePath.getSegmentsList());
- node = graph.getNodeAt(absolutePath);
+ // Create the set of multi-valued property names ...
+ Set<Name> multiValuedPropertyNames = EMPTY_NAMES;
+ Set<Name> newSingleMultiPropertyNames = null;
+ Property multiValuedPropNamesProp =
graphProperties.get(DnaIntLexicon.MULTI_VALUED_PROPERTIES);
+ if (multiValuedPropNamesProp != null &&
!multiValuedPropNamesProp.isEmpty()) {
+ multiValuedPropertyNames =
getSingleMultiPropertyNames(multiValuedPropNamesProp, location);
}
- assert node != null;
- return node.getLocation().getPath();
- } catch (org.jboss.dna.graph.property.PathNotFoundException pnfe) {
- throw new ItemNotFoundException(pnfe);
- } finally {
- graph.useWorkspace(this.workspaceName);
- }
+ // Create the JCR Node payload object ...
+ JcrNodePayload nodePayload = new JcrNodePayload(SessionCache.this, node,
primaryTypeName, mixinTypeNames,
+ definition.getId());
+ AbstractJcrNode jcrNode = nodePayload.getJcrNode();
- }
+ // Now create the JCR property object wrappers around the other properties
...
+ Map<Name, GraphSession.PropertyInfo<JcrPropertyPayload>> props =
new HashMap<Name, GraphSession.PropertyInfo<JcrPropertyPayload>>();
+ for (Property dnaProp : graphProperties.values()) {
+ Name name = dnaProp.getName();
- Path getPathFor( UUID uuid ) throws ItemNotFoundException, InvalidItemStateException,
RepositoryException {
- if (uuid.equals(root)) return rootPath;
- return getPathFor(findNodeInfo(uuid));
- }
+ // Is this is single-valued property?
+ boolean isSingle = dnaProp.isSingle();
+ // Make sure that this isn't a multi-valued property with one value
...
+ if (isSingle && multiValuedPropertyNames.contains(name)) isSingle
= false;
- Path getPathFor( NodeInfo info ) throws ItemNotFoundException,
InvalidItemStateException, RepositoryException {
- if (info == null) {
- return pathFactory.createRootPath();
- }
- UUID uuid = info.getUuid();
- if (uuid.equals(root)) return rootPath;
+ // Figure out the JCR property type for this property ...
+ int propertyType = PropertyTypeUtil.jcrPropertyTypeFor(dnaProp);
+ PropertyDefinition propertyDefinition =
findBestPropertyDefintion(primaryTypeName,
+
mixinTypeNames,
+
dnaProp,
+
propertyType,
+
isSingle,
+
false);
- // This isn't the root node ...
- Path result = pathCache.get(uuid);
- if (result == null) {
- // We need to build a path using the parent path ...
- UUID parent = info.getParent();
- if (parent == null) {
- // Then this node is the root ...
- root = info.getUuid();
- result = rootPath;
+ // If there still is no property type defined ...
+ if (propertyDefinition == null &&
INCLUDE_PROPERTIES_NOT_ALLOWED_BY_NODE_TYPE_OR_MIXINS) {
+ // We can use the "nt:unstructured" property definitions
for any property ...
+ NodeType unstructured =
nodeTypes().getNodeType(JcrNtLexicon.UNSTRUCTURED);
+ for (PropertyDefinition anyDefinition :
unstructured.getDeclaredPropertyDefinitions()) {
+ if (anyDefinition.isMultiple()) {
+ propertyDefinition = anyDefinition;
+ break;
+ }
+ }
+ }
+ if (propertyDefinition == null) {
+ // We're supposed to skip this property (since we don't have
a definition for it) ...
+ continue;
+ }
+
+ // Figure out if this is a multi-valued property ...
+ boolean isMultiple = propertyDefinition.isMultiple();
+ if (!isMultiple && dnaProp.isEmpty()) {
+ // Only multi-valued properties can have no values; so if not
multi-valued, then skip ...
+ continue;
+ }
+
+ // Update the list of single-valued multi-property names ...
+ if (isMultiple && isSingle) {
+ if (newSingleMultiPropertyNames == null) newSingleMultiPropertyNames
= new HashSet<Name>();
+ newSingleMultiPropertyNames.add(name);
+ }
+
+ // Figure out the property type ...
+ int definitionType = propertyDefinition.getRequiredType();
+ if (definitionType != PropertyType.UNDEFINED) {
+ propertyType = definitionType;
+ }
+
+ // Record the property in the node information ...
+ JcrPropertyDefinition defn = (JcrPropertyDefinition)propertyDefinition;
+ AbstractJcrProperty jcrProp = null;
+ if (isMultiple) {
+ jcrProp = new JcrMultiValueProperty(SessionCache.this, jcrNode,
dnaProp.getName());
+ } else {
+ jcrProp = new JcrSingleValueProperty(SessionCache.this, jcrNode,
dnaProp.getName());
+ }
+ JcrPropertyPayload payload = new JcrPropertyPayload(defn.getId(),
propertyType, jcrProp);
+ PropertyInfo<JcrPropertyPayload> propInfo = new
PropertyInfo<JcrPropertyPayload>(dnaProp, defn.isMultiple(),
+
Status.UNCHANGED, payload);
+ props.put(name, propInfo);
+ }
+
+ // Now add the "jcr:uuid" property if and only if referenceable
...
+ if (referenceable) {
+ // We know that this property is single-valued
+ JcrValue value = new JcrValue(factories(), SessionCache.this,
PropertyType.STRING, uuid);
+ JcrPropertyDefinition propDefn =
nodeTypes().findPropertyDefinition(primaryTypeName,
+
mixinTypeNames,
+
JcrLexicon.UUID,
+
value,
+
false,
+
false);
+ PropertyInfo<JcrPropertyPayload> propInfo =
createPropertyInfo(nodePayload,
+
uuidProperty,
+ propDefn,
+
PropertyType.STRING,
+ null);
+ props.put(JcrLexicon.UUID, propInfo);
} else {
- NodeInfo parentInfo = findNodeInfo(parent);
- Path parentPath = getPathFor(parentInfo);
- ChildNode child = parentInfo.getChildren().getChild(info.getUuid());
- result = pathFactory.create(parentPath, child.getSegment());
+ // Make sure there is NOT a "jcr:uuid" property ...
+ props.remove(JcrLexicon.UUID);
}
- pathCache.put(uuid, result);
- }
- assert result != null;
- return result;
- }
+ // Make sure the "dna:uuid" property did not get in there ...
+ props.remove(DnaLexicon.UUID);
- Path getPathFor( PropertyInfo propertyInfo ) throws ItemNotFoundException,
RepositoryException {
- Path nodePath = getPathFor(propertyInfo.getNodeUuid());
- return pathFactory.create(nodePath, propertyInfo.getPropertyName());
- }
+ // Make sure the single-valued multi-property names are stored as a property
...
+ if (newSingleMultiPropertyNames != null) {
+ PropertyInfo<JcrPropertyPayload> info =
createSingleMultipleProperty(nodePayload,
+
null,
+
newSingleMultiPropertyNames);
+ props.put(info.getName(), info);
+ }
- Path getPathFor( PropertyId propertyId ) throws ItemNotFoundException,
RepositoryException {
- return getPathFor(findPropertyInfo(propertyId));
- }
+ // Set the information on the node ...
+ node.loadedWith(persistentNode.getChildren(), props,
persistentNode.getExpirationTime());
+ node.setPayload(nodePayload);
+ }
- protected Name getNameOf( UUID nodeUuid ) throws ItemNotFoundException,
InvalidItemStateException, RepositoryException {
- findNodeInfoForRoot();
- if (nodeUuid == root) return nameFactory.create("");
- // Get the parent ...
- NodeInfo info = findNodeInfo(nodeUuid);
- NodeInfo parent = findNodeInfo(info.getParent());
- ChildNode child = parent.getChildren().getChild(info.getUuid());
- return child.getName();
- }
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.session.GraphSession.NodeOperations#postSetProperty(org.jboss.dna.graph.session.GraphSession.Node,
+ * org.jboss.dna.graph.property.Name,
org.jboss.dna.graph.session.GraphSession.PropertyInfo)
+ */
+ @Override
+ public void postSetProperty( Node<JcrNodePayload, JcrPropertyPayload>
node,
+ Name propertyName,
+ PropertyInfo<JcrPropertyPayload> oldProperty )
{
+ super.postSetProperty(node, propertyName, oldProperty);
- protected int getSnsIndexOf( UUID nodeUuid ) throws ItemNotFoundException,
InvalidItemStateException, RepositoryException {
- findNodeInfoForRoot();
- if (nodeUuid == root) return 1;
- // Get the parent ...
- NodeInfo info = findNodeInfo(nodeUuid);
- NodeInfo parent = findNodeInfo(info.getParent());
- ChildNode child = parent.getChildren().getChild(info.getUuid());
- return child.getSnsIndex();
- }
+ if (propertyName.equals(DnaIntLexicon.MULTI_VALUED_PROPERTIES)) return;
+ if (propertyName.equals(JcrLexicon.MIXIN_TYPES)) {
+ // Add all of the values from the property ...
+ Set<Name> mixinTypeNames = new HashSet<Name>();
+ NameFactory nameFactory =
context().getValueFactories().getNameFactory();
+ for (Object value : node.getProperty(propertyName).getProperty()) {
+ mixinTypeNames.add(nameFactory.create(value));
+ }
+ node.setPayload(node.getPayload().with(new
ArrayList<Name>(mixinTypeNames)));
+ }
- /**
- * Load from the underlying repository graph the information for the node with the
supplied UUID. This method returns the
- * information for the requested node (after placing it in the cache), but this
method may (at its discretion) also load and
- * cache information for other nodes.
- * <p>
- * Note that this method does not check the cache before loading from the repository
graph.
- * </p>
- *
- * @param path the path of the node, if known; may be null only if the UUID is
supplied
- * @param uuid the UUID of the node, if known; may be null only if the path is
supplied
- * @return the information for the node
- * @throws ItemNotFoundException if the node does not exist in the repository
- * @throws RepositoryException if there was an error obtaining this information from
the repository
- */
- protected ImmutableNodeInfo loadFromGraph( Path path,
- UUID uuid ) throws ItemNotFoundException,
RepositoryException {
- // Load the node information from the store ...
- try {
- // See if there is a path for this uuid ...
- Location location = Location.create(path, uuid);
- org.jboss.dna.graph.Node node = store.getNodeAt(location);
- ImmutableNodeInfo info = createNodeInfoFrom(node, null);
- this.cachedNodes.put(info.getUuid(), info);
- return info;
- } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
- throw new ItemNotFoundException(JcrI18n.itemNotFoundWithUuid.text(uuid,
workspaceName, e.getLocalizedMessage()));
- } catch (RepositorySourceException e) {
- throw new RepositoryException(
-
JcrI18n.errorWhileFindingNodeWithUuid.text(uuid, workspaceName, e.getLocalizedMessage()),
- e);
+ // If the property is multi-valued but has only a single value, we need to
record that this property
+ // is actually a multi-valued property definition ...
+ PropertyInfo<JcrPropertyPayload> changedProperty =
node.getProperty(propertyName);
+ if (changedProperty.isMultiValued()) {
+ // We're changing a multi-valued property ...
+ if (changedProperty.getProperty().isSingle()) {
+ // There's only one actual value in this property, so we record
the name of this property in a hidden property
+ updateSingleMultipleProperty(node, propertyName, true);
+ } else {
+ // There are multiple actual values, so we don't need to name
this property in the hidden property ...
+ updateSingleMultipleProperty(node, propertyName, false);
+ }
+ }
}
- }
- /**
- * Load from the underlying repository graph the information for the node with the
supplied UUID. This method returns the
- * information for the requested node (after placing it in the cache), but this
method may (at its discretion) also load and
- * cache information for other nodes.
- * <p>
- * Note that this method does not check the cache before loading from the repository
graph.
- * </p>
- *
- * @param path the path to the node; may not be null
- * @param parentInfo the parent information; may be null if not known
- * @return the information for the node
- * @throws PathNotFoundException if the node does not exist in the repository
- * @throws RepositoryException if there was an error obtaining this information from
the repository
- */
- protected ImmutableNodeInfo loadFromGraph( Path path,
- NodeInfo parentInfo ) throws
PathNotFoundException, RepositoryException {
- // Load the node information from the store ...
- try {
- org.jboss.dna.graph.Node node = store.getNodeAt(path);
- ImmutableNodeInfo info = createNodeInfoFrom(node, parentInfo);
- this.cachedNodes.put(info.getUuid(), info);
- return info;
- } catch (org.jboss.dna.graph.property.PathNotFoundException e) {
- throw new PathNotFoundException(JcrI18n.pathNotFound.text(path,
workspaceName));
- } catch (RepositorySourceException e) {
- throw new
RepositoryException(JcrI18n.errorWhileFindingNodeWithPath.text(path, workspaceName));
- }
- }
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.session.GraphSession.Operations#preSave(org.jboss.dna.graph.session.GraphSession.Node)
+ */
+ @Override
+ public void preSave(
org.jboss.dna.graph.session.GraphSession.Node<JcrNodePayload, JcrPropertyPayload>
node )
+ throws ValidationException {
+ JcrNodePayload payload = node.getPayload();
- /**
- * Create the {@link NodeInfo} object given the DNA graph node and the parent node
information (if it is available).
- *
- * @param graphNode the DNA graph node; may not be null
- * @param parentInfo the information for the parent node, or null if the supplied
graph node represents the root node, or if
- * the parent information is not known
- * @return the node information; never null
- * @throws RepositoryException if there is an error determining the child {@link
NodeDefinition} for the supplied node,
- * preventing the node information from being constructed
- */
- private ImmutableNodeInfo createNodeInfoFrom( org.jboss.dna.graph.Node graphNode,
- NodeInfo parentInfo ) throws
RepositoryException {
- // Now get the DNA node's UUID and find the DNA property containing the UUID
...
- Location location = graphNode.getLocation();
- UUID uuid = location.getUuid();
- org.jboss.dna.graph.property.Property uuidProperty = null;
- if (uuid != null) {
- // Check for an identification property ...
- uuidProperty = location.getIdProperty(JcrLexicon.UUID);
- if (uuidProperty == null) {
- uuidProperty = propertyFactory.create(JcrLexicon.UUID, uuid);
+ Name primaryTypeName = payload.getPrimaryTypeName();
+ List<Name> mixinTypeNames = payload.getMixinTypeNames();
+ Set<JcrNodeDefinition> satisfiedChildNodes = new
HashSet<JcrNodeDefinition>();
+ Set<JcrPropertyDefinition> satisfiedProperties = new
HashSet<JcrPropertyDefinition>();
+
+ for
(org.jboss.dna.graph.session.GraphSession.PropertyInfo<JcrPropertyPayload> property
: node.getProperties()) {
+ JcrPropertyPayload propPayload = property.getPayload();
+ JcrPropertyDefinition definition =
findBestPropertyDefintion(primaryTypeName,
+
mixinTypeNames,
+
property.getProperty(),
+
propPayload.getPropertyType(),
+
property.getProperty().isSingle(),
+ false);
+ if (definition == null) {
+ throw new
ValidationException(JcrI18n.noDefinition.text("property",
+
readable(property.getName()),
+
readable(node.getPath()),
+
readable(primaryTypeName),
+
readable(mixinTypeNames)));
+ }
+
+ satisfiedProperties.add(definition);
}
- }
- if (uuidProperty == null) {
- uuidProperty = graphNode.getProperty(JcrLexicon.UUID);
- if (uuidProperty != null) {
- // Grab the first 'good' UUID value ...
- for (Object uuidValue : uuidProperty) {
- try {
- uuid = factories.getUuidFactory().create(uuidValue);
- break;
- } catch (ValueFormatException e) {
- // Ignore; just continue with the next property value
- }
+
+ for (org.jboss.dna.graph.session.GraphSession.Node<JcrNodePayload,
JcrPropertyPayload> child : node.getChildren()) {
+ int snsCount = node.getChildrenCount(child.getName());
+ JcrNodeDefinition definition =
nodeTypes().findChildNodeDefinition(primaryTypeName,
+
mixinTypeNames,
+
child.getName(),
+
child.getPayload().getPrimaryTypeName(),
+
snsCount,
+
false);
+ if (definition == null) {
+ throw new ValidationException(JcrI18n.noDefinition.text("child
node",
+
readable(child.getName()),
+
readable(node.getPath()),
+
readable(primaryTypeName),
+
readable(mixinTypeNames)));
}
+ satisfiedChildNodes.add(definition);
}
- if (uuid == null) {
- // Look for the DNA UUID property ...
- org.jboss.dna.graph.property.Property dnaUuidProperty =
graphNode.getProperty(DnaLexicon.UUID);
- if (dnaUuidProperty != null) {
- // Grab the first 'good' UUID value ...
- for (Object uuidValue : dnaUuidProperty) {
- try {
- uuid = factories.getUuidFactory().create(uuidValue);
- break;
- } catch (ValueFormatException e) {
- // Ignore; just continue with the next property value
+
+ JcrNodeType primaryType = nodeTypes().getNodeType(primaryTypeName);
+ for (JcrPropertyDefinition definition : primaryType.getPropertyDefinitions())
{
+ if (definition.isMandatory() && !definition.isProtected()
&& !satisfiedProperties.contains(definition)) {
+ throw new
ValidationException(JcrI18n.noDefinition.text("property",
+
definition.getName(),
+
readable(node.getPath()),
+
readable(primaryTypeName),
+
readable(mixinTypeNames)));
+ }
+ }
+ for (JcrNodeDefinition definition : primaryType.getChildNodeDefinitions()) {
+ if (definition.isMandatory() && !definition.isProtected()
&& !satisfiedChildNodes.contains(definition)) {
+ throw new ValidationException(JcrI18n.noDefinition.text("child
node",
+
definition.getName(),
+
readable(node.getPath()),
+
readable(primaryTypeName),
+
readable(mixinTypeNames)));
+ }
+ }
+
+ if (mixinTypeNames != null) {
+ for (Name mixinTypeName : mixinTypeNames) {
+ JcrNodeType mixinType = nodeTypes().getNodeType(mixinTypeName);
+ for (JcrPropertyDefinition definition :
mixinType.getPropertyDefinitions()) {
+ if (definition.isMandatory() && !definition.isProtected()
&& !satisfiedProperties.contains(definition)) {
+ throw new
ValidationException(JcrI18n.noDefinition.text("child node",
+
definition.getName(),
+
readable(node.getPath()),
+
readable(primaryTypeName),
+
readable(mixinTypeNames)));
}
}
+ for (JcrNodeDefinition definition :
mixinType.getChildNodeDefinitions()) {
+ if (definition.isMandatory() && !definition.isProtected()
&& !satisfiedChildNodes.contains(definition)) {
+ throw new
ValidationException(JcrI18n.noDefinition.text("child node",
+
definition.getName(),
+
readable(node.getPath()),
+
readable(primaryTypeName),
+
readable(mixinTypeNames)));
+ }
+ }
+
}
}
}
- if (uuid == null) uuid = UUID.randomUUID();
- if (uuidProperty == null) uuidProperty = propertyFactory.create(JcrLexicon.UUID,
uuid);
- // Either the UUID is not known, or there was no node. Either way, we have to
create the node ...
- if (uuid == null) uuid = UUID.randomUUID();
-
- // Look for the primary type of the node ...
- Map<Name, Property> graphProperties = graphNode.getPropertiesByName();
- final boolean isRoot = location.getPath().isRoot();
- Name primaryTypeName = null;
- org.jboss.dna.graph.property.Property primaryTypeProperty =
graphNode.getProperty(JcrLexicon.PRIMARY_TYPE);
- if (primaryTypeProperty != null && !primaryTypeProperty.isEmpty()) {
- try {
- primaryTypeName =
factories.getNameFactory().create(primaryTypeProperty.getFirstValue());
- } catch (ValueFormatException e) {
- // use the default ...
+ protected final Set<Name> getSingleMultiPropertyNames( Property
dnaProperty,
+ Location location ) {
+ Set<Name> multiValuedPropertyNames = new HashSet<Name>();
+ for (Object value : dnaProperty) {
+ try {
+ multiValuedPropertyNames.add(nameFactory.create(value));
+ } catch (ValueFormatException e) {
+ String msg = "{0} value \"{1}\" on {2} in
\"{3}\" workspace is not a valid name and is being ignored";
+ Logger.getLogger(getClass()).trace(e,
+ msg,
+
readable(DnaIntLexicon.MULTI_VALUED_PROPERTIES),
+ value,
+ readable(location),
+ workspaceName());
+ }
}
+ return multiValuedPropertyNames;
}
- if (primaryTypeName == null) {
- // We have to have a primary type, so use the default ...
- if (isRoot) {
- primaryTypeName = DnaLexicon.ROOT;
- primaryTypeProperty = propertyFactory.create(JcrLexicon.PRIMARY_TYPE,
primaryTypeName);
- } else {
- primaryTypeName = defaultPrimaryTypeName;
- primaryTypeProperty = defaultPrimaryTypeProperty;
- }
- // We have to add this property to the graph node...
- graphProperties = new HashMap<Name, Property>(graphProperties);
- graphProperties.put(primaryTypeProperty.getName(), primaryTypeProperty);
- }
- assert primaryTypeProperty != null;
- assert primaryTypeProperty.isEmpty() == false;
+ }
- // Look for a node definition stored on the node ...
- JcrNodeDefinition definition = null;
- org.jboss.dna.graph.property.Property nodeDefnProperty =
graphProperties.get(DnaIntLexicon.NODE_DEFINITON);
- if (nodeDefnProperty != null && !nodeDefnProperty.isEmpty()) {
- String nodeDefinitionString =
stringFactory.create(nodeDefnProperty.getFirstValue());
- NodeDefinitionId id = NodeDefinitionId.fromString(nodeDefinitionString,
nameFactory);
- definition = nodeTypes().getNodeDefinition(id);
- }
- // Figure out the node definition for this node ...
- if (isRoot) {
- if (definition == null) definition = nodeTypes().getRootNodeDefinition();
- } else {
- // We need the parent ...
- Path path = location.getPath();
- if (parentInfo == null) {
- Path parentPath = path.getParent();
- parentInfo = findNodeInfo(null, parentPath.getNormalizedPath());
+ @Immutable
+ final class JcrAuthorizer implements GraphSession.Authorizer {
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.session.GraphSession.Authorizer#checkPermissions(org.jboss.dna.graph.property.Path,
+ * org.jboss.dna.graph.session.GraphSession.Authorizer.Action)
+ */
+ public void checkPermissions( Path path,
+ Action action ) throws AccessControlException {
+ String jcrAction = null;
+ switch (action) {
+ case ADD_NODE:
+ jcrAction = JcrSession.JCR_ADD_NODE_PERMISSION;
+ break;
+ case READ:
+ jcrAction = JcrSession.JCR_READ_PERMISSION;
+ break;
+ case REMOVE:
+ jcrAction = JcrSession.JCR_REMOVE_PERMISSION;
+ break;
+ case SET_PROPERTY:
+ jcrAction = JcrSession.JCR_SET_PROPERTY_PERMISSION;
+ break;
}
- if (definition == null) {
- Name childName = path.getLastSegment().getName();
- int numExistingChildrenWithSameName =
parentInfo.getChildren().getCountOfSameNameSiblingsWithName(childName);
- definition =
nodeTypes().findChildNodeDefinition(parentInfo.getPrimaryTypeName(),
-
parentInfo.getMixinTypeNames(),
- childName,
- primaryTypeName,
-
numExistingChildrenWithSameName,
- false);
- }
- if (definition == null) {
- String msg = JcrI18n.nodeDefinitionCouldNotBeDeterminedForNode.text(path,
workspaceName);
- throw new RepositorySourceException(sourceName(), msg);
- }
+ session().checkPermission(path, jcrAction);
}
+ }
- // ------------------------------------------------------
- // Set the node's properties ...
- // ------------------------------------------------------
- boolean referenceable = false;
+ @Immutable
+ final static class JcrPropertyPayload {
+ private final PropertyDefinitionId propertyDefinitionId;
+ private final int jcrPropertyType;
+ private final SoftReference<AbstractJcrProperty> jcrProperty;
- // Start with the primary type ...
- JcrNodeType primaryType = nodeTypes().getNodeType(primaryTypeName);
- if (primaryType == null) {
- Path path = location.getPath();
- String msg =
JcrI18n.missingNodeTypeForExistingNode.text(primaryTypeName.getString(namespaces), path,
workspaceName);
- throw new RepositorySourceException(sourceName(), msg);
+ JcrPropertyPayload( PropertyDefinitionId propertyDefinitionId,
+ int jcrPropertyType,
+ AbstractJcrProperty jcrProperty ) {
+ assert jcrProperty != null;
+ this.propertyDefinitionId = propertyDefinitionId;
+ this.jcrPropertyType = jcrPropertyType;
+ this.jcrProperty = new
SoftReference<AbstractJcrProperty>(jcrProperty);
}
- if (primaryType.isNodeType(JcrMixLexicon.REFERENCEABLE)) referenceable = true;
- // The process the mixin types ...
- Property mixinTypesProperty = graphProperties.get(JcrLexicon.MIXIN_TYPES);
- List<Name> mixinTypeNames = null;
- if (mixinTypesProperty != null && !mixinTypesProperty.isEmpty()) {
- for (Object mixinTypeValue : mixinTypesProperty) {
- Name mixinTypeName = nameFactory.create(mixinTypeValue);
- if (mixinTypeNames == null) mixinTypeNames = new
LinkedList<Name>();
- mixinTypeNames.add(mixinTypeName);
- JcrNodeType mixinType = nodeTypes().getNodeType(mixinTypeName);
- if (mixinType == null) continue;
- if (!referenceable &&
mixinType.isNodeType(JcrMixLexicon.REFERENCEABLE)) referenceable = true;
- }
+ JcrPropertyPayload( PropertyDefinitionId propertyDefinitionId,
+ int jcrPropertyType,
+ SoftReference<AbstractJcrProperty> jcrProperty ) {
+ this.propertyDefinitionId = propertyDefinitionId;
+ this.jcrPropertyType = jcrPropertyType;
+ this.jcrProperty = jcrProperty;
}
- // Create the set of multi-valued property names ...
- Set<Name> multiValuedPropertyNames = EMPTY_NAMES;
- Set<Name> newSingleMultiPropertyNames = null;
- Property multiValuedPropNamesProp =
graphProperties.get(DnaIntLexicon.MULTI_VALUED_PROPERTIES);
- if (multiValuedPropNamesProp != null &&
!multiValuedPropNamesProp.isEmpty()) {
- multiValuedPropertyNames =
getSingleMultiPropertyNames(multiValuedPropNamesProp, location.getPath(), uuid);
+ /**
+ * @return jcrProperty
+ */
+ public AbstractJcrProperty getJcrProperty() {
+ return jcrProperty.get();
}
- // Now create the JCR property object wrappers around the other properties ...
- Map<Name, PropertyInfo> props = new HashMap<Name, PropertyInfo>();
- for (Property dnaProp : graphProperties.values()) {
- Name name = dnaProp.getName();
+ /**
+ * @return jcrPropertyType
+ */
+ public int getPropertyType() {
+ return jcrPropertyType;
+ }
- // Is this is single-valued property?
- boolean isSingle = dnaProp.isSingle();
- // Make sure that this isn't a multi-valued property with one value ...
- if (isSingle && multiValuedPropertyNames.contains(name)) isSingle =
false;
+ /**
+ * @return propertyDefinitionId
+ */
+ public PropertyDefinitionId getPropertyDefinitionId() {
+ return propertyDefinitionId;
+ }
- // Figure out the JCR property type for this property ...
- int propertyType = PropertyTypeUtil.jcrPropertyTypeFor(dnaProp);
- PropertyDefinition propertyDefinition =
findBestPropertyDefintion(primaryTypeName,
-
mixinTypeNames,
- dnaProp,
-
propertyType,
- isSingle,
- false);
+ public JcrPropertyPayload with( PropertyDefinitionId propertyDefinitionId ) {
+ return new JcrPropertyPayload(propertyDefinitionId, jcrPropertyType,
jcrProperty);
+ }
- // If there still is no property type defined ...
- if (propertyDefinition == null &&
INCLUDE_PROPERTIES_NOT_ALLOWED_BY_NODE_TYPE_OR_MIXINS) {
- // We can use the "nt:unstructured" property definitions for
any property ...
- NodeType unstructured =
nodeTypes().getNodeType(JcrNtLexicon.UNSTRUCTURED);
- for (PropertyDefinition anyDefinition :
unstructured.getDeclaredPropertyDefinitions()) {
- if (anyDefinition.isMultiple()) {
- propertyDefinition = anyDefinition;
- break;
- }
- }
- }
- if (propertyDefinition == null) {
- // We're supposed to skip this property (since we don't have a
definition for it) ...
- continue;
- }
+ public JcrPropertyPayload with( int jcrPropertyType ) {
+ return new JcrPropertyPayload(propertyDefinitionId, jcrPropertyType,
jcrProperty);
+ }
- // Figure out if this is a multi-valued property ...
- boolean isMultiple = propertyDefinition.isMultiple();
- if (!isMultiple && dnaProp.isEmpty()) {
- // Only multi-valued properties can have no values; so if not
multi-valued, then skip ...
- continue;
- }
+ public JcrPropertyPayload with( AbstractJcrProperty jcrProperty ) {
+ return new JcrPropertyPayload(propertyDefinitionId, jcrPropertyType,
jcrProperty);
+ }
+ }
- // Update the list of single-valued multi-property names ...
- if (isMultiple && isSingle) {
- if (newSingleMultiPropertyNames == null) newSingleMultiPropertyNames =
new HashSet<Name>();
- newSingleMultiPropertyNames.add(name);
- }
+ @Immutable
+ final static class JcrNodePayload {
+ private final SessionCache cache;
+ private final Node<JcrNodePayload, JcrPropertyPayload> owner;
+ private final Name primaryTypeName;
+ private final List<Name> mixinTypeNames;
+ private final NodeDefinitionId nodeDefinitionId;
+ private SoftReference<AbstractJcrNode> jcrNode;
- // Figure out the property type ...
- int definitionType = propertyDefinition.getRequiredType();
- if (definitionType != PropertyType.UNDEFINED) {
- propertyType = definitionType;
- }
+ JcrNodePayload( SessionCache cache,
+ Node<JcrNodePayload, JcrPropertyPayload> owner,
+ Name primaryTypeName,
+ List<Name> mixinTypeNames,
+ NodeDefinitionId nodeDefinitionId ) {
+ assert owner != null;
+ assert cache != null;
+ this.cache = cache;
+ this.owner = owner;
+ this.primaryTypeName = primaryTypeName;
+ this.mixinTypeNames = mixinTypeNames;
+ this.nodeDefinitionId = nodeDefinitionId;
+ this.jcrNode = new SoftReference<AbstractJcrNode>(null);
+ }
- // Record the property in the node information ...
- PropertyId propId = new PropertyId(uuid, name);
- JcrPropertyDefinition defn = (JcrPropertyDefinition)propertyDefinition;
- PropertyInfo propInfo = new PropertyInfo(propId, defn.getId(), propertyType,
dnaProp, defn.isMultiple(), false, false);
- props.put(name, propInfo);
+ JcrNodePayload( SessionCache cache,
+ Node<JcrNodePayload, JcrPropertyPayload> owner,
+ Name primaryTypeName,
+ List<Name> mixinTypeNames,
+ NodeDefinitionId nodeDefinitionId,
+ SoftReference<AbstractJcrNode> jcrNode ) {
+ assert jcrNode != null;
+ assert owner != null;
+ assert cache != null;
+ this.cache = cache;
+ this.owner = owner;
+ this.primaryTypeName = primaryTypeName;
+ this.mixinTypeNames = mixinTypeNames;
+ this.nodeDefinitionId = nodeDefinitionId;
+ this.jcrNode = jcrNode;
}
- // Now add the "jcr:uuid" property if and only if referenceable ...
- if (referenceable) {
- // We know that this property is single-valued
- JcrValue value = new JcrValue(factories(), this, PropertyType.STRING, uuid);
- PropertyDefinition propertyDefinition =
nodeTypes().findPropertyDefinition(primaryTypeName,
-
mixinTypeNames,
-
JcrLexicon.UUID,
-
value,
-
false,
-
false);
- PropertyId propId = new PropertyId(uuid, JcrLexicon.UUID);
- JcrPropertyDefinition defn = (JcrPropertyDefinition)propertyDefinition;
- PropertyInfo propInfo = new PropertyInfo(propId, defn.getId(),
PropertyType.STRING, uuidProperty, defn.isMultiple(),
- false, false);
- props.put(JcrLexicon.UUID, propInfo);
- } else {
- // Make sure there is NOT a "jcr:uuid" property ...
- props.remove(JcrLexicon.UUID);
+ /**
+ * @return primaryTypeName
+ */
+ public Name getPrimaryTypeName() {
+ return this.primaryTypeName;
}
- // Make sure the "dna:uuid" property did not get in there ...
- props.remove(DnaLexicon.UUID);
- // Make sure the single-valued multi-property names are stored as a property ...
- if (newSingleMultiPropertyNames != null) {
- PropertyInfo info = createSingleMultiplePropertyInfo(uuid,
- primaryTypeName,
- mixinTypeNames,
-
newSingleMultiPropertyNames);
- props.put(info.getPropertyName(), info);
+ /**
+ * Get the names of the mixin types for this node.
+ *
+ * @return the unmodifiable list of mixin type names; never null but possibly
empty
+ */
+ public List<Name> getMixinTypeNames() {
+ return this.mixinTypeNames != null ? this.mixinTypeNames :
Collections.<Name>emptyList();
}
- // Create the node information ...
- UUID parentUuid = parentInfo != null ? parentInfo.getUuid() : null;
- List<Location> locations = graphNode.getChildren();
- Children children = locations.isEmpty() ? new EmptyChildren(parentUuid) : new
ImmutableChildren(parentUuid, locations);
- props = Collections.unmodifiableMap(props);
- return new ImmutableNodeInfo(location, primaryTypeName, mixinTypeNames,
definition.getId(), parentUuid, children, props);
- }
-
- protected final PropertyInfo createSingleMultiplePropertyInfo( UUID uuid,
- Name primaryTypeName,
- List<Name>
mixinTypeNames,
- Set<Name>
newSingleMultiPropertyNames ) {
- int number = newSingleMultiPropertyNames.size();
- String[] names = new String[number];
- JcrValue[] values = new JcrValue[number];
- if (number == 1) {
- String str =
newSingleMultiPropertyNames.iterator().next().getString(namespaces);
- names[0] = str;
- values[0] = new JcrValue(factories(), this, PropertyType.STRING, str);
- } else {
- int index = 0;
- for (Name name : newSingleMultiPropertyNames) {
- String str = name.getString(namespaces);
- names[index] = str;
- values[index] = new JcrValue(factories(), this, PropertyType.STRING,
str);
- ++index;
- }
+ /**
+ * @return definition
+ */
+ public NodeDefinitionId getDefinitionId() {
+ return this.nodeDefinitionId;
}
- PropertyDefinition propertyDefinition =
nodeTypes().findPropertyDefinition(primaryTypeName,
-
mixinTypeNames,
-
DnaIntLexicon.MULTI_VALUED_PROPERTIES,
-
values,
-
false);
- Property dnaProp = propertyFactory.create(DnaIntLexicon.MULTI_VALUED_PROPERTIES,
-
newSingleMultiPropertyNames.iterator().next());
- PropertyId propId = new PropertyId(uuid, dnaProp.getName());
- JcrPropertyDefinition defn = (JcrPropertyDefinition)propertyDefinition;
- return new PropertyInfo(propId, defn.getId(), PropertyType.STRING, dnaProp,
defn.isMultiple(), true, false);
- }
- protected final Set<Name> getSingleMultiPropertyNames( Property dnaProperty,
- Path knownPath,
- UUID knownUuid ) {
- Set<Name> multiValuedPropertyNames = new HashSet<Name>();
- for (Object value : dnaProperty) {
- try {
- multiValuedPropertyNames.add(nameFactory.create(value));
- } catch (ValueFormatException e) {
- String msg = "{0} value \"{1}\" on {2} in
\"{3}\" workspace is not a valid name and is being ignored";
- String path = null;
- if (knownPath != null) {
- path = knownPath.getString(namespaces);
+ /**
+ * Get the JCR node instance.
+ *
+ * @return jcrNode
+ */
+ public AbstractJcrNode getJcrNode() {
+ AbstractJcrNode node = jcrNode.get();
+ if (node == null) {
+ if (owner.isRoot()) {
+ node = new JcrRootNode(cache, owner.getNodeId(),
owner.getLocation());
} else {
- assert knownUuid != null;
- try {
- path = getPathFor(knownUuid).getString(namespaces);
- } catch (RepositoryException err) {
- path = knownUuid.toString();
- }
+ node = new JcrNode(cache, owner.getNodeId(), owner.getLocation());
}
- Logger.getLogger(getClass()).trace(e,
- msg,
-
DnaIntLexicon.MULTI_VALUED_PROPERTIES.getString(namespaces),
- value,
- path,
- workspaceName());
+ jcrNode = new SoftReference<AbstractJcrNode>(node);
}
+ return jcrNode.get();
}
- return multiValuedPropertyNames;
- }
- /**
- * This method finds the {@link NodeInfo} for the node with the supplied UUID and
marks it as being deleted, and does the same
- * for all decendants (e.g., children, grandchildren, great-grandchildren, etc.) that
have been cached or changed.
- * <p>
- * Note that this method only processes those nodes that are actually represented in
this cache. Any branches that are not
- * loaded are not processed. This is an acceptable assumption, since all ancestors of
a cached node should also be cached.
- * </p>
- * <p>
- * Also be aware that the returned count of deleted node info representations will
only reflect the total number of nodes in
- * the branch if and only if all branch nodes were cached. In all other cases, the
count returned will be fewer than the
- * number of actual nodes in the branch.
- * </p>
- *
- * @param uuid the UUID of the node that should be marked as deleted; may not be
null
- * @return the number of node info representations that were marked as deleted
- */
- protected int deleteNodeInfos( UUID uuid ) {
- Queue<UUID> nodesToDelete = new LinkedList<UUID>();
- int numDeleted = 0;
- nodesToDelete.add(uuid);
- while (!nodesToDelete.isEmpty()) {
- UUID toDelete = nodesToDelete.remove();
- // Remove the node info from the changed map ...
- NodeInfo info = changedNodes.remove(toDelete);
- if (info == null) {
- // Wasn't changed, so remove it from the cache map ...
- info = cachedNodes.remove(toDelete);
- }
- // Whether or not we found an info, add it to the deleted map ...
- this.deletedNodes.put(toDelete, info);
+ public JcrNodePayload with( Name primaryTypeName ) {
+ return new JcrNodePayload(cache, owner, primaryTypeName, mixinTypeNames,
nodeDefinitionId, jcrNode);
+ }
- // Remove it from the path cache ...
- this.pathCache.remove(toDelete);
+ public JcrNodePayload with( List<Name> mixinTypeNames ) {
+ return new JcrNodePayload(cache, owner, primaryTypeName, mixinTypeNames,
nodeDefinitionId, jcrNode);
+ }
- if (info != null) {
- // Get all the children and add them to the queue ...
- for (ChildNode child : info.getChildren()) {
- nodesToDelete.add(child.getUuid());
- }
- }
- ++numDeleted;
+ public JcrNodePayload with( NodeDefinitionId nodeDefinitionId ) {
+ return new JcrNodePayload(cache, owner, primaryTypeName, mixinTypeNames,
nodeDefinitionId, jcrNode);
}
- return numDeleted;
+
+ public JcrNodePayload with( AbstractJcrNode jcrNode ) {
+ return new JcrNodePayload(cache, owner, primaryTypeName, mixinTypeNames,
nodeDefinitionId,
+ new
SoftReference<AbstractJcrNode>(jcrNode));
+ }
}
+
}
Deleted: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChangedChildren.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChangedChildren.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChangedChildren.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -1,128 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you 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.
- *
- * JBoss DNA 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.jcr.cache;
-
-import java.util.List;
-import java.util.ListIterator;
-import java.util.UUID;
-import net.jcip.annotations.NotThreadSafe;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.Path;
-import org.jboss.dna.graph.property.PathFactory;
-
-/**
- * A {@link NotThreadSafe non-thread safe} implementation of {@link Children} that can be
modified in place. This is typically
- * used to capture changes made within a session.
- */
-@NotThreadSafe
-public class ChangedChildren extends ImmutableChildren {
-
- public ChangedChildren( Children original ) {
- super(original);
- }
-
- /**
- * Creates an empty instance.
- *
- * @param parentUuid the UUID of the parent node
- */
- protected ChangedChildren( UUID parentUuid ) {
- super(parentUuid);
- }
-
- protected ChangedChildren( ImmutableChildren original,
- Name additionalChildName,
- Path.Segment beforeChild,
- UUID childUuid,
- PathFactory pathFactory ) {
- super(original, additionalChildName, beforeChild, childUuid, pathFactory);
- }
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.jcr.cache.ImmutableChildren#with(org.jboss.dna.graph.property.Name,
java.util.UUID,
- * org.jboss.dna.graph.property.PathFactory)
- */
- @Override
- public ChangedChildren with( Name newChildName,
- UUID newChildUuid,
- PathFactory pathFactory ) {
- // Simply add the node to this object ...
- super.add(newChildName, newChildUuid, pathFactory);
- return this;
- }
-
- /**
- * Create another Children object that is equivalent to this node but with the
supplied child added before the named node.
- *
- * @param newChildName the name of the new child; may not be null
- * @param beforeChild the path segment of the child before which this node should be
added; may not be null
- * @param newChildUuid the UUID of the new child; may not be null
- * @param pathFactory the factory that can be used to create Path and/or Path.Segment
instances.
- * @return the new Children object; never null
- */
- public ChangedChildren with( Name newChildName,
- Path.Segment beforeChild,
- UUID newChildUuid,
- PathFactory pathFactory ) {
- return new ChangedChildren(this, newChildName, beforeChild, newChildUuid,
pathFactory);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.ImmutableChildren#without(java.util.UUID,
org.jboss.dna.graph.property.PathFactory)
- */
- @Override
- public ChangedChildren without( UUID childUuid,
- PathFactory pathFactory ) {
- // Remove the object that has the same UUID (regardless of the current SNS index)
...
- ChildNode toBeRemoved = childrenByUuid.get(childUuid);
- if (toBeRemoved == null) {
- return this;
- }
- // Remove the child from this object, then adjust the remaining child node
instances that follow it ...
- Name childName = toBeRemoved.getName();
- List<ChildNode> childrenWithSameName = childrenByName.get(childName);
- int snsIndex = toBeRemoved.getSnsIndex();
- if (snsIndex > childrenWithSameName.size()) {
- // The child node (with that SNS index) is no longer here) ...
- return this;
- }
- ListIterator<ChildNode> iter =
childrenWithSameName.listIterator(--snsIndex);
- assert iter.hasNext();
- ChildNode willBeRemoved = iter.next();
- assert willBeRemoved == toBeRemoved;
- childrenByUuid.remove(toBeRemoved.getUuid());
- iter.remove(); // removes the item that was last returned from 'next()'
- while (iter.hasNext()) {
- ChildNode next = iter.next();
- ChildNode newNext = next.with(pathFactory.createSegment(childName,
++snsIndex));
- childrenByUuid.put(newNext.getUuid(), newNext);
- iter.set(newNext);
- }
- return this;
- }
-
-}
Deleted: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChangedNodeInfo.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChangedNodeInfo.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChangedNodeInfo.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -1,496 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you 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.
- *
- * JBoss DNA 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.jcr.cache;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import net.jcip.annotations.NotThreadSafe;
-import org.jboss.dna.graph.JcrLexicon;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.NameFactory;
-import org.jboss.dna.graph.property.Path;
-import org.jboss.dna.graph.property.PathFactory;
-import org.jboss.dna.graph.property.ValueFactories;
-import org.jboss.dna.graph.property.ValueFactory;
-import org.jboss.dna.graph.property.Path.Segment;
-import org.jboss.dna.jcr.DnaIntLexicon;
-import org.jboss.dna.jcr.NodeDefinitionId;
-
-/**
- * The information that describes a node. This is the information that is kept in the
cache.
- * <p>
- * Each instance maintains a reference to the original (usually immutable) NodeInfo
representation that was probably read from the
- * repository.
- */
-@NotThreadSafe
-public class ChangedNodeInfo implements NodeInfo {
-
- protected static final PropertyInfo DELETED_PROPERTY = null;
-
- /**
- * A reference to the original representation of the node.
- */
- private final NodeInfo original;
-
- /**
- * The new parent for this node if it has been changed, or null if the parent has not
be changed.
- */
- private UUID newParent;
-
- /**
- * The updated children, or null if the children have not been changed from the
original's.
- */
- private ChangedChildren changedChildren;
-
- /**
- * This map, if it is non-null, contains the changed properties, overriding whatever
is in the original. If a property is
- * removed from the original, an entry is added to this map with the name of the
removed property and a null PropertyInfo.
- */
- private Map<Name, PropertyInfo> changedProperties;
-
- /**
- * The updated list of mixin node type names. This is merely a cached version of
what's already in the
- * {@link JcrLexicon#MIXIN_TYPES "jcr:mixinTypes"} property.
- */
- private List<Name> changedMixinTypeNames;
-
- /**
- * The updated node definition, which may be changed when this node is moved to a
different parent (with a different node
- * type)
- */
- private NodeDefinitionId changedDefinitionId;
-
- private List<UUID> peers;
-
- private Set<Name> singleMultiPropertyNames;
-
- /**
- * Create an immutable NodeInfo instance.
- *
- * @param original the original node information, may not be null
- */
- public ChangedNodeInfo( NodeInfo original ) {
- assert original != null;
- this.original = original;
- }
-
- /**
- * Returns the peer nodes for this changed node.
- * <p>
- * Peer nodes are nodes that must be saved with this node (e.g., the other changed
node in a
- * {@link javax.jcr.Session#move(String, String)} operation.
- * </p>
- *
- * @return a collection of the UUIDs for any other nodes that must be saved with this
node; may be null
- */
- public final Collection<UUID> getPeers() {
- return peers;
- }
-
- /**
- * Adds a peer node to this change.
- * <p>
- * Peer nodes are nodes that must be saved with this node (e.g., the other changed
node in a
- * {@link javax.jcr.Session#move(String, String)} operation.
- * </p>
- *
- * @param peerUuid the UUID of the peer node
- */
- public void addPeer( UUID peerUuid ) {
- if (peers == null) {
- peers = new LinkedList<UUID>();
- }
- peers.add(peerUuid);
- }
-
- public boolean setSingleMultiProperty( Name name ) {
- if (singleMultiPropertyNames == null) singleMultiPropertyNames = new
HashSet<Name>();
- return singleMultiPropertyNames.add(name);
- }
-
- public boolean removeSingleMultiProperty( Name name ) {
- return singleMultiPropertyNames == null ? false :
singleMultiPropertyNames.remove(name);
- }
-
- public Set<Name> getSingleMultiPropertyNames() {
- return singleMultiPropertyNames;
- }
-
- /**
- * Return the original node information. May be null if this is a new node.
- *
- * @return the original node information
- */
- public NodeInfo getOriginal() {
- return original;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#getOriginalLocation()
- */
- public Location getOriginalLocation() {
- return original.getOriginalLocation();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#getUuid()
- */
- public UUID getUuid() {
- return original.getUuid();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#getParent()
- */
- public UUID getParent() {
- // Even if this is used for recording changes to the root node (which has no
parent),
- // the root node cannot be moved to a different node (and no other node can be
moved to
- // the root). Therefore, if this represents the root node, the original's
parent UUID will
- // be the correct parent (null), and this representation will not need to have a
different
- // (non-null) value.
- if (newParent != null) return newParent;
- return original.getParent();
- }
-
- /**
- * Record that this node has been moved under a new parent. This method does
<i>not</i> change the ChildNode references in the
- * old or new parent.
- *
- * @param parent the new parent, or null if the original's parent should be used
- * @return the previous parent (either the original's or the last new parent);
may be null
- */
- public UUID setParent( UUID parent ) {
- UUID result = newParent != null ? newParent : original.getParent(); // may still
be null
- newParent = parent;
- return result;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#getPrimaryTypeName()
- */
- public Name getPrimaryTypeName() {
- return original.getPrimaryTypeName();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#getMixinTypeNames()
- */
- public List<Name> getMixinTypeNames() {
- if (changedMixinTypeNames != null) return changedMixinTypeNames;
- return original.getMixinTypeNames();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#getDefinitionId()
- */
- public NodeDefinitionId getDefinitionId() {
- if (changedDefinitionId != null) return changedDefinitionId;
- return original.getDefinitionId();
- }
-
- /**
- * Set the identifier of the node definition for this node. This should normally be
changed by
- * {@link #setProperty(PropertyInfo, ValueFactories) setting} the {@link
DnaIntLexicon#NODE_DEFINITON} property. However,
- * since that property is not always allowed, this method provides a way to set it
locally (without requiring a property).
- *
- * @param definitionId the new property definition identifier; may not be null
- * @see #setProperty(PropertyInfo, ValueFactories)
- */
- public void setDefinitionId( NodeDefinitionId definitionId ) {
- if (!getDefinitionId().equals(definitionId)) {
- assert definitionId != null;
- changedDefinitionId = definitionId;
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#getChildren()
- */
- public Children getChildren() {
- if (changedChildren != null) return changedChildren;
- return original.getChildren();
- }
-
- /**
- * Get the UUIDs for the children for this node that have been removed since the node
was last persisted.
- *
- * @return a collection of the UUIDs of the removed children; never null but possibly
empty
- */
- public Collection<UUID> getUuidsForRemovedChildren() {
- if (original == null) return Collections.emptySet();
-
- Set<UUID> removedChildren = new HashSet<UUID>();
- for (ChildNode originalChildNode : original.getChildren()) {
- if
(!this.changedChildren.childrenByUuid.containsKey(originalChildNode.getUuid())) {
- removedChildren.add(originalChildNode.getUuid());
- }
- }
- return removedChildren;
- }
-
- /**
- * Add a child to the children. This method does nothing if the child is already in
the children.
- *
- * @param childName the name of the child that is to be added; may not be null
- * @param childUuid the UUID of the child that is to be added; may not be null
- * @param factory the path factory that should be used to create a {@link Segment}
for the new {@link ChildNode} object
- * @return the child node that was just added; never null
- */
- public ChildNode addChild( Name childName,
- UUID childUuid,
- PathFactory factory ) {
- if (changedChildren == null) {
- // We need to capture the original children as a changed contained ...
- changedChildren = new ChangedChildren(original.getChildren());
- }
- return changedChildren.add(childName, childUuid, factory);
- }
-
- /**
- * Add a child to the children. This method does nothing if the child is already in
the children.
- *
- * @param childName the name of the child that is to be added; may not be null
- * @param childUuid the UUID of the child that is to be added; may not be null
- * @param beforeChild the segment for the child that the new child should be added
before; may not be null
- * @param factory the path factory that should be used to create a {@link Segment}
for the new {@link ChildNode} object
- */
- public void addChild( Name childName,
- Path.Segment beforeChild,
- UUID childUuid,
- PathFactory factory ) {
- if (changedChildren == null) {
- // We need to capture the original children as a changed contained ...
- changedChildren = new ChangedChildren(original.getChildren());
- }
- changedChildren = changedChildren.with(childName, beforeChild, childUuid,
factory);
- }
-
- /**
- * Remove a child from the children. This method only uses the child's UUID to
identify the contained ChildNode instance that
- * should be removed.
- *
- * @param childUUID the UUID of the child that is to be removed; may not be null
- * @param factory the path factory that should be used to create a {@link Segment}
for replacement {@link ChildNode} objects
- * for nodes with the same name that and higher same-name-sibiling indexes.
- * @return the child node that was removed, or null if no such child could be
removed
- */
- public ChildNode removeChild( UUID childUUID,
- PathFactory factory ) {
- ChildNode deleted = null;
- if (changedChildren == null) {
- // Create the changed children. First check whether there are 0 or 1 child
...
- Children existing = original.getChildren();
- int numExisting = existing.size();
- if (numExisting == 0) {
- // nothing to do, so return the original's children
- return null;
- }
- deleted = existing.getChild(childUUID);
- if (deleted == null) {
- // The requested child doesn't exist in the children, so return ...
- return null;
- }
- if (numExisting == 1) {
- // We're removing the only child in the original ...
- changedChildren = new ChangedChildren(existing.getParentUuid());
- return existing.getChild(childUUID);
- }
- // There is at least one child, so create the new children container ...
- assert existing instanceof InternalChildren;
- InternalChildren internal = (InternalChildren)existing;
- changedChildren = internal.without(childUUID, factory);
- } else {
- deleted = changedChildren.getChild(childUUID);
- changedChildren = changedChildren.without(childUUID, factory);
- }
- return deleted;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#hasProperties()
- */
- public boolean hasProperties() {
- if (changedProperties == null) return original.hasProperties();
- int numUnchanged = original.getPropertyCount();
- int numChangedOrDeleted = changedProperties.size();
- if (numUnchanged > numChangedOrDeleted) return true; // more unchanged than
could be deleted
- // They could all be changed or deleted, so we need to find one changed property
...
- for (Map.Entry<Name, PropertyInfo> entry : changedProperties.entrySet()) {
- if (entry.getValue() != DELETED_PROPERTY) return true;
- }
- return false; // all properties must have been deleted ...
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#getPropertyCount()
- */
- public int getPropertyCount() {
- int numUnchanged = original.getPropertyCount();
- if (changedProperties == null) return numUnchanged;
- return getPropertyNames().size();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#getPropertyNames()
- */
- public Set<Name> getPropertyNames() {
- if (changedProperties != null) {
- Set<Name> result = new
HashSet<Name>(original.getPropertyNames());
- for (Map.Entry<Name, PropertyInfo> entry :
changedProperties.entrySet()) {
- if (entry.getValue() != DELETED_PROPERTY) {
- result.add(entry.getKey());
- } else {
- result.remove(entry.getKey());
- }
- }
- return result; // don't make unmod wrapper, since we've already made
a copy ...
- }
- return original.getPropertyNames();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.jcr.cache.NodeInfo#getProperty(org.jboss.dna.graph.property.Name)
- */
- public PropertyInfo getProperty( Name name ) {
- if (changedProperties != null && changedProperties.containsKey(name)) {
- return changedProperties.get(name); // either the changed PropertyInfo, or
null if property was deleted
- }
- return original.getProperty(name);
- }
-
- public PropertyInfo setProperty( PropertyInfo newProperty,
- ValueFactories factories ) {
- Name name = newProperty.getPropertyName();
- PropertyInfo previous = null;
- if (changedProperties == null) {
- // There were no changes made yet ...
-
- // Create the map of changed properties ...
- changedProperties = new HashMap<Name, PropertyInfo>();
- changedProperties.put(name, newProperty);
-
- // And return the original property (or null if there was none) ...
- previous = original.getProperty(name);
- } else if (changedProperties.containsKey(name)) {
- // The property was already changed, in which case we need to return the
changed one ...
- previous = changedProperties.put(name, newProperty);
- } else {
- // Otherwise, the property was not yet changed or deleted ...
- previous = original.getProperty(name);
- changedProperties.put(name, newProperty);
- }
- // If this property was the "jcr:mixinTypes" property, update the
cached values ...
- if (name.equals(JcrLexicon.MIXIN_TYPES)) {
- if (changedMixinTypeNames == null) {
- changedMixinTypeNames = new LinkedList<Name>();
- } else {
- changedMixinTypeNames.clear();
- }
- NameFactory nameFactory = factories.getNameFactory();
- for (Object value : newProperty.getProperty()) {
- changedMixinTypeNames.add(nameFactory.create(value));
- }
- } else if (name.equals(DnaIntLexicon.NODE_DEFINITON)) {
- ValueFactory<String> stringFactory = factories.getStringFactory();
- String value =
stringFactory.create(newProperty.getProperty().getFirstValue());
- changedDefinitionId = NodeDefinitionId.fromString(value,
factories.getNameFactory());
- }
-
- return previous;
- }
-
- public PropertyInfo removeProperty( Name name ) {
- if (changedProperties == null) {
- // Make sure the property was in the original ...
- PropertyInfo existing = original.getProperty(name);
- if (existing == null) {
- // The named property didn't exist in the original, nor was it added
and deleted in this object ...
- return null;
- }
-
- // Create the map of changed properties ...
- changedProperties = new HashMap<Name, PropertyInfo>();
- changedProperties.put(name, DELETED_PROPERTY);
- return existing;
- }
- // The property may already have been changed, in which case we need to return
the changed one ...
- if (changedProperties.containsKey(name)) {
- PropertyInfo changed = changedProperties.put(name, null);
- // The named property was indeed deleted ...
- return changed;
- }
- // Otherwise, the property was not yet changed or deleted ...
- PropertyInfo changed = original.getProperty(name);
- changedProperties.put(name, null);
- return changed;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#isNew()
- */
- public boolean isNew() {
- return false;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#isModified()
- */
- public boolean isModified() {
- return true;
- }
-}
Deleted: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChildNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChildNode.java 2009-07-09 16:23:09
UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ChildNode.java 2009-07-09 16:26:04
UTC (rev 1082)
@@ -1,139 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you 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.
- *
- * JBoss DNA 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.jcr.cache;
-
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.Path;
-
-/**
- * The representation of a child node. This is an immutable representation of a child
node within the collection of its siblings
- * as the collection appeared at some point in time. This should be used as a guide to
determine how long to hold onto references.
- * <p>
- * For example, adding and removing children may affect the {@link #getSnsIndex()
same-name-sibling index} of the children, so
- * these kinds of operations will result in the replacement of old ChildObject instances.
Therefore, clients should generally find
- * the ChildNode instances in a {@link Children} container, use the ChildNode objects
quickly, then discard their references.
- * </p>
- * <p>
- * There may be times when a client does wish to keep a representation of a ChildNode as
it appeared at some moment in time, and
- * so it may want to hold onto references to ChildNode objects for longer durations. This
is fine, as long as it is understood
- * that at some point the referenced ChildNode may no longer represent the current
state.
- * </p>
- */
-@Immutable
-public final class ChildNode {
-
- private final UUID uuid;
- private final Path.Segment segment;
-
- public ChildNode( UUID uuid,
- Path.Segment segment ) {
- assert uuid != null;
- assert segment != null;
- this.uuid = uuid;
- this.segment = segment;
- }
-
- /**
- * Get the UUID of the node.
- *
- * @return the node's UUID; never null
- */
- public UUID getUuid() {
- return uuid;
- }
-
- /**
- * Get the path segment for this node.
- *
- * @return the path segment; never null
- */
- public Path.Segment getSegment() {
- return segment;
- }
-
- /**
- * Get the name of the node.
- *
- * @return the node's current name; never null
- */
- public Name getName() {
- return segment.getName();
- }
-
- /**
- * Get the same-name-sibling index of the node.
- *
- * @return the node's SNS index; always positive
- */
- public int getSnsIndex() {
- return segment.getIndex();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode() {
- return uuid.hashCode();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals( Object obj ) {
- if (obj == this) return true;
- if (obj instanceof ChildNode) {
- return this.uuid.equals(((ChildNode)obj).uuid);
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- return uuid.toString() + " ( " + getSegment() + " )";
- }
-
- /**
- * Obtain a new instance that uses the same {@link #getUuid() UUID} but the supplied
path segment.
- *
- * @param newSegment the new segment; may not be null
- * @return the new instance; never null
- */
- public ChildNode with( Path.Segment newSegment ) {
- return new ChildNode(uuid, newSegment);
- }
-
-}
Deleted: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/Children.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/Children.java 2009-07-09 16:23:09
UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/Children.java 2009-07-09 16:26:04
UTC (rev 1082)
@@ -1,84 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you 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.
- *
- * JBoss DNA 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.jcr.cache;
-
-import java.util.Iterator;
-import java.util.UUID;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.Path;
-
-/**
- * Class that maintains the ordered list of {@link ChildNode} instances yet allows fast
access to the children with a specified
- * name.
- */
-public interface Children extends Iterable<ChildNode> {
-
- /**
- * Get the number of children.
- *
- * @return the number of children
- */
- int size();
-
- /**
- * The UUID of the parent node.
- *
- * @return the parent node's UUID
- */
- UUID getParentUuid();
-
- /**
- * Get the child with the given UUID.
- *
- * @param uuid the UUID of the child node
- * @return the child node, or null if there is no child with the supplied UUID
- */
- ChildNode getChild( UUID uuid );
-
- /**
- * Get the child given the path segment.
- *
- * @param segment the path segment for the child, which includes the {@link
Path.Segment#getName() name} and
- * {@link Path.Segment#getIndex() one-based same-name-sibling index}; may not
be null
- * @return the information for the child node, or null if no such child existed
- */
- ChildNode getChild( Path.Segment segment );
-
- /**
- * Get the same-name-sibling children that all share the supplied name, in order of
increasing SNS index.
- *
- * @param name the name for the children; may not be null
- * @return the children with the supplied name; never null
- */
- Iterator<ChildNode> getChildren( Name name );
-
- /**
- * Get the number of same-name-siblings that all share the supplied name.
- *
- * @param name the name for the children; may not be null
- * @return the number of same-name-siblings with the supplied name
- */
- int getCountOfSameNameSiblingsWithName( Name name );
-
-}
Deleted: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/EmptyChildren.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/EmptyChildren.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/EmptyChildren.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -1,144 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you 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.
- *
- * JBoss DNA 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.jcr.cache;
-
-import java.util.Iterator;
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.collection.EmptyIterator;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.PathFactory;
-import org.jboss.dna.graph.property.Path.Segment;
-
-/**
- * An immutable implementation of {@link Children}.
- */
-@Immutable
-public final class EmptyChildren implements Children, InternalChildren {
-
- static final Iterator<ChildNode> EMPTY_ITERATOR = new
EmptyIterator<ChildNode>();
-
- private final UUID parentUuid;
-
- public EmptyChildren( UUID parentUuid ) {
- this.parentUuid = parentUuid;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.Children#size()
- */
- public int size() {
- return 0;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Iterable#iterator()
- */
- public Iterator<ChildNode> iterator() {
- return EMPTY_ITERATOR;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.Children#getParentUuid()
- */
- public UUID getParentUuid() {
- return parentUuid;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.Children#getChild(java.util.UUID)
- */
- public ChildNode getChild( UUID uuid ) {
- return null;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.jcr.cache.Children#getChild(org.jboss.dna.graph.property.Path.Segment)
- */
- public ChildNode getChild( Segment segment ) {
- return null;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.jcr.cache.Children#getChildren(org.jboss.dna.graph.property.Name)
- */
- public Iterator<ChildNode> getChildren( Name name ) {
- return EMPTY_ITERATOR;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.jcr.cache.Children#getCountOfSameNameSiblingsWithName(org.jboss.dna.graph.property.Name)
- */
- public int getCountOfSameNameSiblingsWithName( Name name ) {
- return 0;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.jcr.cache.InternalChildren#with(org.jboss.dna.graph.property.Name,
java.util.UUID,
- * org.jboss.dna.graph.property.PathFactory)
- */
- public ChangedChildren with( Name newChildName,
- UUID newChildUuid,
- PathFactory pathFactory ) {
- ChangedChildren result = new ChangedChildren(this);
- result.add(newChildName, newChildUuid, pathFactory);
- return result;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.InternalChildren#without(java.util.UUID,
org.jboss.dna.graph.property.PathFactory)
- */
- public ChangedChildren without( UUID childUuid,
- PathFactory pathFactory ) {
- return new ChangedChildren(this.parentUuid);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- return "";
- }
-}
Deleted: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ImmutableChildren.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ImmutableChildren.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ImmutableChildren.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -1,251 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you 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.
- *
- * JBoss DNA 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.jcr.cache;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.collection.ReadOnlyIterator;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.Path;
-import org.jboss.dna.graph.property.PathFactory;
-import org.jboss.dna.graph.property.Path.Segment;
-import com.google.common.collect.LinkedListMultimap;
-import com.google.common.collect.ListMultimap;
-
-/**
- * An immutable implementation of {@link Children}.
- */
-@Immutable
-public class ImmutableChildren implements Children, InternalChildren {
- protected final UUID parentUuid;
- protected final Map<UUID, ChildNode> childrenByUuid;
- protected final ListMultimap<Name, ChildNode> childrenByName;
-
- public ImmutableChildren( UUID parentUuid,
- Iterable<Location> children ) {
- this(parentUuid);
- for (Location childLocation : children) {
- UUID childUuid = childLocation.getUuid();
- Path.Segment segment = childLocation.getPath().getLastSegment();
- Name name = segment.getName();
- ChildNode child = new ChildNode(childUuid, segment);
- this.childrenByName.put(name, child);
- this.childrenByUuid.put(childUuid, child);
- }
- }
-
- public ImmutableChildren( UUID parentUuid ) {
- this.parentUuid = parentUuid;
- this.childrenByUuid = new HashMap<UUID, ChildNode>();
- this.childrenByName = new LinkedListMultimap<Name, ChildNode>();
- }
-
- protected ImmutableChildren( Children original ) {
- this.parentUuid = original.getParentUuid();
- this.childrenByUuid = new HashMap<UUID, ChildNode>();
- this.childrenByName = new LinkedListMultimap<Name, ChildNode>();
- Iterator<ChildNode> iter = original.iterator();
- while (iter.hasNext()) {
- ChildNode child = iter.next();
- this.childrenByName.put(child.getName(), child);
- this.childrenByUuid.put(child.getUuid(), child);
- }
- }
-
- protected ImmutableChildren( ImmutableChildren original,
- Name additionalChildName,
- Path.Segment beforeChild,
- UUID childUuid,
- PathFactory pathFactory ) {
- assert beforeChild != null;
-
- this.parentUuid = original.getParentUuid();
- this.childrenByUuid = new HashMap<UUID, ChildNode>();
- this.childrenByName = new LinkedListMultimap<Name, ChildNode>();
-
- int snsIndex = 1;
- boolean found = false;
- ChildNode additionalChild = null;
- for (ChildNode child : original.childrenByName.values()) {
- this.childrenByUuid.put(child.getUuid(), child);
- if (beforeChild.equals(child.getSegment())) {
- Path.Segment segment = pathFactory.createSegment(additionalChildName,
snsIndex++);
- additionalChild = new ChildNode(childUuid, segment);
- childrenByName.put(child.getName(), additionalChild);
- found = true;
- }
-
- if (found &&(child.getName().equals(additionalChildName))) {
- Path.Segment newSegment =
pathFactory.createSegment(additionalChildName, snsIndex++);
- childrenByName.put(child.getName(), child.with(newSegment));
- }
- else {
- childrenByName.put(child.getName(), child);
- }
- }
-
- assert additionalChild != null;
- this.childrenByUuid.put(childUuid, additionalChild);
- }
-
- /**
- * Utility method that adds a child with the supplied name. This method is not
exposed publicly, ensuring that this class
- * remains publicly immutable. Subclasses that use this method (in places other than
constructors) will no longer be
- * {@link Immutable immutable}.
- *
- * @param additionalChildName
- * @param childUuid
- * @param pathFactory
- * @return the child node that was just added; never null
- */
- protected ChildNode add( Name additionalChildName,
- UUID childUuid,
- PathFactory pathFactory ) {
- ChildNode existing = this.childrenByUuid.get(childUuid);
- if (existing != null) return existing;
-
- List<ChildNode> childrenWithName =
this.childrenByName.get(additionalChildName);
- Path.Segment segment = pathFactory.createSegment(additionalChildName,
childrenWithName.size() + 1);
- ChildNode additionalChild = new ChildNode(childUuid, segment);
- this.childrenByName.put(additionalChildName, additionalChild);
- this.childrenByUuid.put(childUuid, additionalChild);
- return additionalChild;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.Children#size()
- */
- public int size() {
- return childrenByName.size();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Iterable#iterator()
- */
- public Iterator<ChildNode> iterator() {
- return new
ReadOnlyIterator<ChildNode>(this.childrenByName.values().iterator());
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.Children#getParentUuid()
- */
- public UUID getParentUuid() {
- return parentUuid;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.Children#getChild(java.util.UUID)
- */
- public ChildNode getChild( UUID uuid ) {
- return this.childrenByUuid.get(uuid);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.jcr.cache.Children#getChild(org.jboss.dna.graph.property.Path.Segment)
- */
- public ChildNode getChild( Segment segment ) {
- List<ChildNode> childrenWithName =
this.childrenByName.get(segment.getName());
- int snsIndex = segment.getIndex();
- if (childrenWithName.size() < snsIndex) return null;
- return childrenWithName.get(snsIndex - 1);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.jcr.cache.Children#getChildren(org.jboss.dna.graph.property.Name)
- */
- public Iterator<ChildNode> getChildren( Name name ) {
- return new
ReadOnlyIterator<ChildNode>(this.childrenByName.get(name).iterator());
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.jcr.cache.Children#getCountOfSameNameSiblingsWithName(org.jboss.dna.graph.property.Name)
- */
- public int getCountOfSameNameSiblingsWithName( Name name ) {
- return this.childrenByName.get(name).size();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.jcr.cache.InternalChildren#with(org.jboss.dna.graph.property.Name,
java.util.UUID,
- * org.jboss.dna.graph.property.PathFactory)
- */
- public ChangedChildren with( Name newChildName,
- UUID newChildUuid,
- PathFactory pathFactory ) {
- // Create a mutable version ...
- ChangedChildren newChildren = new ChangedChildren(this);
- return newChildren.with(newChildName, newChildUuid, pathFactory);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.InternalChildren#without(java.util.UUID,
org.jboss.dna.graph.property.PathFactory)
- */
- public ChangedChildren without( UUID childUuid,
- PathFactory pathFactory ) {
- if (this.childrenByUuid.containsKey(childUuid) && this.size() == 1) {
- return new ChangedChildren(this.parentUuid);
- }
- ChangedChildren newChildren = new ChangedChildren(this);
- return newChildren.without(childUuid, pathFactory);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- boolean first = true;
- for (ChildNode child : childrenByName.values()) {
- if (!first) sb.append(", ");
- else first = false;
-
sb.append(child.getName()).append('[').append(child.getSnsIndex()).append(']');
- }
- return sb.toString();
- }
-}
Deleted: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ImmutableNodeInfo.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ImmutableNodeInfo.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/ImmutableNodeInfo.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -1,207 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you 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.
- *
- * JBoss DNA 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.jcr.cache;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.jcr.NodeDefinitionId;
-
-/**
- * The information that describes a node. This is the information that is kept in the
cache.
- */
-@Immutable
-public class ImmutableNodeInfo implements NodeInfo {
- private final Location originalLocation;
- private final UUID uuid;
- private final UUID parent;
- private final Name primaryTypeName;
- private final NodeDefinitionId definition;
- private final Children children;
- private final Map<Name, PropertyInfo> properties;
- private final List<Name> mixinTypeNames;
-
- /**
- * Create an immutable NodeInfo instance.
- *
- * @param originalLocation the original location
- * @param primaryTypeName the name of the node's primary type
- * @param mixinTypeNames the names of the mixin types for this node, or null if there
are none
- * @param definition the definition used when creating the node
- * @param parent the parent
- * @param children the immutable children; may be null if there are no children
- * @param properties the unmodifiable map of properties; may be null if there are no
properties
- */
- public ImmutableNodeInfo( Location originalLocation,
- Name primaryTypeName,
- List<Name> mixinTypeNames,
- NodeDefinitionId definition,
- UUID parent,
- Children children,
- Map<Name, PropertyInfo> properties ) {
- this.originalLocation = originalLocation;
- this.primaryTypeName = primaryTypeName;
- this.definition = definition;
- this.parent = parent;
- this.uuid = this.originalLocation.getUuid();
- this.children = children != null ? children : new EmptyChildren(this.uuid);
- this.properties = properties != null ? properties : Collections.<Name,
PropertyInfo>emptyMap();
- this.mixinTypeNames = mixinTypeNames != null ? mixinTypeNames :
Collections.<Name>emptyList();
- assert this.uuid != null;
- assert this.definition != null;
- assert this.primaryTypeName != null;
- assert this.children != null;
- assert this.mixinTypeNames != null;
- assert this.properties != null;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#getOriginalLocation()
- */
- public Location getOriginalLocation() {
- return originalLocation;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#getUuid()
- */
- public UUID getUuid() {
- return uuid;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#getParent()
- */
- public UUID getParent() {
- return parent;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#getPrimaryTypeName()
- */
- public Name getPrimaryTypeName() {
- return primaryTypeName;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#getMixinTypeNames()
- */
- public List<Name> getMixinTypeNames() {
- return mixinTypeNames;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#getDefinitionId()
- */
- public NodeDefinitionId getDefinitionId() {
- return definition;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#getChildren()
- */
- public Children getChildren() {
- return children;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#hasProperties()
- */
- public boolean hasProperties() {
- return this.properties.size() != 0;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#getPropertyCount()
- */
- public int getPropertyCount() {
- return this.properties.size();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.cache.NodeInfo#getPropertyNames()
- */
- public Set<Name> getPropertyNames() {
- return this.properties.keySet();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.jcr.cache.NodeInfo#getProperty(org.jboss.dna.graph.property.Name)
- */
- public PropertyInfo getProperty( Name name ) {
- return this.properties.get(name);
- }
-
- /**
- * {@inheritDoc}
- *
- * @return {@code false} always as this object represents unmodified nodes only
- * @see org.jboss.dna.jcr.cache.NodeInfo#isNew()
- */
- public boolean isNew() {
- return false;
- }
-
- /**
- * {@inheritDoc}
- *
- * @return {@code false} always as this object represents unmodified nodes only
- * @see org.jboss.dna.jcr.cache.NodeInfo#isModified()
- */
- public boolean isModified() {
- return false;
- }
-
- @Override
- public String toString() {
- return this.uuid + " (" + primaryTypeName + ") {" +
properties + "}";
- }
-}
Deleted: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/InternalChildren.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/InternalChildren.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/InternalChildren.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -1,57 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you 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.
- *
- * JBoss DNA 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.jcr.cache;
-
-import java.util.UUID;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.PathFactory;
-
-/**
- * An internal interface for the {@link Children} implementations. Methods on this
interface are used internally and should not be
- * used by components or clients.
- */
-interface InternalChildren extends Children {
-
- /**
- * Create another Children object that is equivalent to this node but with the
supplied child added.
- *
- * @param newChildName the name of the new child; may not be null
- * @param newChildUuid the UUID of the new child; may not be null
- * @param pathFactory the factory that can be used to create Path and/or Path.Segment
instances.
- * @return the new Children object; never null
- */
- ChangedChildren with( Name newChildName,
- UUID newChildUuid,
- PathFactory pathFactory );
-
- /**
- * Create another Children object that is equivalent to this node but without the
supplied child.
- *
- * @param childUuid the UUID of the child to be removed; may not be null
- * @param pathFactory the factory that can be used to create Path and/or Path.Segment
instances.
- * @return the new Children object; never null
- */
- ChangedChildren without( UUID childUuid,
- PathFactory pathFactory );
-}
Deleted: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/NewNodeInfo.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/NewNodeInfo.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/NewNodeInfo.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -1,79 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you 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.
- *
- * JBoss DNA 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.jcr.cache;
-
-import java.util.Map;
-import java.util.UUID;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.jcr.NodeDefinitionId;
-
-/**
- *
- */
-public class NewNodeInfo extends ChangedNodeInfo {
- /**
- * Create an immutable NodeInfo instance.
- *
- * @param originalLocation the original location
- * @param primaryTypeName the name of the node's primary type
- * @param definition the definition used when creating the node
- * @param parent the parent
- * @param properties the unmodifiable map of properties; may be null if there are no
properties
- */
- public NewNodeInfo( Location originalLocation,
- Name primaryTypeName,
- NodeDefinitionId definition,
- UUID parent,
- Map<Name, PropertyInfo> properties ) {
- super(new ImmutableNodeInfo(originalLocation, primaryTypeName, null, definition,
parent, null, properties));
- }
-
- /**
- * {@inheritDoc}
- * <p>
- * Always returns true.
- * </p>
- *
- * @see org.jboss.dna.jcr.cache.ChangedNodeInfo#isNew()
- */
- @Override
- public boolean isNew() {
- return true;
- }
-
- /**
- * {@inheritDoc}
- * <p>
- * Always returns false, since a new node is not persisted yet.
- * </p>
- *
- * @see org.jboss.dna.jcr.cache.ChangedNodeInfo#isModified()
- */
- @Override
- public boolean isModified() {
- return false;
- }
-
-}
Deleted: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/NodeInfo.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/NodeInfo.java 2009-07-09 16:23:09
UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/NodeInfo.java 2009-07-09 16:26:04
UTC (rev 1082)
@@ -1,126 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you 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.
- *
- * JBoss DNA 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.jcr.cache;
-
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.jcr.NodeDefinitionId;
-
-/**
- * A representation of a node. This is the information that is kept in the cache.
- */
-public interface NodeInfo {
-
- /**
- * @return location
- */
- public Location getOriginalLocation();
-
- /**
- * @return uuid
- */
- public UUID getUuid();
-
- /**
- * @return parent
- */
- public UUID getParent();
-
- /**
- * @return primaryTypeName
- */
- public Name getPrimaryTypeName();
-
- /**
- * Get the names of the mixin types for this node.
- *
- * @return the unmodifiable list of mixin type names; never null but possibly empty
- */
- public List<Name> getMixinTypeNames();
-
- /**
- * @return definition
- */
- public NodeDefinitionId getDefinitionId();
-
- /**
- * Get the children for this node. Generally, clients should not hold onto the
returned object but instead should simply use
- * it and discard the reference. This is because implementations are not required to
return the same instance with each call
- * (although immutable implementations are expected to always return the same
instance).
- *
- * @return the immutable children; never null but possibly empty
- */
- public Children getChildren();
-
- /**
- * Return true of this node has at least one property.
- *
- * @return true if there is at least one property, or false if there are none
- */
- public boolean hasProperties();
-
- /**
- * Return the number of properties on this node.
- *
- * @return the number of properties; never negative
- */
- public int getPropertyCount();
-
- /**
- * Get the names of the properties that are owned by this node.
- *
- * @return the unmodifiable set of property names
- */
- public Set<Name> getPropertyNames();
-
- /**
- * Get this node's property that has the supplied name.
- *
- * @param name the property name; may not be null
- * @return the property information, or null if this node has no property with the
supplied name
- */
- public PropertyInfo getProperty( Name name );
-
- /**
- * Indicates whether the node represented by this {@link NodeInfo} is new (i.e., does
not yet exist in the persistent
- * repository).
- *
- * @return {@code true} if the node represented by this {@link NodeInfo} has not yet
been saved to the persistent repository.
- * @see javax.jcr.Item#isNew()
- */
- public boolean isNew();
-
- /**
- * Indicates whether the node represented by this {@link NodeInfo} is modified (i.e.,
exists in the persistent repository with
- * different child items).
- *
- * @return {@code true} if the immediate child items of the node represented by this
{@link NodeInfo} have been modified since
- * the last time the node was saved to the persistent repository
- * @see javax.jcr.Item#isModified()
- */
- public boolean isModified();
-}
Deleted: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/PropertyInfo.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/PropertyInfo.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/cache/PropertyInfo.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -1,198 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you 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.
- *
- * JBoss DNA 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.jcr.cache;
-
-import java.util.UUID;
-import javax.jcr.PropertyType;
-import net.jcip.annotations.Immutable;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.Property;
-import org.jboss.dna.jcr.PropertyDefinitionId;
-import org.jboss.dna.jcr.PropertyId;
-
-/**
- * An immutable representation of the name and current value(s) for a property, along
with the JCR metadata for the property,
- * including the {@link PropertyInfo#getDefinitionId() property definition} and {@link
PropertyInfo#getPropertyType() property
- * type}.
- * <p>
- * This class is immutable, which means that clients should never hold onto an instance.
Instead, clients can obtain an instance
- * by using a {@link PropertyId}, quickly use the information in the instance, and then
immediately discard their reference. This
- * is because these instances are replaced and discarded whenever anything about the
property changes.
- * </p>
- */
-@Immutable
-public class PropertyInfo {
- private final PropertyId propertyId;
- private final PropertyDefinitionId definitionId;
- private final Property dnaProperty;
- private final int propertyType;
- private final boolean multiValued;
- private final boolean isNew;
- private final boolean isModified;
-
- public PropertyInfo( PropertyId propertyId,
- PropertyDefinitionId definitionId,
- int propertyType,
- Property dnaProperty,
- boolean multiValued,
- boolean isNew,
- boolean isModified ) {
- this.propertyId = propertyId;
- this.definitionId = definitionId;
- this.propertyType = propertyType;
- this.dnaProperty = dnaProperty;
- this.multiValued = multiValued;
- this.isNew = isNew;
- this.isModified = isModified;
-
- assert isNew ? !isModified : true;
- assert isModified ? !isNew : true;
- }
-
- /**
- * Get the durable identifier for this property.
- *
- * @return propertyId
- */
- public PropertyId getPropertyId() {
- return propertyId;
- }
-
- /**
- * Get the UUID of the node to which this property belongs.
- *
- * @return the owner node's UUID; never null
- */
- public UUID getNodeUuid() {
- return propertyId.getNodeId();
- }
-
- /**
- * The identifier for the property definition.
- *
- * @return the property definition ID; never null
- */
- public PropertyDefinitionId getDefinitionId() {
- return definitionId;
- }
-
- /**
- * Get the DNA Property, which contains the name and value(s)
- *
- * @return the property; never null
- */
- public Property getProperty() {
- return dnaProperty;
- }
-
- /**
- * Get the property name.
- *
- * @return the property name; never null
- */
- public Name getPropertyName() {
- return dnaProperty.getName();
- }
-
- /**
- * Get the JCR {@link PropertyType} for this property.
- *
- * @return the property type
- */
- public int getPropertyType() {
- return propertyType;
- }
-
- /**
- * @return multiValued
- */
- public boolean isMultiValued() {
- return multiValued;
- }
-
- /**
- * Indicates whether this property/value combination is new (i.e., does not yet exist
in the persistent repository).
- *
- * @return {@code true} if the property has not yet been saved to the persistent
repository.
- * @see javax.jcr.Item#isNew()
- */
- public boolean isNew() {
- return this.isNew;
- }
-
- /**
- * Indicates whether this property/value combination is modified (i.e., exists in the
persistent repository with a different
- * value or values).
- *
- * @return {@code true} if the property has been modified since the last time it was
saved to the persistent repository
- * @see javax.jcr.Item#isModified()
- */
- public boolean isModified() {
- return this.isModified;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode() {
- return propertyId.hashCode();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals( Object obj ) {
- if (obj == this) return true;
- if (obj instanceof PropertyInfo) {
- return propertyId.equals(((PropertyInfo)obj).getPropertyId());
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append(propertyId);
- sb.append(" defined by ").append(definitionId);
- sb.append(" of type
").append(PropertyType.nameFromValue(propertyType));
- if (dnaProperty.isSingle()) {
- sb.append(" with value ");
- } else {
- sb.append(" with values ");
- }
- sb.append(dnaProperty.getValuesAsArray());
- return sb.toString();
- }
-}
Modified: trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties
===================================================================
--- trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties 2009-07-09
16:26:04 UTC (rev 1082)
@@ -69,15 +69,16 @@
childNotFoundUnderNode = The child "{0}" could not be found under
"{1}" in workspace "{2}"
errorWhileFindingNodeWithUuid = Error while finding the node with UUID "{0}" in
workspace "{1}": {2}
errorWhileFindingNodeWithPath = Error while finding the node "{0}" in workspace
"{1}"
-nodeDefinitionCouldNotBeDeterminedForNode = Unable to determine a valid node definition
for the node "{0}" in workspace "{1}"
+nodeDefinitionCouldNotBeDeterminedForNode = Unable to determine a valid node definition
for the node "{0}" in workspace "{1}" of "{2}"
noSnsDefinitionForNode = A node definition that allows same name siblings could not be
found for the node "{0}" in workspace "{1}"
-missingNodeTypeForExistingNode = Missing primary node type "{0}" for node {1}
in workspace "{2}"
+missingNodeTypeForExistingNode = Missing primary node type "{0}" for node {1}
in workspace "{2}" of "{3}"
unableToCreateNodeWithPrimaryTypeThatDoesNotExist = Unable to create child
"{1}" in workspace "{2}" because the node type "{0}" does
not exist
unableToCreateNodeWithNoDefaultPrimaryTypeOnChildNodeDefinition = Unable to create child
"{2}" in workspace "{3}" because the node definition "{0}"
on the "{1}" node type has no default primary type
unableToSaveNodeThatWasCreatedSincePreviousSave = Unable to save node "{0}" in
workspace "{1}" because it was created since the last save
unableToSetMultiValuedPropertyUsingSingleValue = Unable to set existing multi-valued
property "{0}" on node "{1}" in workspace "{2}" using
single-value setter methods
unableToSetSingleValuedPropertyUsingMultipleValues = Unable to set existing single-valued
property "{0}" on node "{1}" in workspace "{2}" using
multi-value setter methods
-unableToRefreshBranchSinceAtLeastOneNodeMovedToParentOutsideOfBranch = Unable to refresh
"{0}" in workspace "{2}" because at least one of its decendants was
moved to another node outside of the branch that is not being refreshed
+unableToRefreshBranchBecauseChangesDependOnChangesToNodesOutsideOfBranch = Unable to
refresh "{0}" in workspace "{1}" because it contains changes that
depend on changes to nodes outside of this branch
+unableToSaveBranchBecauseChangesDependOnChangesToNodesOutsideOfBranch = Unable to save
"{0}" in workspace "{1}" because it contains changes that depend on
changes to nodes outside of this branch
allPropertyValuesMustHaveSameType = All values of property "{0}" on node
"{3}" in workspace "{4}" must all be {2} values (values were: {1})
cannotRemoveNodeFromClone = The node at "{0}" with UUID "{1}" exists
in the current workspace but cannot be removed because it is a mandatory child node
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -4,13 +4,13 @@
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
* See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
+ * individual contributors.
*
* JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
* is licensed to you 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.
- *
+ *
* JBoss DNA 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
@@ -24,694 +24,654 @@
package org.jboss.dna.jcr;
import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.stub;
-import java.util.UUID;
import javax.jcr.Item;
import javax.jcr.ItemNotFoundException;
import javax.jcr.ItemVisitor;
-import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
-import javax.jcr.Property;
-import javax.jcr.PropertyType;
import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
import javax.jcr.UnsupportedRepositoryOperationException;
-import javax.jcr.Value;
import javax.jcr.Workspace;
+import javax.jcr.nodetype.NodeType;
import javax.jcr.version.Version;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.Path;
-import org.jboss.dna.jcr.cache.ChangedChildren;
-import org.jboss.dna.jcr.cache.Children;
-import org.jboss.dna.jcr.cache.EmptyChildren;
-import org.jboss.dna.jcr.cache.NodeInfo;
-import org.jboss.dna.jcr.cache.PropertyInfo;
+import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoAnnotations.Mock;
/**
- * @author jverhaeg
+ *
*/
-public class AbstractJcrNodeTest {
+public class AbstractJcrNodeTest extends AbstractJcrTest {
- static class MockAbstractJcrNode extends AbstractJcrNode {
+ private AbstractJcrNode rootNode;
+ private AbstractJcrNode cars;
+ private AbstractJcrNode hybrid;
+ private AbstractJcrNode prius;
+ private AbstractJcrNode highlander;
+ private AbstractJcrNode altima;
- MockAbstractJcrNode( SessionCache cache,
- UUID uuid ) {
- super(cache, uuid);
- }
-
- @Override
- boolean isRoot() {
- return false;
- }
-
- @Override
- public int getDepth() {
- return 0;
- }
-
- public int getIndex() {
- return 0;
- }
-
- public String getName() throws RepositoryException {
- return
cache.getPathFor(nodeInfo()).getLastSegment().getString(namespaces());
- }
-
- @Override
- public AbstractJcrNode getParent() throws RepositoryException {
- return cache.findJcrNode(nodeInfo().getParent());
- }
-
- public String getPath() throws RepositoryException {
- return cache.getPathFor(nodeInfo()).getString(namespaces());
- }
-
- public void remove() {
- throw new UnsupportedOperationException();
- }
+ @Override
+ @Before
+ public void beforeEach() throws Exception {
+ super.beforeEach();
+ rootNode = cache.findJcrRootNode();
+ cars = cache.findJcrNode(null, path("/Cars"));
+ hybrid = cache.findJcrNode(null, path("/Cars/Hybrid"));
+ prius = cache.findJcrNode(null, path("/Cars/Hybrid/Toyota Prius"));
+ highlander = cache.findJcrNode(null, path("/Cars/Hybrid/Toyota
Highlander"));
+ altima = cache.findJcrNode(null, path("/Cars/Hybrid/Nissan Altima"));
}
- private ExecutionContext context;
- private UUID uuid;
- private AbstractJcrNode node;
- private Children children;
- @Mock
- private SessionCache cache;
- @Mock
- private JcrSession session;
- @Mock
- private JcrNodeTypeManager nodeTypes;
- @Mock
- private NodeInfo info;
+ /*
+ * Visitors
+ */
- @Before
- public void before() throws Exception {
- MockitoAnnotations.initMocks(this);
- context = new ExecutionContext();
- context.getNamespaceRegistry().register("acme",
"http://www.example.com");
- uuid = UUID.randomUUID();
- stub(cache.session()).toReturn(session);
- stub(cache.context()).toReturn(context);
- stub(cache.workspaceName()).toReturn("my workspace");
- stub(cache.findNodeInfo(uuid)).toReturn(info);
- stub(cache.getPathFor(info)).toReturn(path("/a/b/c/d"));
- stub(session.nodeTypeManager()).toReturn(nodeTypes);
- node = new MockAbstractJcrNode(cache, uuid);
-
- // Create the children container for the node ...
- children = new EmptyChildren(uuid);
- stub(info.getChildren()).toReturn(children);
+ @Test
+ public void shouldAllowVisitation() throws Exception {
+ ItemVisitor visitor = Mockito.mock(ItemVisitor.class);
+ hybrid.accept(visitor);
+ Mockito.verify(visitor).visit(hybrid);
}
- protected Name name( String name ) {
- return context.getValueFactories().getNameFactory().create(name);
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowVisitationIfNoVisitor() throws Exception {
+ hybrid.accept(null);
}
- protected Path relativePath( String relativePath ) {
- return context.getValueFactories().getPathFactory().create(relativePath);
- }
+ /*
+ * Ancestors
+ */
- protected Path path( String absolutePath ) {
- return context.getValueFactories().getPathFactory().create(absolutePath);
+ @Test( expected = ItemNotFoundException.class )
+ public void shouldNotAllowNegativeAncestorDepth() throws Exception {
+ hybrid.getAncestor(-1);
}
- protected Value stringValueFor( Object value ) {
- return new JcrValue(context.getValueFactories(), cache, PropertyType.STRING,
value);
+ @Test
+ public void shouldReturnRootForAncestorOfDepthZero() throws Exception {
+ assertThat(hybrid.getAncestor(0), is((Item)rootNode));
}
- protected void addChild( Name childName,
- UUID childUuid ) {
- if (children instanceof EmptyChildren) {
- children = ((EmptyChildren)children).with(childName, childUuid,
context.getValueFactories().getPathFactory());
- } else if (children instanceof ChangedChildren) {
- children = ((ChangedChildren)children).with(childName, childUuid,
context.getValueFactories().getPathFactory());
- }
- stub(info.getChildren()).toReturn(children);
+ @Test
+ public void shouldReturnAncestorAtLevelOneForAncestorOfDepthOne() throws Exception {
+ assertThat(hybrid.getAncestor(1), is((Item)cars));
}
@Test
- public void shouldAllowVisitation() throws Exception {
- ItemVisitor visitor = Mockito.mock(ItemVisitor.class);
- node.accept(visitor);
- Mockito.verify(visitor).visit(node);
+ public void shouldReturnSelfForAncestorOfDepthEqualToDepthOfNode() throws Exception
{
+ assertThat(hybrid.getAncestor(hybrid.getDepth()), is((Item)hybrid));
}
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowVisitationIfNoVisitor() throws Exception {
- node.accept(null);
- }
-
@Test( expected = ItemNotFoundException.class )
- public void shouldNotAllowNegativeAncestorDepth() throws Exception {
- node.getAncestor(-1);
+ public void shouldFailToReturnAncestorWhenDepthIsGreaterThanNodeDepth() throws
Exception {
+ hybrid.getAncestor(hybrid.getDepth() + 1);
}
@Test
- public void shouldProvideAncestor() throws Exception {
- assertThat(node.getAncestor(0), is((Item)node));
+ public void shouldIndicateIsNode() {
+ assertThat(prius.isNode(), is(true));
}
+ /*
+ * Property-related methods
+ */
+
@Test
public void shouldReturnPropertyFromGetPropertyWithValidName() throws Exception {
- PropertyId propertyId = new PropertyId(uuid, name("test"));
- AbstractJcrProperty property = mock(AbstractJcrProperty.class);
- stub(cache.findJcrProperty(propertyId)).toReturn(property);
- assertThat(node.getProperty("test"), is((Property)property));
+ javax.jcr.Property property = prius.getProperty("vehix:model");
+ assertThat(property, is(notNullValue()));
+ assertThat(property.getName(), is("vehix:model"));
+ assertThat(property.getString(), is("Prius"));
}
@Test
public void shouldReturnPropertyFromGetPropertyWithValidRelativePath() throws
Exception {
- PropertyId propertyId = new PropertyId(uuid, name("test"));
- AbstractJcrProperty property = mock(AbstractJcrProperty.class);
- stub(cache.findJcrProperty(propertyId)).toReturn(property);
- assertThat(node.getProperty("test"), is((Property)property));
+ javax.jcr.Property property = prius.getProperty("./vehix:model");
+ assertThat(property, is(notNullValue()));
+ assertThat(property.getName(), is("vehix:model"));
+ assertThat(property.getString(), is("Prius"));
}
@Test( expected = PathNotFoundException.class )
public void
shouldFailToReturnPropertyFromGetPropertyWithNameOfPropertyThatDoesNotExist() throws
Exception {
- node.getProperty("nonExistantProperty");
+ prius.getProperty("nonExistantProperty");
}
@Test( expected = IllegalArgumentException.class )
public void shouldFailToReturnPropertyFromGetPropertyWithAbsolutePath() throws
Exception {
- node.getProperty("/test");
+ prius.getProperty("/test");
}
@Test( expected = PathNotFoundException.class )
public void
shouldFailToReturnPropertyFromGetPropertyWithRelativePathToNonExistantItem() throws
Exception {
- node.getProperty("../bogus/path");
+ prius.getProperty("../bogus/path");
}
@Test
public void
shouldReturnPropertyFromGetPropertyWithRelativePathToPropertyOnOtherNode() throws
Exception {
- AbstractJcrProperty property = mock(AbstractJcrProperty.class);
- stub(cache.findJcrItem(uuid,
relativePath("../good/path"))).toReturn(property);
- assertThat(node.getProperty("../good/path"), is((Property)property));
+ javax.jcr.Property property = prius.getProperty("../Nissan
Altima/vehix:model");
+ assertThat(property, is(notNullValue()));
+ assertThat(property.getName(), is("vehix:model"));
+ assertThat(property.getString(), is("Altima"));
}
@Test( expected = PathNotFoundException.class )
public void shouldReturnPropertyFromGetPropertyWithRelativePathToOtherNode() throws
Exception {
- AbstractJcrNode otherNode = mock(AbstractJcrNode.class);
- stub(cache.findJcrItem(uuid,
relativePath("../good/path"))).toReturn(otherNode);
- node.getProperty("../good/path");
+ prius.getProperty("../Nissan Altima");
}
- /*
- * More comprehensive tests of addMixin, removeMixin, and canAddMixin require
additional setup
- * and are in MixinTest
- */
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowGetPropertyWithNullPath() throws Exception {
+ prius.getProperty((String)null);
+ }
- @Test( expected = UnsupportedOperationException.class )
- public void shoudNotAllowCancelMerge() throws Exception {
- node.cancelMerge(null);
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowGetPropertyWithEmptyPath() throws Exception {
+ prius.getProperty("");
}
- @Test( expected = UnsupportedRepositoryOperationException.class )
- public void shoudNotAllowCheckin() throws Exception {
- node.checkin();
+ @Test
+ public void shouldReturnTrueFromHasPropertyWithValidName() throws Exception {
+ assertThat(prius.hasProperty("vehix:model"), is(true));
}
- @Test( expected = UnsupportedRepositoryOperationException.class )
- public void shoudNotAllowCheckout() throws Exception {
- node.checkout();
+ @Test
+ public void shouldReturnTrueFromHasPropertyWithValidRelativePath() throws Exception
{
+ assertThat(prius.hasProperty("./vehix:model"), is(true));
}
- @Test( expected = UnsupportedOperationException.class )
- public void shoudNotAllowDoneMerge() throws Exception {
- node.doneMerge(null);
+ @Test
+ public void shouldReturnFalseFromHasPropertyWithNameOfPropertyThatDoesNotExist()
throws Exception {
+ assertThat(prius.hasProperty("non-existant"), is(false));
}
- @Test( expected = UnsupportedRepositoryOperationException.class )
- public void shoudNotAllowGetBaseVersion() throws Exception {
- node.getBaseVersion();
+ @Test
+ public void shouldReturnFalseFromHasPropertyWithRelativePathToNonExistantItem()
throws Exception {
+ assertThat(prius.hasProperty("../Nissan Altima/non-existant"),
is(false));
}
- @Test( expected = UnsupportedRepositoryOperationException.class )
- public void shoudNotAllowGetLock() throws Exception {
- node.getLock();
+ @Test
+ public void shouldReturnTrueFromHasPropertyWithRelativePathToPropertyOnOtherNode()
throws Exception {
+ assertThat(prius.hasProperty("../Nissan Altima/vehix:model"),
is(true));
}
+ @Test
+ public void shouldReturnFalseFromHasPropertyWithRelativePathToOtherNode() throws
Exception {
+ assertThat(prius.hasProperty("../Nissan Altima"), is(false));
+ }
+
@Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowGetPropertyWithNullPath() throws Exception {
- node.getProperty((String)null);
+ public void shouldNotAllowHasPropertyWithAbsolutePath() throws Exception {
+ prius.hasProperty("/Cars/Hybrid/Toyota Prius/vehix:model");
}
@Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowGetPropertyWithEmptyPath() throws Exception {
- node.getProperty("");
+ public void shouldNotAllowHasPropertyWithNullPath() throws Exception {
+ prius.hasProperty((String)null);
}
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowHasPropertyWithEmptyPath() throws Exception {
+ prius.hasProperty("");
+ }
+
@Test
+ public void shouldReturnFalseFromHasPropertyIfPathIsParentPath() throws Exception {
+ assertThat(prius.hasProperty(".."), is(false));
+ }
+
+ @Test
+ public void shouldReturnFalseFromHasPropertyIfPathIsSelfPath() throws Exception {
+ assertThat(prius.hasProperty("."), is(false));
+ }
+
+ @Test
+ public void shouldReturnTrueFromHasPropertiesIfNodeHasAtLeastOneProperty() throws
Exception {
+ assertThat(prius.hasProperties(), is(true));
+ }
+
+ @Test
+ public void shouldReturnFalseFromHasPropertiesIfNodeHasNoProperties() throws
Exception {
+ // can't really test this, since all nodes have at least one property ...
+ // assertThat(child.hasProperties(), is(false));
+ }
+
+ /*
+ * getNode() and related methods
+ */
+
+ @Test
public void shouldReturnChildNodeFromGetNodeWithValidName() throws Exception {
- AbstractJcrNode child = mock(AbstractJcrNode.class);
- UUID childUuid = UUID.randomUUID();
- addChild(name("child"), childUuid);
- stub(cache.findJcrNode(childUuid)).toReturn(child);
- assertThat(node.getNode("child"), is((Node)child));
+ assertThat(hybrid.getNode("Toyota Prius"), is((javax.jcr.Node)prius));
+ assertThat(hybrid.getNode("Toyota Prius"),
is(sameInstance((javax.jcr.Node)prius)));
}
@Test
public void shouldReturnNonChildNodeFromGetNodeWithValidRelativePath() throws
Exception {
- AbstractJcrNode otherNode = mock(AbstractJcrNode.class);
- stub(cache.findJcrItem(uuid,
path("../other/node"))).toReturn(otherNode);
- assertThat(node.getNode("../other/node"), is((Node)otherNode));
+ assertThat(altima.getNode("../Toyota Prius"),
is((javax.jcr.Node)prius));
+ assertThat(altima.getNode("../Toyota Prius"),
is(sameInstance((javax.jcr.Node)prius)));
}
@Test( expected = PathNotFoundException.class )
public void shouldFailToReturnNodeFromGetNodeWithValidRelativePathToProperty() throws
Exception {
- AbstractJcrProperty property = mock(AbstractJcrProperty.class);
- stub(cache.findJcrItem(uuid,
path("../other/node"))).toReturn(property);
- node.getNode("../other/node");
+ altima.getNode("../Toyota Prius/vehix:model");
}
@Test( expected = PathNotFoundException.class )
public void
shouldFailToReturnNodeFromGetNodeWithValidRelativePathToNoNodeOrProperty() throws
Exception {
- node.getNode("../other/node");
+ altima.getNode("../../nonExistant");
}
@Test
public void shouldReturnSelfFromGetNodeWithRelativePathContainingOnlySelfReference()
throws Exception {
- assertThat(node.getNode("."), is((Node)node));
+ assertThat(hybrid.getNode("."), is((javax.jcr.Node)hybrid));
+ assertThat(hybrid.getNode("."),
is(sameInstance((javax.jcr.Node)hybrid)));
}
@Test
+ public void shouldReturnSelfFromGetNodeWithRelativePathResolvingToSelf() throws
Exception {
+ assertThat(hybrid.getNode("Toyota Prius/.."),
is((javax.jcr.Node)hybrid));
+ assertThat(hybrid.getNode("Toyota Prius/.."),
is(sameInstance((javax.jcr.Node)hybrid)));
+ }
+
+ @Test
public void
shouldReturnParentFromGetNodeWithRelativePathContainingOnlyParentReference() throws
Exception {
- AbstractJcrNode parent = mock(AbstractJcrNode.class);
- UUID parentUuid = UUID.randomUUID();
- stub(info.getParent()).toReturn(parentUuid);
- stub(cache.findJcrNode(parentUuid)).toReturn(parent);
- assertThat(node.getNode(".."), is((Node)parent));
+ assertThat(prius.getNode("../.."), is((javax.jcr.Node)cars));
+ assertThat(prius.getNode("../.."),
is(sameInstance((javax.jcr.Node)cars)));
}
@Test( expected = PathNotFoundException.class )
public void shouldFailToReturnChildNodeFromGetNodeWithNameOfChildThatDoesNotExist()
throws Exception {
- node.getNode("something");
+ altima.getNode("nonExistant");
}
@Test( expected = IllegalArgumentException.class )
public void shouldNotAllowGetNodeWithNoPath() throws Exception {
- node.getNode(null);
+ prius.getNode(null);
}
@Test
public void shouldProvideNodeIterator() throws Exception {
- AbstractJcrNode child = mock(AbstractJcrNode.class);
- UUID childUuid = UUID.randomUUID();
- addChild(name("child"), childUuid);
- stub(cache.findJcrNode(childUuid)).toReturn(child);
- NodeIterator iter = node.getNodes();
+ NodeIterator iter = hybrid.getNodes();
assertThat(iter, notNullValue());
- assertThat(iter.getSize(), is(1L));
- assertThat(iter.next(), is((Object)child));
+ assertThat(iter.getSize(), is(3L));
+ assertThat(iter.next(), is((Object)prius));
+ assertThat(iter.next(), is((Object)highlander));
+ assertThat(iter.next(), is((Object)altima));
+ assertThat(iter.hasNext(), is(false));
}
@Test
- public void shoudReturnItemFromGetPrimaryItemIfItExists() throws Exception {
- // Define the node type ...
- Name primaryTypeName = name("thePrimaryType");
- JcrNodeType primaryType = mock(JcrNodeType.class);
- stub(nodeTypes.getNodeType(primaryTypeName)).toReturn(primaryType);
- stub(primaryType.getPrimaryItemName()).toReturn("thePrimaryItemName");
- // Define the node info to use this primary type ...
- stub(info.getPrimaryTypeName()).toReturn(primaryTypeName);
- // Now make an item with the appropriate name ...
- AbstractJcrNode child = mock(AbstractJcrNode.class);
- stub(cache.findJcrItem(uuid,
path("thePrimaryItemName"))).toReturn(child);
- // Now call the method ...
- assertThat(node.getPrimaryItem(), is((Item)child));
+ public void shouldReturnTrueFromHasNodeWithValidName() throws Exception {
+ assertThat(hybrid.hasNode("Toyota Prius"), is(true));
}
- @Test( expected = ItemNotFoundException.class )
- public void
shoudFailToReturnItemFromGetPrimaryItemIfPrimaryTypeDoesNotHavePrimaryItemName() throws
Exception {
- // Define the node type ...
- Name primaryTypeName = name("thePrimaryType");
- JcrNodeType primaryType = mock(JcrNodeType.class);
- stub(nodeTypes.getNodeType(primaryTypeName)).toReturn(primaryType);
- stub(primaryType.getPrimaryItemName()).toReturn(null);
- // Define the node info to use this primary type ...
- stub(info.getPrimaryTypeName()).toReturn(primaryTypeName);
- // Now call the method ...
- node.getPrimaryItem();
+ @Test
+ public void shouldReturnTrueFromHasNodeWithValidRelativePath() throws Exception {
+ assertThat(altima.hasNode("../Toyota Prius"), is(true));
}
- @Test( expected = ItemNotFoundException.class )
- public void
shoudFailToReturnItemFromGetPrimaryItemIfThePrimaryTypeAsInvalidPrimaryItemName() throws
Exception {
- // Define the node type ...
- Name primaryTypeName = name("thePrimaryType");
- JcrNodeType primaryType = mock(JcrNodeType.class);
- stub(nodeTypes.getNodeType(primaryTypeName)).toReturn(primaryType);
- stub(primaryType.getPrimaryItemName()).toReturn("/this/is/not/valid");
- // Define the node info to use this primary type ...
- stub(info.getPrimaryTypeName()).toReturn(primaryTypeName);
- // Now call the method ...
- node.getPrimaryItem();
+ @Test
+ public void shouldReturnFalseFromHasNodeWithValidRelativePathToProperty() throws
Exception {
+ assertThat(altima.hasNode("../Toyota Prius/vehix:model"), is(false));
}
- @Test( expected = ItemNotFoundException.class )
- public void
shoudFailToReturnItemFromGetPrimaryItemIfTheNodeHasNoItemMatchingThatSpecifiedByThePrimaryType()
throws Exception {
- // Define the node type ...
- Name primaryTypeName = name("thePrimaryType");
- JcrNodeType primaryType = mock(JcrNodeType.class);
- stub(nodeTypes.getNodeType(primaryTypeName)).toReturn(primaryType);
- stub(primaryType.getPrimaryItemName()).toReturn("thePrimaryItemName");
- // Define the node info to use this primary type ...
- stub(info.getPrimaryTypeName()).toReturn(primaryTypeName);
- // Now call the method ...
- stub(cache.findJcrItem(uuid, path("thePrimaryItemName"))).toThrow(new
ItemNotFoundException());
- node.getPrimaryItem();
+ @Test
+ public void shouldReturnFalseFromHasNodeWithWithValidRelativePathToNoNodeOrProperty()
throws Exception {
+ assertThat(altima.hasNode("../../nonExistant"), is(false));
+ assertThat(altima.hasNode("../nonExistant"), is(false));
+ assertThat(altima.hasNode("nonExistant"), is(false));
}
- // @Test
- // public void shouldReturnEmptyIteratorFromGetReferencesWhenThereAreNoProperties()
throws Exception {
- // // Set up two properties (one containing references, the other not) ...
- // List<AbstractJcrProperty> props = Arrays.asList(new AbstractJcrProperty[]
{});
- // stub(cache.findJcrPropertiesFor(uuid)).toReturn(props);
- // // Now call the method ...
- // PropertyIterator iter = node.getReferences();
- // assertThat(iter.getSize(), is(0L));
- // assertThat(iter.hasNext(), is(false));
- // }
- //
- // @Test
- // public void
shouldReturnEmptyIteratorFromGetReferencesWhenThereAreNoReferenceProperties() throws
Exception {
- // // Set up two properties (one containing references, the other not) ...
- // AbstractJcrProperty propertyA = mock(AbstractJcrProperty.class);
- // AbstractJcrProperty propertyB = mock(AbstractJcrProperty.class);
- // List<AbstractJcrProperty> props = Arrays.asList(new AbstractJcrProperty[]
{propertyA, propertyB});
- // stub(cache.findJcrPropertiesFor(uuid)).toReturn(props);
- // stub(propertyA.getType()).toReturn(PropertyType.LONG);
- // stub(propertyB.getType()).toReturn(PropertyType.BOOLEAN);
- // // Now call the method ...
- // PropertyIterator iter = node.getReferences();
- // assertThat(iter.getSize(), is(0L));
- // assertThat(iter.hasNext(), is(false));
- // }
- //
- // @Test
- // public void
shouldReturnIteratorFromGetReferencesWhenThereIsAtLeastOneReferenceProperty() throws
Exception {
- // // Set up two properties (one containing references, the other not) ...
- // AbstractJcrProperty propertyA = mock(AbstractJcrProperty.class);
- // AbstractJcrProperty propertyB = mock(AbstractJcrProperty.class);
- // List<AbstractJcrProperty> props = Arrays.asList(new AbstractJcrProperty[]
{propertyA, propertyB});
- // stub(cache.findJcrPropertiesFor(uuid)).toReturn(props);
- // stub(propertyA.getType()).toReturn(PropertyType.LONG);
- // stub(propertyB.getType()).toReturn(PropertyType.REFERENCE);
- // // Now call the method ...
- // PropertyIterator iter = node.getReferences();
- // assertThat(iter.getSize(), is(1L));
- // assertThat(iter.next(), is(sameInstance((Object)propertyB)));
- // assertThat(iter.hasNext(), is(false));
- // }
+ @Test
+ public void shouldReturnTrueFromHasNodeWithRelativePathContainingOnlySelfReference()
throws Exception {
+ assertThat(hybrid.hasNode("."), is(true));
+ }
@Test
- public void shouldProvideSession() throws Exception {
- assertThat((JcrSession)node.getSession(), is(session));
+ public void shouldReturnTrueFromHasNodeWithRelativePathResolvingToSelf() throws
Exception {
+ assertThat(hybrid.hasNode("Toyota Prius/.."), is(true));
}
- @Test( expected = UnsupportedRepositoryOperationException.class )
- public void shouldNotAllowGetVersionHistory() throws Exception {
- node.getVersionHistory();
+ @Test
+ public void
shouldReturnTrueFromHasNodeWithRelativePathContainingOnlyParentReference() throws
Exception {
+ assertThat(prius.hasNode("../.."), is(true));
}
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowNullPathInHasNode() throws Exception {
- node.hasNode((String)null);
+ @Test
+ public void shouldReturnFalseFromHasNodeWithNameOfChildThatDoesNotExist() throws
Exception {
+ assertThat(altima.hasNode("nonExistant"), is(false));
}
@Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowEmptyPathInHasNode() throws Exception {
- node.hasNode("");
+ public void shouldNotAllowHasNodeWithNoPath() throws Exception {
+ prius.hasNode(null);
}
@Test( expected = IllegalArgumentException.class )
public void shouldNotAbsolutePathInHasNode() throws Exception {
- node.hasNode("/a/b/c");
+ cars.hasNode("/a/b/c");
}
@Test
- public void shouldReturnTrueFromHasNodeWithSelfReference() throws Exception {
- assertThat(node.hasNode("."), is(true));
+ public void shouldReturnTrueFromHasNodesIfThereIsAtLeastOneChild() throws Exception
{
+ assertThat(hybrid.hasNodes(), is(true));
}
@Test
- public void shouldReturnTrueFromHasNodeWithParentReferenceIfNotRootNode() throws
Exception {
- assertThat(node.hasNode(".."), is(!node.isRoot()));
+ public void shouldReturnFalseFromHasNodesIfThereAreNoChildren() throws Exception {
+ assertThat(prius.hasNodes(), is(false));
}
- @Test
- public void shouldReturnTrueFromHasNodeIfRelativePathIdentifiesExistingNode() throws
Exception {
- AbstractJcrNode otherNode = mock(AbstractJcrNode.class);
- stub(cache.findJcrNode(uuid,
path("../other/node"))).toReturn(otherNode);
- assertThat(node.hasNode("../other/node"), is(true));
+ /*
+ * More comprehensive tests of addMixin, removeMixin, and canAddMixin require
additional setup
+ * and are in MixinTest
+ */
+
+ @Test( expected = UnsupportedOperationException.class )
+ public void shouldNotAllowCancelMerge() throws Exception {
+ hybrid.cancelMerge(null);
}
- @Test
- public void shouldReturnTrueFromHasNodeIfChildWithNameExists() throws Exception {
- addChild(name("child"), UUID.randomUUID());
- assertThat(node.hasNode("child[1]"), is(true));
- assertThat(node.hasNode("child[2]"), is(false));
- addChild(name("child"), UUID.randomUUID());
- assertThat(node.hasNode("child[2]"), is(true));
- assertThat(node.hasNode("child[3]"), is(false));
+ @Test( expected = UnsupportedRepositoryOperationException.class )
+ public void shouldNotAllowCheckin() throws Exception {
+ hybrid.checkin();
}
+ @Test( expected = UnsupportedRepositoryOperationException.class )
+ public void shouldNotAllowCheckout() throws Exception {
+ hybrid.checkout();
+ }
+
+ @Test( expected = UnsupportedOperationException.class )
+ public void shouldNotAllowDoneMerge() throws Exception {
+ hybrid.doneMerge(null);
+ }
+
+ @Test( expected = UnsupportedRepositoryOperationException.class )
+ public void shouldNotAllowGetBaseVersion() throws Exception {
+ hybrid.getBaseVersion();
+ }
+
+ @Test( expected = UnsupportedRepositoryOperationException.class )
+ public void shouldNotAllowGetLock() throws Exception {
+ hybrid.getLock();
+ }
+
@Test
- public void shouldReturnFalseFromHasNodeWithNameOfChildThatDoesNotExist() throws
Exception {
- assertThat(node.hasNode("something"), is(false));
+ public void shouldNotAllowHoldsLock() throws Exception {
+ assertThat(hybrid.holdsLock(), is(false));
}
@Test
- public void shouldReturnFalseFromHasNodesIfThereAreNoChildren() throws Exception {
- assertThat(node.hasNodes(), is(false));
+ public void shouldNotAllowIsCheckedOut() throws Exception {
+ assertThat(hybrid.isCheckedOut(), is(false));
}
@Test
- public void shouldReturnTrueFromHasNodesIfThereIsAtLeastOneChild() throws Exception
{
- addChild(name("child"), UUID.randomUUID());
- assertThat(node.hasNodes(), is(true));
+ public void shouldNotAllowIsLocked() throws Exception {
+ assertThat(hybrid.isLocked(), is(false));
}
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowNullPathInHasProperty() throws Exception {
- node.hasProperty((String)null);
+ @Test( expected = UnsupportedRepositoryOperationException.class )
+ public void shouldNotAllowLock() throws Exception {
+ hybrid.lock(false, false);
}
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowEmptyPathInHasProperty() throws Exception {
- node.hasProperty("");
+ @Test( expected = UnsupportedOperationException.class )
+ public void shouldNotAllowMerge() throws Exception {
+ hybrid.merge(null, false);
}
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAbsolutePathInHasProperty() throws Exception {
- node.hasProperty("/a/b/c");
+ @Test( expected = NullPointerException.class )
+ public void shouldNotAllowOrderBeforeWithNullArgs() throws Exception {
+ hybrid.orderBefore(null, null);
}
- @Test
- public void
shouldReturnTrueFromHasPropertyIfPathIsRelativePathToOtherNodeWithNamedProperty() throws
Exception {
- AbstractJcrProperty property = mock(AbstractJcrProperty.class);
- stub(cache.findJcrItem(uuid,
relativePath("../good/path"))).toReturn(property);
- assertThat(node.hasProperty("../good/path"), is(true));
+ @Test( expected = UnsupportedRepositoryOperationException.class )
+ public void shouldNotAllowRestoreVersionName() throws Exception {
+ hybrid.restore((String)null, false);
}
- @Test
- public void
shouldReturnFalseFromHasPropertyIfPathIsRelativePathToOtherNodeWithoutNamedProperty()
throws Exception {
- stub(cache.findJcrItem(uuid, relativePath("../good/path"))).toThrow(new
PathNotFoundException());
- assertThat(node.hasProperty("../good/path"), is(false));
+ @Test( expected = UnsupportedRepositoryOperationException.class )
+ public void shouldNotAllowRestoreVersion() throws Exception {
+ hybrid.restore((Version)null, false);
}
- @Test
- public void shouldReturnFalseFromHasPropertyIfPathIsParentPath() throws Exception {
- assertThat(node.hasProperty(".."), is(false));
+ @Test( expected = UnsupportedRepositoryOperationException.class )
+ public void shouldNotAllowRestoreVersionAtPath() throws Exception {
+ hybrid.restore(null, null, false);
}
- @Test
- public void shouldReturnFalseFromHasPropertyIfPathIsSelfPath() throws Exception {
- assertThat(node.hasProperty("."), is(false));
+ @Test( expected = UnsupportedRepositoryOperationException.class )
+ public void shouldNotAllowRestoreByLabel() throws Exception {
+ hybrid.restoreByLabel(null, false);
}
- @Test
- public void shouldReturnTrueFromHasPropertyIfPathIsNameAndNodeHasProperty() throws
Exception {
- PropertyInfo propertyInfo = mock(PropertyInfo.class);
- stub(cache.findPropertyInfo(new PropertyId(uuid,
name("prop")))).toReturn(propertyInfo);
- assertThat(node.hasProperty("prop"), is(true));
+ @Test( expected = UnsupportedRepositoryOperationException.class )
+ public void shouldNotAllowUnlock() throws Exception {
+ hybrid.unlock();
}
+ /*
+ * Primary-type and -item methods
+ */
+
@Test
- public void shouldReturnFalseFromHasPropertyIfPathIsNameAndNodeDoesNotHaveProperty()
throws Exception {
- stub(cache.findPropertyInfo(new PropertyId(uuid,
name("prop")))).toReturn(null);
- assertThat(node.hasProperty("prop"), is(false));
+ public void shouldReturnItemFromGetPrimaryNodeType() throws Exception {
+ NodeType carType = nodeTypes.getNodeType("vehix:car");
+ assertThat(carType, is(notNullValue()));
+ assertThat(prius.getPrimaryNodeType(), is(carType));
}
@Test
- public void shouldReturnTrueFromHasPropertiesIfNodeHasAtLeastOneProperty() throws
Exception {
- stub(info.hasProperties()).toReturn(true);
- assertThat(node.hasProperties(), is(true));
+ public void shouldReturnItemFromGetPrimaryItemIfItExists() throws Exception {
+ NodeType carType = nodeTypes.getNodeType("vehix:car");
+ assertThat(carType, is(notNullValue()));
+ assertThat(carType.getPrimaryItemName(), is("vehix:model"));
+ assertThat(prius.getPrimaryItem(),
is(sameInstance((Item)prius.getProperty("vehix:model"))));
}
- @Test
- public void shouldReturnFalseFromHasPropertiesIfNodeHasNoProperties() throws
Exception {
- stub(info.hasProperties()).toReturn(false);
- assertThat(node.hasProperties(), is(false));
+ @Test( expected = ItemNotFoundException.class )
+ public void
shouldFailToReturnItemFromGetPrimaryItemIfPrimaryTypeDoesNotHavePrimaryItemName() throws
Exception {
+ // Get nt:unstructured and verify it has no primary item name ...
+ NodeType ntUnstructured = nodeTypes.getNodeType("nt:unstructured");
+ assertThat(ntUnstructured, is(notNullValue()));
+ assertThat(ntUnstructured.getPrimaryItemName(), is(nullValue()));
+
+ // Now check using a node that has the "nt:unstructured" primary type
...
+ cars.getPrimaryItem();
}
- @Test
- public void shouldNotAllowHoldsLock() throws Exception {
- assertThat(node.holdsLock(), is(false));
+ @Test( expected = ItemNotFoundException.class )
+ public void
shouldFailToReturnItemFromGetPrimaryItemIfTheNodeHasNoItemMatchingThatSpecifiedByThePrimaryType()
+ throws Exception {
+ // Find the "vehix:car" type ...
+ NodeType carType = nodeTypes.getNodeType("vehix:car");
+ assertThat(carType, is(notNullValue()));
+ assertThat(carType.getPrimaryItemName(), is("vehix:model"));
+ assertThat(prius.getPrimaryItem(),
is(sameInstance((Item)prius.getProperty("vehix:model"))));
+
+ // Now remove the "vehix:model" property so there is no such item ...
+ prius.getProperty("vehix:model").remove();
+ prius.getPrimaryItem();
}
+ /*
+ * Miscellaneous methods
+ */
+
@Test
- public void shouldNotAllowIsCheckedOut() throws Exception {
- assertThat(node.isCheckedOut(), is(false));
+ public void shouldProvideSession() throws Exception {
+ assertThat((JcrSession)prius.getSession(), is(jcrSession));
}
- @Test
- public void shouldNotAllowIsLocked() throws Exception {
- assertThat(node.isLocked(), is(false));
+ @Test( expected = UnsupportedRepositoryOperationException.class )
+ public void shouldNotAllowGetVersionHistory() throws Exception {
+ cars.getVersionHistory();
}
- @Test
- public void shouldIndicateIsNode() {
- assertThat(node.isNode(), is(true));
+ /*
+ * Same-ness
+ */
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowIsSameWithNoItem() throws Exception {
+ hybrid.isSame(null);
}
@Test
public void shouldReturnFalseFromIsSameIfTheRepositoryInstanceIsDifferent() throws
Exception {
- Workspace workspace1 = mock(Workspace.class);
- Repository repository1 = mock(Repository.class);
- stub(session.getWorkspace()).toReturn(workspace1);
- stub(session.getRepository()).toReturn(repository1);
- stub(workspace1.getName()).toReturn("workspace1");
+ // Set up the store ...
+ InMemoryRepositorySource source2 = new InMemoryRepositorySource();
+ source2.setName("store");
+ Graph store2 = Graph.create(source2, context);
+
store2.importXmlFrom(AbstractJcrTest.class.getClassLoader().getResourceAsStream("cars.xml")).into("/");
+ JcrSession jcrSession2 = mock(JcrSession.class);
+ stub(jcrSession2.nodeTypeManager()).toReturn(nodeTypes);
+ SessionCache cache2 = new SessionCache(jcrSession2,
store2.getCurrentWorkspaceName(), context, nodeTypes, store2);
Workspace workspace2 = mock(Workspace.class);
- JcrSession session2 = Mockito.mock(JcrSession.class);
Repository repository2 = mock(Repository.class);
- SessionCache cache2 = mock(SessionCache.class);
- stub(session2.getWorkspace()).toReturn(workspace2);
- stub(session2.getRepository()).toReturn(repository2);
+ stub(jcrSession2.getWorkspace()).toReturn(workspace2);
+ stub(jcrSession2.getRepository()).toReturn(repository2);
stub(workspace2.getName()).toReturn("workspace1");
- stub(cache2.session()).toReturn(session2);
- UUID uuid2 = uuid;
- Node node2 = new MockAbstractJcrNode(cache2, uuid2);
- assertThat(node.isSame(node2), is(false));
+ // Use the same id and location ...
+ javax.jcr.Node prius2 = cache2.findJcrNode(null, path("/Cars/Hybrid/Toyota
Prius"));
+ assertThat(prius2.isSame(prius), is(false));
}
@Test
public void shouldReturnFalseFromIsSameIfTheWorkspaceNameIsDifferent() throws
Exception {
- Workspace workspace1 = mock(Workspace.class);
- Repository repository1 = mock(Repository.class);
- stub(session.getWorkspace()).toReturn(workspace1);
- stub(session.getRepository()).toReturn(repository1);
- stub(workspace1.getName()).toReturn("workspace1");
+ // Set up the store ...
+ InMemoryRepositorySource source2 = new InMemoryRepositorySource();
+ source2.setName("store");
+ Graph store2 = Graph.create(source2, context);
+
store2.importXmlFrom(AbstractJcrTest.class.getClassLoader().getResourceAsStream("cars.xml")).into("/");
+ JcrSession jcrSession2 = mock(JcrSession.class);
+ stub(jcrSession2.nodeTypeManager()).toReturn(nodeTypes);
+ SessionCache cache2 = new SessionCache(jcrSession2,
store2.getCurrentWorkspaceName(), context, nodeTypes, store2);
Workspace workspace2 = mock(Workspace.class);
- JcrSession session2 = Mockito.mock(JcrSession.class);
- SessionCache cache2 = mock(SessionCache.class);
- stub(session2.getWorkspace()).toReturn(workspace2);
- stub(session2.getRepository()).toReturn(repository1);
+ Repository repository2 = mock(Repository.class);
+ stub(jcrSession2.getWorkspace()).toReturn(workspace2);
+ stub(jcrSession2.getRepository()).toReturn(repository2);
stub(workspace2.getName()).toReturn("workspace2");
- stub(cache2.session()).toReturn(session2);
- UUID uuid2 = uuid;
- Node node2 = new MockAbstractJcrNode(cache2, uuid2);
- assertThat(node.isSame(node2), is(false));
+ // Use the same id and location; use 'Toyota Prius'
+ // since the UUID is defined in 'cars.xml' and therefore will be the
same
+ javax.jcr.Node prius2 = cache2.findJcrNode(null, path("/Cars/Hybrid/Toyota
Prius"));
+ prius2.addMixin("mix:referenceable");
+ prius.addMixin("mix:referenceable");
+ String priusUuid2 = prius2.getUUID();
+ String priusUuid = prius.getUUID();
+ assertThat(priusUuid, is(priusUuid2));
+ assertThat(prius2.isSame(prius), is(false));
}
@Test
public void shouldReturnFalseFromIsSameIfTheNodeUuidIsDifferent() throws Exception {
- Workspace workspace1 = mock(Workspace.class);
- Repository repository1 = mock(Repository.class);
- stub(session.getWorkspace()).toReturn(workspace1);
- stub(session.getRepository()).toReturn(repository1);
- stub(workspace1.getName()).toReturn("workspace1");
+ // Set up the store ...
+ InMemoryRepositorySource source2 = new InMemoryRepositorySource();
+ source2.setName("store");
+ Graph store2 = Graph.create(source2, context);
+
store2.importXmlFrom(AbstractJcrTest.class.getClassLoader().getResourceAsStream("cars.xml")).into("/");
+ JcrSession jcrSession2 = mock(JcrSession.class);
+ stub(jcrSession2.nodeTypeManager()).toReturn(nodeTypes);
+ SessionCache cache2 = new SessionCache(jcrSession2,
store2.getCurrentWorkspaceName(), context, nodeTypes, store2);
Workspace workspace2 = mock(Workspace.class);
- JcrSession session2 = Mockito.mock(JcrSession.class);
- SessionCache cache2 = mock(SessionCache.class);
- stub(session2.getWorkspace()).toReturn(workspace2);
- stub(session2.getRepository()).toReturn(repository1);
+ Repository repository2 = mock(Repository.class);
+ stub(jcrSession2.getWorkspace()).toReturn(workspace2);
+ stub(jcrSession2.getRepository()).toReturn(repository2);
stub(workspace2.getName()).toReturn("workspace1");
- stub(cache2.session()).toReturn(session2);
- UUID uuid2 = UUID.randomUUID();
- Node node2 = new MockAbstractJcrNode(cache2, uuid2);
- assertThat(node.isSame(node2), is(false));
+ // Use the same id and location; use 'Nissan Altima'
+ // since the UUIDs will be different (cars.xml doesn't define on this node)
...
+ javax.jcr.Node altima2 = cache2.findJcrNode(null, path("/Cars/Hybrid/Nissan
Altima"));
+ altima2.addMixin("mix:referenceable");
+ altima.addMixin("mix:referenceable");
+ String altimaUuid = altima.getUUID();
+ String altimaUuid2 = altima2.getUUID();
+ assertThat(altimaUuid, is(not(altimaUuid2)));
+ assertThat(altima2.isSame(altima), is(false));
}
@Test
public void
shouldReturnTrueFromIsSameIfTheNodeUuidAndWorkspaceNameAndRepositoryInstanceAreSame()
throws Exception {
- Workspace workspace1 = mock(Workspace.class);
- Repository repository1 = mock(Repository.class);
- stub(session.getWorkspace()).toReturn(workspace1);
- stub(session.getRepository()).toReturn(repository1);
- stub(workspace1.getName()).toReturn("workspace1");
+ // Set up the store ...
+ InMemoryRepositorySource source2 = new InMemoryRepositorySource();
+ source2.setName("store");
+ Graph store2 = Graph.create(source2, context);
+
store2.importXmlFrom(AbstractJcrTest.class.getClassLoader().getResourceAsStream("cars.xml")).into("/");
+ JcrSession jcrSession2 = mock(JcrSession.class);
+ stub(jcrSession2.nodeTypeManager()).toReturn(nodeTypes);
+ SessionCache cache2 = new SessionCache(jcrSession2,
store2.getCurrentWorkspaceName(), context, nodeTypes, store2);
Workspace workspace2 = mock(Workspace.class);
- JcrSession session2 = Mockito.mock(JcrSession.class);
- SessionCache cache2 = mock(SessionCache.class);
- stub(session2.getWorkspace()).toReturn(workspace2);
- stub(session2.getRepository()).toReturn(repository1);
+ stub(jcrSession2.getWorkspace()).toReturn(workspace2);
+ stub(jcrSession2.getRepository()).toReturn(repository);
stub(workspace2.getName()).toReturn("workspace1");
- stub(cache2.session()).toReturn(session2);
- UUID uuid2 = uuid;
- Node node2 = new MockAbstractJcrNode(cache2, uuid2);
- assertThat(node.isSame(node2), is(true));
+ // Use the same id and location ...
+ javax.jcr.Node prius2 = cache2.findJcrNode(null, path("/Cars/Hybrid/Toyota
Prius"));
+ prius2.addMixin("mix:referenceable");
+ prius.addMixin("mix:referenceable");
+ String priusUuid = prius.getUUID();
+ String priusUuid2 = prius2.getUUID();
+ assertThat(priusUuid, is(priusUuid2));
+ assertThat(prius2.isSame(prius), is(true));
}
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowIsSameWithNoItem() throws Exception {
- node.isSame(null);
+ @Test
+ public void shouldAlwaysHaveCorrespondenceIdForRootNodeThatContainsSelfPath() throws
Exception {
+ CorrespondenceId id = rootNode.getCorrespondenceId();
+ assertThat(id.getReferenceableId(), is(rootNode.getUUID()));
+ assertThat(id.getRelativePath().size(), is(1));
+ assertThat(id.getRelativePath().getLastSegment().isSelfReference(), is(true));
}
- @Test( expected = UnsupportedRepositoryOperationException.class )
- public void shouldNotAllowLock() throws Exception {
- node.lock(false, false);
- }
+ @Test
+ public void shouldAlwaysHaveCorrespondenceId() throws Exception {
+ assertThat(cars.isReferenceable(), is(false));
+ CorrespondenceId id = cars.getCorrespondenceId();
+ assertThat(id.getReferenceableId(), is(rootNode.getUUID()));
+ assertThat(id.getRelativePath().size(), is(1));
+ assertThat(id.getRelativePath(), is(path("Cars")));
- @Test( expected = UnsupportedOperationException.class )
- public void shouldNotAllowMerge() throws Exception {
- node.merge(null, false);
- }
+ assertThat(hybrid.isReferenceable(), is(false));
+ id = hybrid.getCorrespondenceId();
+ assertThat(id.getReferenceableId(), is(rootNode.getUUID()));
+ assertThat(id.getRelativePath().size(), is(2));
+ assertThat(id.getRelativePath(), is(path("Cars/Hybrid")));
- @Test( expected = NullPointerException.class )
- public void shouldNotAllowOrderBeforeWithNullArgs() throws Exception {
- node.orderBefore(null, null);
+ altima.addMixin("mix:referenceable");
+ assertThat(altima.isReferenceable(), is(true));
+ id = altima.getCorrespondenceId();
+ assertThat(id.getReferenceableId(), is(altima.getUUID()));
+ assertThat(id.getRelativePath().size(), is(1));
+ assertThat(id.getRelativePath(), is(path(".")));
}
- @Test( expected = UnsupportedRepositoryOperationException.class )
- public void shouldNotAllowRestoreVersionName() throws Exception {
- node.restore((String)null, false);
+ @Test
+ public void shouldAddNodeWhenIntermediateNodesDoExist() throws Exception {
+ javax.jcr.Node newNode = rootNode.addNode("Cars/Hybrid/CreateThis",
"nt:unstructured");
+ assertThat(newNode.getName(), is("CreateThis"));
+ assertThat(newNode.getParent(), is(sameInstance((javax.jcr.Node)hybrid)));
}
- @Test( expected = UnsupportedRepositoryOperationException.class )
- public void shouldNotAllowRestoreVersion() throws Exception {
- node.restore((Version)null, false);
+ @Test( expected = PathNotFoundException.class )
+ public void shouldFailToAddNodeWhenIntermediateNodesDoNotExist() throws Exception {
+ rootNode.addNode("Cars/nonExistant/CreateThis",
"nt:unstructured");
}
-
- @Test( expected = UnsupportedRepositoryOperationException.class )
- public void shouldNotAllowRestoreVersionAtPath() throws Exception {
- node.restore(null, null, false);
- }
-
- @Test( expected = UnsupportedRepositoryOperationException.class )
- public void shouldNotAllowRestoreByLabel() throws Exception {
- node.restoreByLabel(null, false);
- }
-
- @Test( expected = UnsupportedRepositoryOperationException.class )
- public void shouldNotAllowUnlock() throws Exception {
- node.unlock();
- }
-
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -4,13 +4,13 @@
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
* See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
+ * individual contributors.
*
* JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
* is licensed to you 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.
- *
+ *
* JBoss DNA 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
@@ -24,463 +24,237 @@
package org.jboss.dna.jcr;
import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.stub;
-import java.io.InputStream;
-import java.util.Calendar;
-import java.util.UUID;
import javax.jcr.Item;
import javax.jcr.ItemNotFoundException;
import javax.jcr.ItemVisitor;
import javax.jcr.Node;
-import javax.jcr.Property;
import javax.jcr.Repository;
import javax.jcr.Session;
-import javax.jcr.Value;
import javax.jcr.Workspace;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.Path;
-import org.jboss.dna.jcr.cache.NodeInfo;
-import org.jboss.dna.jcr.cache.PropertyInfo;
+import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoAnnotations.Mock;
/**
- * @author jverhaeg
+ *
*/
-public class AbstractJcrPropertyTest {
+public class AbstractJcrPropertyTest extends AbstractJcrTest {
- private PropertyId propertyId;
- private PropertyInfo info;
- private ExecutionContext executionContext;
- private JcrNode node;
- private AbstractJcrProperty prop;
- @Mock
- private JcrSession session;
- @Mock
- private SessionCache cache;
+ protected AbstractJcrNode rootNode;
+ protected AbstractJcrNode cars;
+ protected AbstractJcrNode prius;
+ protected AbstractJcrNode altima;
+ protected AbstractJcrProperty altimaModel;
+ @Override
@Before
- public void before() throws Exception {
- MockitoAnnotations.initMocks(this);
- executionContext = new ExecutionContext();
- stub(session.getExecutionContext()).toReturn(executionContext);
-
- UUID uuid = UUID.randomUUID();
- node = new JcrNode(cache, uuid);
- propertyId = new PropertyId(uuid, JcrLexicon.MIMETYPE);
- prop = new MockAbstractJcrProperty(cache, propertyId);
-
- info = mock(PropertyInfo.class);
- stub(info.getPropertyId()).toReturn(propertyId);
- stub(info.getPropertyName()).toReturn(propertyId.getPropertyName());
-
- stub(cache.session()).toReturn(session);
- stub(cache.context()).toReturn(executionContext);
- stub(cache.findJcrProperty(propertyId)).toReturn(prop);
- stub(cache.findPropertyInfo(propertyId)).toReturn(info);
- stub(cache.getPathFor(info)).toReturn(path("/a/b/c/jcr:mimeType"));
-
stub(cache.getPathFor(propertyId)).toReturn(path("/a/b/c/jcr:mimeType"));
- stub(cache.getPathFor(uuid)).toReturn(path("/a/b/c"));
-
- NodeInfo nodeInfo = mock(NodeInfo.class);
- stub(cache.findJcrNode(uuid)).toReturn(node);
- stub(cache.findNodeInfo(uuid)).toReturn(nodeInfo);
- stub(cache.getPathFor(uuid)).toReturn(path("/a/b/c"));
- stub(cache.getPathFor(nodeInfo)).toReturn(path("/a/b/c"));
+ public void beforeEach() throws Exception {
+ super.beforeEach();
+ rootNode = cache.findJcrRootNode();
+ cars = cache.findJcrNode(null, path("/Cars"));
+ prius = cache.findJcrNode(null, path("/Cars/Hybrid/Toyota Prius"));
+ altima = cache.findJcrNode(null, path("/Cars/Hybrid/Nissan Altima"));
+ altimaModel = cache.findJcrProperty(altima.nodeId, altima.path(),
Vehicles.Lexicon.MODEL);
}
- protected Name name( String name ) {
- return executionContext.getValueFactories().getNameFactory().create(name);
- }
-
- protected Path path( String path ) {
- return executionContext.getValueFactories().getPathFactory().create(path);
- }
-
@Test
public void shouldAllowVisitation() throws Exception {
ItemVisitor visitor = Mockito.mock(ItemVisitor.class);
- prop.accept(visitor);
- Mockito.verify(visitor).visit(prop);
+ altimaModel.accept(visitor);
+ Mockito.verify(visitor).visit(altimaModel);
}
@Test( expected = IllegalArgumentException.class )
public void shouldNotAllowVisitationIfNoVisitor() throws Exception {
- prop.accept(null);
+ altimaModel.accept(null);
}
@Test( expected = ItemNotFoundException.class )
public void shouldNotAllowNegativeAncestorDepth() throws Exception {
- stub(node.getAncestor(-2)).toThrow(new IllegalArgumentException());
- prop.getAncestor(-1);
+ altimaModel.getAncestor(-1);
}
@Test
- public void shouldProvideAncestor() throws Exception {
- assertThat(prop.getAncestor(prop.getDepth()), is((Item)prop));
- assertThat(prop.getAncestor(prop.getDepth() - 1), is((Item)node));
+ public void shouldReturnRootForAncestorOfDepthZero() throws Exception {
+ assertThat(altimaModel.getAncestor(0), is((Item)rootNode));
}
+ @Test
+ public void shouldReturnAncestorAtLevelOneForAncestorOfDepthOne() throws Exception {
+ assertThat(altimaModel.getAncestor(1), is((Item)cars));
+ }
+
+ @Test
+ public void shouldReturnSelfForAncestorOfDepthEqualToDepthOfNode() throws Exception
{
+ assertThat(altimaModel.getAncestor(altimaModel.getDepth()),
is((Item)altimaModel));
+ assertThat(altimaModel.getAncestor(altimaModel.getDepth() - 1),
is((Item)altima));
+ }
+
@Test( expected = ItemNotFoundException.class )
- public void shouldNotAllowAncestorDepthGreaterThanPropertyDepth() throws Exception {
- prop.getAncestor(prop.getDepth() + 1);
+ public void shouldFailToReturnAncestorWhenDepthIsGreaterThanNodeDepth() throws
Exception {
+ altimaModel.getAncestor(40);
}
@Test
- public void shouldProvideDepth() throws Exception {
- assertThat(prop.getDepth(), is(4));
+ public void shouldIndicateIsNotNode() {
+ assertThat(altimaModel.isNode(), is(false));
}
@Test
public void shouldProvideExecutionContext() throws Exception {
- assertThat(prop.context(), is(executionContext));
+ assertThat(altimaModel.context(), is(context));
}
@Test
public void shouldProvideName() throws Exception {
- assertThat(prop.getName(), is("jcr:mimeType"));
+ assertThat(altimaModel.getName(), is("vehix:model"));
}
@Test
public void shouldProvideParent() throws Exception {
- assertThat(prop.getParent(), is((Node)node));
+ assertThat(altimaModel.getParent(), is((Node)altima));
}
@Test
public void shouldProvidePath() throws Exception {
- assertThat(prop.getPath(), is("/a/b/c/jcr:mimeType"));
+ assertThat(altimaModel.getPath(), is(altima.getPath() +
"/vehix:model"));
}
@Test
public void shouldProvideSession() throws Exception {
- assertThat(prop.getSession(), is((Session)session));
+ assertThat(altimaModel.getSession(), is((Session)jcrSession));
}
@Test
- public void shouldIndicateIsNotANode() {
- assertThat(prop.isNode(), is(false));
- }
+ public void shouldReturnFalseFromIsSameIfTheRepositoryInstanceIsDifferent() throws
Exception {
+ // Set up the store ...
+ InMemoryRepositorySource source2 = new InMemoryRepositorySource();
+ source2.setName("store");
+ Graph store2 = Graph.create(source2, context);
+
store2.importXmlFrom(AbstractJcrTest.class.getClassLoader().getResourceAsStream("cars.xml")).into("/");
+ JcrSession jcrSession2 = mock(JcrSession.class);
+ stub(jcrSession2.nodeTypeManager()).toReturn(nodeTypes);
+ SessionCache cache2 = new SessionCache(jcrSession2,
store2.getCurrentWorkspaceName(), context, nodeTypes, store2);
- @Test
- public void shouldIndicateSameAsPropertyWithSameNodeAndSamePropertyName() throws
Exception {
- Repository repository = mock(Repository.class);
- Workspace workspace = mock(Workspace.class);
Workspace workspace2 = mock(Workspace.class);
- stub(workspace.getName()).toReturn("workspace");
- stub(workspace2.getName()).toReturn("workspace");
- JcrSession session2 = mock(JcrSession.class);
- SessionCache cache2 = mock(SessionCache.class);
- stub(session2.getRepository()).toReturn(repository);
- stub(session.getRepository()).toReturn(repository);
- stub(session2.getWorkspace()).toReturn(workspace2);
- stub(session.getWorkspace()).toReturn(workspace);
- stub(cache2.session()).toReturn(session2);
- stub(cache2.context()).toReturn(executionContext);
+ Repository repository2 = mock(Repository.class);
+ stub(jcrSession2.getWorkspace()).toReturn(workspace2);
+ stub(jcrSession2.getRepository()).toReturn(repository2);
+ stub(workspace2.getName()).toReturn("workspace1");
- // Make the other node have the same UUID ...
- UUID uuid = node.internalUuid();
- NodeInfo nodeInfo = mock(NodeInfo.class);
- PropertyInfo propertyInfo = mock(PropertyInfo.class);
- AbstractJcrNode otherNode = new JcrNode(cache2, uuid);
- stub(propertyInfo.getPropertyId()).toReturn(propertyId);
- stub(propertyInfo.getPropertyName()).toReturn(propertyId.getPropertyName());
- stub(cache2.findJcrNode(uuid)).toReturn(otherNode);
- stub(cache2.findNodeInfo(uuid)).toReturn(nodeInfo);
- stub(cache2.getPathFor(uuid)).toReturn(path("/a/b/c"));
- stub(cache2.getPathFor(nodeInfo)).toReturn(path("/a/b/c"));
- stub(cache2.findPropertyInfo(propertyId)).toReturn(info);
+ // Use the same id and location ...
+ javax.jcr.Node prius2 = cache2.findJcrNode(null, path("/Cars/Hybrid/Toyota
Prius"));
+ assertThat(prius2.isSame(prius), is(false));
- assertThat(node.isSame(otherNode), is(true));
-
- Property prop = new MockAbstractJcrProperty(cache, propertyId);
- Property otherProp = new MockAbstractJcrProperty(cache2, propertyId);
- assertThat(prop.isSame(otherProp), is(true));
+ // Check the properties ...
+ javax.jcr.Property model = prius.getProperty("vehix:model");
+ javax.jcr.Property model2 = prius2.getProperty("vehix:model");
+ assertThat(model.isSame(model2), is(false));
}
@Test
- public void shouldIndicateDifferentThanNodeWithDifferentParent() throws Exception {
- Repository repository = mock(Repository.class);
- Workspace workspace = mock(Workspace.class);
+ public void shouldReturnFalseFromIsSameIfTheWorkspaceNameIsDifferent() throws
Exception {
+ // Set up the store ...
+ InMemoryRepositorySource source2 = new InMemoryRepositorySource();
+ source2.setName("store");
+ Graph store2 = Graph.create(source2, context);
+
store2.importXmlFrom(AbstractJcrTest.class.getClassLoader().getResourceAsStream("cars.xml")).into("/");
+ JcrSession jcrSession2 = mock(JcrSession.class);
+ stub(jcrSession2.nodeTypeManager()).toReturn(nodeTypes);
+ SessionCache cache2 = new SessionCache(jcrSession2,
store2.getCurrentWorkspaceName(), context, nodeTypes, store2);
+
Workspace workspace2 = mock(Workspace.class);
- stub(workspace.getName()).toReturn("workspace");
- stub(workspace2.getName()).toReturn("workspace");
- JcrSession session2 = mock(JcrSession.class);
- SessionCache cache2 = mock(SessionCache.class);
- stub(session2.getRepository()).toReturn(repository);
- stub(session.getRepository()).toReturn(repository);
- stub(session2.getWorkspace()).toReturn(workspace2);
- stub(session.getWorkspace()).toReturn(workspace);
- stub(cache2.session()).toReturn(session2);
- stub(cache2.context()).toReturn(executionContext);
+ Repository repository2 = mock(Repository.class);
+ stub(jcrSession2.getWorkspace()).toReturn(workspace2);
+ stub(jcrSession2.getRepository()).toReturn(repository2);
+ stub(workspace2.getName()).toReturn("workspace2");
- // Make the other node have a different UUID ...
- UUID uuid = UUID.randomUUID();
- PropertyId propertyId2 = new PropertyId(uuid, JcrLexicon.MIXIN_TYPES);
- NodeInfo nodeInfo = mock(NodeInfo.class);
- PropertyInfo propertyInfo = mock(PropertyInfo.class);
- AbstractJcrNode otherNode = new JcrNode(cache2, uuid);
- stub(propertyInfo.getPropertyId()).toReturn(propertyId2);
- stub(propertyInfo.getPropertyName()).toReturn(propertyId2.getPropertyName());
- stub(cache2.findJcrNode(uuid)).toReturn(otherNode);
- stub(cache2.findNodeInfo(uuid)).toReturn(nodeInfo);
- stub(cache2.getPathFor(uuid)).toReturn(path("/a/b/c"));
- stub(cache2.getPathFor(nodeInfo)).toReturn(path("/a/b/c"));
+ // Use the same id and location; use 'Toyota Prius'
+ // since the UUID is defined in 'cars.xml' and therefore will be the
same
+ javax.jcr.Node prius2 = cache2.findJcrNode(null, path("/Cars/Hybrid/Toyota
Prius"));
+ prius2.addMixin("mix:referenceable");
+ prius.addMixin("mix:referenceable");
+ String priusUuid2 = prius2.getUUID();
+ String priusUuid = prius.getUUID();
+ assertThat(priusUuid, is(priusUuid2));
+ assertThat(prius2.isSame(prius), is(false));
- assertThat(node.isSame(otherNode), is(false));
-
- Property prop = new MockAbstractJcrProperty(cache, propertyId);
- Property otherProp = new MockAbstractJcrProperty(cache2, propertyId2);
- assertThat(prop.isSame(otherProp), is(false));
+ // Check the properties ...
+ javax.jcr.Property model = prius.getProperty("vehix:model");
+ javax.jcr.Property model2 = prius2.getProperty("vehix:model");
+ assertThat(model.isSame(model2), is(false));
}
@Test
- public void
shouldIndicateDifferentThanPropertyWithSameNodeWithDifferentPropertyName() throws
Exception {
- Repository repository = mock(Repository.class);
- Workspace workspace = mock(Workspace.class);
+ public void shouldReturnFalseFromIsSameIfTheNodeUuidIsDifferent() throws Exception {
+ // Set up the store ...
+ InMemoryRepositorySource source2 = new InMemoryRepositorySource();
+ source2.setName("store");
+ Graph store2 = Graph.create(source2, context);
+
store2.importXmlFrom(AbstractJcrTest.class.getClassLoader().getResourceAsStream("cars.xml")).into("/");
+ JcrSession jcrSession2 = mock(JcrSession.class);
+ stub(jcrSession2.nodeTypeManager()).toReturn(nodeTypes);
+ SessionCache cache2 = new SessionCache(jcrSession2,
store2.getCurrentWorkspaceName(), context, nodeTypes, store2);
+
Workspace workspace2 = mock(Workspace.class);
- stub(workspace.getName()).toReturn("workspace");
- stub(workspace2.getName()).toReturn("workspace");
- JcrSession session2 = mock(JcrSession.class);
- SessionCache cache2 = mock(SessionCache.class);
- stub(session2.getRepository()).toReturn(repository);
- stub(session.getRepository()).toReturn(repository);
- stub(session2.getWorkspace()).toReturn(workspace2);
- stub(session.getWorkspace()).toReturn(workspace);
- stub(cache2.session()).toReturn(session2);
- stub(cache2.context()).toReturn(executionContext);
+ Repository repository2 = mock(Repository.class);
+ stub(jcrSession2.getWorkspace()).toReturn(workspace2);
+ stub(jcrSession2.getRepository()).toReturn(repository2);
+ stub(workspace2.getName()).toReturn("workspace1");
- // Make the other node have the same UUID ...
- UUID uuid = node.internalUuid();
- NodeInfo nodeInfo = mock(NodeInfo.class);
- PropertyInfo propertyInfo = mock(PropertyInfo.class);
- PropertyId propertyId2 = new PropertyId(uuid, JcrLexicon.NAME);
- AbstractJcrNode otherNode = new JcrNode(cache2, uuid);
- stub(propertyInfo.getPropertyId()).toReturn(propertyId2);
- stub(propertyInfo.getPropertyName()).toReturn(propertyId2.getPropertyName());
- stub(cache2.findJcrNode(uuid)).toReturn(otherNode);
- stub(cache2.findNodeInfo(uuid)).toReturn(nodeInfo);
- stub(cache2.getPathFor(uuid)).toReturn(path("/a/b/c"));
- stub(cache2.getPathFor(nodeInfo)).toReturn(path("/a/b/c"));
- stub(cache2.findPropertyInfo(propertyId2)).toReturn(propertyInfo);
+ // Use the same id and location; use 'Nissan Altima'
+ // since the UUIDs will be different (cars.xml doesn't define on this node)
...
+ javax.jcr.Node altima2 = cache2.findJcrNode(null, path("/Cars/Hybrid/Nissan
Altima"));
+ altima2.addMixin("mix:referenceable");
+ altima.addMixin("mix:referenceable");
+ String altimaUuid = altima.getUUID();
+ String altimaUuid2 = altima2.getUUID();
+ assertThat(altimaUuid, is(not(altimaUuid2)));
+ assertThat(altima2.isSame(altima), is(false));
- assertThat(node.isSame(otherNode), is(true));
-
- Property prop = new MockAbstractJcrProperty(cache, propertyId);
- Property otherProp = new MockAbstractJcrProperty(cache2, propertyId2);
- assertThat(prop.isSame(otherProp), is(false));
+ // Check the properties ...
+ javax.jcr.Property model = altima.getProperty("vehix:model");
+ javax.jcr.Property model2 = altima2.getProperty("vehix:model");
+ assertThat(model.isSame(model2), is(false));
}
- private class MockAbstractJcrProperty extends AbstractJcrProperty {
+ @Test
+ public void
shouldReturnTrueFromIsSameIfTheNodeUuidAndWorkspaceNameAndRepositoryInstanceAreSame()
throws Exception {
+ // Set up the store ...
+ InMemoryRepositorySource source2 = new InMemoryRepositorySource();
+ source2.setName("store");
+ Graph store2 = Graph.create(source2, context);
+
store2.importXmlFrom(AbstractJcrTest.class.getClassLoader().getResourceAsStream("cars.xml")).into("/");
+ JcrSession jcrSession2 = mock(JcrSession.class);
+ stub(jcrSession2.nodeTypeManager()).toReturn(nodeTypes);
+ SessionCache cache2 = new SessionCache(jcrSession2,
store2.getCurrentWorkspaceName(), context, nodeTypes, store2);
- MockAbstractJcrProperty( SessionCache cache,
- PropertyId propertyId ) {
- super(cache, propertyId);
- }
+ Workspace workspace2 = mock(Workspace.class);
+ stub(jcrSession2.getWorkspace()).toReturn(workspace2);
+ stub(jcrSession2.getRepository()).toReturn(repository);
+ stub(workspace2.getName()).toReturn("workspace1");
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.jcr.AbstractJcrProperty#isMultiple()
- */
- @Override
- boolean isMultiple() {
- return false;
- }
+ // Use the same id and location ...
+ javax.jcr.Node prius2 = cache2.findJcrNode(null, path("/Cars/Hybrid/Toyota
Prius"));
+ prius2.addMixin("mix:referenceable");
+ prius.addMixin("mix:referenceable");
+ String priusUuid = prius.getUUID();
+ String priusUuid2 = prius2.getUUID();
+ assertThat(priusUuid, is(priusUuid2));
+ assertThat(prius2.isSame(prius), is(true));
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#getNode()
- */
- @SuppressWarnings( "synthetic-access" )
- public Node getNode() {
- return node;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#getBoolean()
- */
- public boolean getBoolean() {
- return false;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#getDate()
- */
- public Calendar getDate() {
- return null;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#getDouble()
- */
- public double getDouble() {
- return 0;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#getLength()
- */
- public long getLength() {
- return 0;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#getLengths()
- */
- public long[] getLengths() {
- return null;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#getLong()
- */
- public long getLong() {
- return 0;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#getStream()
- */
- public InputStream getStream() {
- return null;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#getString()
- */
- public String getString() {
- return null;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#getValue()
- */
- public Value getValue() {
- return null;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#getValues()
- */
- public Value[] getValues() {
- return null;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#setValue(javax.jcr.Value)
- */
- public void setValue( Value value ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#setValue(javax.jcr.Value[])
- */
- public void setValue( Value[] values ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#setValue(java.lang.String)
- */
- public void setValue( String value ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#setValue(java.lang.String[])
- */
- public void setValue( String[] values ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#setValue(java.io.InputStream)
- */
- public void setValue( InputStream value ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#setValue(long)
- */
- public void setValue( long value ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#setValue(double)
- */
- public void setValue( double value ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#setValue(java.util.Calendar)
- */
- public void setValue( Calendar value ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#setValue(boolean)
- */
- public void setValue( boolean value ) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Property#setValue(javax.jcr.Node)
- */
- public void setValue( Node value ) {
- throw new UnsupportedOperationException();
- }
+ // Check the properties ...
+ javax.jcr.Property model = prius.getProperty("vehix:model");
+ javax.jcr.Property model2 = prius2.getProperty("vehix:model");
+ javax.jcr.Property year2 = prius2.getProperty("vehix:year");
+ assertThat(model.isSame(model2), is(true));
+ assertThat(model.isSame(year2), is(false));
}
+
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrTest.java 2009-07-09 16:23:09
UTC (rev 1081)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrTest.java 2009-07-09 16:26:04
UTC (rev 1082)
@@ -1,84 +1,77 @@
+/*
+ * JBoss DNA (
http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you 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.
+ *
+ * JBoss DNA 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.jcr;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.stub;
import java.io.IOException;
-import java.util.Collections;
-import java.util.EnumMap;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import javax.jcr.Repository;
import javax.jcr.RepositoryException;
+import javax.jcr.Workspace;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
-import org.jboss.dna.graph.MockSecurityContext;
-import org.jboss.dna.graph.SecurityContext;
import org.jboss.dna.graph.connector.RepositoryConnection;
import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
import org.jboss.dna.graph.connector.RepositorySourceException;
import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
-import org.jboss.dna.graph.property.NamespaceRegistry;
-import org.jboss.dna.jcr.nodetype.NodeTypeTemplate;
-import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoAnnotations.Mock;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.junit.Before;
+import org.junit.BeforeClass;
-public abstract class AbstractJcrTest {
+/**
+ *
+ */
+public class AbstractJcrTest {
-
- protected String workspaceName;
- protected ExecutionContext context;
+ protected static ExecutionContext context;
+ protected static RepositoryNodeTypeManager rntm;
protected InMemoryRepositorySource source;
- protected JcrWorkspace workspace;
- protected JcrSession session;
- protected Graph graph;
- protected RepositoryConnectionFactory connectionFactory;
- protected RepositoryNodeTypeManager repoTypeManager;
- protected Map<String, Object> sessionAttributes;
- protected Map<JcrRepository.Option, String> options;
- protected NamespaceRegistry registry;
- @Mock
- protected JcrRepository repository;
+ protected Graph store;
+ protected int numberOfConnections;
+ protected SessionCache cache;
+ protected JcrSession jcrSession;
+ protected JcrNodeTypeManager nodeTypes;
+ protected Workspace workspace;
+ protected Repository repository;
- protected void beforeEach() throws Exception {
- MockitoAnnotations.initMocks(this);
-
- workspaceName = "workspace1";
- final String repositorySourceName = "repository";
-
- // Set up the source ...
- source = new InMemoryRepositorySource();
- source.setName(workspaceName);
- source.setDefaultWorkspaceName(workspaceName);
-
- // Set up the execution context ...
+ /**
+ * Initialize the expensive activities, and in particular the
RepositoryNodeTypeManager instance.
+ *
+ * @throws Exception
+ */
+ @BeforeClass
+ public static void beforeAll() throws Exception {
context = new ExecutionContext();
- // Register the test namespace
- context.getNamespaceRegistry().register(TestLexicon.Namespace.PREFIX,
TestLexicon.Namespace.URI);
- // Set up the initial content ...
- graph = Graph.create(source, context);
- initializeContent();
-
- // Stub out the connection factory ...
- connectionFactory = new RepositoryConnectionFactory() {
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.graph.connector.RepositoryConnectionFactory#createConnection(java.lang.String)
- */
- @SuppressWarnings( "synthetic-access" )
- public RepositoryConnection createConnection( String sourceName ) throws
RepositorySourceException {
- return repositorySourceName.equals(sourceName) ? source.getConnection() :
null;
- }
- };
-
- // Stub out the repository, since we only need a few methods ...
- repoTypeManager = new RepositoryNodeTypeManager(context);
-
+ // Create the node type manager ...
+ context.getNamespaceRegistry().register(Vehicles.Lexicon.Namespace.PREFIX,
Vehicles.Lexicon.Namespace.URI);
+ rntm = new RepositoryNodeTypeManager(context);
try {
- this.repoTypeManager.registerNodeTypes(new CndNodeTypeSource(new String[]
{"/org/jboss/dna/jcr/jsr_170_builtins.cnd",
+ rntm.registerNodeTypes(new CndNodeTypeSource(new String[]
{"/org/jboss/dna/jcr/jsr_170_builtins.cnd",
"/org/jboss/dna/jcr/dna_builtins.cnd"}));
- this.repoTypeManager.registerNodeTypes(new
NodeTemplateNodeTypeSource(getTestTypes()));
-
+ rntm.registerNodeTypes(new
NodeTemplateNodeTypeSource(Vehicles.getNodeTypes(context)));
} catch (RepositoryException re) {
re.printStackTrace();
throw new IllegalStateException("Could not load node type definition
files", re);
@@ -86,41 +79,59 @@
ioe.printStackTrace();
throw new IllegalStateException("Could not access node type definition
files", ioe);
}
+ }
- stub(repository.getRepositoryTypeManager()).toReturn(repoTypeManager);
- stub(repository.getRepositorySourceName()).toReturn(repositorySourceName);
- stub(repository.getConnectionFactory()).toReturn(connectionFactory);
+ /**
+ * Set up and initialize the store and session. This allows each test method to be
independent; any changes made to the
+ * sessions or store state will not be seen by other tests.
+ *
+ * @throws Exception
+ */
+ @Before
+ public void beforeEach() throws Exception {
+ // Set up the store ...
+ source = new InMemoryRepositorySource();
+ source.setName("store");
+ // Use a connection factory so we can count the number of connections that were
made
+ RepositoryConnectionFactory connectionFactory = new RepositoryConnectionFactory()
{
+ public RepositoryConnection createConnection( String sourceName ) throws
RepositorySourceException {
+ if (source.getName().equals(sourceName)) {
+ ++numberOfConnections;
+ return source.getConnection();
+ }
+ return null;
+ }
+ };
+ store = Graph.create(source.getName(), connectionFactory, context);
- initializeOptions();
- stub(repository.getOptions()).toReturn(options);
+ // Load the store with content ...
+
store.importXmlFrom(AbstractJcrTest.class.getClassLoader().getResourceAsStream("cars.xml")).into("/");
+ numberOfConnections = 0; // reset the number of connections
- // Set up the session attributes ...
- // Set up the session attributes ...
- sessionAttributes = new HashMap<String, Object>();
- sessionAttributes.put("attribute1", "value1");
+ nodeTypes = new JcrNodeTypeManager(context, rntm);
- // Now create the workspace ...
- SecurityContext mockSecurityContext = new MockSecurityContext(null,
-
Collections.singleton(JcrSession.DNA_WRITE_PERMISSION));
- workspace = new JcrWorkspace(repository, workspaceName,
context.with(mockSecurityContext), sessionAttributes);
+ // Stub the session ...
+ jcrSession = mock(JcrSession.class);
+ stub(jcrSession.nodeTypeManager()).toReturn(nodeTypes);
- // Create the session and log in ...
- session = (JcrSession)workspace.getSession();
- registry = session.getExecutionContext().getNamespaceRegistry();
+ cache = new SessionCache(jcrSession, store.getCurrentWorkspaceName(), context,
nodeTypes, store);
+
+ workspace = mock(Workspace.class);
+ repository = mock(Repository.class);
+ stub(jcrSession.getWorkspace()).toReturn(workspace);
+ stub(jcrSession.getRepository()).toReturn(repository);
+ stub(workspace.getName()).toReturn("workspace1");
}
- protected List<NodeTypeTemplate> getTestTypes() {
- return Collections.emptyList();
+ protected Name name( String name ) {
+ return context.getValueFactories().getNameFactory().create(name);
}
- protected void initializeContent() {
-
+ protected Path relativePath( String relativePath ) {
+ return context.getValueFactories().getPathFactory().create(relativePath);
}
-
- protected void initializeOptions() {
- // Stub out the repository options ...
- options = new EnumMap<JcrRepository.Option,
String>(JcrRepository.Option.class);
- options.put(JcrRepository.Option.PROJECT_NODE_TYPES, Boolean.FALSE.toString());
+ protected Path path( String absolutePath ) {
+ return context.getValueFactories().getPathFactory().create(absolutePath);
}
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrChildNodeIteratorTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrChildNodeIteratorTest.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrChildNodeIteratorTest.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -27,52 +27,39 @@
import static org.hamcrest.core.IsSame.sameInstance;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.stub;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
-import java.util.UUID;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
-import org.jboss.dna.graph.property.basic.BasicName;
-import org.jboss.dna.graph.property.basic.BasicPathSegment;
-import org.jboss.dna.jcr.cache.ChildNode;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoAnnotations.Mock;
/**
*
*/
public class JcrChildNodeIteratorTest {
- private List<ChildNode> children;
- private List<Node> childNodes;
+ private List<AbstractJcrNode> children;
private NodeIterator iter;
- @Mock
- private SessionCache cache;
@Before
public void beforeEach() throws Exception {
MockitoAnnotations.initMocks(this);
- children = new ArrayList<ChildNode>();
- childNodes = new ArrayList<Node>();
+ children = new ArrayList<AbstractJcrNode>();
for (int i = 0; i != 10; ++i) {
- UUID uuid = UUID.randomUUID();
- ChildNode child = new ChildNode(uuid, new BasicPathSegment(new
BasicName("", "name"), i + 1));
- AbstractJcrNode node = mock(AbstractJcrNode.class);
- stub(cache.findJcrNode(uuid)).toReturn(node);
- children.add(child);
- childNodes.add(node);
+ // Create a child (node with payload and JCR node object, all mock) ...
+ AbstractJcrNode childJcrNode = mock(AbstractJcrNode.class);
+ children.add(childJcrNode);
}
- iter = new JcrChildNodeIterator(cache, children, children.size());
+ iter = new JcrChildNodeIterator(children, children.size());
}
@Test
public void shouldProperlyDetermineHasNext() {
- Iterator<Node> nodeIter = childNodes.iterator();
+ Iterator<AbstractJcrNode> nodeIter = children.iterator();
long position = 0L;
assertThat(iter.getPosition(), is(position));
while (iter.hasNext()) {
@@ -94,7 +81,7 @@
@Test
public void shouldHaveCorrectSize() {
- assertThat(iter.getSize(), is((long)childNodes.size()));
+ assertThat(iter.getSize(), is((long)children.size()));
}
@Test( expected = UnsupportedOperationException.class )
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrMultiValuePropertyTest.java
===================================================================
---
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrMultiValuePropertyTest.java 2009-07-09
16:23:09 UTC (rev 1081)
+++
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrMultiValuePropertyTest.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -26,176 +26,322 @@
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.stub;
-import java.util.UUID;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import javax.jcr.Node;
+import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.Value;
import javax.jcr.ValueFormatException;
import javax.jcr.nodetype.PropertyDefinition;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.jcr.cache.PropertyInfo;
+import org.jboss.dna.graph.property.DateTime;
+import org.jboss.dna.graph.property.DateTimeFactory;
+import org.jboss.dna.jcr.nodetype.NodeTypeDefinition;
+import org.jboss.dna.jcr.nodetype.PropertyDefinitionTemplate;
import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Test;
-import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoAnnotations.Mock;
/**
* @author jverhaeg
*/
-public class JcrMultiValuePropertyTest {
+public class JcrMultiValuePropertyTest extends AbstractJcrTest {
- private PropertyId propertyId;
- private JcrMultiValueProperty prop;
- private ExecutionContext executionContext;
- private org.jboss.dna.graph.property.Property dnaProperty;
- @Mock
- private SessionCache cache;
- @Mock
- private JcrSession session;
- @Mock
- private PropertyInfo propertyInfo;
- @Mock
- private JcrPropertyDefinition definition;
- @Mock
- private JcrNodeTypeManager nodeTypes;
+ private Property prop;
+ private byte[][] binaryValue;
+ private DateTime[] dateValue;
+ private double[] doubleValue;
+ private long[] longValue;
+ private String[] stringValue;
+ private boolean[] booleanValue;
+ private String[] nameValue;
+ private String[] pathValue;
+ private DateTimeFactory dateFactory;
+ protected AbstractJcrNode cars;
+ protected AbstractJcrNode altima;
+ /**
+ * Initialize the expensive activities, and in particular the
RepositoryNodeTypeManager instance.
+ *
+ * @throws Exception
+ */
+ @BeforeClass
+ public static void beforeAll() throws Exception {
+ AbstractJcrTest.beforeAll();
+
+ // Define the node definition that will have all the different kinds of
properties ...
+ JcrNodeTypeTemplate nodeType = new JcrNodeTypeTemplate(context);
+ nodeType.setMixin(true);
+ nodeType.setName("mixinWithAllPropTypes");
+ List<PropertyDefinitionTemplate> propDefns =
nodeType.getPropertyDefinitionTemplates();
+
+ // Add a property for each type ...
+ JcrPropertyDefinitionTemplate binaryDefn = new
JcrPropertyDefinitionTemplate(context);
+ binaryDefn.setName("binaryProperty");
+ binaryDefn.setRequiredType(PropertyType.BINARY);
+ binaryDefn.setMultiple(true);
+ propDefns.add(binaryDefn);
+
+ JcrPropertyDefinitionTemplate booleanDefn = new
JcrPropertyDefinitionTemplate(context);
+ booleanDefn.setName("booleanProperty");
+ booleanDefn.setRequiredType(PropertyType.BOOLEAN);
+ booleanDefn.setMultiple(true);
+ propDefns.add(booleanDefn);
+
+ JcrPropertyDefinitionTemplate dateDefn = new
JcrPropertyDefinitionTemplate(context);
+ dateDefn.setName("dateProperty");
+ dateDefn.setRequiredType(PropertyType.DATE);
+ dateDefn.setMultiple(true);
+ propDefns.add(dateDefn);
+
+ JcrPropertyDefinitionTemplate doubleDefn = new
JcrPropertyDefinitionTemplate(context);
+ doubleDefn.setName("doubleProperty");
+ doubleDefn.setRequiredType(PropertyType.DOUBLE);
+ doubleDefn.setMultiple(true);
+ propDefns.add(doubleDefn);
+
+ JcrPropertyDefinitionTemplate longDefn = new
JcrPropertyDefinitionTemplate(context);
+ longDefn.setName("longProperty");
+ longDefn.setRequiredType(PropertyType.LONG);
+ longDefn.setMultiple(true);
+ propDefns.add(longDefn);
+
+ JcrPropertyDefinitionTemplate nameDefn = new
JcrPropertyDefinitionTemplate(context);
+ nameDefn.setName("nameProperty");
+ nameDefn.setRequiredType(PropertyType.NAME);
+ nameDefn.setMultiple(true);
+ propDefns.add(nameDefn);
+
+ JcrPropertyDefinitionTemplate pathDefn = new
JcrPropertyDefinitionTemplate(context);
+ pathDefn.setName("pathProperty");
+ pathDefn.setRequiredType(PropertyType.PATH);
+ pathDefn.setMultiple(true);
+ propDefns.add(pathDefn);
+
+ JcrPropertyDefinitionTemplate refDefn = new
JcrPropertyDefinitionTemplate(context);
+ refDefn.setName("referenceProperty");
+ refDefn.setRequiredType(PropertyType.REFERENCE);
+ refDefn.setMultiple(true);
+ propDefns.add(refDefn);
+
+ JcrPropertyDefinitionTemplate stringDefn = new
JcrPropertyDefinitionTemplate(context);
+ stringDefn.setName("stringProperty");
+ stringDefn.setRequiredType(PropertyType.STRING);
+ stringDefn.setMultiple(true);
+ propDefns.add(stringDefn);
+
+ JcrPropertyDefinitionTemplate undefinedDefn = new
JcrPropertyDefinitionTemplate(context);
+ undefinedDefn.setName("undefinedProperty");
+ undefinedDefn.setRequiredType(PropertyType.UNDEFINED);
+ undefinedDefn.setMultiple(true);
+ propDefns.add(undefinedDefn);
+
+ // Add the node type ...
+ Collection<NodeTypeDefinition> defns = new
ArrayList<NodeTypeDefinition>();
+ defns.add(nodeType);
+ rntm.registerNodeTypes(defns, false);
+ }
+
+ @Override
@Before
- public void before() throws Exception {
- MockitoAnnotations.initMocks(this);
- executionContext = new ExecutionContext();
- stub(cache.session()).toReturn(session);
- stub(cache.context()).toReturn(executionContext);
- stub(session.nodeTypeManager()).toReturn(nodeTypes);
+ public void beforeEach() throws Exception {
+ super.beforeEach();
+ context.getNamespaceRegistry().register("acme",
"http://example.com");
+ dateFactory = context.getValueFactories().getDateFactory();
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
true);
- stub(definition.getRequiredType()).toReturn(PropertyType.BOOLEAN);
- stub(definition.isMultiple()).toReturn(true);
- PropertyDefinitionId definitionId = new
PropertyDefinitionId(name("nodeTypeName"), name("propDefnName"),
-
PropertyType.BOOLEAN, true);
- stub(nodeTypes.getPropertyDefinition(definitionId)).toReturn(definition);
+ binaryValue = new byte[][] {"This is a binary value1".getBytes(),
"This is a binary value2".getBytes()};
+ dateValue = new DateTime[] {dateFactory.create(),
dateFactory.create().plusDays(1)};
+ doubleValue = new double[] {3.14159d, 1.0d};
+ longValue = new long[] {100L, 101L};
+ booleanValue = new boolean[] {true, false};
+ stringValue = new String[] {"stringValue1", "string value
2"};
+ nameValue = new String[] {"acme:SomeName1",
"acme:SomeName2"};
+ pathValue = new String[] {"/Cars/Hybrid/Toyota
Highlander/acme:SomethingElse", "/Cars/acme:Wow"};
- UUID uuid = UUID.randomUUID();
- propertyId = new PropertyId(uuid, JcrLexicon.MIMETYPE);
- prop = new JcrMultiValueProperty(cache, propertyId);
+ // Add the mixin to the 'Cars' node ...
+ cars = cache.findJcrNode(null, path("/Cars"));
+ cars.addMixin("mixinWithAllPropTypes");
- stub(cache.findPropertyInfo(propertyId)).toReturn(propertyInfo);
- stub(propertyInfo.getDefinitionId()).toReturn(definitionId);
- stub(propertyInfo.getPropertyType()).toReturn(PropertyType.BOOLEAN);
- stub(propertyInfo.isMultiValued()).toReturn(true);
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
+ altima = cache.findJcrNode(null, path("/Cars/Hybrid/Nissan Altima"));
+ altima.addMixin("mix:referenceable");
+
+ // Set each property ...
+ cars.setProperty("booleanProperty", values(booleanValue));
+ cars.setProperty("dateProperty", values(dateValue));
+ cars.setProperty("doubleProperty", values(doubleValue));
+ cars.setProperty("binaryProperty", values(binaryValue));
+ cars.setProperty("longProperty", values(longValue));
+ cars.setProperty("referenceProperty", values(new Node[] {altima}));
+ cars.setProperty("stringProperty", values(PropertyType.STRING,
stringValue));
+ cars.setProperty("pathProperty", values(PropertyType.PATH,
pathValue));
+ cars.setProperty("nameProperty", values(PropertyType.NAME,
nameValue));
+ cars.setProperty("undefinedProperty", values(PropertyType.STRING, new
String[] {"100", "200"}));
}
- protected Name name( String name ) {
- return executionContext.getValueFactories().getNameFactory().create(name);
+ protected Value[] values( boolean[] values ) throws Exception {
+ Value[] result = new Value[values.length];
+ for (int i = 0; i != values.length; ++i) {
+ result[i] = new JcrValue(context.getValueFactories(), cache,
PropertyType.BOOLEAN, values[i]);
+ }
+ return result;
}
- @Test
- public void shouldProvideAppropriateType() throws Exception {
- assertThat(prop.getType(), is(definition.getRequiredType()));
+ protected Value[] values( long[] values ) throws Exception {
+ Value[] result = new Value[values.length];
+ for (int i = 0; i != values.length; ++i) {
+ result[i] = new JcrValue(context.getValueFactories(), cache,
PropertyType.LONG, values[i]);
+ }
+ return result;
}
- @Test
- public void shouldProvidePropertyDefinition() throws Exception {
- assertThat(prop.getDefinition(), is((PropertyDefinition)definition));
+ protected Value[] values( double[] values ) throws Exception {
+ Value[] result = new Value[values.length];
+ for (int i = 0; i != values.length; ++i) {
+ result[i] = new JcrValue(context.getValueFactories(), cache,
PropertyType.DOUBLE, values[i]);
+ }
+ return result;
}
+ protected Value[] values( byte[][] values ) throws Exception {
+ Value[] result = new Value[values.length];
+ for (int i = 0; i != values.length; ++i) {
+ result[i] = new JcrValue(context.getValueFactories(), cache,
PropertyType.BINARY, values[i]);
+ }
+ return result;
+ }
+
+ protected Value[] values( DateTime[] values ) throws Exception {
+ Value[] result = new Value[values.length];
+ for (int i = 0; i != values.length; ++i) {
+ result[i] = new JcrValue(context.getValueFactories(), cache,
PropertyType.DATE, values[i].toCalendar());
+ }
+ return result;
+ }
+
+ protected Value[] values( Node[] values ) throws Exception {
+ Value[] result = new Value[values.length];
+ for (int i = 0; i != values.length; ++i) {
+ result[i] = new JcrValue(context.getValueFactories(), cache,
PropertyType.REFERENCE, values[i]);
+ }
+ return result;
+ }
+
+ protected Value[] values( int type,
+ String[] values ) throws Exception {
+ Value[] result = new Value[values.length];
+ for (int i = 0; i != values.length; ++i) {
+ result[i] = new JcrValue(context.getValueFactories(), cache, type,
values[i]);
+ }
+ return result;
+ }
+
@Test
public void shouldIndicateHasMultipleValues() throws Exception {
+ prop = cars.getProperty("booleanProperty");
PropertyDefinition def = prop.getDefinition();
- assertThat(def, notNullValue());
assertThat(def.isMultiple(), is(true));
}
@Test( expected = ValueFormatException.class )
public void shouldNotProvideBooleanForMultiValuedProperty() throws Exception {
+ prop = cars.getProperty("booleanProperty");
prop.getBoolean();
}
@Test( expected = ValueFormatException.class )
public void shouldNotProvideDateForMultiValuedProperty() throws Exception {
+ prop = cars.getProperty("dateProperty");
prop.getDate();
}
@Test( expected = ValueFormatException.class )
public void shouldNotProvideDoubleForMultiValuedProperty() throws Exception {
+ prop = cars.getProperty("doubleProperty");
prop.getDouble();
}
@Test( expected = ValueFormatException.class )
public void shouldNotProvideLongForMultiValuedProperty() throws Exception {
+ prop = cars.getProperty("longProperty");
prop.getLong();
}
@Test( expected = ValueFormatException.class )
public void shouldNotProvideStreamForMultiValuedProperty() throws Exception {
+ prop = cars.getProperty("binaryProperty");
prop.getStream();
}
@Test( expected = ValueFormatException.class )
public void shouldNotProvideStringForMultiValuedProperty() throws Exception {
+ prop = cars.getProperty("stringProperty");
prop.getString();
}
@Test( expected = ValueFormatException.class )
public void shouldNotProvideValue() throws Exception {
+ prop = cars.getProperty("stringProperty");
prop.getValue();
}
@Test
public void shouldProvideValues() throws Exception {
+ prop = cars.getProperty("booleanProperty");
Value[] vals = prop.getValues();
assertThat(vals, notNullValue());
- assertThat(vals.length, is(1));
+ assertThat(vals.length, is(2));
assertThat(vals[0].getBoolean(), is(true));
+ assertThat(vals[1].getBoolean(), is(false));
}
@Test( expected = ValueFormatException.class )
public void shouldNotProvideLength() throws Exception {
+ prop = cars.getProperty("stringProperty");
prop.getLength();
}
- @Test
- public void shouldProvideLengths() throws Exception {
- long[] lengths = prop.getLengths();
- assertThat(lengths, notNullValue());
- assertThat(lengths.length, is(1));
- assertThat(lengths[0], is(4L));
-
- Object value = "value";
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
value);
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
- stub(definition.getRequiredType()).toReturn(PropertyType.STRING);
- stub(definition.isMultiple()).toReturn(true);
- prop = new JcrMultiValueProperty(cache, propertyId);
- lengths = prop.getLengths();
- assertThat(lengths, notNullValue());
- assertThat(lengths.length, is(1));
- assertThat(lengths[0], is(5L));
-
- value = new Object();
- long expectedLength =
executionContext.getValueFactories().getBinaryFactory().create(value).getSize();
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
value);
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
- stub(definition.getRequiredType()).toReturn(PropertyType.STRING);
- stub(definition.isMultiple()).toReturn(true);
- prop = new JcrMultiValueProperty(cache, propertyId);
- lengths = prop.getLengths();
- assertThat(lengths, notNullValue());
- assertThat(lengths.length, is(1));
- assertThat(lengths[0], is(expectedLength));
-
- String[] values = new String[] {"value1", "value2",
"value 3 is longer"};
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
(Object[])values);
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
- stub(definition.getRequiredType()).toReturn(PropertyType.STRING);
- stub(definition.isMultiple()).toReturn(true);
- prop = new JcrMultiValueProperty(cache, propertyId);
- lengths = prop.getLengths();
- assertThat(lengths, notNullValue());
- assertThat(lengths.length, is(values.length));
- assertThat(lengths[0], is((long)values[0].length()));
- assertThat(lengths[1], is((long)values[1].length()));
- assertThat(lengths[2], is((long)values[2].length()));
- }
+ // @Test
+ // public void shouldProvideLengths() throws Exception {
+ // long[] lengths = prop.getLengths();
+ // assertThat(lengths, notNullValue());
+ // assertThat(lengths.length, is(1));
+ // assertThat(lengths[0], is(4L));
+ //
+ // Object value = "value";
+ // dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
value);
+ // stub(propertyInfo.getProperty()).toReturn(dnaProperty);
+ // stub(definition.getRequiredType()).toReturn(PropertyType.STRING);
+ // stub(definition.isMultiple()).toReturn(true);
+ // prop = new JcrMultiValueProperty(cache, propertyId);
+ // lengths = prop.getLengths();
+ // assertThat(lengths, notNullValue());
+ // assertThat(lengths.length, is(1));
+ // assertThat(lengths[0], is(5L));
+ //
+ // value = new Object();
+ // long expectedLength =
executionContext.getValueFactories().getBinaryFactory().create(value).getSize();
+ // dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
value);
+ // stub(propertyInfo.getProperty()).toReturn(dnaProperty);
+ // stub(definition.getRequiredType()).toReturn(PropertyType.STRING);
+ // stub(definition.isMultiple()).toReturn(true);
+ // prop = new JcrMultiValueProperty(cache, propertyId);
+ // lengths = prop.getLengths();
+ // assertThat(lengths, notNullValue());
+ // assertThat(lengths.length, is(1));
+ // assertThat(lengths[0], is(expectedLength));
+ //
+ // String[] values = new String[] {"value1", "value2",
"value 3 is longer"};
+ // dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
(Object[])values);
+ // stub(propertyInfo.getProperty()).toReturn(dnaProperty);
+ // stub(definition.getRequiredType()).toReturn(PropertyType.STRING);
+ // stub(definition.isMultiple()).toReturn(true);
+ // prop = new JcrMultiValueProperty(cache, propertyId);
+ // lengths = prop.getLengths();
+ // assertThat(lengths, notNullValue());
+ // assertThat(lengths.length, is(values.length));
+ // assertThat(lengths[0], is((long)values[0].length()));
+ // assertThat(lengths[1], is((long)values[1].length()));
+ // assertThat(lengths[2], is((long)values[2].length()));
+ // }
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java 2009-07-09 16:23:09 UTC
(rev 1081)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java 2009-07-09 16:26:04 UTC
(rev 1082)
@@ -4,13 +4,13 @@
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
* See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
+ * individual contributors.
*
* JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
* is licensed to you 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.
- *
+ *
* JBoss DNA 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
@@ -24,81 +24,51 @@
package org.jboss.dna.jcr;
import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.stub;
-import java.util.UUID;
-import javax.jcr.ItemNotFoundException;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.Path;
-import org.jboss.dna.jcr.cache.NodeInfo;
import org.junit.Before;
import org.junit.Test;
-import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoAnnotations.Mock;
/**
- * @author jverhaeg
+ *
*/
-public class JcrNodeTest {
+public class JcrNodeTest extends AbstractJcrTest {
- private UUID uuid;
- private JcrNode node;
- private ExecutionContext context;
- @Mock
- private SessionCache cache;
+ private AbstractJcrNode hybrid;
+ private AbstractJcrNode altima;
+ @Override
@Before
- public void before() throws Exception {
- MockitoAnnotations.initMocks(this);
-
- uuid = UUID.randomUUID();
- node = new JcrNode(cache, uuid);
-
- context = new ExecutionContext();
- stub(cache.context()).toReturn(context);
+ public void beforeEach() throws Exception {
+ super.beforeEach();
+ hybrid = cache.findJcrNode(null, path("/Cars/Hybrid"));
+ altima = cache.findJcrNode(null, path("/Cars/Hybrid/Nissan Altima"));
}
- protected Name name( String name ) {
- return context.getValueFactories().getNameFactory().create(name);
- }
+ @Test
+ public void shouldHavePath() throws Exception {
+ assertThat(altima.getPath(), is("/Cars/Hybrid/Nissan Altima"));
- protected Path path( String path ) {
- return context.getValueFactories().getPathFactory().create(path);
+ javax.jcr.Node altima2 = hybrid.addNode("Nissan Altima");
+ assertThat(altima2, is(notNullValue()));
+ assertThat(altima2.getPath(), is("/Cars/Hybrid/Nissan Altima[2]"));
}
- @Test( expected = ItemNotFoundException.class )
- public void shouldNotAllowAncestorDepthGreaterThanNodeDepth() throws Exception {
- NodeInfo info = mock(NodeInfo.class);
- stub(cache.findNodeInfo(uuid)).toReturn(info);
- stub(cache.getPathFor(info)).toReturn(path("/a/b/c/name[2]"));
- node.getAncestor(6);
- }
-
@Test
- public void shouldProvideDepth() throws Exception {
- NodeInfo info = mock(NodeInfo.class);
- stub(cache.findNodeInfo(uuid)).toReturn(info);
- stub(cache.getPathFor(info)).toReturn(path("/a/b/c/name[2]"));
- assertThat(node.getDepth(), is(4));
- }
+ public void shouldHaveSameNameSiblingIndex() throws Exception {
+ assertThat(altima.getIndex(), is(1));
- @Test
- public void shouldProvideIndex() throws Exception {
- stub(cache.getSnsIndexOf(uuid)).toReturn(1);
- assertThat(node.getIndex(), is(1));
+ javax.jcr.Node altima2 = hybrid.addNode("Nissan Altima");
+ assertThat(altima2, is(notNullValue()));
+ assertThat(altima2.getIndex(), is(2));
}
@Test
- public void shouldProvideName() throws Exception {
- stub(cache.getNameOf(uuid)).toReturn(name("name"));
- assertThat(node.getName(), is("name"));
+ public void shouldHaveNameThatExcludesSameNameSiblingIndex() throws Exception {
+ assertThat(altima.getName(), is("Nissan Altima"));
+ javax.jcr.Node altima2 = hybrid.addNode("Nissan Altima");
+ assertThat(altima2, is(notNullValue()));
+ assertThat(altima2.getPath(), is("/Cars/Hybrid/Nissan Altima[2]"));
+ assertThat(altima2.getName(), is("Nissan Altima"));
}
-
- @Test
- public void shouldProvidePath() throws Exception {
- stub(cache.getPathFor(uuid)).toReturn(path("/a/b/c/name[2]"));
- assertThat(node.getPath(), is("/a/b/c/name[2]"));
- }
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRootNodeTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRootNodeTest.java 2009-07-09 16:23:09
UTC (rev 1081)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRootNodeTest.java 2009-07-09 16:26:04
UTC (rev 1082)
@@ -26,76 +26,53 @@
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.stub;
-import java.util.UUID;
import javax.jcr.ItemNotFoundException;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.Path;
import org.junit.Before;
import org.junit.Test;
-import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoAnnotations.Mock;
/**
* @author jverhaeg
*/
-public class JcrRootNodeTest {
+public class JcrRootNodeTest extends AbstractJcrTest {
- private UUID uuid;
- private JcrRootNode root;
- private ExecutionContext context;
- @Mock
- private SessionCache cache;
+ private AbstractJcrNode rootNode;
+ @Override
@Before
- public void before() throws Exception {
- MockitoAnnotations.initMocks(this);
-
- uuid = UUID.randomUUID();
- root = new JcrRootNode(cache, uuid);
-
- context = new ExecutionContext();
- stub(cache.context()).toReturn(context);
+ public void beforeEach() throws Exception {
+ super.beforeEach();
+ rootNode = cache.findJcrRootNode();
}
- protected Name name( String name ) {
- return context.getValueFactories().getNameFactory().create(name);
- }
-
- protected Path path( String path ) {
- return context.getValueFactories().getPathFactory().create(path);
- }
-
@Test( expected = ItemNotFoundException.class )
public void shouldNotAllowAncestorDepthGreaterThanNodeDepth() throws Exception {
- root.getAncestor(1);
+ rootNode.getAncestor(1);
}
@Test
public void shouldHaveZeroDepth() throws Exception {
- assertThat(root.getDepth(), is(0));
+ assertThat(rootNode.getDepth(), is(0));
}
@Test
public void shouldIndicateIndexIsOne() throws Exception {
- assertThat(root.getIndex(), is(1));
+ assertThat(rootNode.getIndex(), is(1));
}
@Test
public void shouldHaveEmptyName() throws Exception {
- String name = root.getName();
+ String name = rootNode.getName();
assertThat(name, notNullValue());
assertThat(name.length(), is(0));
}
@Test( expected = ItemNotFoundException.class )
public void shouldHaveNoParent() throws Exception {
- root.getParent();
+ rootNode.getParent();
}
@Test
public void shouldProvidePath() throws Exception {
- assertThat(root.getPath(), is("/"));
+ assertThat(rootNode.getPath(), is("/"));
}
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java 2009-07-09 16:23:09
UTC (rev 1081)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java 2009-07-09 16:26:04
UTC (rev 1082)
@@ -74,7 +74,6 @@
@Before
public void beforeEach() throws Exception {
super.beforeEach();
-
}
@Override
@@ -89,6 +88,17 @@
// Make sure the path to the namespaces exists ...
graph.create("/jcr:system").and().create("/jcr:system/dna:namespaces").and();
+ // Set up the session attributes ...
+ sessionAttributes = new HashMap<String, Object>();
+ sessionAttributes.put("attribute1", "value1");
+
+ // Now create the workspace ...
+ SecurityContext mockSecurityContext = new MockSecurityContext(null,
+
Collections.singleton(JcrSession.DNA_WRITE_PERMISSION));
+ workspace = new JcrWorkspace(repository, workspaceName,
context.with(mockSecurityContext), sessionAttributes);
+
+ // Create the session and log in ...
+ session = (JcrSession)workspace.getSession();
}
@@ -126,7 +136,7 @@
@Test( expected = IllegalArgumentException.class )
public void shouldNotAllowCheckPermissionWithNoPath() throws Exception {
- session.checkPermission((String) null, "read");
+ session.checkPermission((String)null, "read");
}
@Test( expected = IllegalArgumentException.class )
@@ -224,7 +234,8 @@
Subject subject = new Subject(false, Collections.singleton(principal),
Collections.EMPTY_SET, Collections.EMPTY_SET);
LoginContext loginContext = mock(LoginContext.class);
stub(loginContext.getSubject()).toReturn(subject);
- Session session = new JcrSession(repository, workspace, context.with(new
JaasSecurityContext(loginContext)), sessionAttributes);
+ Session session = new JcrSession(repository, workspace, context.with(new
JaasSecurityContext(loginContext)),
+ sessionAttributes);
try {
assertThat(session.getUserID(), is("name"));
} finally {
@@ -236,8 +247,6 @@
public void shouldProvideRootNode() throws Exception {
Node root = session.getRootNode();
assertThat(root, notNullValue());
- UUID uuid = ((JcrRootNode)root).internalUuid();
- assertThat(uuid, notNullValue());
}
@Test
@@ -375,7 +384,8 @@
public void rootNodeShouldBeReferenceable() throws RepositoryException {
Node rootNode = session.getRootNode();
-
assertTrue(rootNode.getPrimaryNodeType().isNodeType(JcrMixLexicon.REFERENCEABLE.getString(context.getNamespaceRegistry())));
+ assertTrue(rootNode.getPrimaryNodeType()
+
.isNodeType(JcrMixLexicon.REFERENCEABLE.getString(context.getNamespaceRegistry())));
}
@Test
@@ -415,7 +425,7 @@
// The root node is referenceable in DNA
Node rootNode = session.getRootNode();
- UUID uuid = ((AbstractJcrNode)rootNode).internalUuid();
+ UUID uuid = ((AbstractJcrNode)rootNode).location.getUuid();
assertThat(rootNode.getUUID(), is(uuid.toString()));
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSingleValuePropertyTest.java
===================================================================
---
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSingleValuePropertyTest.java 2009-07-09
16:23:09 UTC (rev 1081)
+++
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSingleValuePropertyTest.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -26,157 +26,211 @@
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.stub;
+import static org.junit.Assert.fail;
+import java.io.ByteArrayInputStream;
import java.io.InputStream;
-import java.util.UUID;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
import javax.jcr.Node;
+import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.Value;
import javax.jcr.ValueFormatException;
import javax.jcr.nodetype.PropertyDefinition;
-import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.property.DateTime;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.Path;
-import org.jboss.dna.jcr.cache.PropertyInfo;
+import org.jboss.dna.graph.property.ValueFactory;
+import org.jboss.dna.jcr.nodetype.NodeTypeDefinition;
+import org.jboss.dna.jcr.nodetype.PropertyDefinitionTemplate;
import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Test;
-import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoAnnotations.Mock;
-/**
- * @author jverhaeg
- */
-public class JcrSingleValuePropertyTest {
+public class JcrSingleValuePropertyTest extends AbstractJcrTest {
- private PropertyId propertyId;
- private JcrSingleValueProperty prop;
- private ExecutionContext executionContext;
- private org.jboss.dna.graph.property.Property dnaProperty;
- @Mock
- private SessionCache cache;
- @Mock
- private JcrSession session;
- @Mock
- private PropertyInfo propertyInfo;
- @Mock
- private JcrPropertyDefinition definition;
- @Mock
- private JcrNodeTypeManager nodeTypes;
+ private Property prop;
+ private byte[] binaryValue;
+ private DateTime dateValue;
+ private double doubleValue;
+ private long longValue;
+ private String stringValue;
+ private boolean booleanValue;
+ private String nameValue;
+ private String pathValue;
+ private ValueFactory<String> stringFactory;
+ protected AbstractJcrNode cars;
+ protected AbstractJcrNode altima;
- @Before
- public void before() throws Exception {
- MockitoAnnotations.initMocks(this);
- executionContext = new ExecutionContext();
- stub(cache.session()).toReturn(session);
- stub(cache.context()).toReturn(executionContext);
- stub(session.nodeTypeManager()).toReturn(nodeTypes);
- stub(session.getExecutionContext()).toReturn(executionContext);
+ /**
+ * Initialize the expensive activities, and in particular the
RepositoryNodeTypeManager instance.
+ *
+ * @throws Exception
+ */
+ @BeforeClass
+ public static void beforeAll() throws Exception {
+ AbstractJcrTest.beforeAll();
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
"text/plain");
- stub(definition.getRequiredType()).toReturn(PropertyType.STRING);
- stub(definition.isMultiple()).toReturn(false);
- PropertyDefinitionId definitionId = new
PropertyDefinitionId(name("nodeTypeName"), name("propDefnName"),
- PropertyType.STRING,
false);
- stub(nodeTypes.getPropertyDefinition(definitionId)).toReturn(definition);
+ // Define the node definition that will have all the different kinds of
properties ...
+ JcrNodeTypeTemplate nodeType = new JcrNodeTypeTemplate(context);
+ nodeType.setMixin(true);
+ nodeType.setName("mixinWithAllPropTypes");
+ List<PropertyDefinitionTemplate> propDefns =
nodeType.getPropertyDefinitionTemplates();
- UUID uuid = UUID.randomUUID();
- propertyId = new PropertyId(uuid, JcrLexicon.MIMETYPE);
- prop = new JcrSingleValueProperty(cache, propertyId);
+ // Add a property for each type ...
+ JcrPropertyDefinitionTemplate binaryDefn = new
JcrPropertyDefinitionTemplate(context);
+ binaryDefn.setName("binaryProperty");
+ binaryDefn.setRequiredType(PropertyType.BINARY);
+ propDefns.add(binaryDefn);
- stub(cache.findPropertyInfo(propertyId)).toReturn(propertyInfo);
- stub(propertyInfo.getDefinitionId()).toReturn(definitionId);
- stub(propertyInfo.getPropertyType()).toReturn(PropertyType.STRING);
- stub(propertyInfo.isMultiValued()).toReturn(false);
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
- stub(propertyInfo.getPropertyName()).toReturn(dnaProperty.getName());
- }
+ JcrPropertyDefinitionTemplate booleanDefn = new
JcrPropertyDefinitionTemplate(context);
+ booleanDefn.setName("booleanProperty");
+ booleanDefn.setRequiredType(PropertyType.BOOLEAN);
+ propDefns.add(booleanDefn);
- protected Name name( String name ) {
- return executionContext.getValueFactories().getNameFactory().create(name);
+ JcrPropertyDefinitionTemplate dateDefn = new
JcrPropertyDefinitionTemplate(context);
+ dateDefn.setName("dateProperty");
+ dateDefn.setRequiredType(PropertyType.DATE);
+ propDefns.add(dateDefn);
+
+ JcrPropertyDefinitionTemplate doubleDefn = new
JcrPropertyDefinitionTemplate(context);
+ doubleDefn.setName("doubleProperty");
+ doubleDefn.setRequiredType(PropertyType.DOUBLE);
+ propDefns.add(doubleDefn);
+
+ JcrPropertyDefinitionTemplate longDefn = new
JcrPropertyDefinitionTemplate(context);
+ longDefn.setName("longProperty");
+ longDefn.setRequiredType(PropertyType.LONG);
+ propDefns.add(longDefn);
+
+ JcrPropertyDefinitionTemplate nameDefn = new
JcrPropertyDefinitionTemplate(context);
+ nameDefn.setName("nameProperty");
+ nameDefn.setRequiredType(PropertyType.NAME);
+ propDefns.add(nameDefn);
+
+ JcrPropertyDefinitionTemplate pathDefn = new
JcrPropertyDefinitionTemplate(context);
+ pathDefn.setName("pathProperty");
+ pathDefn.setRequiredType(PropertyType.PATH);
+ propDefns.add(pathDefn);
+
+ JcrPropertyDefinitionTemplate refDefn = new
JcrPropertyDefinitionTemplate(context);
+ refDefn.setName("referenceProperty");
+ refDefn.setRequiredType(PropertyType.REFERENCE);
+ propDefns.add(refDefn);
+
+ JcrPropertyDefinitionTemplate stringDefn = new
JcrPropertyDefinitionTemplate(context);
+ stringDefn.setName("stringProperty");
+ stringDefn.setRequiredType(PropertyType.STRING);
+ propDefns.add(stringDefn);
+
+ JcrPropertyDefinitionTemplate undefinedDefn = new
JcrPropertyDefinitionTemplate(context);
+ undefinedDefn.setName("undefinedProperty");
+ undefinedDefn.setRequiredType(PropertyType.UNDEFINED);
+ propDefns.add(undefinedDefn);
+
+ // Add the node type ...
+ Collection<NodeTypeDefinition> defns = new
ArrayList<NodeTypeDefinition>();
+ defns.add(nodeType);
+ rntm.registerNodeTypes(defns, false);
}
- @Test
- public void shouldProvideBoolean() throws Exception {
- stub(propertyInfo.getPropertyType()).toReturn(PropertyType.BOOLEAN);
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
"true");
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
- assertThat(prop.getBoolean(), is(true));
- assertThat(prop.getType(), is(PropertyType.BOOLEAN));
+ @Override
+ @Before
+ public void beforeEach() throws Exception {
+ super.beforeEach();
+ context.getNamespaceRegistry().register("acme",
"http://example.com");
+ stringFactory = context.getValueFactories().getStringFactory();
+
+ binaryValue = "This is a binary value".getBytes();
+ dateValue = context.getValueFactories().getDateFactory().create();
+ doubleValue = 3.14159d;
+ longValue = 100L;
+ booleanValue = true;
+ stringValue = "stringValue";
+ nameValue = "acme:SomeName";
+ pathValue = "/Cars/Hybrid/Toyota Highlander/acme:SomethingElse";
+
+ // Add the mixin to the 'Cars' node ...
+ cars = cache.findJcrNode(null, path("/Cars"));
+ cars.addMixin("mixinWithAllPropTypes");
+
+ altima = cache.findJcrNode(null, path("/Cars/Hybrid/Nissan Altima"));
+ altima.addMixin("mix:referenceable");
+
+ // Set each property ...
+ cars.setProperty("booleanProperty", booleanValue);
+ cars.setProperty("dateProperty", dateValue.toCalendar());
+ cars.setProperty("doubleProperty", doubleValue);
+ cars.setProperty("binaryProperty", new
ByteArrayInputStream(binaryValue));
+ cars.setProperty("longProperty", longValue);
+ cars.setProperty("referenceProperty", altima);
+ cars.setProperty("stringProperty", stringValue);
+ cars.setProperty("pathProperty", pathValue);
+ cars.setProperty("nameProperty", nameValue);
+ cars.setProperty("undefinedProperty", "100");
}
@Test
public void shouldIndicateHasSingleValue() throws Exception {
+ prop = cars.getProperty("booleanProperty");
PropertyDefinition def = prop.getDefinition();
assertThat(def.isMultiple(), is(false));
}
@Test
+ public void shouldProvideBoolean() throws Exception {
+ prop = cars.getProperty("booleanProperty");
+ assertThat(prop.getBoolean(), is(booleanValue));
+ assertThat(prop.getType(), is(PropertyType.BOOLEAN));
+ assertThat(prop.getString(), is(stringFactory.create(booleanValue)));
+ assertThat(prop.getLength(),
is((long)stringFactory.create(booleanValue).length()));
+ checkValue(prop);
+ }
+
+ @Test
public void shouldProvideDate() throws Exception {
- DateTime dnaDate =
executionContext.getValueFactories().getDateFactory().create();
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
dnaDate);
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
- stub(propertyInfo.getPropertyType()).toReturn(PropertyType.DATE);
- assertThat(prop.getDate(), is(dnaDate.toCalendar()));
- assertThat(prop.getLong(), is(dnaDate.getMilliseconds()));
+ prop = cars.getProperty("dateProperty");
+ assertThat(prop.getDate(), is(dateValue.toCalendar()));
+ assertThat(prop.getLong(), is(dateValue.getMilliseconds()));
+ assertThat(prop.getString(), is(stringFactory.create(dateValue)));
assertThat(prop.getType(), is(PropertyType.DATE));
- assertThat(prop.getName(),
is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
+ assertThat(prop.getLength(),
is((long)stringFactory.create(dateValue).length()));
+ checkValue(prop);
}
@Test
public void shouldProvideNode() throws Exception {
- UUID referencedUuid = UUID.randomUUID();
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
referencedUuid);
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
- stub(propertyInfo.getPropertyType()).toReturn(PropertyType.REFERENCE);
- AbstractJcrNode referencedNode = mock(AbstractJcrNode.class);
- stub(cache.findJcrNode(referencedUuid)).toReturn(referencedNode);
- assertThat(prop.getNode(), is((Node)referencedNode));
+ prop = cars.getProperty("referenceProperty");
+ assertThat(prop.getNode(), is((Node)altima));
assertThat(prop.getType(), is(PropertyType.REFERENCE));
- assertThat(prop.getName(),
is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
+ assertThat(prop.getString(), is(altima.getUUID()));
+ assertThat(prop.getLength(), is((long)altima.getUUID().length()));
+ checkValue(prop);
}
@Test
public void shouldProvideDouble() throws Exception {
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
1.0);
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
- stub(propertyInfo.getPropertyType()).toReturn(PropertyType.DOUBLE);
- assertThat(prop.getDouble(), is(1.0));
+ prop = cars.getProperty("doubleProperty");
+ assertThat(prop.getDouble(), is(doubleValue));
+ assertThat(prop.getString(), is(stringFactory.create(doubleValue)));
assertThat(prop.getType(), is(PropertyType.DOUBLE));
- assertThat(prop.getName(),
is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
1.0F);
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
- assertThat(prop.getDouble(), is(1.0));
- assertThat(prop.getType(), is(PropertyType.DOUBLE));
- assertThat(prop.getName(),
is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
+ assertThat(prop.getLength(),
is((long)stringFactory.create(doubleValue).length()));
+ checkValue(prop);
}
@Test
public void shouldProvideLong() throws Exception {
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
1);
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
- stub(propertyInfo.getPropertyType()).toReturn(PropertyType.LONG);
- assertThat(prop.getLong(), is(1L));
+ prop = cars.getProperty("longProperty");
+ assertThat(prop.getLong(), is(longValue));
+ assertThat(prop.getString(), is(stringFactory.create(longValue)));
assertThat(prop.getType(), is(PropertyType.LONG));
- assertThat(prop.getName(),
is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
-
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
1L);
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
- stub(propertyInfo.getPropertyType()).toReturn(PropertyType.LONG);
- assertThat(prop.getLong(), is(1L));
- assertThat(prop.getString(), is("1"));
- assertThat(prop.getType(), is(PropertyType.LONG));
- assertThat(prop.getName(),
is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
+ assertThat(prop.getLength(),
is((long)stringFactory.create(longValue).length()));
+ checkValue(prop);
}
@Test
public void shouldProvideStream() throws Exception {
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
new Object());
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
- stub(propertyInfo.getPropertyType()).toReturn(PropertyType.BINARY);
+ prop = cars.getProperty("binaryProperty");
assertThat(prop.getType(), is(PropertyType.BINARY));
- assertThat(prop.getName(),
is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
InputStream stream = prop.getStream();
try {
assertThat(stream, notNullValue());
@@ -185,95 +239,62 @@
stream.close();
}
}
+ assertThat(prop.getString(), is(stringFactory.create(binaryValue)));
+ assertThat(prop.getLength(), is((long)binaryValue.length)); // note this value!!
+ checkValue(prop);
}
@Test
public void shouldProvideString() throws Exception {
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
"value");
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
- stub(propertyInfo.getPropertyType()).toReturn(PropertyType.STRING);
- assertThat(prop.getString(), is("value"));
+ prop = cars.getProperty("stringProperty");
+ assertThat(prop.getString(), is(stringValue));
assertThat(prop.getType(), is(PropertyType.STRING));
- assertThat(prop.getName(),
is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
+ assertThat(prop.getLength(), is((long)stringValue.length()));
+ checkValue(prop);
}
@Test
- public void shouldAllowReferenceValue() throws Exception {
- UUID uuid = UUID.randomUUID();
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
uuid);
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
- stub(propertyInfo.getPropertyType()).toReturn(PropertyType.STRING);
- assertThat(prop.getString(), is(uuid.toString()));
- assertThat(prop.getType(), is(PropertyType.STRING));
- assertThat(prop.getName(),
is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
- }
-
- @Test
public void shouldAllowNameValue() throws Exception {
- executionContext.getNamespaceRegistry().register("acme",
"http://example.com");
- Name path =
executionContext.getValueFactories().getNameFactory().create("acme:something");
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
path);
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
- stub(propertyInfo.getPropertyType()).toReturn(PropertyType.NAME);
- assertThat(prop.getString(), is("acme:something"));
+ prop = cars.getProperty("nameProperty");
assertThat(prop.getType(), is(PropertyType.NAME));
- assertThat(prop.getName(),
is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
+ assertThat(prop.getString(), is(nameValue));
+ assertThat(prop.getLength(), is((long)nameValue.length()));
// Change the namespace registry ...
- executionContext.getNamespaceRegistry().register("acme2",
"http://example.com");
- assertThat(prop.getString(), is("acme2:something"));
+ context.getNamespaceRegistry().register("acme2",
"http://example.com");
+ assertThat(prop.getString(), is("acme2:SomeName"));
+ checkValue(prop);
}
@Test
public void shouldAllowPathValue() throws Exception {
- executionContext.getNamespaceRegistry().register("acme",
"http://example.com");
- Path path =
executionContext.getValueFactories().getPathFactory().create("/a/b/acme:c");
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
(Object)path);
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
- stub(propertyInfo.getPropertyType()).toReturn(PropertyType.PATH);
- assertThat(prop.getString(), is("/a/b/acme:c"));
+ prop = cars.getProperty("pathProperty");
assertThat(prop.getType(), is(PropertyType.PATH));
- assertThat(prop.getName(),
is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
+ assertThat(prop.getString(), is(pathValue));
// Change the namespace registry ...
- executionContext.getNamespaceRegistry().register("acme2",
"http://example.com");
- assertThat(prop.getString(), is("/a/b/acme2:c"));
+ context.getNamespaceRegistry().register("acme2",
"http://example.com");
+ assertThat(prop.getString(), is("/Cars/Hybrid/Toyota
Highlander/acme2:SomethingElse"));
+ checkValue(prop);
}
- @Test
- public void shouldProvideValue() throws Exception {
+ public void checkValue( Property prop ) throws Exception {
+ // Should provide a value and not multiple values ...
Value val = prop.getValue();
assertThat(val, notNullValue());
- }
+ assertThat(prop.getDefinition(), notNullValue());
- @Test( expected = ValueFormatException.class )
- public void shouldNotProvideValues() throws Exception {
- prop.getValues();
+ // Should not allow multiple-value methods ...
+ try {
+ prop.getValues();
+ fail("Should not be able to call 'getValues()' on a single-value
property");
+ } catch (ValueFormatException e) {
+ // expected
+ }
+ try {
+ prop.getLengths();
+ fail("Should not be able to call 'getValues()' on a single-value
property");
+ } catch (ValueFormatException e) {
+ // expected
+ }
}
- @Test
- public void shouldProvideLength() throws Exception {
- String dnaValue =
executionContext.getValueFactories().getStringFactory().create(dnaProperty.getFirstValue());
- assertThat(prop.getLength(), is((long)dnaValue.length()));
-
- dnaValue = "some other value";
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
dnaValue);
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
- assertThat(prop.getLength(), is((long)dnaValue.length()));
-
- Object obj = new Object();
- long binaryLength =
executionContext.getValueFactories().getBinaryFactory().create(obj).getSize();
- dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE,
obj);
- stub(propertyInfo.getProperty()).toReturn(dnaProperty);
- assertThat(prop.getLength(), is(binaryLength));
- }
-
- @Test( expected = ValueFormatException.class )
- public void shouldNotProvideLengths() throws Exception {
- prop.getLengths();
- }
-
- @Test
- public void shouldProvidePropertyDefinition() throws Exception {
- assertThat(prop.getDefinition(), notNullValue());
- }
-
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -23,753 +23,599 @@
*/
package org.jboss.dna.jcr;
-import static javax.jcr.PropertyType.DOUBLE;
-import static javax.jcr.PropertyType.LONG;
-import static javax.jcr.PropertyType.STRING;
-import static javax.jcr.PropertyType.UNDEFINED;
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.jboss.dna.graph.IsNodeWithChildren.hasChildren;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-import static org.junit.matchers.JUnitMatchers.hasItems;
-import static org.mockito.Mockito.stub;
-import java.io.File;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import javax.jcr.InvalidItemStateException;
-import javax.jcr.RepositoryException;
-import javax.jcr.nodetype.ConstraintViolationException;
-import org.jboss.dna.common.statistic.Stopwatch;
-import org.jboss.dna.common.util.StringUtil;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.Graph;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.Node;
-import org.jboss.dna.graph.Graph.Children;
-import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.Path;
-import org.jboss.dna.graph.property.PathNotFoundException;
-import org.jboss.dna.graph.property.Property;
-import org.jboss.dna.graph.property.ValueFactory;
-import org.jboss.dna.jcr.SessionCache.NodeEditor;
-import org.jboss.dna.jcr.Vehicles.Lexicon;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoAnnotations.Mock;
-import org.xml.sax.SAXException;
+public class SessionCacheTest extends AbstractJcrTest {
-/**
- *
- */
-public class SessionCacheTest {
-
- private ExecutionContext context;
- private RepositoryNodeTypeManager repoTypes;
- private JcrNodeTypeManager nodeTypes;
- private Stopwatch sw;
- private Graph store;
- private SessionCache cache;
- private Map<String, Graph> storesByName;
- private Map<String, SessionCache> cachesByName;
-
- @Mock
- private JcrSession session;
-
- @Before
- public void beforeEach() throws Exception {
- MockitoAnnotations.initMocks(this);
- sw = new Stopwatch();
- storesByName = new HashMap<String, Graph>();
- cachesByName = new HashMap<String, SessionCache>();
-
- context = new ExecutionContext();
- context.getNamespaceRegistry().register(Vehicles.Lexicon.Namespace.PREFIX,
Vehicles.Lexicon.Namespace.URI);
-
- stub(session.getExecutionContext()).toReturn(context);
- stub(session.namespaces()).toReturn(context.getNamespaceRegistry());
-
- // Load up all the node types ...
- repoTypes = new RepositoryNodeTypeManager(context);
- try {
- this.repoTypes.registerNodeTypes(new CndNodeTypeSource(new String[]
{"/org/jboss/dna/jcr/jsr_170_builtins.cnd",
- "/org/jboss/dna/jcr/dna_builtins.cnd"}));
- this.repoTypes.registerNodeTypes(new
NodeTemplateNodeTypeSource(Vehicles.getNodeTypes(context)));
- } catch (RepositoryException re) {
- re.printStackTrace();
- throw new IllegalStateException("Could not load node type definition
files", re);
- } catch (IOException ioe) {
- ioe.printStackTrace();
- throw new IllegalStateException("Could not access node type definition
files", ioe);
- }
-
- nodeTypes = new JcrNodeTypeManager(this.session, repoTypes);
- stub(session.nodeTypeManager()).toReturn(nodeTypes);
-
- // Now set up the graph and session cache ...
- store = getGraph("vehicles"); // imports the
"/src/test/resources/vehicles.xml" file
- cache = getCache("vehicles");
- }
-
- protected Graph createFrom( String repositoryName,
- String workspaceName,
- File file ) throws IOException, SAXException {
- InMemoryRepositorySource source = new InMemoryRepositorySource();
- source.setName(repositoryName);
- Graph graph = Graph.create(source, context);
- graph.createWorkspace().named(workspaceName);
-
- if (file != null) {
- graph.importXmlFrom(file).into("/");
- }
- return graph;
- }
-
- protected Graph getGraph( String name ) throws IOException, SAXException {
- Graph graph = storesByName.get(name);
- if (graph == null) {
- graph = createFrom(name, name + " workspace", new
File("src/test/resources/" + name + ".xml"));
- storesByName.put(name, graph);
- }
- return graph;
- }
-
- protected SessionCache getCache( String name ) throws IOException, SAXException {
- SessionCache cache = cachesByName.get(name);
- if (cache == null) {
- cache = new SessionCache(session, name + " workspace", context,
nodeTypes, getGraph(name));
- cachesByName.put(name, cache);
- }
- return cache;
- }
-
- protected Name name( String name ) {
- return context.getValueFactories().getNameFactory().create(name);
- }
-
- protected Path path( String path ) {
- return context.getValueFactories().getPathFactory().create(path);
- }
-
- protected Path.Segment segment( String segment ) {
- return context.getValueFactories().getPathFactory().createSegment(segment);
- }
-
- protected String pad( String name ) {
- return StringUtil.justifyLeft(name, 22, ' ');
- }
-
- protected void assertSameProperties( NodeInfo nodeInfo,
- Node dnaNode ) {
- UUID uuid = dnaNode.getLocation().getUuid();
- assertThat(nodeInfo.getUuid(), is(uuid));
- assertThat(nodeInfo.getOriginalLocation().getUuid(), is(uuid));
- Set<Name> propertyNames = nodeInfo.getPropertyNames();
- for (Name propertyName : propertyNames) {
- PropertyInfo info = nodeInfo.getProperty(propertyName);
- assertThat(info.getNodeUuid(), is(uuid));
- assertThat(info.getPropertyId().getNodeId(), is(uuid));
- assertThat(info.getPropertyId().getPropertyName(), is(propertyName));
- assertThat(info.getProperty().getName(), is(propertyName));
- Property actual = dnaNode.getProperty(propertyName);
- if (actual != null) {
- assertThat(info.getProperty().size(), is(actual.size()));
- assertThat(info.getProperty().getValuesAsArray(),
is(actual.getValuesAsArray()));
- } else {
- if (propertyName.equals(JcrLexicon.UUID)) {
- // check for a DNA UUID property ...
- actual = dnaNode.getProperty(DnaLexicon.UUID);
- if (actual != null) {
- assertThat(info.getProperty().size(), is(actual.size()));
- assertThat(info.getProperty().getValuesAsArray(),
is(actual.getValuesAsArray()));
- } else {
- fail("missing property \"" + propertyName +
"\" on " + dnaNode);
- }
- } else if (propertyName.equals(JcrLexicon.PRIMARY_TYPE)) {
- // This is okay
- } else if (propertyName.equals(DnaIntLexicon.MULTI_VALUED_PROPERTIES)) {
- // This is okay
- } else {
- fail("missing property \"" + propertyName +
"\" on " + dnaNode);
- }
- }
- }
- }
-
- protected JcrValue value( int propertyType,
- Object value ) {
- return new JcrValue(context.getValueFactories(), cache, propertyType, value);
- }
-
- protected void assertDoesExist( Graph graph,
- Location location ) {
- Node node = store.getNodeAt(location);
- assertThat(node, is(notNullValue()));
- assertThat(node.getLocation(), is(location));
- }
-
- protected void assertDoesNotExist( Graph graph,
- Location location ) {
- try {
- store.getNodeAt(location);
- fail("Shouldn't have found the node " + location);
- } catch (PathNotFoundException e) {
- // expected
- }
- }
-
- protected void assertDoesNotExist( Graph graph,
- Path path ) {
- try {
- store.getNodeAt(path);
- fail("Shouldn't have found the node " + path);
- } catch (PathNotFoundException e) {
- // expected
- }
- }
-
- protected void assertDoesNotExist( Graph graph,
- UUID uuid ) {
- try {
- store.getNodeAt(uuid);
- fail("Shouldn't have found the node " + uuid);
- } catch (PathNotFoundException e) {
- // expected
- }
- }
-
- protected void assertDoNotExist( Graph graph,
- List<Location> locations ) {
- for (Location location : locations)
- assertDoesNotExist(graph, location);
- }
-
- protected void assertDoesNotExist( SessionCache cache,
- UUID uuid ) throws InvalidItemStateException {
- assertThat(cache.findNodeInfoInCache(uuid), is(nullValue()));
- }
-
- protected void assertIsDeleted( SessionCache cache,
- UUID uuid ) {
- try {
- cache.findNodeInfoInCache(uuid);
- fail("Shouldn't have found the node " + uuid);
- } catch (InvalidItemStateException err) {
- // expected
- }
- }
-
- protected void assertDoesExist( SessionCache cache,
- UUID uuid ) throws InvalidItemStateException {
- NodeInfo info = cache.findNodeInfoInCache(uuid);
- assertThat(info, is(notNullValue()));
- assertThat(info.getUuid(), is(uuid));
- }
-
- protected void assertProperty( NodeInfo info,
- Name propertyName,
- int type,
- Name nodeTypeName,
- Name propertyDefinitionName,
- int definitionType,
- Object value ) {
- PropertyDefinitionId defnId = new PropertyDefinitionId(nodeTypeName,
propertyDefinitionName, definitionType, false);
- PropertyInfo propertyInfo = info.getProperty(propertyName);
- assertThat(propertyInfo, is(notNullValue()));
- assertThat(propertyInfo.getPropertyType(), is(type));
- assertThat(propertyInfo.getDefinitionId(), is(defnId));
- org.jboss.dna.graph.property.PropertyType dnaPropertyType =
PropertyTypeUtil.dnaPropertyTypeFor(type);
- // Check the value ...
- ValueFactory<?> factory =
context.getValueFactories().getValueFactory(dnaPropertyType);
- Object actual = factory.create(propertyInfo.getProperty().getFirstValue());
- assertThat(actual, is(value));
- }
-
- protected void assertProperty( NodeInfo info,
- Name propertyName,
- int type,
- Name nodeTypeName,
- Name propertyDefinitionName,
- int definitionType,
- Object... values ) {
- PropertyDefinitionId defnId = new PropertyDefinitionId(nodeTypeName,
propertyDefinitionName, definitionType, true);
- PropertyInfo propertyInfo = info.getProperty(propertyName);
- assertThat(propertyInfo, is(notNullValue()));
- assertThat(propertyInfo.getPropertyType(), is(type));
- assertThat(propertyInfo.getDefinitionId(), is(defnId));
- org.jboss.dna.graph.property.PropertyType dnaPropertyType =
PropertyTypeUtil.dnaPropertyTypeFor(type);
- // Check the values ...
- ValueFactory<?> factory =
context.getValueFactories().getValueFactory(dnaPropertyType);
- int i = 0;
- for (Object value : propertyInfo.getProperty()) {
- assertThat(factory.create(value), is(values[i++]));
- }
- }
-
- protected void assertNoProperty( NodeInfo info,
- Name propertyName ) {
- PropertyInfo propertyInfo = info.getProperty(propertyName);
- assertThat(propertyInfo, is(nullValue()));
- }
-
- @Test
- public void shouldCreateWithValidParameters() {
- assertThat(cache, is(notNullValue()));
- }
-
- @Test
- public void shouldFindNodeInfoForRootByUuid() throws Exception {
- Node root = store.getNodeAt("/");
- UUID rootUuid = root.getLocation().getUuid();
- NodeInfo rootInfo = cache.findNodeInfo(rootUuid);
- assertThat(rootInfo, is(notNullValue()));
- assertThat(rootInfo.getUuid(), is(rootUuid));
- assertThat(rootInfo.getDefinitionId().getNodeTypeName(),
is(name("dna:root")));
- assertThat(rootInfo.getDefinitionId().getChildDefinitionName(),
is(name("*")));
- assertThat(rootInfo.getPrimaryTypeName(), is(name("dna:root")));
- assertThat(rootInfo.getOriginalLocation().getPath().isRoot(), is(true));
- assertThat(rootInfo.getOriginalLocation().getUuid(), is(rootUuid));
- Set<Name> rootProperties = rootInfo.getPropertyNames();
- assertThat(rootProperties, hasItems(name("jcr:primaryType")));
- assertSameProperties(rootInfo, root);
-
- PropertyInfo info = rootInfo.getProperty(JcrLexicon.PRIMARY_TYPE);
- assertThat(info.getProperty().getFirstValue(),
is((Object)name("dna:root")));
- }
-
- @Test
- public void shouldRepeatedlyFindRootNodeInfoByUuid() throws Exception {
- Node root = store.getNodeAt("/");
- UUID rootUuid = root.getLocation().getUuid();
- for (int i = 0; i != 20; ++i) {
- NodeInfo rootInfo = cache.findNodeInfo(rootUuid);
- assertThat(rootInfo, is(notNullValue()));
- }
- }
-
- @Test
- public void shouldRepeatedlyFindRootNodeInfoByPath() throws Exception {
- String sourceName = "cars";
- Graph store = getGraph(sourceName);
- SessionCache cache = getCache(sourceName);
- Node root = store.getNodeAt("/");
- UUID rootUuid = root.getLocation().getUuid();
- NodeInfo nodeInfo = cache.findNodeInfoForRoot();
- assertThat(nodeInfo.getUuid(), is(rootUuid));
- for (int i = 0; i != 20; ++i) {
- sw.start();
- assertThat(nodeInfo, is(sameInstance(cache.findNodeInfoForRoot())));
- sw.stop();
- assertThat(nodeInfo, is(sameInstance(cache.findNodeInfo(rootUuid))));
- }
- // System.out.println(pad(sourceName) + " ==> " +
sw.getSimpleStatistics());
- }
-
- @Test
- public void shouldRepeatedlyFindRootNodeInfoByUuidFromVehiclesSource() throws
Exception {
- String sourceName = "vehicles";
- Graph store = getGraph(sourceName);
- SessionCache cache = getCache(sourceName);
- sw.start();
- Node root = store.getNodeAt("/");
- sw.stop();
- UUID rootUuid = root.getLocation().getUuid();
- for (int i = 0; i != 20; ++i) {
- sw.start();
- NodeInfo rootInfo = cache.findNodeInfo(rootUuid);
- sw.stop();
- assertThat(rootInfo, is(notNullValue()));
- }
- // System.out.println(pad(sourceName) + " ==> " +
sw.getSimpleStatistics());
- }
-
- @Test
- public void shouldRepeatedlyFindRootNodeInfoByUuidFromSourceWithPrimaryTypes() throws
Exception {
- String sourceName = "repositoryForTckTests";
- Graph store = getGraph(sourceName);
- SessionCache cache = getCache(sourceName);
- sw.start();
- Node root = store.getNodeAt("/");
- sw.stop();
- UUID rootUuid = root.getLocation().getUuid();
- for (int i = 0; i != 20; ++i) {
- sw.start();
- NodeInfo rootInfo = cache.findNodeInfo(rootUuid);
- sw.stop();
- assertThat(rootInfo, is(notNullValue()));
- }
- // System.out.println(pad(sourceName) + " ==> " +
sw.getSimpleStatistics());
- }
-
- @Test
- public void shouldFindChildrenInNodeInfoForRoot() throws Exception {
- NodeInfo root = cache.findNodeInfoForRoot();
- Children children = root.getChildren();
- assertThat(children, is(notNullValue()));
- assertThat(children.size(), is(1));
- assertThat(children.getChild(segment("vehix:Vehicles")),
is(notNullValue()));
- }
-
- @Test
- public void shouldFindNodeInfoForNonRootNodeByPath() throws Exception {
- String sourceName = "vehicles";
- Graph store = getGraph(sourceName);
- SessionCache cache = getCache(sourceName);
- // Get the root ...
- NodeInfo root = cache.findNodeInfoForRoot();
-
- // Now try to load a node that is well-below the root ...
- Path lr3Path = path("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land
Rover LR3");
- Node lr3Node = store.getNodeAt(lr3Path);
- sw.start();
- NodeInfo lr3 = cache.findNodeInfo(root.getUuid(), lr3Path);
- sw.stop();
- assertThat(lr3.getUuid(), is(lr3Node.getLocation().getUuid()));
- assertSameProperties(lr3, lr3Node);
- // System.out.println(pad(sourceName) + " ==> " +
sw.getSimpleStatistics());
-
- // Verify that this loaded all the intermediate nodes, by walking up ...
- NodeInfo info = lr3;
- while (true) {
- UUID parent = info.getParent();
- if (parent == null) {
- // then we should be at the root ...
- assertThat(info.getUuid(), is(root.getUuid()));
- break;
- }
- // Otherwise, we're not at the root, so we should find the parent ...
- info = cache.findNodeInfoInCache(parent);
- assertThat(info, is(notNullValue()));
- }
- }
-
- @Test
- public void shouldFindInfoForNodeUsingRelativePathFromRoot() throws Exception {
- String sourceName = "vehicles";
- Graph store = getGraph(sourceName);
- SessionCache cache = getCache(sourceName);
-
- // Verify that the node does exist in the source ...
- Path lr3AbsolutePath =
path("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover LR3");
- Node lr3Node = store.getNodeAt(lr3AbsolutePath);
-
- // Get the root ...
- NodeInfo root = cache.findNodeInfoForRoot();
-
- // Now try to load a node that is well-below the root ...
- Path lr3Path = path("vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land
Rover LR3");
- assertThat(lr3Path.isAbsolute(), is(false));
- NodeInfo lr3 = cache.findNodeInfo(root.getUuid(), lr3Path);
- assertThat(lr3.getUuid(), is(lr3Node.getLocation().getUuid()));
- assertSameProperties(lr3, lr3Node);
-
- Path recoveredPath = cache.getPathFor(lr3);
- assertThat(recoveredPath, is(lr3AbsolutePath));
- }
-
- @Test
- public void shouldFindInfoForNodeUsingRelativePathFromNonRoot() throws Exception {
- // Verify that the node does exist in the source ...
- Path carsAbsolutePath = path("/vehix:Vehicles/vehix:Cars");
- Node carsNode = store.getNodeAt(carsAbsolutePath);
- Path lr3AbsolutePath =
path("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover LR3");
- Node lr3Node = store.getNodeAt(lr3AbsolutePath);
- Path b787AbsolutePath =
path("/vehix:Vehicles/vehix:Aircraft/vehix:Commercial/vehix:Boeing 787");
- Node b787Node = store.getNodeAt(b787AbsolutePath);
-
- // Get the root ...
- NodeInfo root = cache.findNodeInfoForRoot();
-
- // Now try to load the cars node ...
- Path carsPath = path("vehix:Vehicles/vehix:Cars");
- assertThat(carsPath.isAbsolute(), is(false));
- NodeInfo cars = cache.findNodeInfo(root.getUuid(), carsPath);
- assertThat(cars.getUuid(), is(carsNode.getLocation().getUuid()));
- assertSameProperties(cars, carsNode);
-
- // Now try to find the LR3 node relative to the car ...
- Path lr3Path = path("vehix:Utility/vehix:Land Rover LR3");
- assertThat(lr3Path.isAbsolute(), is(false));
- NodeInfo lr3 = cache.findNodeInfo(cars.getUuid(), lr3Path);
- assertThat(lr3.getUuid(), is(lr3Node.getLocation().getUuid()));
- assertSameProperties(lr3, lr3Node);
-
- // Now try to find the "Boeing 787" node relative to the LR3 node ...
- Path b787Path = path("../../../vehix:Aircraft/vehix:Commercial/vehix:Boeing
787");
- assertThat(b787Path.isAbsolute(), is(false));
- assertThat(b787Path.isNormalized(), is(true));
- NodeInfo b787 = cache.findNodeInfo(lr3.getUuid(), b787Path);
- assertThat(b787.getUuid(), is(b787Node.getLocation().getUuid()));
- assertSameProperties(b787, b787Node);
-
- assertThat(cache.getPathFor(cars), is(carsAbsolutePath));
- assertThat(cache.getPathFor(lr3), is(lr3AbsolutePath));
- assertThat(cache.getPathFor(b787), is(b787AbsolutePath));
- }
-
- @Test
- public void shouldFindJcrNodeUsingAbsolutePaths() throws Exception {
- // Verify that the node does exist in the source ...
- Path carsAbsolutePath = path("/vehix:Vehicles/vehix:Cars");
- Node carsNode = store.getNodeAt(carsAbsolutePath);
- Path lr3AbsolutePath =
path("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover LR3");
- Node lr3Node = store.getNodeAt(lr3AbsolutePath);
- Path b787AbsolutePath =
path("/vehix:Vehicles/vehix:Aircraft/vehix:Commercial/vehix:Boeing 787");
- Node b787Node = store.getNodeAt(b787AbsolutePath);
-
- // Get the root ...
- NodeInfo root = cache.findNodeInfoForRoot();
-
- // Now try to load the cars node ...
- Path carsPath = path("vehix:Vehicles/vehix:Cars");
- assertThat(carsPath.isAbsolute(), is(false));
- AbstractJcrNode carJcrNode = cache.findJcrNode(root.getUuid(),
carsAbsolutePath);
- assertThat(carJcrNode.internalUuid(), is(carsNode.getLocation().getUuid()));
- NodeInfo cars = cache.findNodeInfo(root.getUuid(), carsPath);
- assertThat(cars.getUuid(), is(carsNode.getLocation().getUuid()));
- assertSameProperties(cars, carsNode);
-
- // Now try to find the LR3 node relative to the car ...
- Path lr3Path = path("vehix:Utility/vehix:Land Rover LR3");
- assertThat(lr3Path.isAbsolute(), is(false));
- AbstractJcrNode lr3JcrNode = cache.findJcrNode(root.getUuid(), lr3AbsolutePath);
- assertThat(lr3JcrNode.internalUuid(), is(lr3Node.getLocation().getUuid()));
- NodeInfo lr3 = cache.findNodeInfo(cars.getUuid(), lr3Path);
- assertThat(lr3.getUuid(), is(lr3Node.getLocation().getUuid()));
- assertSameProperties(lr3, lr3Node);
-
- // Now try to find the "Boeing 787" node relative to the LR3 node ...
- Path b787Path = path("../../../vehix:Aircraft/vehix:Commercial/vehix:Boeing
787");
- assertThat(b787Path.isAbsolute(), is(false));
- assertThat(b787Path.isNormalized(), is(true));
- AbstractJcrNode b787JcrNode = cache.findJcrNode(root.getUuid(),
b787AbsolutePath);
- assertThat(b787JcrNode.internalUuid(), is(b787Node.getLocation().getUuid()));
- NodeInfo b787 = cache.findNodeInfo(lr3.getUuid(), b787Path);
- assertThat(b787.getUuid(), is(b787Node.getLocation().getUuid()));
- assertSameProperties(b787, b787Node);
-
- assertThat(cache.getPathFor(cars), is(carsAbsolutePath));
- assertThat(cache.getPathFor(lr3), is(lr3AbsolutePath));
- assertThat(cache.getPathFor(b787), is(b787AbsolutePath));
- }
-
- @Test
- public void shouldDeleteLeafNode() throws Exception {
- // Find the state of some Graph nodes we'll be using in the test ...
- Node utility =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Utility");
- Node lr2Node =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover
LR2");
- Node lr3Node =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover
LR3");
- int numChildrenOfUtility = utility.getChildren().size();
- assertThat(numChildrenOfUtility, is(4));
- assertThat(utility.getChildren(), hasChildren(segment("vehix:Land Rover
LR2"),
- segment("vehix:Land Rover
LR3"),
- segment("vehix:Hummer
H3"),
- segment("vehix:Ford
F-150")));
-
- // Now get the editor for the 'vehix:Utility' node ...
- NodeEditor editor = cache.getEditorFor(utility.getLocation().getUuid());
- assertThat(editor, is(notNullValue()));
-
- // Destroy the LR3 node, which is a leaf ...
- editor.destroyChild(lr3Node.getLocation().getUuid());
-
- // Verify that the store has not yet been changed ...
- assertDoesExist(store, lr3Node.getLocation());
-
- // Save the session and verify that the node was deleted ...
- cache.save();
- Node utilityNode2 = store.getNodeAt(utility.getLocation());
- assertThat(utilityNode2.getChildren().size(), is(numChildrenOfUtility - 1));
- assertThat(utilityNode2.getChildren(), hasChildren(segment("vehix:Land Rover
LR2"), // no LR3!
- segment("vehix:Hummer
H3"),
- segment("vehix:Ford
F-150")));
- // Should no longer find the LR3 node in the graph ...
- assertDoesNotExist(store, lr3Node.getLocation().getUuid());
- assertDoesExist(store, lr2Node.getLocation());
- }
-
- @Test
- public void shouldDeleteNonLeafNode() throws Exception {
- // Find the state of some Graph nodes we'll be using in the test ...
- Node carsNode = store.getNodeAt("/vehix:Vehicles/vehix:Cars");
- Node utility =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Utility");
- Node hybrid =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Hybrid");
- Node luxury =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Luxury");
- Node sports =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Sports");
- Node lr3 =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover
LR3");
- Node lr2 =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover
LR2");
- Node f150 =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Ford F-150");
- int numChildrenOfCars = carsNode.getChildren().size();
- assertThat(numChildrenOfCars, is(4));
- assertThat(carsNode.getChildren(),
hasChildren(segment("vehix:Hybrid"),
-
segment("vehix:Sports"),
-
segment("vehix:Luxury"),
-
segment("vehix:Utility")));
-
- // Load the LR2 and Hummer nodes ...
- NodeInfo h3i = cache.findNodeInfo(utility.getLocation().getUuid(),
path("vehix:Hummer H3"));
- NodeInfo lr2i = cache.findNodeInfo(utility.getLocation().getUuid(),
path("vehix:Land Rover LR2"));
- assertThat(h3i, is(notNullValue()));
- assertThat(lr2i, is(notNullValue()));
- assertThat(lr2i.getUuid(), is(lr2.getLocation().getUuid()));
-
- // Now get the editor for the 'vehix:Cars' node ...
- NodeEditor editor = cache.getEditorFor(carsNode.getLocation().getUuid());
- assertThat(editor, is(notNullValue()));
-
- // Destroy the Utility node, which is NOT a leaf ...
- editor.destroyChild(utility.getLocation().getUuid());
-
- // Verify that the store has not yet been changed ...
- assertDoesExist(store, utility.getLocation());
-
- // ... but the utility node and its two loaded children have been marked for
deletion ...
- assertIsDeleted(cache, utility.getLocation().getUuid());
- assertIsDeleted(cache, h3i.getUuid());
- assertIsDeleted(cache, lr2i.getUuid());
-
- // Save the session and verify that the Utility node and its children were
deleted ...
- cache.save();
- Node carsNode2 = store.getNodeAt(carsNode.getLocation());
- assertThat(carsNode2.getChildren().size(), is(numChildrenOfCars - 1));
- assertThat(carsNode2.getChildren(),
- hasChildren(segment("vehix:Hybrid"),
segment("vehix:Sports"), segment("vehix:Luxury")));
- // Should no longer find the Utility node in the graph ...
- assertDoesNotExist(store, utility.getLocation());
- assertDoesNotExist(cache, utility.getLocation().getUuid());
- assertDoesNotExist(cache, h3i.getUuid());
- assertDoesNotExist(cache, lr2i.getUuid());
- assertDoesNotExist(cache, lr3.getLocation().getUuid());
- assertDoesNotExist(cache, f150.getLocation().getUuid());
- assertDoNotExist(store, utility.getChildren());
- assertDoesExist(store, hybrid.getLocation());
- assertDoesExist(store, luxury.getLocation());
- assertDoesExist(store, sports.getLocation());
- }
-
- @Test
- public void shouldGetExistingPropertyOnExistingNode() throws Exception {
- NodeInfo root = cache.findNodeInfoForRoot();
- NodeInfo lr3 = cache.findNodeInfo(root.getUuid(),
path("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover LR3"));
- assertProperty(lr3, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING,
"LR3");
- assertProperty(lr3, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING,
"Land Rover");
- assertProperty(lr3, Lexicon.YEAR, LONG, Lexicon.CAR, Lexicon.YEAR, LONG, 2008L);
- assertProperty(lr3, Lexicon.MSRP, STRING, Lexicon.CAR, Lexicon.MSRP, STRING,
"$48,525");
-
- NodeInfo db9 = cache.findNodeInfo(root.getUuid(),
path("/vehix:Vehicles/vehix:Cars/vehix:Sports/vehix:Aston Martin DB9"));
- assertProperty(db9, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING,
"DB9");
- assertProperty(db9, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING,
"Aston Martin");
- assertProperty(db9, Lexicon.LENGTH_IN_INCHES, DOUBLE, Lexicon.CAR,
Lexicon.LENGTH_IN_INCHES, DOUBLE, 185.5D);
-
- NodeInfo b878 = cache.findNodeInfo(root.getUuid(),
-
path("/vehix:Vehicles/vehix:Aircraft/vehix:Commercial/vehix:Boeing 787"));
- assertProperty(b878, Lexicon.MODEL, STRING, Lexicon.AIRCRAFT, Lexicon.MODEL,
STRING, "787-3");
- assertProperty(b878, Lexicon.MAKER, STRING, Lexicon.AIRCRAFT, Lexicon.MAKER,
STRING, "Boeing");
- assertProperty(b878, Lexicon.INTRODUCED, LONG, Lexicon.AIRCRAFT,
Lexicon.INTRODUCED, LONG, 2009L);
- assertProperty(b878, Lexicon.EMPTY_WEIGHT, STRING, JcrNtLexicon.UNSTRUCTURED,
name("*"), UNDEFINED, "223000lb");
-
- }
-
- @Test
- public void shouldNotFindNonExistantPropertyOnExistingNode() throws Exception {
- NodeInfo root = cache.findNodeInfoForRoot();
- NodeInfo lr3 = cache.findNodeInfo(root.getUuid(),
path("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover LR3"));
- assertProperty(lr3, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING,
"LR3");
- assertProperty(lr3, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING,
"Land Rover");
- assertNoProperty(lr3, Lexicon.LENGTH_IN_INCHES);
- assertNoProperty(lr3, Lexicon.INTRODUCED);
- }
-
- @Test
- public void shouldSetNewValueOnExistingPropertyOnExistingNode() throws Exception {
- NodeInfo root = cache.findNodeInfoForRoot();
- NodeInfo lr3 = cache.findNodeInfo(root.getUuid(),
path("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover LR3"));
- assertProperty(lr3, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING,
"LR3");
- assertProperty(lr3, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING,
"Land Rover");
- assertNoProperty(lr3, Lexicon.LENGTH_IN_INCHES);
-
- SessionCache.NodeEditor editor = cache.getEditorFor(lr3.getUuid());
- editor.setProperty(Lexicon.LENGTH_IN_INCHES, value(DOUBLE, 100.0D));
- }
-
- @Test
- public void shouldSetNewPropertyOnExistingNode() throws Exception {
- NodeInfo root = cache.findNodeInfoForRoot();
- NodeInfo db9 = cache.findNodeInfo(root.getUuid(),
path("/vehix:Vehicles/vehix:Cars/vehix:Sports/vehix:Aston Martin DB9"));
- assertProperty(db9, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING,
"DB9");
- assertProperty(db9, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING,
"Aston Martin");
- assertProperty(db9, Lexicon.LENGTH_IN_INCHES, DOUBLE, Lexicon.CAR,
Lexicon.LENGTH_IN_INCHES, DOUBLE, 185.5D);
-
- SessionCache.NodeEditor editor = cache.getEditorFor(db9.getUuid());
- editor.setProperty(Lexicon.LENGTH_IN_INCHES, value(DOUBLE, 100.0D));
- }
-
- @Test( expected = ConstraintViolationException.class )
- public void shouldFailToSetPropertyToInvalidValuesOnExistingNode() throws Exception
{
- NodeInfo root = cache.findNodeInfoForRoot();
- NodeInfo db9 = cache.findNodeInfo(root.getUuid(),
path("/vehix:Vehicles/vehix:Cars/vehix:Sports/vehix:Aston Martin DB9"));
- assertProperty(db9, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING,
"DB9");
- assertProperty(db9, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING,
"Aston Martin");
- assertProperty(db9, Lexicon.LENGTH_IN_INCHES, DOUBLE, Lexicon.CAR,
Lexicon.LENGTH_IN_INCHES, DOUBLE, 185.5D);
-
- SessionCache.NodeEditor editor = cache.getEditorFor(db9.getUuid());
- editor.setProperty(Lexicon.LENGTH_IN_INCHES, value(STRING, "This is not a
valid double"));
- }
-
- @Test
- public void shouldRemoveExistingPropertyOnExistingNode() throws Exception {
- NodeInfo root = cache.findNodeInfoForRoot();
- NodeInfo db9 = cache.findNodeInfo(root.getUuid(),
path("/vehix:Vehicles/vehix:Cars/vehix:Sports/vehix:Aston Martin DB9"));
- assertProperty(db9, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING,
"DB9");
- assertProperty(db9, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING,
"Aston Martin");
- assertProperty(db9, Lexicon.LENGTH_IN_INCHES, DOUBLE, Lexicon.CAR,
Lexicon.LENGTH_IN_INCHES, DOUBLE, 185.5D);
-
- UUID db9uuid = db9.getUuid();
- SessionCache.NodeEditor editor = cache.getEditorFor(db9uuid);
- editor.removeProperty(Lexicon.LENGTH_IN_INCHES);
-
- db9 = cache.findNodeInfo(db9uuid);
- assertNoProperty(db9, Lexicon.LENGTH_IN_INCHES);
-
- db9 = cache.findNodeInfo(root.getUuid(),
path("/vehix:Vehicles/vehix:Cars/vehix:Sports/vehix:Aston Martin DB9"));
- assertNoProperty(db9, Lexicon.LENGTH_IN_INCHES);
- }
-
- protected void walkInfosForNodesUnder( NodeInfo parentInfo,
- Stopwatch sw ) throws Exception {
- for (ChildNode child : parentInfo.getChildren()) {
- sw.start();
- NodeInfo childInfo = cache.findNodeInfo(child.getUuid());
- cache.getPathFor(childInfo);
- sw.stop();
-
- // Walk the infos for nodes under the child (this is recursive) ...
- walkInfosForNodesUnder(childInfo, sw);
- }
- }
-
- @Test
- public void shouldFindInfoForAllNodesInGraph() throws Exception {
- for (int i = 0; i != 3; ++i) {
- Stopwatch sw = new Stopwatch();
-
- // Get the root ...
- sw.start();
- NodeInfo root = cache.findNodeInfoForRoot();
- cache.getPathFor(root);
- sw.stop();
-
- // Walk the infos for nodes under the root (this is recursive) ...
- walkInfosForNodesUnder(root, sw);
- System.out.println("Statistics for walking nodes using SessionCache:
" + sw.getSimpleStatistics());
- }
- }
+ // @Override
+ // @Before
+ // public void beforeEach() throws Exception {
+ // super.beforeEach();
+ // }
+ //
+ // protected Graph createFrom( String repositoryName,
+ // String workspaceName,
+ // File file ) throws IOException, SAXException {
+ // InMemoryRepositorySource source = new InMemoryRepositorySource();
+ // source.setName(repositoryName);
+ // Graph graph = Graph.create(source, context);
+ // graph.createWorkspace().named(workspaceName);
+ //
+ // if (file != null) {
+ // graph.importXmlFrom(file).into("/");
+ // }
+ // return graph;
+ // }
+ //
+ // protected Graph getGraph( String name ) throws IOException, SAXException {
+ // Graph graph = storesByName.get(name);
+ // if (graph == null) {
+ // graph = createFrom(name, name + " workspace", new
File("src/test/resources/" + name + ".xml"));
+ // storesByName.put(name, graph);
+ // }
+ // return graph;
+ // }
+ //
+ // protected SessionCache getCache( String name ) throws IOException, SAXException {
+ // SessionCache cache = cachesByName.get(name);
+ // if (cache == null) {
+ // cache = new SessionCache(session, name + " workspace", context,
nodeTypes, getGraph(name));
+ // cachesByName.put(name, cache);
+ // }
+ // return cache;
+ // }
+ //
+ // protected Name name( String name ) {
+ // return context.getValueFactories().getNameFactory().create(name);
+ // }
+ //
+ // protected Path path( String path ) {
+ // return context.getValueFactories().getPathFactory().create(path);
+ // }
+ //
+ // protected Path.Segment segment( String segment ) {
+ // return context.getValueFactories().getPathFactory().createSegment(segment);
+ // }
+ //
+ // protected String pad( String name ) {
+ // return StringUtil.justifyLeft(name, 22, ' ');
+ // }
+ //
+ // protected void assertSameProperties( Node<JcrNodePayload,
JcrPropertyPayload> nodeInfo,
+ // org.jboss.dna.graph.Node dnaNode ) {
+ // assertThat(nodeInfo.getLocation(), is(dnaNode.getLocation()));
+ // Set<Name> propertyNames = nodeInfo.getPropertyNames();
+ // for (Name propertyName : propertyNames) {
+ // PropertyInfo<JcrPropertyPayload> info = nodeInfo.getProperty(propertyName);
+ // assertThat(info.getName(), is(propertyName));
+ // assertThat(info.getProperty().getName(), is(propertyName));
+ // Property actual = dnaNode.getProperty(propertyName);
+ // if (actual != null) {
+ // assertThat(info.getProperty().size(), is(actual.size()));
+ // assertThat(info.getProperty().getValuesAsArray(), is(actual.getValuesAsArray()));
+ // } else {
+ // if (propertyName.equals(JcrLexicon.UUID)) {
+ // // check for a DNA UUID property ...
+ // actual = dnaNode.getProperty(DnaLexicon.UUID);
+ // if (actual != null) {
+ // assertThat(info.getProperty().size(), is(actual.size()));
+ // assertThat(info.getProperty().getValuesAsArray(), is(actual.getValuesAsArray()));
+ // } else {
+ // fail("missing property \"" + propertyName + "\" on "
+ dnaNode);
+ // }
+ // } else if (propertyName.equals(JcrLexicon.PRIMARY_TYPE)) {
+ // // This is okay
+ // } else if (propertyName.equals(DnaIntLexicon.MULTI_VALUED_PROPERTIES)) {
+ // // This is okay
+ // } else {
+ // fail("missing property \"" + propertyName + "\" on "
+ dnaNode);
+ // }
+ // }
+ // }
+ // }
+ //
+ // protected JcrValue value( int propertyType,
+ // Object value ) {
+ // return new JcrValue(context.getValueFactories(), cache, propertyType, value);
+ // }
+ //
+ // protected void assertDoesExist( Graph graph,
+ // Location location ) {
+ // org.jboss.dna.graph.Node node = store.getNodeAt(location);
+ // assertThat(node, is(notNullValue()));
+ // assertThat(node.getLocation(), is(location));
+ // }
+ //
+ // protected void assertDoesNotExist( Graph graph,
+ // Location location ) {
+ // try {
+ // store.getNodeAt(location);
+ // fail("Shouldn't have found the node " + location);
+ // } catch (PathNotFoundException e) {
+ // // expected
+ // }
+ // }
+ //
+ // protected void assertDoesNotExist( Graph graph,
+ // Path path ) {
+ // try {
+ // store.getNodeAt(path);
+ // fail("Shouldn't have found the node " + path);
+ // } catch (PathNotFoundException e) {
+ // // expected
+ // }
+ // }
+ //
+ // protected void assertDoNotExist( Graph graph,
+ // List<Location> locations ) {
+ // for (Location location : locations)
+ // assertDoesNotExist(graph, location);
+ // }
+ //
+ // protected void assertProperty(
org.jboss.dna.graph.session.GraphSession.Node<JcrNodePayload, JcrPropertyPayload>
info,
+ // Name propertyName,
+ // int type,
+ // Name nodeTypeName,
+ // Name propertyDefinitionName,
+ // int definitionType,
+ // Object value ) {
+ // PropertyDefinitionId defnId = new PropertyDefinitionId(nodeTypeName,
propertyDefinitionName, definitionType, false);
+ // PropertyInfo<JcrPropertyPayload> propertyInfo =
info.getProperty(propertyName);
+ // assertThat(propertyInfo, is(notNullValue()));
+ // assertThat(propertyInfo.getPayload().getPropertyType(), is(type));
+ // assertThat(propertyInfo.getPayload().getPropertyDefinitionId(), is(defnId));
+ // org.jboss.dna.graph.property.PropertyType dnaPropertyType =
PropertyTypeUtil.dnaPropertyTypeFor(type);
+ // // Check the value ...
+ // ValueFactory<?> factory =
context.getValueFactories().getValueFactory(dnaPropertyType);
+ // Object actual = factory.create(propertyInfo.getProperty().getFirstValue());
+ // assertThat(actual, is(value));
+ // }
+ //
+ // protected void assertProperty(
org.jboss.dna.graph.session.GraphSession.Node<JcrNodePayload, JcrPropertyPayload>
info,
+ // Name propertyName,
+ // int type,
+ // Name nodeTypeName,
+ // Name propertyDefinitionName,
+ // int definitionType,
+ // Object... values ) {
+ // PropertyDefinitionId defnId = new PropertyDefinitionId(nodeTypeName,
propertyDefinitionName, definitionType, true);
+ // PropertyInfo<JcrPropertyPayload> propertyInfo =
info.getProperty(propertyName);
+ // assertThat(propertyInfo, is(notNullValue()));
+ // assertThat(propertyInfo.getPayload().getPropertyType(), is(type));
+ // assertThat(propertyInfo.getPayload().getPropertyDefinitionId(), is(defnId));
+ // org.jboss.dna.graph.property.PropertyType dnaPropertyType =
PropertyTypeUtil.dnaPropertyTypeFor(type);
+ // // Check the values ...
+ // ValueFactory<?> factory =
context.getValueFactories().getValueFactory(dnaPropertyType);
+ // int i = 0;
+ // for (Object value : propertyInfo.getProperty()) {
+ // assertThat(factory.create(value), is(values[i++]));
+ // }
+ // }
+ //
+ // protected void assertNoProperty(
org.jboss.dna.graph.session.GraphSession.Node<JcrNodePayload, JcrPropertyPayload>
info,
+ // Name propertyName ) {
+ // assertThat(info.getProperty(propertyName), is(nullValue()));
+ // }
+ //
+ // @Test
+ // public void shouldCreateWithValidParameters() {
+ // assertThat(cache, is(notNullValue()));
+ // }
+ //
+ // @Test
+ // public void shouldRepeatedlyFindRootNodeInfoByPath() throws Exception {
+ // String sourceName = "cars";
+ // Graph store = getGraph(sourceName);
+ // SessionCache cache = getCache(sourceName);
+ // org.jboss.dna.graph.Node root = store.getNodeAt("/");
+ // UUID rootUuid = root.getLocation().getUuid();
+ // AbstractJcrNode nodeInfo = cache.findJcrRootNode();
+ // assertSameProperties(nod, root)
+ // assertThat(nodeInfo.getUuid(), is(rootUuid));
+ // for (int i = 0; i != 20; ++i) {
+ // sw.start();
+ // assertThat(nodeInfo, is(sameInstance(cache.findNodeInfoForRoot())));
+ // sw.stop();
+ // assertThat(nodeInfo, is(sameInstance(cache.findNodeInfo(rootUuid))));
+ // }
+ // // System.out.println(pad(sourceName) + " ==> " +
sw.getSimpleStatistics());
+ // }
+ //
+ // @Test
+ // public void shouldRepeatedlyFindRootNodeInfoByUuidFromVehiclesSource() throws
Exception {
+ // String sourceName = "vehicles";
+ // Graph store = getGraph(sourceName);
+ // SessionCache cache = getCache(sourceName);
+ // sw.start();
+ // Node root = store.getNodeAt("/");
+ // sw.stop();
+ // UUID rootUuid = root.getLocation().getUuid();
+ // for (int i = 0; i != 20; ++i) {
+ // sw.start();
+ // NodeInfo rootInfo = cache.findNodeInfo(rootUuid);
+ // sw.stop();
+ // assertThat(rootInfo, is(notNullValue()));
+ // }
+ // // System.out.println(pad(sourceName) + " ==> " +
sw.getSimpleStatistics());
+ // }
+ //
+ // @Test
+ // public void shouldRepeatedlyFindRootNodeInfoByUuidFromSourceWithPrimaryTypes()
throws Exception {
+ // String sourceName = "repositoryForTckTests";
+ // Graph store = getGraph(sourceName);
+ // SessionCache cache = getCache(sourceName);
+ // sw.start();
+ // Node root = store.getNodeAt("/");
+ // sw.stop();
+ // UUID rootUuid = root.getLocation().getUuid();
+ // for (int i = 0; i != 20; ++i) {
+ // sw.start();
+ // NodeInfo rootInfo = cache.findNodeInfo(rootUuid);
+ // sw.stop();
+ // assertThat(rootInfo, is(notNullValue()));
+ // }
+ // // System.out.println(pad(sourceName) + " ==> " +
sw.getSimpleStatistics());
+ // }
+ //
+ // @Test
+ // public void shouldFindChildrenInNodeInfoForRoot() throws Exception {
+ // NodeInfo root = cache.findNodeInfoForRoot();
+ // Children children = root.getChildren();
+ // assertThat(children, is(notNullValue()));
+ // assertThat(children.size(), is(1));
+ // assertThat(children.getChild(segment("vehix:Vehicles")),
is(notNullValue()));
+ // }
+ //
+ // @Test
+ // public void shouldFindNodeInfoForNonRootNodeByPath() throws Exception {
+ // String sourceName = "vehicles";
+ // Graph store = getGraph(sourceName);
+ // SessionCache cache = getCache(sourceName);
+ // // Get the root ...
+ // NodeInfo root = cache.findNodeInfoForRoot();
+ //
+ // // Now try to load a node that is well-below the root ...
+ // Path lr3Path = path("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land
Rover LR3");
+ // Node lr3Node = store.getNodeAt(lr3Path);
+ // sw.start();
+ // NodeInfo lr3 = cache.findNodeInfo(root.getUuid(), lr3Path);
+ // sw.stop();
+ // assertThat(lr3.getUuid(), is(lr3Node.getLocation().getUuid()));
+ // assertSameProperties(lr3, lr3Node);
+ // // System.out.println(pad(sourceName) + " ==> " +
sw.getSimpleStatistics());
+ //
+ // // Verify that this loaded all the intermediate nodes, by walking up ...
+ // NodeInfo info = lr3;
+ // while (true) {
+ // UUID parent = info.getParent();
+ // if (parent == null) {
+ // // then we should be at the root ...
+ // assertThat(info.getUuid(), is(root.getUuid()));
+ // break;
+ // }
+ // // Otherwise, we're not at the root, so we should find the parent ...
+ // info = cache.findNodeInfoInCache(parent);
+ // assertThat(info, is(notNullValue()));
+ // }
+ // }
+ //
+ // @Test
+ // public void shouldFindInfoForNodeUsingRelativePathFromRoot() throws Exception {
+ // String sourceName = "vehicles";
+ // Graph store = getGraph(sourceName);
+ // SessionCache cache = getCache(sourceName);
+ //
+ // // Verify that the node does exist in the source ...
+ // Path lr3AbsolutePath =
path("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover LR3");
+ // Node lr3Node = store.getNodeAt(lr3AbsolutePath);
+ //
+ // // Get the root ...
+ // NodeInfo root = cache.findNodeInfoForRoot();
+ //
+ // // Now try to load a node that is well-below the root ...
+ // Path lr3Path = path("vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover
LR3");
+ // assertThat(lr3Path.isAbsolute(), is(false));
+ // NodeInfo lr3 = cache.findNodeInfo(root.getUuid(), lr3Path);
+ // assertThat(lr3.getUuid(), is(lr3Node.getLocation().getUuid()));
+ // assertSameProperties(lr3, lr3Node);
+ //
+ // Path recoveredPath = cache.getPathFor(lr3);
+ // assertThat(recoveredPath, is(lr3AbsolutePath));
+ // }
+ //
+ // @Test
+ // public void shouldFindInfoForNodeUsingRelativePathFromNonRoot() throws Exception
{
+ // // Verify that the node does exist in the source ...
+ // Path carsAbsolutePath = path("/vehix:Vehicles/vehix:Cars");
+ // Node carsNode = store.getNodeAt(carsAbsolutePath);
+ // Path lr3AbsolutePath =
path("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover LR3");
+ // Node lr3Node = store.getNodeAt(lr3AbsolutePath);
+ // Path b787AbsolutePath =
path("/vehix:Vehicles/vehix:Aircraft/vehix:Commercial/vehix:Boeing 787");
+ // Node b787Node = store.getNodeAt(b787AbsolutePath);
+ //
+ // // Get the root ...
+ // NodeInfo root = cache.findNodeInfoForRoot();
+ //
+ // // Now try to load the cars node ...
+ // Path carsPath = path("vehix:Vehicles/vehix:Cars");
+ // assertThat(carsPath.isAbsolute(), is(false));
+ // NodeInfo cars = cache.findNodeInfo(root.getUuid(), carsPath);
+ // assertThat(cars.getUuid(), is(carsNode.getLocation().getUuid()));
+ // assertSameProperties(cars, carsNode);
+ //
+ // // Now try to find the LR3 node relative to the car ...
+ // Path lr3Path = path("vehix:Utility/vehix:Land Rover LR3");
+ // assertThat(lr3Path.isAbsolute(), is(false));
+ // NodeInfo lr3 = cache.findNodeInfo(cars.getUuid(), lr3Path);
+ // assertThat(lr3.getUuid(), is(lr3Node.getLocation().getUuid()));
+ // assertSameProperties(lr3, lr3Node);
+ //
+ // // Now try to find the "Boeing 787" node relative to the LR3 node ...
+ // Path b787Path = path("../../../vehix:Aircraft/vehix:Commercial/vehix:Boeing
787");
+ // assertThat(b787Path.isAbsolute(), is(false));
+ // assertThat(b787Path.isNormalized(), is(true));
+ // NodeInfo b787 = cache.findNodeInfo(lr3.getUuid(), b787Path);
+ // assertThat(b787.getUuid(), is(b787Node.getLocation().getUuid()));
+ // assertSameProperties(b787, b787Node);
+ //
+ // assertThat(cache.getPathFor(cars), is(carsAbsolutePath));
+ // assertThat(cache.getPathFor(lr3), is(lr3AbsolutePath));
+ // assertThat(cache.getPathFor(b787), is(b787AbsolutePath));
+ // }
+ //
+ // @Test
+ // public void shouldFindJcrNodeUsingAbsolutePaths() throws Exception {
+ // // Verify that the node does exist in the source ...
+ // Path carsAbsolutePath = path("/vehix:Vehicles/vehix:Cars");
+ // Node carsNode = store.getNodeAt(carsAbsolutePath);
+ // Path lr3AbsolutePath =
path("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover LR3");
+ // Node lr3Node = store.getNodeAt(lr3AbsolutePath);
+ // Path b787AbsolutePath =
path("/vehix:Vehicles/vehix:Aircraft/vehix:Commercial/vehix:Boeing 787");
+ // Node b787Node = store.getNodeAt(b787AbsolutePath);
+ //
+ // // Get the root ...
+ // NodeInfo root = cache.findNodeInfoForRoot();
+ //
+ // // Now try to load the cars node ...
+ // Path carsPath = path("vehix:Vehicles/vehix:Cars");
+ // assertThat(carsPath.isAbsolute(), is(false));
+ // AbstractJcrNode carJcrNode = cache.findJcrNode(root.getUuid(), carsAbsolutePath);
+ // assertThat(carJcrNode.internalUuid(), is(carsNode.getLocation().getUuid()));
+ // NodeInfo cars = cache.findNodeInfo(root.getUuid(), carsPath);
+ // assertThat(cars.getUuid(), is(carsNode.getLocation().getUuid()));
+ // assertSameProperties(cars, carsNode);
+ //
+ // // Now try to find the LR3 node relative to the car ...
+ // Path lr3Path = path("vehix:Utility/vehix:Land Rover LR3");
+ // assertThat(lr3Path.isAbsolute(), is(false));
+ // AbstractJcrNode lr3JcrNode = cache.findJcrNode(root.getUuid(), lr3AbsolutePath);
+ // assertThat(lr3JcrNode.internalUuid(), is(lr3Node.getLocation().getUuid()));
+ // NodeInfo lr3 = cache.findNodeInfo(cars.getUuid(), lr3Path);
+ // assertThat(lr3.getUuid(), is(lr3Node.getLocation().getUuid()));
+ // assertSameProperties(lr3, lr3Node);
+ //
+ // // Now try to find the "Boeing 787" node relative to the LR3 node ...
+ // Path b787Path = path("../../../vehix:Aircraft/vehix:Commercial/vehix:Boeing
787");
+ // assertThat(b787Path.isAbsolute(), is(false));
+ // assertThat(b787Path.isNormalized(), is(true));
+ // AbstractJcrNode b787JcrNode = cache.findJcrNode(root.getUuid(),
b787AbsolutePath);
+ // assertThat(b787JcrNode.internalUuid(), is(b787Node.getLocation().getUuid()));
+ // NodeInfo b787 = cache.findNodeInfo(lr3.getUuid(), b787Path);
+ // assertThat(b787.getUuid(), is(b787Node.getLocation().getUuid()));
+ // assertSameProperties(b787, b787Node);
+ //
+ // assertThat(cache.getPathFor(cars), is(carsAbsolutePath));
+ // assertThat(cache.getPathFor(lr3), is(lr3AbsolutePath));
+ // assertThat(cache.getPathFor(b787), is(b787AbsolutePath));
+ // }
+ //
+ // @Test
+ // public void shouldDeleteLeafNode() throws Exception {
+ // // Find the state of some Graph nodes we'll be using in the test ...
+ // Node utility =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Utility");
+ // Node lr2Node =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover
LR2");
+ // Node lr3Node =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover
LR3");
+ // int numChildrenOfUtility = utility.getChildren().size();
+ // assertThat(numChildrenOfUtility, is(4));
+ // assertThat(utility.getChildren(), hasChildren(segment("vehix:Land Rover
LR2"),
+ // segment("vehix:Land Rover LR3"),
+ // segment("vehix:Hummer H3"),
+ // segment("vehix:Ford F-150")));
+ //
+ // // Now get the editor for the 'vehix:Utility' node ...
+ // NodeEditor editor = cache.getEditorFor(utility.getLocation().getUuid());
+ // assertThat(editor, is(notNullValue()));
+ //
+ // // Destroy the LR3 node, which is a leaf ...
+ // editor.destroyChild(lr3Node.getLocation().getUuid());
+ //
+ // // Verify that the store has not yet been changed ...
+ // assertDoesExist(store, lr3Node.getLocation());
+ //
+ // // Save the session and verify that the node was deleted ...
+ // cache.save();
+ // Node utilityNode2 = store.getNodeAt(utility.getLocation());
+ // assertThat(utilityNode2.getChildren().size(), is(numChildrenOfUtility - 1));
+ // assertThat(utilityNode2.getChildren(), hasChildren(segment("vehix:Land Rover
LR2"), // no LR3!
+ // segment("vehix:Hummer H3"),
+ // segment("vehix:Ford F-150")));
+ // // Should no longer find the LR3 node in the graph ...
+ // assertDoesNotExist(store, lr3Node.getLocation().getUuid());
+ // assertDoesExist(store, lr2Node.getLocation());
+ // }
+ //
+ // @Test
+ // public void shouldDeleteNonLeafNode() throws Exception {
+ // // Find the state of some Graph nodes we'll be using in the test ...
+ // Node carsNode = store.getNodeAt("/vehix:Vehicles/vehix:Cars");
+ // Node utility =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Utility");
+ // Node hybrid =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Hybrid");
+ // Node luxury =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Luxury");
+ // Node sports =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Sports");
+ // Node lr3 =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover
LR3");
+ // Node lr2 =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover
LR2");
+ // Node f150 =
store.getNodeAt("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Ford F-150");
+ // int numChildrenOfCars = carsNode.getChildren().size();
+ // assertThat(numChildrenOfCars, is(4));
+ // assertThat(carsNode.getChildren(), hasChildren(segment("vehix:Hybrid"),
+ // segment("vehix:Sports"),
+ // segment("vehix:Luxury"),
+ // segment("vehix:Utility")));
+ //
+ // // Load the LR2 and Hummer nodes ...
+ // NodeInfo h3i = cache.findNodeInfo(utility.getLocation().getUuid(),
path("vehix:Hummer H3"));
+ // NodeInfo lr2i = cache.findNodeInfo(utility.getLocation().getUuid(),
path("vehix:Land Rover LR2"));
+ // assertThat(h3i, is(notNullValue()));
+ // assertThat(lr2i, is(notNullValue()));
+ // assertThat(lr2i.getUuid(), is(lr2.getLocation().getUuid()));
+ //
+ // // Now get the editor for the 'vehix:Cars' node ...
+ // NodeEditor editor = cache.getEditorFor(carsNode.getLocation().getUuid());
+ // assertThat(editor, is(notNullValue()));
+ //
+ // // Destroy the Utility node, which is NOT a leaf ...
+ // editor.destroyChild(utility.getLocation().getUuid());
+ //
+ // // Verify that the store has not yet been changed ...
+ // assertDoesExist(store, utility.getLocation());
+ //
+ // // ... but the utility node and its two loaded children have been marked for
deletion ...
+ // assertIsDeleted(cache, utility.getLocation().getUuid());
+ // assertIsDeleted(cache, h3i.getUuid());
+ // assertIsDeleted(cache, lr2i.getUuid());
+ //
+ // // Save the session and verify that the Utility node and its children were deleted
...
+ // cache.save();
+ // Node carsNode2 = store.getNodeAt(carsNode.getLocation());
+ // assertThat(carsNode2.getChildren().size(), is(numChildrenOfCars - 1));
+ // assertThat(carsNode2.getChildren(),
+ // hasChildren(segment("vehix:Hybrid"), segment("vehix:Sports"),
segment("vehix:Luxury")));
+ // // Should no longer find the Utility node in the graph ...
+ // assertDoesNotExist(store, utility.getLocation());
+ // assertDoesNotExist(cache, utility.getLocation().getUuid());
+ // assertDoesNotExist(cache, h3i.getUuid());
+ // assertDoesNotExist(cache, lr2i.getUuid());
+ // assertDoesNotExist(cache, lr3.getLocation().getUuid());
+ // assertDoesNotExist(cache, f150.getLocation().getUuid());
+ // assertDoNotExist(store, utility.getChildren());
+ // assertDoesExist(store, hybrid.getLocation());
+ // assertDoesExist(store, luxury.getLocation());
+ // assertDoesExist(store, sports.getLocation());
+ // }
+ //
+ // @Test
+ // public void shouldGetExistingPropertyOnExistingNode() throws Exception {
+ // NodeInfo root = cache.findNodeInfoForRoot();
+ // NodeInfo lr3 = cache.findNodeInfo(root.getUuid(),
path("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover LR3"));
+ // assertProperty(lr3, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING,
"LR3");
+ // assertProperty(lr3, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING,
"Land Rover");
+ // assertProperty(lr3, Lexicon.YEAR, LONG, Lexicon.CAR, Lexicon.YEAR, LONG, 2008L);
+ // assertProperty(lr3, Lexicon.MSRP, STRING, Lexicon.CAR, Lexicon.MSRP, STRING,
"$48,525");
+ //
+ // NodeInfo db9 = cache.findNodeInfo(root.getUuid(),
path("/vehix:Vehicles/vehix:Cars/vehix:Sports/vehix:Aston Martin DB9"));
+ // assertProperty(db9, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING,
"DB9");
+ // assertProperty(db9, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING,
"Aston Martin");
+ // assertProperty(db9, Lexicon.LENGTH_IN_INCHES, DOUBLE, Lexicon.CAR,
Lexicon.LENGTH_IN_INCHES, DOUBLE, 185.5D);
+ //
+ // NodeInfo b878 = cache.findNodeInfo(root.getUuid(),
+ // path("/vehix:Vehicles/vehix:Aircraft/vehix:Commercial/vehix:Boeing
787"));
+ // assertProperty(b878, Lexicon.MODEL, STRING, Lexicon.AIRCRAFT, Lexicon.MODEL,
STRING, "787-3");
+ // assertProperty(b878, Lexicon.MAKER, STRING, Lexicon.AIRCRAFT, Lexicon.MAKER,
STRING, "Boeing");
+ // assertProperty(b878, Lexicon.INTRODUCED, LONG, Lexicon.AIRCRAFT,
Lexicon.INTRODUCED, LONG, 2009L);
+ // assertProperty(b878, Lexicon.EMPTY_WEIGHT, STRING, JcrNtLexicon.UNSTRUCTURED,
name("*"), UNDEFINED, "223000lb");
+ //
+ // }
+ //
+ // @Test
+ // public void shouldNotFindNonExistantPropertyOnExistingNode() throws Exception {
+ // NodeInfo root = cache.findNodeInfoForRoot();
+ // NodeInfo lr3 = cache.findNodeInfo(root.getUuid(),
path("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover LR3"));
+ // assertProperty(lr3, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING,
"LR3");
+ // assertProperty(lr3, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING,
"Land Rover");
+ // assertNoProperty(lr3, Lexicon.LENGTH_IN_INCHES);
+ // assertNoProperty(lr3, Lexicon.INTRODUCED);
+ // }
+ //
+ // @Test
+ // public void shouldSetNewValueOnExistingPropertyOnExistingNode() throws Exception
{
+ // NodeInfo root = cache.findNodeInfoForRoot();
+ // NodeInfo lr3 = cache.findNodeInfo(root.getUuid(),
path("/vehix:Vehicles/vehix:Cars/vehix:Utility/vehix:Land Rover LR3"));
+ // assertProperty(lr3, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING,
"LR3");
+ // assertProperty(lr3, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING,
"Land Rover");
+ // assertNoProperty(lr3, Lexicon.LENGTH_IN_INCHES);
+ //
+ // SessionCache.NodeEditor editor = cache.getEditorFor(lr3.getUuid());
+ // editor.setProperty(Lexicon.LENGTH_IN_INCHES, value(DOUBLE, 100.0D));
+ // }
+ //
+ // @Test
+ // public void shouldSetNewPropertyOnExistingNode() throws Exception {
+ // NodeInfo root = cache.findNodeInfoForRoot();
+ // NodeInfo db9 = cache.findNodeInfo(root.getUuid(),
path("/vehix:Vehicles/vehix:Cars/vehix:Sports/vehix:Aston Martin DB9"));
+ // assertProperty(db9, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING,
"DB9");
+ // assertProperty(db9, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING,
"Aston Martin");
+ // assertProperty(db9, Lexicon.LENGTH_IN_INCHES, DOUBLE, Lexicon.CAR,
Lexicon.LENGTH_IN_INCHES, DOUBLE, 185.5D);
+ //
+ // SessionCache.NodeEditor editor = cache.getEditorFor(db9.getUuid());
+ // editor.setProperty(Lexicon.LENGTH_IN_INCHES, value(DOUBLE, 100.0D));
+ // }
+ //
+ // @Test( expected = ConstraintViolationException.class )
+ // public void shouldFailToSetPropertyToInvalidValuesOnExistingNode() throws
Exception {
+ // NodeInfo root = cache.findNodeInfoForRoot();
+ // NodeInfo db9 = cache.findNodeInfo(root.getUuid(),
path("/vehix:Vehicles/vehix:Cars/vehix:Sports/vehix:Aston Martin DB9"));
+ // assertProperty(db9, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING,
"DB9");
+ // assertProperty(db9, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING,
"Aston Martin");
+ // assertProperty(db9, Lexicon.LENGTH_IN_INCHES, DOUBLE, Lexicon.CAR,
Lexicon.LENGTH_IN_INCHES, DOUBLE, 185.5D);
+ //
+ // SessionCache.NodeEditor editor = cache.getEditorFor(db9.getUuid());
+ // editor.setProperty(Lexicon.LENGTH_IN_INCHES, value(STRING, "This is not a
valid double"));
+ // }
+ //
+ // @Test
+ // public void shouldRemoveExistingPropertyOnExistingNode() throws Exception {
+ // NodeInfo root = cache.findNodeInfoForRoot();
+ // NodeInfo db9 = cache.findNodeInfo(root.getUuid(),
path("/vehix:Vehicles/vehix:Cars/vehix:Sports/vehix:Aston Martin DB9"));
+ // assertProperty(db9, Lexicon.MODEL, STRING, Lexicon.CAR, Lexicon.MODEL, STRING,
"DB9");
+ // assertProperty(db9, Lexicon.MAKER, STRING, Lexicon.CAR, Lexicon.MAKER, STRING,
"Aston Martin");
+ // assertProperty(db9, Lexicon.LENGTH_IN_INCHES, DOUBLE, Lexicon.CAR,
Lexicon.LENGTH_IN_INCHES, DOUBLE, 185.5D);
+ //
+ // UUID db9uuid = db9.getUuid();
+ // SessionCache.NodeEditor editor = cache.getEditorFor(db9uuid);
+ // editor.removeProperty(Lexicon.LENGTH_IN_INCHES);
+ //
+ // db9 = cache.findNodeInfo(db9uuid);
+ // assertNoProperty(db9, Lexicon.LENGTH_IN_INCHES);
+ //
+ // db9 = cache.findNodeInfo(root.getUuid(),
path("/vehix:Vehicles/vehix:Cars/vehix:Sports/vehix:Aston Martin DB9"));
+ // assertNoProperty(db9, Lexicon.LENGTH_IN_INCHES);
+ // }
+ //
+ // protected void walkInfosForNodesUnder( NodeInfo parentInfo,
+ // Stopwatch sw ) throws Exception {
+ // for (ChildNode child : parentInfo.getChildren()) {
+ // sw.start();
+ // NodeInfo childInfo = cache.findNodeInfo(child.getUuid());
+ // cache.getPathFor(childInfo);
+ // sw.stop();
+ //
+ // // Walk the infos for nodes under the child (this is recursive) ...
+ // walkInfosForNodesUnder(childInfo, sw);
+ // }
+ // }
+ //
+ // @Test
+ // public void shouldFindInfoForAllNodesInGraph() throws Exception {
+ // for (int i = 0; i != 3; ++i) {
+ // Stopwatch sw = new Stopwatch();
+ //
+ // // Get the root ...
+ // sw.start();
+ // NodeInfo root = cache.findNodeInfoForRoot();
+ // cache.getPathFor(root);
+ // sw.stop();
+ //
+ // // Walk the infos for nodes under the root (this is recursive) ...
+ // walkInfosForNodesUnder(root, sw);
+ // System.out.println("Statistics for walking nodes using SessionCache: " +
sw.getSimpleStatistics());
+ // }
+ // }
}
Added: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest2.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest2.java
(rev 0)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest2.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -0,0 +1,382 @@
+/*
+ * JBoss DNA (
http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you 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.
+ *
+ * JBoss DNA 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.jcr;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.session.GraphSession.Node;
+import org.jboss.dna.graph.session.GraphSession.PropertyInfo;
+import org.jboss.dna.jcr.SessionCache.JcrNodePayload;
+import org.jboss.dna.jcr.SessionCache.JcrPropertyPayload;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class SessionCacheTest2 extends AbstractJcrTest {
+
+ @Override
+ @Before
+ public void beforeEach() throws Exception {
+ super.beforeEach();
+ }
+
+ @Test
+ public void shouldRepeatedlyFindRootNode() throws Exception {
+ AbstractJcrNode root = cache.findJcrRootNode();
+ for (int i = 0; i != 10; ++i) {
+ AbstractJcrNode node = cache.findJcrRootNode();
+ assertThat(node, is(sameInstance(root)));
+ // Look up the graph node ...
+ assertMatchesStore(node);
+ }
+ }
+
+ @Test
+ public void shouldRepeatedlyFindRootNodeByPath() throws Exception {
+ AbstractJcrNode root = cache.findJcrNode(null, path("/"));
+ for (int i = 0; i != 10; ++i) {
+ AbstractJcrNode node = cache.findJcrRootNode();
+ assertThat(node, is(sameInstance(root)));
+ // Look up the graph node ...
+ assertMatchesStore(node);
+ }
+ }
+
+ @Test
+ public void shouldRepeatedlyFindRootNodeByLocationWithoutPath() throws Exception {
+ AbstractJcrNode root = cache.findJcrRootNode();
+ AbstractJcrNode root2 =
cache.findJcrNode(Location.create(root.location.getIdProperties()));
+ assertThat(root2, is(sameInstance(root)));
+ }
+
+ @Test
+ public void shouldRepeatedlyFindNodeByPath() throws Exception {
+ AbstractJcrNode hybrid = cache.findJcrNode(null,
path("/Cars/Hybrid"));
+ for (int i = 0; i != 10; ++i) {
+ AbstractJcrNode hybrid2 = cache.findJcrNode(null, hybrid.path());
+ assertThat(hybrid, is(sameInstance(hybrid2)));
+ // Look up the graph node ...
+ assertMatchesStore(hybrid2);
+ }
+ }
+
+ @Test
+ public void shouldRepeatedlyFindNodeByNodeId() throws Exception {
+ AbstractJcrNode hybrid = cache.findJcrNode(null,
path("/Cars/Hybrid"));
+ for (int i = 0; i != 10; ++i) {
+ AbstractJcrNode hybrid2 = cache.findJcrNode(hybrid.nodeId, null);
+ assertThat(hybrid, is(sameInstance(hybrid2)));
+ // Look up the graph node ...
+ assertMatchesStore(hybrid2);
+ }
+ }
+
+ @Test
+ public void shouldRepeatedlyFindNodeByLocationWithoutPath() throws Exception {
+ AbstractJcrNode hybrid = cache.findJcrNode(null,
path("/Cars/Hybrid"));
+ AbstractJcrNode hybrid2 =
cache.findJcrNode(Location.create(hybrid.location.getIdProperties()));
+ assertThat(hybrid2, is(sameInstance(hybrid)));
+ }
+
+ @Test
+ public void shouldFindNodeUsingStartingNodeAndRelativePath() throws Exception {
+ AbstractJcrNode hybrid = cache.findJcrNode(null,
path("/Cars/Hybrid"));
+ AbstractJcrNode highlander = cache.findJcrNode(hybrid.nodeId, hybrid.path(),
path("../Hybrid/Toyota Highlander"));
+ // Make sure this is the same as if we find it directly ...
+ AbstractJcrNode highlander2 = cache.findJcrNode(null,
path("/Cars/Hybrid/Toyota Highlander"));
+ assertThat(highlander, is(sameInstance(highlander2)));
+ assertMatchesStore(highlander);
+ }
+
+ @Test
+ public void shouldFindNodeItemUsingStartingNodeAndRelativePath() throws Exception {
+ AbstractJcrNode hybrid = cache.findJcrNode(null,
path("/Cars/Hybrid"));
+ AbstractJcrItem highlander = cache.findJcrItem(hybrid.nodeId, hybrid.path(),
path("../Hybrid/Toyota Highlander"));
+ assertThat(highlander.isNode(), is(true));
+ // Make sure this is the same as if we find it directly ...
+ AbstractJcrNode highlander2 = cache.findJcrNode(null,
path("/Cars/Hybrid/Toyota Highlander"));
+ assertThat((AbstractJcrNode)highlander, is(sameInstance(highlander2)));
+ }
+
+ @Test
+ public void shouldFindPropertyItemUsingStartingNodeAndRelativePath() throws Exception
{
+ AbstractJcrNode hybrid = cache.findJcrNode(null,
path("/Cars/Hybrid"));
+ AbstractJcrItem altimaModel = cache.findJcrItem(hybrid.nodeId, hybrid.path(),
path("../Hybrid/Nissan Altima/vehix:model"));
+ assertThat(altimaModel.isNode(), is(false));
+ javax.jcr.Node altimaModelParent = altimaModel.getParent();
+ javax.jcr.Node altima = cache.findJcrNode(null, path("/Cars/Hybrid/Nissan
Altima"));
+ assertThat(altima, is(sameInstance(altimaModelParent)));
+ }
+
+ @Test
+ public void shouldFindPropertyForNodeUsingPropertyName() throws Exception {
+ AbstractJcrNode altima = cache.findJcrNode(null, path("/Cars/Hybrid/Nissan
Altima"));
+ AbstractJcrItem altimaModel = cache.findJcrProperty(altima.nodeId, altima.path(),
name("vehix:model"));
+ assertThat(altimaModel.isNode(), is(false));
+ javax.jcr.Node altimaModelParent = altimaModel.getParent();
+ assertThat(altima, is(sameInstance(altimaModelParent)));
+ }
+
+ @Test
+ public void shouldFindPropertiesForNode() throws Exception {
+ AbstractJcrNode altima = cache.findJcrNode(null, path("/Cars/Hybrid/Nissan
Altima"));
+ Collection<AbstractJcrProperty> properties =
cache.findJcrPropertiesFor(altima.nodeId, altima.path());
+ assertThat(properties.size(), is(7));
+ List<AbstractJcrProperty> properties2 = new
ArrayList<AbstractJcrProperty>(properties);
+ Collections.sort(properties2);
+ Iterator<AbstractJcrProperty> iter = properties2.iterator();
+ assertProperty(iter.next(), altima, "jcr:primaryType",
PropertyType.NAME, "vehix:car");
+ assertProperty(iter.next(), altima, "vehix:maker", PropertyType.STRING,
"Nissan");
+ assertProperty(iter.next(), altima, "vehix:model", PropertyType.STRING,
"Altima");
+ assertProperty(iter.next(), altima, "vehix:mpgCity", PropertyType.LONG,
"23");
+ assertProperty(iter.next(), altima, "vehix:mpgHighway",
PropertyType.LONG, "32");
+ assertProperty(iter.next(), altima, "vehix:msrp", PropertyType.STRING,
"$18,260");
+ assertProperty(iter.next(), altima, "vehix:year", PropertyType.LONG,
"2008");
+ }
+
+ @Test
+ public void shouldRefreshWithoutKeepingChanges() throws Exception {
+ AbstractJcrNode altima1 = cache.findJcrNode(null, path("/Cars/Hybrid/Nissan
Altima"));
+ assertMatchesStore(altima1);
+ assertThat(altima1.isNew(), is(false));
+
+ // Add the child ...
+ AbstractJcrNode hybrid = cache.findJcrNode(null,
path("/Cars/Hybrid"));
+ javax.jcr.Node child = hybrid.addNode("child");
+ assertThat(hybrid.isModified(), is(true));
+ assertThat(child.isNew(), is(true));
+ assertThat(hybrid.hasNode("child"), is(true));
+
+ cache.refresh(false);
+ AbstractJcrNode altima2 = cache.findJcrNode(null, path("/Cars/Hybrid/Nissan
Altima"));
+ assertMatchesStore(altima2);
+
+ // The objects should no longer be the same ...
+ assertThat(altima1, is(altima2));
+ assertThat(altima1, is(not(sameInstance(altima2))));
+ assertThat(altima2.isNew(), is(false));
+
+ // The new child should no longer exist ...
+ assertThat(hybrid.hasNode("child"), is(false));
+ }
+
+ @Test
+ public void shouldRefreshAndKeepChanges() throws Exception {
+ AbstractJcrNode altima1 = cache.findJcrNode(null, path("/Cars/Hybrid/Nissan
Altima"));
+ assertMatchesStore(altima1);
+ assertThat(altima1.isNew(), is(false));
+
+ // Add the child ...
+ AbstractJcrNode hybrid = cache.findJcrNode(null,
path("/Cars/Hybrid"));
+ javax.jcr.Node child = hybrid.addNode("child");
+ assertThat(hybrid.isModified(), is(true));
+ assertThat(child.isNew(), is(true));
+ assertThat(hybrid.hasNode("child"), is(true));
+
+ cache.refresh(true);
+ AbstractJcrNode altima2 = cache.findJcrNode(null, path("/Cars/Hybrid/Nissan
Altima"));
+ assertMatchesStore(altima2);
+
+ // The objects should still be the same ...
+ assertThat(altima1, is(altima2));
+ assertThat(altima1, is(sameInstance(altima2)));
+ assertThat(altima2.isNew(), is(false));
+
+ // The new child should still exist ...
+ assertThat(hybrid.hasNode("child"), is(true));
+ }
+
+ @Test
+ public void shouldSaveChanges() throws Exception {
+ AbstractJcrNode altima1 = cache.findJcrNode(null, path("/Cars/Hybrid/Nissan
Altima"));
+ assertMatchesStore(altima1);
+ assertThat(altima1.isNew(), is(false));
+
+ // Add the child ...
+ AbstractJcrNode hybrid = cache.findJcrNode(null,
path("/Cars/Hybrid"));
+ javax.jcr.Node child = hybrid.addNode("child");
+ assertThat(hybrid.isModified(), is(true));
+ assertThat(child.isNew(), is(true));
+ assertThat(hybrid.hasNode("child"), is(true));
+
+ cache.save();
+ AbstractJcrNode altima2 = cache.findJcrNode(null, path("/Cars/Hybrid/Nissan
Altima"));
+ assertMatchesStore(altima2);
+
+ // The objects should no longer be the same ...
+ assertThat(altima1, is(altima2));
+ assertThat(altima1, is(not(sameInstance(altima2))));
+ assertThat(altima2.isNew(), is(false));
+
+ // The new child should still exist ...
+ assertThat(hybrid.hasNode("child"), is(true));
+ }
+
+ protected void assertProperty( AbstractJcrProperty property,
+ javax.jcr.Node node,
+ String name,
+ int propertyType,
+ Object... values ) throws Exception {
+ assertThat(property.getName(), is(name));
+ assertThat(property.getType(), is(propertyType));
+ assertThat(property.getParent(), is(node));
+ if (values.length > 1) {
+ int i = 0;
+ for (Value actual : property.getValues()) {
+ String actualString = actual.getString();
+ String expectedString =
context.getValueFactories().getStringFactory().create(values[i]);
+ assertThat(actualString, is(expectedString));
+ assertCanObtainValue(actual, propertyType);
+ ++i;
+ }
+ // Getting the single value should result in an error ...
+ try {
+ property.getValue();
+ fail("Should not be able to call Property.getValue() on multi-valued
properties");
+ } catch (ValueFormatException e) {
+ // expected ...
+ }
+ } else {
+ String actualString = property.getValue().getString();
+ String expectedString =
context.getValueFactories().getStringFactory().create(values[0]);
+ assertThat(actualString, is(expectedString));
+ assertThat(actualString, is(property.getString()));
+ assertCanObtainValue(property.getValue(), propertyType);
+ // Getting the multiple values should result in an error ...
+ try {
+ property.getValues();
+ fail("Should not be able to call Property.getValues() on
single-valued properties");
+ } catch (ValueFormatException e) {
+ // expected ...
+ }
+ // Check resolving the reference ...
+ if (propertyType == PropertyType.REFERENCE) {
+ javax.jcr.Node referenced = property.getNode();
+ assertThat(referenced, is(notNullValue()));
+ }
+ }
+ }
+
+ protected void assertCanObtainValue( Value value,
+ int expectedType ) throws Exception {
+ switch (expectedType) {
+ case PropertyType.BINARY:
+ InputStream stream = value.getStream();
+ assertThat(stream, is(notNullValue()));
+ try {
+ stream.read();
+ } finally {
+ stream.close();
+ }
+ break;
+ case PropertyType.BOOLEAN:
+ assertThat(value.getBoolean() || !value.getBoolean(), is(true));
+ break;
+ case PropertyType.DATE:
+ Calendar cal = value.getDate();
+ assertThat(cal, is(notNullValue()));
+ break;
+ case PropertyType.DOUBLE:
+ double doubleValue = value.getDouble();
+ assertThat(doubleValue < 0.0d || doubleValue >= -1.0d, is(true));
+ break;
+ case PropertyType.LONG:
+ long longValue = value.getLong();
+ assertThat(longValue < 0L || longValue >= 0L, is(true));
+ break;
+ case PropertyType.NAME:
+ context.getValueFactories().getNameFactory().create(value.getString());
+ break;
+ case PropertyType.PATH:
+ context.getValueFactories().getPathFactory().create(value.getString());
+ break;
+ case PropertyType.REFERENCE:
+ UUID uuid =
context.getValueFactories().getUuidFactory().create(value.getString());
+ assertThat(uuid, is(notNullValue()));
+ break;
+ case PropertyType.STRING:
+ value.getString();
+ break;
+ }
+ }
+
+ protected void assertMatchesStore( AbstractJcrNode jcrNode ) throws
RepositoryException {
+ // Find the corresponding session node ...
+ Node<JcrNodePayload, JcrPropertyPayload> nodeInfo =
cache.findNode(jcrNode.nodeId, jcrNode.path());
+ // And the graph node ...
+ org.jboss.dna.graph.Node dnaNode = store.getNodeAt(jcrNode.location);
+
+ assertThat(nodeInfo.getLocation(), is(dnaNode.getLocation()));
+ Set<Name> propertyNames = nodeInfo.getPropertyNames();
+ for (Name propertyName : propertyNames) {
+ PropertyInfo<JcrPropertyPayload> info =
nodeInfo.getProperty(propertyName);
+ assertThat(info.getName(), is(propertyName));
+ assertThat(info.getProperty().getName(), is(propertyName));
+ Property actual = dnaNode.getProperty(propertyName);
+ if (actual != null) {
+ assertThat(info.getProperty().size(), is(actual.size()));
+ assertThat(info.getProperty().getValuesAsArray(),
is(actual.getValuesAsArray()));
+ } else {
+ if (propertyName.equals(JcrLexicon.UUID)) {
+ // check for a DNA UUID property ...
+ actual = dnaNode.getProperty(DnaLexicon.UUID);
+ if (actual != null) {
+ assertThat(info.getProperty().size(), is(actual.size()));
+ assertThat(info.getProperty().getValuesAsArray(),
is(actual.getValuesAsArray()));
+ } else {
+ fail("missing property \"" + propertyName +
"\" on " + dnaNode);
+ }
+ } else if (propertyName.equals(JcrLexicon.PRIMARY_TYPE)) {
+ // This is okay
+ } else if (propertyName.equals(DnaIntLexicon.MULTI_VALUED_PROPERTIES)) {
+ // This is okay
+ } else {
+ fail("missing property \"" + propertyName +
"\" on " + dnaNode);
+ }
+ }
+ }
+ }
+}
Property changes on: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest2.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/Vehicles.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/Vehicles.java 2009-07-09 16:23:09 UTC
(rev 1081)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/Vehicles.java 2009-07-09 16:26:04 UTC
(rev 1082)
@@ -69,6 +69,7 @@
NodeTypeTemplate car = new JcrNodeTypeTemplate(context);
car.setName("vehix:car");
car.setOrderableChildNodes(true);
+ car.setPrimaryItemName("vehix:model");
property = new JcrPropertyDefinitionTemplate(context);
property.setName("vehix:maker");
Deleted: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/AbstractChildrenTest.java
===================================================================
---
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/AbstractChildrenTest.java 2009-07-09
16:23:09 UTC (rev 1081)
+++
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/AbstractChildrenTest.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -1,168 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you 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.
- *
- * JBoss DNA 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.jcr.cache;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicInteger;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.NameFactory;
-import org.jboss.dna.graph.property.PathFactory;
-import org.jboss.dna.graph.property.Path.Segment;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @param <ChildrenType> the type for the {@link #children} variable
- */
-public abstract class AbstractChildrenTest<ChildrenType extends Children> {
-
- protected ChildrenType children;
- protected ExecutionContext context;
- protected PathFactory pathFactory;
- protected NameFactory nameFactory;
- protected UUID parentUuid;
- protected UUID firstChildUuid;
- protected Name firstChildName;
- protected ChildNode firstChild;
-
- @Before
- public void beforeEach() {
- context = new ExecutionContext();
- pathFactory = context.getValueFactories().getPathFactory();
- nameFactory = context.getValueFactories().getNameFactory();
-
- parentUuid = UUID.randomUUID();
- firstChildUuid = UUID.randomUUID();
- firstChildName = nameFactory.create("childA");
- }
-
- protected Name name( String name ) {
- return nameFactory.create(name);
- }
-
- protected void assertChildNodesWithName( Children children,
- String childName,
- Object... childNodes ) {
- Name name = name(childName);
- Iterator<ChildNode> iter = children.getChildren(name);
- int expectedSnsIndex = 1;
- for (Object expectedChild : childNodes) {
- assertThat(iter.hasNext(), is(true));
- ChildNode next = iter.next();
- assertThat(next.getName(), is(name));
- assertThat(next.getSnsIndex(), is(expectedSnsIndex++));
- if (expectedChild instanceof ChildNode) {
- assertThat(next, is(sameInstance(expectedChild)));
- } else if (expectedChild instanceof Name) {
- Name expectedName = (Name)expectedChild;
- assertThat(next.getName(), is(expectedName));
- } else if (expectedChild instanceof String) {
- Name expectedName = name((String)expectedChild);
- assertThat(next.getName(), is(expectedName));
- }
- }
- assertThat(iter.hasNext(), is(false));
- }
-
- protected void assertChildNodes( Children children,
- Object... childNodes ) {
- Iterator<ChildNode> iter = children.iterator();
- Map<Name, AtomicInteger> expectedSnsIndexes = new HashMap<Name,
AtomicInteger>();
- for (Object expectedChild : childNodes) {
- assertThat(iter.hasNext(), is(true));
- ChildNode next = iter.next();
- Name actualName = next.getName();
- // Check the name ...
- if (expectedChild instanceof ChildNode) {
- assertThat(next, is(sameInstance(expectedChild)));
- } else if (expectedChild instanceof Name) {
- Name expectedName = (Name)expectedChild;
- assertThat(actualName, is(expectedName));
- } else if (expectedChild instanceof String) {
- Name expectedName = name((String)expectedChild);
- assertThat(actualName, is(expectedName));
- }
- // Check the SNS ...
- AtomicInteger expectedSns = expectedSnsIndexes.get(actualName);
- if (expectedSns == null) {
- expectedSns = new AtomicInteger(1);
- expectedSnsIndexes.put(actualName, expectedSns);
- }
- assertThat(next.getSnsIndex(), is(expectedSns.getAndIncrement()));
- }
- assertThat(iter.hasNext(), is(false));
- }
-
- protected void assertSameContent( Children children,
- Children other ) {
- Iterator<ChildNode> iter = children.iterator();
- Iterator<ChildNode> otherIter = other.iterator();
- while (iter.hasNext()) {
- assertThat(otherIter.hasNext(), is(true));
- ChildNode next = iter.next();
- ChildNode otherNext = otherIter.next();
- assertThat(next, is(otherNext));
- }
- assertThat(iter.hasNext(), is(false));
- assertThat(otherIter.hasNext(), is(false));
- }
-
- @Test
- public void shouldFindFirstChildByUuid() {
- ChildNode firstChild = children.getChild(firstChildUuid);
- assertThat(firstChild, is(notNullValue()));
- assertThat(firstChild, is(sameInstance(this.firstChild)));
- assertThat(firstChild.getUuid(), is(firstChildUuid));
- assertThat(firstChild.getName(), is(firstChildName));
- assertThat(firstChild.getSnsIndex(), is(1));
- assertThat(firstChild.getSegment().getIndex(), is(1));
- assertThat(firstChild.getSegment().getName(), is(firstChildName));
- }
-
- @Test
- public void shouldFindFirstChildByName() {
- Segment segment = pathFactory.createSegment(firstChildName, 1);
- ChildNode firstChild = children.getChild(segment);
- assertThat(firstChild, is(notNullValue()));
- assertThat(firstChild, is(sameInstance(this.firstChild)));
- assertThat(firstChild.getUuid(), is(firstChildUuid));
- assertThat(firstChild.getName(), is(firstChildName));
- assertThat(firstChild.getSnsIndex(), is(1));
- assertThat(firstChild.getSegment().getIndex(), is(1));
- assertThat(firstChild.getSegment().getName(), is(firstChildName));
- }
-
- @Test
- public void shouldImplementToString() {
- children.toString();
- }
-}
Deleted: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/ChangedChildrenTest.java
===================================================================
---
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/ChangedChildrenTest.java 2009-07-09
16:23:09 UTC (rev 1081)
+++
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/ChangedChildrenTest.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -1,150 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you 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.
- *
- * JBoss DNA 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.jcr.cache;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import java.util.UUID;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- *
- */
-public class ChangedChildrenTest extends AbstractChildrenTest<ChangedChildren> {
-
- private ImmutableChildren original;
-
- @Override
- @Before
- public void beforeEach() {
- super.beforeEach();
-
- original = new ImmutableChildren(parentUuid);
- firstChild = original.add(firstChildName, firstChildUuid, pathFactory);
-
- children = new ChangedChildren(original);
- }
-
- @Test
- public void shouldHaveCorrectSize() {
- assertThat(children.size(), is(1));
- }
-
- @Test
- public void shouldHaveSameContentsAsOriginal() {
- assertSameContent(children, original);
- }
-
- @Test
- public void shouldFindChildrenByName() {
- Iterator<ChildNode> iter = children.getChildren(firstChildName);
- assertThat(iter.hasNext(), is(true));
- assertThat(iter.next(), is(sameInstance(firstChild)));
- assertThat(iter.hasNext(), is(false));
- try {
- iter.next();
- fail("Failed to throw exception");
- } catch (NoSuchElementException e) {
- // expected
- }
- }
-
- @Test
- public void shouldReturnSameInstanceFromWithoutIfSuppliedChildIsNotFound() {
- ChildNode nonExistant = new ChildNode(UUID.randomUUID(),
pathFactory.createSegment("some segment"));
- assertThat(children.without(nonExistant.getUuid(), pathFactory),
is(sameInstance((Children)children)));
- }
-
- @Test
- public void shouldReturnEmptyChildrenFromWithoutIfOnlyChildIsRemoved() {
- Children newChildren = children.without(firstChild.getUuid(), pathFactory);
- assertThat(newChildren.size(), is(0));
- }
-
- @Test
- public void shouldReturnSameInstanceFromWithIfSuppliedChildThatIsFoundInContainer()
{
- assertThat(children.with(firstChildName, firstChildUuid, pathFactory),
is(sameInstance((Children)children)));
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldReturnIteratorThatDoesNotSupportRemoving() {
- Iterator<ChildNode> iter = children.getChildren(firstChildName);
- assertThat(iter.hasNext(), is(true));
- assertThat(iter.next(), is(sameInstance(firstChild)));
- iter.remove();
- }
-
- @Test
- public void shouldReturnChangedChildrenFromWithoutIfSuppliedChildIsFound() {
- ChildNode child2 = children.add(name("childB"), UUID.randomUUID(),
pathFactory);
- ChildNode child3 = children.add(name("childC"), UUID.randomUUID(),
pathFactory);
- ChildNode child4 = children.add(name("childA"), UUID.randomUUID(),
pathFactory);
- ChildNode child5 = children.add(name("childA"), UUID.randomUUID(),
pathFactory);
- ChildNode child6 = children.add(name("childD"), UUID.randomUUID(),
pathFactory);
-
- // Check that the children contains what we expect ...
- assertChildNodes(children, firstChild, child2, child3, child4, child5, child6);
- assertChildNodesWithName(children, "childA", firstChild, child4,
child5);
-
- // Remove 'child4' ...
- Children result = children.without(child4.getUuid(), pathFactory);
-
- // but the result should not have child4 ...
- assertChildNodesWithName(result, "childA", firstChild,
"childA");
-
- // Now check that all the child nodes are in the result, in the expected order
...
- assertChildNodes(result, firstChild, child2, child3, "childA",
child6);
- }
-
- @Test
- public void shouldReturnChangedChildrenFromWithIfSuppliedChildIsNotFound() {
- // Make sure that children contains what we expect ...
- assertChildNodes(children, firstChild);
- assertChildNodesWithName(children, "childA", firstChild);
-
- // Add a node ...
- Children result = children.with(name("childB"), UUID.randomUUID(),
pathFactory);
- assertThat(result, is(sameInstance((Children)children)));
- assertChildNodes(children, firstChild, "childB");
- assertChildNodesWithName(children, "childA", firstChild);
-
- // Add another node ...
- result = children.with(name("childC"), UUID.randomUUID(),
pathFactory);
- assertThat(result, is(sameInstance((Children)children)));
- assertChildNodes(children, firstChild, "childB", "childC");
- assertChildNodesWithName(children, "childA", firstChild);
-
- // Add another node ...
- result = children.with(name("childA"), UUID.randomUUID(),
pathFactory);
- assertThat(result, is(sameInstance((Children)children)));
- assertChildNodes(children, firstChild, "childB", "childC",
"childA");
- assertChildNodesWithName(children, "childA", firstChild,
"childA");
- }
-
-}
Deleted: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/ChangedNodeInfoTest.java
===================================================================
---
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/ChangedNodeInfoTest.java 2009-07-09
16:23:09 UTC (rev 1081)
+++
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/ChangedNodeInfoTest.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -1,671 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you 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.
- *
- * JBoss DNA 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.jcr.cache;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNot.not;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.jboss.dna.jcr.cache.IsNodeInfoWithChildrenHavingNames.hasChild;
-import static org.jboss.dna.jcr.cache.IsNodeInfoWithChildrenHavingNames.hasChildren;
-import static org.jboss.dna.jcr.cache.IsNodeInfoWithChildrenHavingUuids.hasChild;
-import static org.jboss.dna.jcr.cache.IsNodeInfoWithChildrenHavingUuids.hasChildren;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.hasItems;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.stub;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.JcrLexicon;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.PathFactory;
-import org.jboss.dna.graph.property.Property;
-import org.jboss.dna.graph.property.Path.Segment;
-import org.jboss.dna.jcr.NodeDefinitionId;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- *
- */
-public class ChangedNodeInfoTest {
-
- private ExecutionContext context;
- private PathFactory pathFactory;
- private NodeInfo original;
- private UUID uuid;
- private Name primaryTypeName;
- private Name[] requiredPrimaryTypes;
- private Location location;
- private NodeDefinitionId definitionId;
- private ChangedChildren children;
- private Map<Name, PropertyInfo> properties;
- private List<Name> mixinTypeNames;
- private ChangedNodeInfo changes;
-
- @Before
- public void beforeEach() {
- context = new ExecutionContext();
- context.getNamespaceRegistry().register("acme",
"http://example.com/acme");
- pathFactory = context.getValueFactories().getPathFactory();
-
- // Set up the original ...
- uuid = UUID.randomUUID();
- location = Location.create(uuid);
- primaryTypeName = name("acme:geniusType");
- requiredPrimaryTypes = new Name[] {name("acme:requiredTypeA"),
name("acme:requiredTypeB")};
- definitionId = new NodeDefinitionId(name("acme:geniusContainerType"),
name("acme:geniuses"), requiredPrimaryTypes);
- children = new ChangedChildren(uuid);
- properties = new HashMap<Name, PropertyInfo>();
- mixinTypeNames = new LinkedList<Name>();
- original = new ImmutableNodeInfo(location, primaryTypeName, mixinTypeNames,
definitionId, uuid, children, properties);
-
- // Create the changed node representation ...
- changes = new ChangedNodeInfo(original);
- }
-
- protected Name name( String name ) {
- return context.getValueFactories().getNameFactory().create(name);
- }
-
- protected Segment segment( String segment ) {
- return pathFactory.createSegment(segment);
- }
-
- /**
- * Utility to set a property to the original node representation. This will replace
any existing property with the same name.
- *
- * @param name the name of the property; may not be null
- * @return the new property representation; never null
- */
- protected PropertyInfo makePropertyInOriginal( String name ) {
- Name propName = name(name);
- PropertyInfo propertyInfo = mock(PropertyInfo.class);
- stub(propertyInfo.getPropertyName()).toReturn(propName);
- properties.put(propName, propertyInfo);
- return propertyInfo;
- }
-
- /**
- * Utility to change a property in the changed representation.
- *
- * @param name the name of the property to change; may not be null
- * @return the new property; never null
- */
- protected PropertyInfo setPropertyInChanged( String name ) {
- Name propName = name(name);
- PropertyInfo propertyInfo = mock(PropertyInfo.class);
- stub(propertyInfo.getPropertyName()).toReturn(propName);
- changes.setProperty(propertyInfo, context.getValueFactories());
- return propertyInfo;
- }
-
- protected ChildNode makeChildInOriginal( String childName ) {
- ChildNode newChild = children.add(name(childName), UUID.randomUUID(),
pathFactory);
- return newChild;
- }
-
- protected ChildNode addChildInChanged( String childName ) {
- ChildNode newChild = changes.addChild(name(childName), UUID.randomUUID(),
pathFactory);
- // Make sure that the 'changes' object no longer returns the original
object's children object
- assertThat(changes.getChildren(),
is(not(sameInstance(original.getChildren()))));
- return newChild;
- }
-
- protected void removeChildFromChanged( ChildNode child ) {
- // Verify that a child node with the supplied UUID is contained.
- // Note that it may not be the same ChildNode instance if another SNS node with
smaller index was removed
- assertThat(changes.getChildren().getChild(child.getUuid()), is(notNullValue()));
- // Now remove the child, making sure the result is the same as the next
'getChildren()' call ...
- assertThat(changes.removeChild(child.getUuid(), pathFactory),
is(notNullValue()));
- // Verify it no longer exists ...
- assertThat(changes.getChildren().getChild(child.getUuid()), is(nullValue()));
- }
-
- @Test
- public void shouldNotBeNew() {
- assertThat(changes.isNew(), is(false));
- }
-
- @Test
- public void shouldBeModified() {
- assertThat(changes.isModified(), is(true));
- }
-
- @Test
- public void shouldHaveLocationFromOriginal() {
- assertThat(changes.getOriginalLocation(), is(sameInstance(location)));
- }
-
- @Test
- public void shouldHaveParentUuidFromOriginal() {
- assertThat(changes.getParent(), is(sameInstance(uuid)));
- }
-
- @Test
- public void shouldHavePrimaryTypeNameFromOriginal() {
- assertThat(changes.getPrimaryTypeName(), is(sameInstance(primaryTypeName)));
- }
-
- @Test
- public void shouldHaveMixinTypeNamesFromOriginal() {
- assertThat(changes.getMixinTypeNames(), is(sameInstance(mixinTypeNames)));
- }
-
- @Test
- public void shouldUpdateMixinTypeNamesWhenSettingJcrMixinTypeProperty() {
- // Create the DNA property ...
- Property mixinTypes = context.getPropertyFactory().create(JcrLexicon.MIXIN_TYPES,
"dna:type1", "dna:type2");
-
- // Modify the property ...
- PropertyInfo newPropertyInfo = mock(PropertyInfo.class);
- stub(newPropertyInfo.getPropertyName()).toReturn(mixinTypes.getName());
- stub(newPropertyInfo.getProperty()).toReturn(mixinTypes);
- PropertyInfo previous = changes.setProperty(newPropertyInfo,
context.getValueFactories());
- assertThat(previous, is(nullValue()));
-
- // Verify that the mixin types were updated ...
- assertThat(changes.getProperty(name("jcr:mixinTypes")),
is(sameInstance(newPropertyInfo)));
- assertThat(changes.getMixinTypeNames(), hasItems(name("dna:type2"),
name("dna:type1")));
- }
-
- @Test
- public void shouldHaveNodeDefinitionIdFromOriginal() {
- assertThat(changes.getDefinitionId(), is(sameInstance(definitionId)));
- }
-
- @Test
- public void shouldHaveChildrenFromOriginal() {
- assertThat(changes.getChildren(), is(sameInstance((Children)children)));
-
- ChildNode childA = makeChildInOriginal("childA");
- assertThat(changes.getChildren().size(), is(1));
- assertThat(changes.getChildren().getChild(childA.getUuid()),
is(sameInstance(childA)));
- assertThat(changes.getChildren(), hasChild(segment("childA[1]")));
- assertThat(changes.getChildren(), hasChild(childA.getUuid()));
- }
-
- @Test
- public void shouldHaveChildrenAfterAddingChild() {
- // Set up the original ...
- ChildNode childA1 = makeChildInOriginal("childA");
- ChildNode childB1 = makeChildInOriginal("childB");
- ChildNode childA2 = makeChildInOriginal("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Add child ...
- ChildNode childA3 = addChildInChanged("childA");
-
- // Verify that all children are there in the proper order ...
- assertThat(changes.getChildren().size(), is(4));
- assertThat(changes.getChildren(), hasChildren(segment("childA[1]"),
- segment("childB[1]"),
- segment("childA[2]"),
- segment("childA[3]")));
- assertThat(changes.getChildren(), hasChildren(childA1.getUuid(),
childB1.getUuid(), childA2.getUuid(), childA3.getUuid()));
- assertThat(changes.getChildren(), hasItems(childA1, childB1, childA2, childA3));
- }
-
- @Test
- public void shouldHaveChildrenAfterAddingMultipleChildren() {
- // Set up the original ...
- ChildNode childA1 = makeChildInOriginal("childA");
- ChildNode childB1 = makeChildInOriginal("childB");
- ChildNode childA2 = makeChildInOriginal("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Add some children in the changed representation ...
- ChildNode childA3 = addChildInChanged("childA");
- ChildNode childC1 = addChildInChanged("childC");
- ChildNode childC2 = addChildInChanged("childC");
-
- // Verify that all children are there in the proper order ...
- assertThat(changes.getChildren().size(), is(6));
- assertThat(changes.getChildren(), hasChildren(segment("childA[1]"),
- segment("childB[1]"),
- segment("childA[2]"),
- segment("childA[3]"),
- segment("childC[1]"),
- segment("childC[2]")));
- assertThat(changes.getChildren(), hasChildren(childA1.getUuid(),
- childB1.getUuid(),
- childA2.getUuid(),
- childA3.getUuid(),
- childC1.getUuid(),
- childC2.getUuid()));
- assertThat(changes.getChildren(), hasItems(childA1, childB1, childA2, childA3,
childC1, childC2));
- }
-
- @Test
- public void shouldHaveChildrenAfterAddingMultipleChildrenAndRemovingOthers() {
- // Set up the original ...
- ChildNode childA1 = makeChildInOriginal("childA");
- ChildNode childB1 = makeChildInOriginal("childB");
- ChildNode childA2 = makeChildInOriginal("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Add some children in the changed representation ...
- ChildNode childA3 = addChildInChanged("childA");
- ChildNode childC1 = addChildInChanged("childC");
- ChildNode childC2 = addChildInChanged("childC");
-
- // Delete a child that was added and another that was an original ...
- removeChildFromChanged(childC1);
- removeChildFromChanged(childA2);
-
- // Verify that all children are there in the proper order ...
- assertThat(changes.getChildren().size(), is(4));
- assertThat(changes.getChildren(), hasChildren(segment("childA[1]"),
- segment("childB[1]"),
- segment("childA[2]"),
- segment("childC[1]")));
- assertThat(changes.getChildren(), hasChildren(childA1.getUuid(),
childB1.getUuid(), childA3.getUuid(), childC2.getUuid()));
- }
-
- @Test
- public void
shouldHaveChildrenAfterAddingMultipleChildrenAndThenRemovingThoseJustAdded() {
- // Set up the original ...
- ChildNode childA1 = makeChildInOriginal("childA");
- ChildNode childB1 = makeChildInOriginal("childB");
- ChildNode childA2 = makeChildInOriginal("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Add some children in the changed representation ...
- ChildNode childA3 = addChildInChanged("childA");
- ChildNode childC1 = addChildInChanged("childC");
- ChildNode childC2 = addChildInChanged("childC");
-
- // Delete a child that was added and another that was an original...
- removeChildFromChanged(childA3);
- removeChildFromChanged(childC1); // causes replacement of 'childC2' with
lower SNS index
- removeChildFromChanged(childC2);
-
- // Verify that all children are there in the proper order ...
- assertThat(changes.getChildren().size(), is(3));
- assertThat(changes.getChildren(), hasChildren(segment("childA[1]"),
segment("childB[1]"), segment("childA[2]")));
- assertThat(changes.getChildren(), hasChildren(childA1.getUuid(),
childB1.getUuid(), childA2.getUuid()));
-
- // Do it again, but change the order of delete to delete from the back ...
-
- // Add some children in the changed representation ...
- childA3 = addChildInChanged("childA");
- childC1 = addChildInChanged("childC");
- childC2 = addChildInChanged("childC");
-
- // Delete a child that was added and another that was an original ...
- removeChildFromChanged(childC2);
- removeChildFromChanged(childC1);
- removeChildFromChanged(childA3);
-
- // Verify that all children are there in the proper order ...
- assertThat(changes.getChildren().size(), is(3));
- assertThat(changes.getChildren(), hasChildren(segment("childA[1]"),
segment("childB[1]"), segment("childA[2]")));
- assertThat(changes.getChildren(), hasChildren(childA1.getUuid(),
childB1.getUuid(), childA2.getUuid()));
-
- }
-
- @Test
- public void shouldHaveChildrenAfterDeletingChild() {
- // Set up the original ...
- ChildNode childA1 = makeChildInOriginal("childA");
- ChildNode childB1 = makeChildInOriginal("childB");
- ChildNode childA2 = makeChildInOriginal("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Delete a child that was added and another that was an original ...
- removeChildFromChanged(childA1);
-
- // Verify that all children are there in the proper order ...
- assertThat(changes.getChildren().size(), is(2));
- assertThat(changes.getChildren(), hasChildren(segment("childB[1]"),
segment("childA[1]")));
- assertThat(changes.getChildren(), hasChildren(childB1.getUuid(),
childA2.getUuid()));
- }
-
- @Test
- public void shouldHaveChildrenAfterDeletingMultipleChildren() {
- // Set up the original ...
- ChildNode childA1 = makeChildInOriginal("childA");
- ChildNode childB1 = makeChildInOriginal("childB");
- ChildNode childA2 = makeChildInOriginal("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Delete a child that was added and another that was an original ...
- removeChildFromChanged(childA1);
- removeChildFromChanged(childA2);
-
- // Verify that all children are there in the proper order ...
- assertThat(changes.getChildren().size(), is(1));
- assertThat(changes.getChildren(), hasChildren(segment("childB[1]")));
- assertThat(changes.getChildren(), hasChildren(childB1.getUuid()));
- }
-
- @Test
- public void shouldHaveChildrenAfterDeletingAllChildrenFromTheFirsttChildToTheLast()
{
- // Set up the original ...
- ChildNode childA1 = makeChildInOriginal("childA");
- ChildNode childB1 = makeChildInOriginal("childB");
- ChildNode childA2 = makeChildInOriginal("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Delete all children, from the front to the back ...
- removeChildFromChanged(childA1); // causes replacement of 'childA2' with
lower SNS index
- removeChildFromChanged(childA2);
- removeChildFromChanged(childB1);
-
- // Verify that all children have been removed ...
- assertThat(changes.getChildren().size(), is(0));
- }
-
- @Test
- public void shouldHaveChildrenAfterDeletingAllChildrenFromTheLastChildToTheFirst() {
- // Set up the original ...
- ChildNode childA1 = makeChildInOriginal("childA");
- ChildNode childB1 = makeChildInOriginal("childB");
- ChildNode childA2 = makeChildInOriginal("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Delete all children, from the back to the front ...
- removeChildFromChanged(childA2);
- removeChildFromChanged(childB1);
- removeChildFromChanged(childA1);
-
- // Verify that all children have been removed ...
- assertThat(changes.getChildren().size(), is(0));
- }
-
- @Test
- public void
shouldHaveChildrenAfterAddingSomeChildrenThenDeletingAllChildrenFromTheFirstChildToTheLast()
{
- // Set up the original ...
- ChildNode childA1 = makeChildInOriginal("childA");
- ChildNode childB1 = makeChildInOriginal("childB");
- ChildNode childA2 = makeChildInOriginal("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Add some children in the changed representation ...
- ChildNode childA3 = addChildInChanged("childA");
- ChildNode childC1 = addChildInChanged("childC");
- ChildNode childC2 = addChildInChanged("childC");
-
- // Delete all children, from the front to the back ...
- removeChildFromChanged(childA3);
- removeChildFromChanged(childC1); // causes replacement of 'childC2' with
lower SNS index
- removeChildFromChanged(childC2);
- removeChildFromChanged(childA1); // causes replacement of 'childA2' with
lower SNS index
- removeChildFromChanged(childB1);
- removeChildFromChanged(childA2);
-
- // Verify that all children have been removed ...
- assertThat(changes.getChildren().size(), is(0));
- }
-
- @Test
- public void
shouldHaveChildrenAfterAddingSomeChildrenThenDeletingAllChildrenFromTheLastChildToTheFirst()
{
- // Set up the original ...
- ChildNode childA1 = makeChildInOriginal("childA");
- ChildNode childB1 = makeChildInOriginal("childB");
- ChildNode childA2 = makeChildInOriginal("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Add some children in the changed representation ...
- ChildNode childA3 = addChildInChanged("childA");
- ChildNode childC1 = addChildInChanged("childC");
- ChildNode childC2 = addChildInChanged("childC");
-
- // Delete all children, from the back to the front ...
- removeChildFromChanged(childC2);
- removeChildFromChanged(childC1);
- removeChildFromChanged(childA3);
- removeChildFromChanged(childA2);
- removeChildFromChanged(childB1);
- removeChildFromChanged(childA1);
-
- // Verify that all children have been removed ...
- assertThat(changes.getChildren().size(), is(0));
- }
-
- @Test
- public void shouldHaveChildrenAfterReorderingChildren() {
-
- }
-
- @Test
- @SuppressWarnings( "unused" )
- public void
shouldNotRemoveFromNodeInfoWithNoChildChangesAChildThatMatchesSegmentButNotUuid() {
- // Set up the original ...
- ChildNode childA1 = makeChildInOriginal("childA");
- ChildNode childB1 = makeChildInOriginal("childB");
- ChildNode childA2 = makeChildInOriginal("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Create a bogus node that has a new UUID but with the same segment as
'childA3' ...
- Children before = changes.getChildren();
- int beforeSize = before.size();
- assertThat(changes.removeChild(UUID.randomUUID(), pathFactory),
is(nullValue()));
- Children after = changes.getChildren();
- assertThat(after.size(), is(beforeSize));
- assertThat(after, is(sameInstance(before)));
- assertThat(after, is(sameInstance(changes.getChildren())));
- }
-
- @Test
- @SuppressWarnings( "unused" )
- public void
shouldNotRemoveFromNodeInfoWithSomeChildChangesAChildThatMatchesSegmentButNotUuid() {
- // Set up the original ...
- ChildNode childA1 = makeChildInOriginal("childA");
- ChildNode childB1 = makeChildInOriginal("childB");
- ChildNode childA2 = makeChildInOriginal("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Add some children in the changed representation ...
- ChildNode childA3 = addChildInChanged("childA");
- ChildNode childC1 = addChildInChanged("childC");
- ChildNode childC2 = addChildInChanged("childC");
-
- // Create a bogus node that has a new UUID but with the same segment as
'childA3' ...
- Children before = changes.getChildren();
- int beforeSize = before.size();
- assertThat(changes.removeChild(UUID.randomUUID(), pathFactory),
is(nullValue()));
- Children after = changes.getChildren();
- assertThat(after.size(), is(beforeSize));
- assertThat(after, is(sameInstance(before)));
- assertThat(after, is(sameInstance(changes.getChildren())));
- }
-
- @Test
- public void shouldFindPropertyThatHasNotBeenModifiedButIsInOriginal() {
- PropertyInfo propertyInfo = makePropertyInOriginal("test");
- assertThat(changes.getProperty(name("test")),
is(sameInstance(propertyInfo)));
- }
-
- @Test
- public void shouldFindPropertyThatHasBeenModifiedFromOriginal() {
- PropertyInfo propertyInfo = makePropertyInOriginal("test");
- assertThat(changes.getProperty(name("test")),
is(sameInstance(propertyInfo)));
-
- // Modify the property ...
- PropertyInfo newPropertyInfo = mock(PropertyInfo.class);
- stub(newPropertyInfo.getPropertyName()).toReturn(name("test"));
- PropertyInfo previous = changes.setProperty(newPropertyInfo,
context.getValueFactories());
- assertThat(previous, is(sameInstance(propertyInfo)));
-
- // Verify we can find the new property ...
- assertThat(changes.getProperty(name("test")),
is(sameInstance(newPropertyInfo)));
- }
-
- @Test
- public void shouldNotFindPropertyThatHasBeenDeletedFromOriginal() {
- PropertyInfo propertyInfo = makePropertyInOriginal("test");
- assertThat(changes.getProperty(name("test")),
is(sameInstance(propertyInfo)));
-
- // Delete the property ...
- PropertyInfo previous = changes.removeProperty(name("test"));
- assertThat(previous, is(sameInstance(propertyInfo)));
-
- // Verify we can not find the new property ...
- assertThat(changes.getProperty(name("test")), is(nullValue()));
- }
-
- @Test
- public void shouldNotFindPropertyThatIsNotInOriginal() {
- assertThat(changes.getProperty(name("test")), is(nullValue()));
-
- makePropertyInOriginal("test");
- assertThat(changes.getProperty(name("nonExistant")), is(nullValue()));
- }
-
- @Test
- public void shouldFindAllPropertyNamesWhenChangedNodeHasNoChangedProperties() {
- PropertyInfo propA = makePropertyInOriginal("propA");
- PropertyInfo propB = makePropertyInOriginal("propB");
- PropertyInfo propC = makePropertyInOriginal("propC");
- PropertyInfo propD = makePropertyInOriginal("propD");
- Set<Name> names = changes.getPropertyNames();
- assertThat(names.size(), is(4));
- assertThat(names, hasItems(propA.getPropertyName(),
- propB.getPropertyName(),
- propC.getPropertyName(),
- propD.getPropertyName()));
- }
-
- @Test
- public void shouldFindAllPropertyNamesWhenChangedNodeHasDeletedAllProperties() {
- PropertyInfo propA = makePropertyInOriginal("propA");
- PropertyInfo propB = makePropertyInOriginal("propB");
- PropertyInfo propC = makePropertyInOriginal("propC");
- PropertyInfo propD = makePropertyInOriginal("propD");
- // Remove all properties ...
- assertThat(changes.removeProperty(propA.getPropertyName()),
is(sameInstance(propA)));
- assertThat(changes.removeProperty(propB.getPropertyName()),
is(sameInstance(propB)));
- assertThat(changes.removeProperty(propC.getPropertyName()),
is(sameInstance(propC)));
- assertThat(changes.removeProperty(propD.getPropertyName()),
is(sameInstance(propD)));
- // Now ask for names
- Set<Name> names = changes.getPropertyNames();
- assertThat(names.size(), is(0));
- }
-
- @Test
- public void shouldFindAllPropertyNamesWhenChangedNodeHasDeletedSomeProperties() {
- PropertyInfo propA = makePropertyInOriginal("propA");
- PropertyInfo propB = makePropertyInOriginal("propB");
- PropertyInfo propC = makePropertyInOriginal("propC");
- PropertyInfo propD = makePropertyInOriginal("propD");
- // Remove some properties ...
- assertThat(changes.removeProperty(propB.getPropertyName()),
is(sameInstance(propB)));
- assertThat(changes.removeProperty(propD.getPropertyName()),
is(sameInstance(propD)));
- // Now ask for names
- Set<Name> names = changes.getPropertyNames();
- assertThat(names.size(), is(2));
- assertThat(names, hasItems(propA.getPropertyName(), propC.getPropertyName()));
- }
-
- @Test
- @SuppressWarnings( "unused" )
- public void shouldFindAllPropertyNamesWhenChangedNodeHasChangedSomeProperties() {
- PropertyInfo propA = makePropertyInOriginal("propA");
- PropertyInfo propB = makePropertyInOriginal("propB");
- PropertyInfo propC = makePropertyInOriginal("propC");
- PropertyInfo propD = makePropertyInOriginal("propD");
- // Change some properties ...
- PropertyInfo propB2 = setPropertyInChanged("propB");
- PropertyInfo propC2 = setPropertyInChanged("propC");
- // Now ask for names
- Set<Name> names = changes.getPropertyNames();
- assertThat(names.size(), is(4));
- assertThat(names, hasItems(propA.getPropertyName(),
- propB2.getPropertyName(),
- propC2.getPropertyName(),
- propD.getPropertyName()));
- }
-
- @Test
- @SuppressWarnings( "unused" )
- public void shouldFindAllPropertyNamesWhenChangedNodeHasAddedSomeProperties() {
- PropertyInfo propA = makePropertyInOriginal("propA");
- PropertyInfo propB = makePropertyInOriginal("propB");
- PropertyInfo propC = makePropertyInOriginal("propC");
- PropertyInfo propD = makePropertyInOriginal("propD");
- // Add some properties ...
- PropertyInfo propE = setPropertyInChanged("propE");
- PropertyInfo propF = setPropertyInChanged("propF");
- PropertyInfo propG = setPropertyInChanged("propG");
- // Now ask for names
- Set<Name> names = changes.getPropertyNames();
- assertThat(names.size(), is(7));
- assertThat(names, hasItems(propA.getPropertyName(),
- propB.getPropertyName(),
- propC.getPropertyName(),
- propD.getPropertyName(),
- propE.getPropertyName(),
- propF.getPropertyName()));
- }
-
- @Test
- @SuppressWarnings( "unused" )
- public void
shouldFindAllPropertyNamesWhenChangedNodeHasChangedAndDeletedAndAddedSomeProperties() {
- PropertyInfo propA = makePropertyInOriginal("propA");
- PropertyInfo propB = makePropertyInOriginal("propB");
- PropertyInfo propC = makePropertyInOriginal("propC");
- PropertyInfo propD = makePropertyInOriginal("propD");
- // Change some properties ...
- PropertyInfo propB2 = setPropertyInChanged("propB");
- PropertyInfo propC2 = setPropertyInChanged("propC");
- // Add some properties ...
- PropertyInfo propE = setPropertyInChanged("propE");
- // Remove some properties ...
- assertThat(changes.removeProperty(propB2.getPropertyName()),
is(sameInstance(propB2)));
- assertThat(changes.removeProperty(propD.getPropertyName()),
is(sameInstance(propD)));
- // Now ask for names
- Set<Name> names = changes.getPropertyNames();
- assertThat(names.size(), is(3));
- assertThat(names, hasItems(propA.getPropertyName(), propC2.getPropertyName(),
propE.getPropertyName()));
- }
-
- @Test
- @SuppressWarnings( "unused" )
- public void
shouldFindAllPropertyNamesWhenChangedNodeHasChangedAndDeletedAllProperties() {
- PropertyInfo propA = makePropertyInOriginal("propA");
- PropertyInfo propB = makePropertyInOriginal("propB");
- PropertyInfo propC = makePropertyInOriginal("propC");
- PropertyInfo propD = makePropertyInOriginal("propD");
- // Change some properties ...
- PropertyInfo propB2 = setPropertyInChanged("propB");
- PropertyInfo propC2 = setPropertyInChanged("propC");
- // Remove all properties ...
- assertThat(changes.removeProperty(propA.getPropertyName()),
is(sameInstance(propA)));
- assertThat(changes.removeProperty(propB2.getPropertyName()),
is(sameInstance(propB2)));
- assertThat(changes.removeProperty(propC2.getPropertyName()),
is(sameInstance(propC2)));
- assertThat(changes.removeProperty(propD.getPropertyName()),
is(sameInstance(propD)));
- // Now ask for names
- Set<Name> names = changes.getPropertyNames();
- assertThat(names.size(), is(0));
- }
-
-}
Deleted: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/ImmutableChildrenTest.java
===================================================================
---
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/ImmutableChildrenTest.java 2009-07-09
16:23:09 UTC (rev 1081)
+++
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/ImmutableChildrenTest.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -1,141 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you 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.
- *
- * JBoss DNA 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.jcr.cache;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import java.util.UUID;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- *
- */
-public class ImmutableChildrenTest extends AbstractChildrenTest<ImmutableChildren>
{
-
- @Override
- @Before
- public void beforeEach() {
- super.beforeEach();
-
- children = new ImmutableChildren(parentUuid);
- firstChild = children.add(firstChildName, firstChildUuid, pathFactory);
- }
-
- @Test
- public void shouldHaveCorrectSize() {
- assertThat(children.size(), is(1));
- }
-
- @Test
- public void shouldFindChildrenByName() {
- Iterator<ChildNode> iter = children.getChildren(firstChildName);
- assertThat(iter.hasNext(), is(true));
- assertThat(iter.next(), is(sameInstance(firstChild)));
- assertThat(iter.hasNext(), is(false));
- try {
- iter.next();
- fail("Failed to throw exception");
- } catch (NoSuchElementException e) {
- // expected
- }
- }
-
- @Test( expected = UnsupportedOperationException.class )
- public void shouldReturnIteratorThatDoesNotSupportRemoving() {
- Iterator<ChildNode> iter = children.getChildren(firstChildName);
- assertThat(iter.hasNext(), is(true));
- assertThat(iter.next(), is(sameInstance(firstChild)));
- iter.remove();
- }
-
- @Test
- public void shouldReturnEmptyChildrenFromWithoutIfOnlyChildIsRemoved() {
- Children newChildren = children.without(firstChild.getUuid(), pathFactory);
- assertThat(newChildren.size(), is(0));
- }
-
- @Test
- public void shouldReturnChangedChildrenFromWithoutIfSuppliedChildIsFound() {
- ChildNode child2 = children.add(name("childB"), UUID.randomUUID(),
pathFactory);
- ChildNode child3 = children.add(name("childC"), UUID.randomUUID(),
pathFactory);
- ChildNode child4 = children.add(name("childA"), UUID.randomUUID(),
pathFactory);
- ChildNode child5 = children.add(name("childA"), UUID.randomUUID(),
pathFactory);
- ChildNode child6 = children.add(name("childD"), UUID.randomUUID(),
pathFactory);
-
- // Check that the children contains what we expect ...
- assertChildNodes(children, firstChild, child2, child3, child4, child5, child6);
- assertChildNodesWithName(children, "childA", firstChild, child4,
child5);
-
- // Remove 'child4' ...
- Children result = children.without(child4.getUuid(), pathFactory);
-
- // the original should not have been changed ...
- assertChildNodesWithName(children, "childA", firstChild, child4,
child5);
- // but the result should not have child4 ...
- assertChildNodesWithName(result, "childA", firstChild,
"childA");
-
- // Now check that all the child nodes are still in the original, in the same
order ...
- assertChildNodes(children, firstChild, child2, child3, child4, child5, child6);
-
- // Now check that all the child nodes are in the result, in the expected order
...
- assertChildNodes(result, firstChild, child2, child3, "childA",
child6);
- }
-
- @Test
- public void shouldReturnChangedChildrenFromWithIfSuppliedChildIsNotFound() {
- // Make sure that children contains what we expect ...
- assertChildNodes(children, firstChild);
- assertChildNodesWithName(children, "childA", firstChild);
-
- // Add a node ...
- ChangedChildren newChildren = children.with(name("childB"),
UUID.randomUUID(), pathFactory);
- assertChildNodes(newChildren, firstChild, "childB");
- assertChildNodesWithName(newChildren, "childA", firstChild);
- // And make sure 'children' hasn't changed ...
- assertChildNodes(children, firstChild);
- assertChildNodesWithName(children, "childA", firstChild);
-
- // Add another node ...
- newChildren = newChildren.with(name("childC"), UUID.randomUUID(),
pathFactory);
- assertChildNodes(newChildren, firstChild, "childB",
"childC");
- assertChildNodesWithName(newChildren, "childA", firstChild);
- // And make sure 'children' hasn't changed ...
- assertChildNodes(children, firstChild);
- assertChildNodesWithName(children, "childA", firstChild);
-
- // Add another node ...
- newChildren = newChildren.with(name("childA"), UUID.randomUUID(),
pathFactory);
- assertChildNodes(newChildren, firstChild, "childB", "childC",
"childA");
- assertChildNodesWithName(newChildren, "childA", firstChild,
"childA");
- // And make sure 'children' hasn't changed ...
- assertChildNodes(children, firstChild);
- assertChildNodesWithName(children, "childA", firstChild);
- }
-
-}
Deleted:
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/IsNodeInfoWithChildrenHavingNames.java
===================================================================
---
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/IsNodeInfoWithChildrenHavingNames.java 2009-07-09
16:23:09 UTC (rev 1081)
+++
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/IsNodeInfoWithChildrenHavingNames.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -1,84 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
- * is licensed to you 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.
- *
- * JBoss DNA 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.jcr.cache;
-
-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.property.Name;
-import org.jboss.dna.graph.property.Path;
-import org.jboss.dna.graph.property.basic.BasicPathSegment;
-import org.junit.matchers.IsCollectionContaining;
-import org.junit.matchers.TypeSafeMatcher;
-
-/**
- * A JUnit {@link TypeSafeMatcher matcher} that can be used to assert that a NodeInfo (or
other
- * <code>Iterable<ChildNode></code>) has {@link ChildNode}
instances with specific {@link ChildNode#getSegment() names}.
- */
-public class IsNodeInfoWithChildrenHavingNames extends TypeSafeMatcher<Children> {
- private final Matcher<Iterable<Path.Segment>> childMatcher;
-
- public IsNodeInfoWithChildrenHavingNames( Matcher<Iterable<Path.Segment>>
childMatcher ) {
- this.childMatcher = childMatcher;
- }
-
- @Override
- public boolean matchesSafely( Children children ) {
- List<Path.Segment> childSegments = new
ArrayList<Path.Segment>(children.size());
- for (ChildNode child : children) {
- childSegments.add(child.getSegment());
- }
- return childMatcher.matches(childSegments);
- }
-
- public void describeTo( Description description ) {
- description.appendText("children").appendDescriptionOf(childMatcher);
- }
-
- @Factory
- public static IsNodeInfoWithChildrenHavingNames hasChild( Name name,
- int sameNameSiblingIndex )
{
- Path.Segment segment = new BasicPathSegment(name, sameNameSiblingIndex);
- return new
IsNodeInfoWithChildrenHavingNames(IsCollectionContaining.hasItem(segment));
- }
-
- @Factory
- public static IsNodeInfoWithChildrenHavingNames hasChild( Path.Segment child ) {
- return new
IsNodeInfoWithChildrenHavingNames(IsCollectionContaining.hasItem(child));
- }
-
- @Factory
- public static IsNodeInfoWithChildrenHavingNames hasChildren( Path.Segment...
childSegments ) {
- return new
IsNodeInfoWithChildrenHavingNames(IsCollectionContaining.hasItems(childSegments));
- }
-
- @Factory
- public static IsNodeInfoWithChildrenHavingNames isEmpty() {
- Path.Segment[] childSegments = new Path.Segment[] {};
- return new
IsNodeInfoWithChildrenHavingNames(IsCollectionContaining.hasItems(childSegments));
- }
-
-}
Deleted:
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/IsNodeInfoWithChildrenHavingUuids.java
===================================================================
---
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/IsNodeInfoWithChildrenHavingUuids.java 2009-07-09
16:23:09 UTC (rev 1081)
+++
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/IsNodeInfoWithChildrenHavingUuids.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -1,75 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
- * is licensed to you 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.
- *
- * JBoss DNA 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.jcr.cache;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-import org.hamcrest.Description;
-import org.hamcrest.Factory;
-import org.hamcrest.Matcher;
-import org.junit.matchers.IsCollectionContaining;
-import org.junit.matchers.TypeSafeMatcher;
-
-/**
- * A JUnit {@link TypeSafeMatcher matcher} that can be used to assert that a NodeInfo (or
other
- * <code>Iterable<ChildNode></code>) has {@link ChildNode}
instances with specific {@link ChildNode#getUuid() UUIDs}.
- */
-public class IsNodeInfoWithChildrenHavingUuids extends TypeSafeMatcher<Children> {
- private final Matcher<Iterable<UUID>> childMatcher;
-
- public IsNodeInfoWithChildrenHavingUuids( Matcher<Iterable<UUID>>
childMatcher ) {
- this.childMatcher = childMatcher;
- }
-
- @Override
- public boolean matchesSafely( Children children ) {
- List<UUID> childSegments = new ArrayList<UUID>(children.size());
- for (ChildNode child : children) {
- childSegments.add(child.getUuid());
- }
- return childMatcher.matches(childSegments);
- }
-
- public void describeTo( Description description ) {
- description.appendText("children with
UUIDs").appendDescriptionOf(childMatcher);
- }
-
- @Factory
- public static IsNodeInfoWithChildrenHavingUuids hasChild( UUID uuid ) {
- return new
IsNodeInfoWithChildrenHavingUuids(IsCollectionContaining.hasItem(uuid));
- }
-
- @Factory
- public static IsNodeInfoWithChildrenHavingUuids hasChildren( UUID... uuids ) {
- return new
IsNodeInfoWithChildrenHavingUuids(IsCollectionContaining.hasItems(uuids));
- }
-
- @Factory
- public static IsNodeInfoWithChildrenHavingUuids isEmpty() {
- UUID[] uuids = new UUID[] {};
- return new
IsNodeInfoWithChildrenHavingUuids(IsCollectionContaining.hasItems(uuids));
- }
-
-}
Deleted: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/NewNodeInfoTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/NewNodeInfoTest.java 2009-07-09
16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/cache/NewNodeInfoTest.java 2009-07-09
16:26:04 UTC (rev 1082)
@@ -1,672 +0,0 @@
-/*
- * JBoss DNA (
http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you 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.
- *
- * JBoss DNA 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.jcr.cache;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.jboss.dna.jcr.cache.IsNodeInfoWithChildrenHavingNames.hasChildren;
-import static org.jboss.dna.jcr.cache.IsNodeInfoWithChildrenHavingUuids.hasChildren;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.hasItems;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.stub;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.JcrLexicon;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.PathFactory;
-import org.jboss.dna.graph.property.Property;
-import org.jboss.dna.graph.property.Path.Segment;
-import org.jboss.dna.jcr.NodeDefinitionId;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- *
- */
-public class NewNodeInfoTest {
-
- private ExecutionContext context;
- private PathFactory pathFactory;
- private UUID uuid;
- private Name primaryTypeName;
- private Name[] requiredPrimaryTypes;
- private Location location;
- private NodeDefinitionId definitionId;
- private Map<Name, PropertyInfo> properties;
- private ChangedNodeInfo changes;
-
- @Before
- public void beforeEach() {
- context = new ExecutionContext();
- context.getNamespaceRegistry().register("acme",
"http://example.com/acme");
- pathFactory = context.getValueFactories().getPathFactory();
-
- // Set up the original ...
- uuid = UUID.randomUUID();
- location = Location.create(uuid);
- primaryTypeName = name("acme:geniusType");
- requiredPrimaryTypes = new Name[] {name("acme:requiredTypeA"),
name("acme:requiredTypeB")};
- definitionId = new NodeDefinitionId(name("acme:geniusContainerType"),
name("acme:geniuses"), requiredPrimaryTypes);
- properties = new HashMap<Name, PropertyInfo>();
-
- // Create the changed node representation ...
- changes = new NewNodeInfo(location, primaryTypeName, definitionId, uuid,
properties);
- }
-
- protected Name name( String name ) {
- return context.getValueFactories().getNameFactory().create(name);
- }
-
- protected Segment segment( String segment ) {
- return pathFactory.createSegment(segment);
- }
-
- /**
- * Utility to set a property to the original node representation. This will replace
any existing property with the same name.
- *
- * @param name the name of the property; may not be null
- * @return the new property representation; never null
- */
- protected PropertyInfo makePropertyInOriginal( String name ) {
- Name propName = name(name);
- PropertyInfo propertyInfo = mock(PropertyInfo.class);
- stub(propertyInfo.getPropertyName()).toReturn(propName);
- properties.put(propName, propertyInfo);
- return propertyInfo;
- }
-
- /**
- * Utility to change a property in the changed representation.
- *
- * @param name the name of the property to change; may not be null
- * @return the new property; never null
- */
- protected PropertyInfo setPropertyInChanged( String name ) {
- Name propName = name(name);
- PropertyInfo propertyInfo = mock(PropertyInfo.class);
- stub(propertyInfo.getPropertyName()).toReturn(propName);
- changes.setProperty(propertyInfo, context.getValueFactories());
- return propertyInfo;
- }
-
- protected ChildNode addChildInChanged( String childName ) {
- ChildNode newChild = changes.addChild(name(childName), UUID.randomUUID(),
pathFactory);
- return newChild;
- }
-
- protected void removeChildFromChanged( ChildNode child ) {
- // Verify that a child node with the supplied UUID is contained.
- // Note that it may not be the same ChildNode instance if another SNS node with
smaller index was removed
- assertThat(changes.getChildren().getChild(child.getUuid()), is(notNullValue()));
- // Now remove the child, making sure the result is the same as the next
'getChildren()' call ...
- assertThat(changes.removeChild(child.getUuid(), pathFactory),
is(notNullValue()));
- // Verify it no longer exists ...
- assertThat(changes.getChildren().getChild(child.getUuid()), is(nullValue()));
- }
-
- @Test
- public void shouldBeNew() {
- assertThat(changes.isNew(), is(true));
- }
-
- @Test
- public void shouldNotBeModified() {
- assertThat(changes.isModified(), is(false));
- }
-
- @Test
- public void shouldInitiallyHaveLocation() {
- assertThat(changes.getOriginalLocation(), is(sameInstance(location)));
- }
-
- @Test
- public void shouldInitiallyHaveParentUuid() {
- assertThat(changes.getParent(), is(sameInstance(uuid)));
- }
-
- @Test
- public void shouldInitiallyHavePrimaryTypeName() {
- assertThat(changes.getPrimaryTypeName(), is(sameInstance(primaryTypeName)));
- }
-
- @Test
- public void shouldInitiallyHaveMixinNoTypeNames() {
- assertThat(changes.getMixinTypeNames().size(), is(0));
- }
-
- @Test
- public void shouldUpdateMixinTypeNamesWhenSettingJcrMixinTypeProperty() {
- // Create the DNA property ...
- Property mixinTypes = context.getPropertyFactory().create(JcrLexicon.MIXIN_TYPES,
"dna:type1", "dna:type2");
-
- // Modify the property ...
- PropertyInfo newPropertyInfo = mock(PropertyInfo.class);
- stub(newPropertyInfo.getPropertyName()).toReturn(mixinTypes.getName());
- stub(newPropertyInfo.getProperty()).toReturn(mixinTypes);
- PropertyInfo previous = changes.setProperty(newPropertyInfo,
context.getValueFactories());
- assertThat(previous, is(nullValue()));
-
- // Verify that the mixin types were updated ...
- assertThat(changes.getProperty(name("jcr:mixinTypes")),
is(sameInstance(newPropertyInfo)));
- assertThat(changes.getMixinTypeNames(), hasItems(name("dna:type2"),
name("dna:type1")));
- }
-
- @Test
- public void shouldHaveNodeDefinitionId() {
- assertThat(changes.getDefinitionId(), is(sameInstance(definitionId)));
- }
-
- @Test
- public void shouldHaveNoChildren() {
- assertThat(changes.getChildren().size(), is(0));
- }
-
- @Test
- public void shouldHaveChildrenAfterAddingChild() {
- assertThat(changes.getChildren().size(), is(0));
-
- // Add child ...
- ChildNode childA1 = addChildInChanged("childA");
- assertThat(changes.getChildren().size(), is(1));
- assertThat(changes.getChildren(), hasChildren(segment("childA")));
-
- // Add more children ...
- ChildNode childB1 = addChildInChanged("childB");
- ChildNode childA2 = addChildInChanged("childA");
- ChildNode childA3 = addChildInChanged("childA");
-
- // Verify that all children are there in the proper order ...
- assertThat(changes.getChildren().size(), is(4));
- assertThat(changes.getChildren(), hasChildren(segment("childA[1]"),
- segment("childB[1]"),
- segment("childA[2]"),
- segment("childA[3]")));
- assertThat(changes.getChildren(), hasChildren(childA1.getUuid(),
childB1.getUuid(), childA2.getUuid(), childA3.getUuid()));
- assertThat(changes.getChildren(), hasItems(childA1, childB1, childA2, childA3));
- }
-
- @Test
- public void shouldHaveChildrenAfterAddingMultipleChildren() {
- assertThat(changes.getChildren().size(), is(0));
-
- // Add some children ...
- ChildNode childA1 = addChildInChanged("childA");
- ChildNode childB1 = addChildInChanged("childB");
- ChildNode childA2 = addChildInChanged("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Add some children in the changed representation ...
- ChildNode childA3 = addChildInChanged("childA");
- ChildNode childC1 = addChildInChanged("childC");
- ChildNode childC2 = addChildInChanged("childC");
-
- // Verify that all children are there in the proper order ...
- assertThat(changes.getChildren().size(), is(6));
- assertThat(changes.getChildren(), hasChildren(segment("childA[1]"),
- segment("childB[1]"),
- segment("childA[2]"),
- segment("childA[3]"),
- segment("childC[1]"),
- segment("childC[2]")));
- assertThat(changes.getChildren(), hasChildren(childA1.getUuid(),
- childB1.getUuid(),
- childA2.getUuid(),
- childA3.getUuid(),
- childC1.getUuid(),
- childC2.getUuid()));
- assertThat(changes.getChildren(), hasItems(childA1, childB1, childA2, childA3,
childC1, childC2));
- }
-
- @Test
- public void shouldHaveChildrenAfterAddingMultipleChildrenAndRemovingOthers() {
- assertThat(changes.getChildren().size(), is(0));
-
- // Add some children ...
- ChildNode childA1 = addChildInChanged("childA");
- ChildNode childB1 = addChildInChanged("childB");
- ChildNode childA2 = addChildInChanged("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Add some children in the changed representation ...
- ChildNode childA3 = addChildInChanged("childA");
- ChildNode childC1 = addChildInChanged("childC");
- ChildNode childC2 = addChildInChanged("childC");
-
- // Delete a child that was added and another that was an original ...
- removeChildFromChanged(childC1);
- removeChildFromChanged(childA2);
-
- // Verify that all children are there in the proper order ...
- assertThat(changes.getChildren().size(), is(4));
- assertThat(changes.getChildren(), hasChildren(segment("childA[1]"),
- segment("childB[1]"),
- segment("childA[2]"),
- segment("childC[1]")));
- assertThat(changes.getChildren(), hasChildren(childA1.getUuid(),
childB1.getUuid(), childA3.getUuid(), childC2.getUuid()));
- }
-
- @Test
- public void
shouldHaveChildrenAfterAddingMultipleChildrenAndThenRemovingThoseJustAdded() {
- assertThat(changes.getChildren().size(), is(0));
-
- // Add some children ...
- ChildNode childA1 = addChildInChanged("childA");
- ChildNode childB1 = addChildInChanged("childB");
- ChildNode childA2 = addChildInChanged("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Add some children in the changed representation ...
- ChildNode childA3 = addChildInChanged("childA");
- ChildNode childC1 = addChildInChanged("childC");
- ChildNode childC2 = addChildInChanged("childC");
-
- // Delete a child that was added and another that was an original...
- removeChildFromChanged(childA3);
- removeChildFromChanged(childC1); // causes replacement of 'childC2' with
lower SNS index
- removeChildFromChanged(childC2);
-
- // Verify that all children are there in the proper order ...
- assertThat(changes.getChildren().size(), is(3));
- assertThat(changes.getChildren(), hasChildren(segment("childA[1]"),
segment("childB[1]"), segment("childA[2]")));
- assertThat(changes.getChildren(), hasChildren(childA1.getUuid(),
childB1.getUuid(), childA2.getUuid()));
-
- // Do it again, but change the order of delete to delete from the back ...
-
- // Add some children in the changed representation ...
- childA3 = addChildInChanged("childA");
- childC1 = addChildInChanged("childC");
- childC2 = addChildInChanged("childC");
-
- // Delete a child that was added and another that was an original ...
- removeChildFromChanged(childC2);
- removeChildFromChanged(childC1);
- removeChildFromChanged(childA3);
-
- // Verify that all children are there in the proper order ...
- assertThat(changes.getChildren().size(), is(3));
- assertThat(changes.getChildren(), hasChildren(segment("childA[1]"),
segment("childB[1]"), segment("childA[2]")));
- assertThat(changes.getChildren(), hasChildren(childA1.getUuid(),
childB1.getUuid(), childA2.getUuid()));
-
- }
-
- @Test
- public void shouldHaveChildrenAfterDeletingChild() {
- assertThat(changes.getChildren().size(), is(0));
-
- // Add some children ...
- ChildNode childA1 = addChildInChanged("childA");
- ChildNode childB1 = addChildInChanged("childB");
- ChildNode childA2 = addChildInChanged("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Delete a child that was added and another that was an original ...
- removeChildFromChanged(childA1);
-
- // Verify that all children are there in the proper order ...
- assertThat(changes.getChildren().size(), is(2));
- assertThat(changes.getChildren(), hasChildren(segment("childB[1]"),
segment("childA[1]")));
- assertThat(changes.getChildren(), hasChildren(childB1.getUuid(),
childA2.getUuid()));
- }
-
- @Test
- public void shouldHaveChildrenAfterDeletingMultipleChildren() {
- assertThat(changes.getChildren().size(), is(0));
-
- // Add some children ...
- ChildNode childA1 = addChildInChanged("childA");
- ChildNode childB1 = addChildInChanged("childB");
- ChildNode childA2 = addChildInChanged("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Delete a child that was added and another that was an original ...
- removeChildFromChanged(childA1);
- removeChildFromChanged(childA2);
-
- // Verify that all children are there in the proper order ...
- assertThat(changes.getChildren().size(), is(1));
- assertThat(changes.getChildren(), hasChildren(segment("childB[1]")));
- assertThat(changes.getChildren(), hasChildren(childB1.getUuid()));
- }
-
- @Test
- public void shouldHaveChildrenAfterDeletingAllChildrenFromTheFirsttChildToTheLast()
{
- assertThat(changes.getChildren().size(), is(0));
-
- // Add some children ...
- ChildNode childA1 = addChildInChanged("childA");
- ChildNode childB1 = addChildInChanged("childB");
- ChildNode childA2 = addChildInChanged("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Delete all children, from the front to the back ...
- removeChildFromChanged(childA1); // causes replacement of 'childA2' with
lower SNS index
- removeChildFromChanged(childA2);
- removeChildFromChanged(childB1);
-
- // Verify that all children have been removed ...
- assertThat(changes.getChildren().size(), is(0));
- }
-
- @Test
- public void shouldHaveChildrenAfterDeletingAllChildrenFromTheLastChildToTheFirst() {
- assertThat(changes.getChildren().size(), is(0));
-
- // Add some children ...
- ChildNode childA1 = addChildInChanged("childA");
- ChildNode childB1 = addChildInChanged("childB");
- ChildNode childA2 = addChildInChanged("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Delete all children, from the back to the front ...
- removeChildFromChanged(childA2);
- removeChildFromChanged(childB1);
- removeChildFromChanged(childA1);
-
- // Verify that all children have been removed ...
- assertThat(changes.getChildren().size(), is(0));
- }
-
- @Test
- public void
shouldHaveChildrenAfterAddingSomeChildrenThenDeletingAllChildrenFromTheFirstChildToTheLast()
{
- assertThat(changes.getChildren().size(), is(0));
-
- // Add some children ...
- ChildNode childA1 = addChildInChanged("childA");
- ChildNode childB1 = addChildInChanged("childB");
- ChildNode childA2 = addChildInChanged("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Add some children in the changed representation ...
- ChildNode childA3 = addChildInChanged("childA");
- ChildNode childC1 = addChildInChanged("childC");
- ChildNode childC2 = addChildInChanged("childC");
-
- // Delete all children, from the front to the back ...
- removeChildFromChanged(childA3);
- removeChildFromChanged(childC1); // causes replacement of 'childC2' with
lower SNS index
- removeChildFromChanged(childC2);
- removeChildFromChanged(childA1); // causes replacement of 'childA2' with
lower SNS index
- removeChildFromChanged(childB1);
- removeChildFromChanged(childA2);
-
- // Verify that all children have been removed ...
- assertThat(changes.getChildren().size(), is(0));
- }
-
- @Test
- public void
shouldHaveChildrenAfterAddingSomeChildrenThenDeletingAllChildrenFromTheLastChildToTheFirst()
{
- assertThat(changes.getChildren().size(), is(0));
-
- // Add some children ...
- ChildNode childA1 = addChildInChanged("childA");
- ChildNode childB1 = addChildInChanged("childB");
- ChildNode childA2 = addChildInChanged("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Add some children in the changed representation ...
- ChildNode childA3 = addChildInChanged("childA");
- ChildNode childC1 = addChildInChanged("childC");
- ChildNode childC2 = addChildInChanged("childC");
-
- // Delete all children, from the back to the front ...
- removeChildFromChanged(childC2);
- removeChildFromChanged(childC1);
- removeChildFromChanged(childA3);
- removeChildFromChanged(childA2);
- removeChildFromChanged(childB1);
- removeChildFromChanged(childA1);
-
- // Verify that all children have been removed ...
- assertThat(changes.getChildren().size(), is(0));
- }
-
- @Test
- public void shouldHaveChildrenAfterReorderingChildren() {
-
- }
-
- @Test
- @SuppressWarnings( "unused" )
- public void
shouldNotRemoveFromNodeInfoWithNoChildChangesAChildThatMatchesSegmentButNotUuid() {
- assertThat(changes.getChildren().size(), is(0));
-
- // Add some children ...
- ChildNode childA1 = addChildInChanged("childA");
- ChildNode childB1 = addChildInChanged("childB");
- ChildNode childA2 = addChildInChanged("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Create a bogus node that has a new UUID but with the same segment as
'childA3' ...
- Children before = changes.getChildren();
- int beforeSize = before.size();
- assertThat(changes.removeChild(UUID.randomUUID(), pathFactory),
is(nullValue()));
- Children after = changes.getChildren();
- assertThat(after.size(), is(beforeSize));
- assertThat(after, is(sameInstance(before)));
- assertThat(after, is(sameInstance(changes.getChildren())));
- }
-
- @Test
- @SuppressWarnings( "unused" )
- public void
shouldNotRemoveFromNodeInfoWithSomeChildChangesAChildThatMatchesSegmentButNotUuid() {
- assertThat(changes.getChildren().size(), is(0));
-
- // Add some children ...
- ChildNode childA1 = addChildInChanged("childA");
- ChildNode childB1 = addChildInChanged("childB");
- ChildNode childA2 = addChildInChanged("childA");
- assertThat(changes.getChildren().size(), is(3));
-
- // Add some children in the changed representation ...
- ChildNode childA3 = addChildInChanged("childA");
- ChildNode childC1 = addChildInChanged("childC");
- ChildNode childC2 = addChildInChanged("childC");
-
- // Create a bogus node that has a new UUID but with the same segment as
'childA3' ...
- Children before = changes.getChildren();
- int beforeSize = before.size();
- assertThat(changes.removeChild(UUID.randomUUID(), pathFactory),
is(nullValue()));
- Children after = changes.getChildren();
- assertThat(after.size(), is(beforeSize));
- assertThat(after, is(sameInstance(before)));
- assertThat(after, is(sameInstance(changes.getChildren())));
- }
-
- @Test
- public void shouldFindPropertyThatHasNotBeenModifiedButIsInOriginal() {
- PropertyInfo propertyInfo = makePropertyInOriginal("test");
- assertThat(changes.getProperty(name("test")),
is(sameInstance(propertyInfo)));
- }
-
- @Test
- public void shouldFindPropertyThatHasBeenModifiedFromOriginal() {
- PropertyInfo propertyInfo = makePropertyInOriginal("test");
- assertThat(changes.getProperty(name("test")),
is(sameInstance(propertyInfo)));
-
- // Modify the property ...
- PropertyInfo newPropertyInfo = mock(PropertyInfo.class);
- stub(newPropertyInfo.getPropertyName()).toReturn(name("test"));
- PropertyInfo previous = changes.setProperty(newPropertyInfo,
context.getValueFactories());
- assertThat(previous, is(sameInstance(propertyInfo)));
-
- // Verify we can find the new property ...
- assertThat(changes.getProperty(name("test")),
is(sameInstance(newPropertyInfo)));
- }
-
- @Test
- public void shouldNotFindPropertyThatHasBeenDeletedFromOriginal() {
- PropertyInfo propertyInfo = makePropertyInOriginal("test");
- assertThat(changes.getProperty(name("test")),
is(sameInstance(propertyInfo)));
-
- // Delete the property ...
- PropertyInfo previous = changes.removeProperty(name("test"));
- assertThat(previous, is(sameInstance(propertyInfo)));
-
- // Verify we can not find the new property ...
- assertThat(changes.getProperty(name("test")), is(nullValue()));
- }
-
- @Test
- public void shouldNotFindPropertyThatIsNotInOriginal() {
- assertThat(changes.getProperty(name("test")), is(nullValue()));
-
- makePropertyInOriginal("test");
- assertThat(changes.getProperty(name("nonExistant")), is(nullValue()));
- }
-
- @Test
- public void shouldFindAllPropertyNamesWhenChangedNodeHasNoChangedProperties() {
- PropertyInfo propA = makePropertyInOriginal("propA");
- PropertyInfo propB = makePropertyInOriginal("propB");
- PropertyInfo propC = makePropertyInOriginal("propC");
- PropertyInfo propD = makePropertyInOriginal("propD");
- Set<Name> names = changes.getPropertyNames();
- assertThat(names.size(), is(4));
- assertThat(names, hasItems(propA.getPropertyName(),
- propB.getPropertyName(),
- propC.getPropertyName(),
- propD.getPropertyName()));
- }
-
- @Test
- public void shouldFindAllPropertyNamesWhenChangedNodeHasDeletedAllProperties() {
- PropertyInfo propA = makePropertyInOriginal("propA");
- PropertyInfo propB = makePropertyInOriginal("propB");
- PropertyInfo propC = makePropertyInOriginal("propC");
- PropertyInfo propD = makePropertyInOriginal("propD");
- // Remove all properties ...
- assertThat(changes.removeProperty(propA.getPropertyName()),
is(sameInstance(propA)));
- assertThat(changes.removeProperty(propB.getPropertyName()),
is(sameInstance(propB)));
- assertThat(changes.removeProperty(propC.getPropertyName()),
is(sameInstance(propC)));
- assertThat(changes.removeProperty(propD.getPropertyName()),
is(sameInstance(propD)));
- // Now ask for names
- Set<Name> names = changes.getPropertyNames();
- assertThat(names.size(), is(0));
- }
-
- @Test
- public void shouldFindAllPropertyNamesWhenChangedNodeHasDeletedSomeProperties() {
- PropertyInfo propA = makePropertyInOriginal("propA");
- PropertyInfo propB = makePropertyInOriginal("propB");
- PropertyInfo propC = makePropertyInOriginal("propC");
- PropertyInfo propD = makePropertyInOriginal("propD");
- // Remove some properties ...
- assertThat(changes.removeProperty(propB.getPropertyName()),
is(sameInstance(propB)));
- assertThat(changes.removeProperty(propD.getPropertyName()),
is(sameInstance(propD)));
- // Now ask for names
- Set<Name> names = changes.getPropertyNames();
- assertThat(names.size(), is(2));
- assertThat(names, hasItems(propA.getPropertyName(), propC.getPropertyName()));
- }
-
- @Test
- @SuppressWarnings( "unused" )
- public void shouldFindAllPropertyNamesWhenChangedNodeHasChangedSomeProperties() {
- PropertyInfo propA = makePropertyInOriginal("propA");
- PropertyInfo propB = makePropertyInOriginal("propB");
- PropertyInfo propC = makePropertyInOriginal("propC");
- PropertyInfo propD = makePropertyInOriginal("propD");
- // Change some properties ...
- PropertyInfo propB2 = setPropertyInChanged("propB");
- PropertyInfo propC2 = setPropertyInChanged("propC");
- // Now ask for names
- Set<Name> names = changes.getPropertyNames();
- assertThat(names.size(), is(4));
- assertThat(names, hasItems(propA.getPropertyName(),
- propB2.getPropertyName(),
- propC2.getPropertyName(),
- propD.getPropertyName()));
- }
-
- @Test
- @SuppressWarnings( "unused" )
- public void shouldFindAllPropertyNamesWhenChangedNodeHasAddedSomeProperties() {
- PropertyInfo propA = makePropertyInOriginal("propA");
- PropertyInfo propB = makePropertyInOriginal("propB");
- PropertyInfo propC = makePropertyInOriginal("propC");
- PropertyInfo propD = makePropertyInOriginal("propD");
- // Add some properties ...
- PropertyInfo propE = setPropertyInChanged("propE");
- PropertyInfo propF = setPropertyInChanged("propF");
- PropertyInfo propG = setPropertyInChanged("propG");
- // Now ask for names
- Set<Name> names = changes.getPropertyNames();
- assertThat(names.size(), is(7));
- assertThat(names, hasItems(propA.getPropertyName(),
- propB.getPropertyName(),
- propC.getPropertyName(),
- propD.getPropertyName(),
- propE.getPropertyName(),
- propF.getPropertyName()));
- }
-
- @Test
- @SuppressWarnings( "unused" )
- public void
shouldFindAllPropertyNamesWhenChangedNodeHasChangedAndDeletedAndAddedSomeProperties() {
- PropertyInfo propA = makePropertyInOriginal("propA");
- PropertyInfo propB = makePropertyInOriginal("propB");
- PropertyInfo propC = makePropertyInOriginal("propC");
- PropertyInfo propD = makePropertyInOriginal("propD");
- // Change some properties ...
- PropertyInfo propB2 = setPropertyInChanged("propB");
- PropertyInfo propC2 = setPropertyInChanged("propC");
- // Add some properties ...
- PropertyInfo propE = setPropertyInChanged("propE");
- // Remove some properties ...
- assertThat(changes.removeProperty(propB2.getPropertyName()),
is(sameInstance(propB2)));
- assertThat(changes.removeProperty(propD.getPropertyName()),
is(sameInstance(propD)));
- // Now ask for names
- Set<Name> names = changes.getPropertyNames();
- assertThat(names.size(), is(3));
- assertThat(names, hasItems(propA.getPropertyName(), propC2.getPropertyName(),
propE.getPropertyName()));
- }
-
- @Test
- @SuppressWarnings( "unused" )
- public void
shouldFindAllPropertyNamesWhenChangedNodeHasChangedAndDeletedAllProperties() {
- PropertyInfo propA = makePropertyInOriginal("propA");
- PropertyInfo propB = makePropertyInOriginal("propB");
- PropertyInfo propC = makePropertyInOriginal("propC");
- PropertyInfo propD = makePropertyInOriginal("propD");
- // Change some properties ...
- PropertyInfo propB2 = setPropertyInChanged("propB");
- PropertyInfo propC2 = setPropertyInChanged("propC");
- // Remove all properties ...
- assertThat(changes.removeProperty(propA.getPropertyName()),
is(sameInstance(propA)));
- assertThat(changes.removeProperty(propB2.getPropertyName()),
is(sameInstance(propB2)));
- assertThat(changes.removeProperty(propC2.getPropertyName()),
is(sameInstance(propC2)));
- assertThat(changes.removeProperty(propD.getPropertyName()),
is(sameInstance(propD)));
- // Now ask for names
- Set<Name> names = changes.getPropertyNames();
- assertThat(names.size(), is(0));
- }
-
-}
Modified: trunk/dna-jcr/src/test/resources/cars.xml
===================================================================
--- trunk/dna-jcr/src/test/resources/cars.xml 2009-07-09 16:23:09 UTC (rev 1081)
+++ trunk/dna-jcr/src/test/resources/cars.xml 2009-07-09 16:26:04 UTC (rev 1082)
@@ -24,25 +24,25 @@
~ 51 Franklin Street, Fifth Floor
~ Boston, MA 02110-1301 USA
-->
-<Cars
xmlns:jcr="http://www.jcp.org/jcr/1.0">
+<Cars
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:vehix="http://example.com/vehicles">
<Hybrid>
- <car jcr:name="Toyota Prius" maker="Toyota"
model="Prius" year="2008" msrp="$21,500"
userRating="4.2" valueRating="5" mpgCity="48"
mpgHighway="45"/>
- <car jcr:name="Toyota Highlander" maker="Toyota"
model="Highlander" year="2008" msrp="$34,200"
userRating="4" valueRating="5" mpgCity="27"
mpgHighway="25"/>
- <car jcr:name="Nissan Altima" maker="Nissan"
model="Altima" year="2008" msrp="$18,260"
mpgCity="23" mpgHighway="32"/>
+ <car jcr:primaryType="vehix:car" jcr:name="Toyota Prius"
vehix:maker="Toyota" vehix:model="Prius" vehix:year="2008"
vehix:msrp="$21,500" vehix:userRating="4.2"
vehix:valueRating="5" vehix:mpgCity="48"
vehix:mpgHighway="45"
jcr:uuid="3b9e4a2f-040e-4d65-9778-abe70ae48324"/>
+ <car jcr:primaryType="vehix:car" jcr:name="Toyota
Highlander" vehix:maker="Toyota" vehix:model="Highlander"
year="2008" vehix:msrp="$34,200" vehix:userRating="4"
vehix:valueRating="5" vehix:mpgCity="27"
vehix:mpgHighway="25"/>
+ <car jcr:primaryType="vehix:car" jcr:name="Nissan Altima"
vehix:maker="Nissan" vehix:model="Altima" vehix:year="2008"
vehix:msrp="$18,260" vehix:mpgCity="23"
vehix:mpgHighway="32"/>
</Hybrid>
<Sports>
- <car jcr:name="Aston Martin DB9" maker="Aston Martin"
model="DB9" year="2008" msrp="$171,600"
userRating="5" mpgCity="12" mpgHighway="19"
lengthInInches="185.5" wheelbaseInInches="108.0" engine="5,935 cc
5.9 liters V 12"/>
- <car jcr:name="Infiniti G37" maker="Infiniti"
model="G37" year="2008" msrp="$34,900"
userRating="3.5" valueRating="4" mpgCity="18"
mpgHighway="24" />
+ <car jcr:primaryType="vehix:car" jcr:name="Aston Martin
DB9" vehix:maker="Aston Martin" vehix:model="DB9"
vehix:year="2008" vehix:msrp="$171,600" vehix:userRating="5"
vehix:mpgCity="12" vehix:mpgHighway="19"
vehix:lengthInInches="185.5" vehix:wheelbaseInInches="108.0"
vehix:engine="5,935 cc 5.9 liters V 12"/>
+ <car jcr:primaryType="vehix:car" jcr:name="Infiniti G37"
vehix:maker="Infiniti" vehix:model="G37" vehix:year="2008"
vehix:msrp="$34,900" vehix:userRating="3.5"
vehix:valueRating="4" vehix:mpgCity="18"
vehix:mpgHighway="24" />
</Sports>
<Luxury>
- <car jcr:name="Cadillac DTS" maker="Cadillac"
model="DTS" year="2008" engine="3.6-liter V6"
userRating="0"/>
- <car jcr:name="Bentley Continental" maker="Bentley"
model="Continental" year="2008" msrp="$170,990"
mpgCity="10" mpgHighway="17" />
- <car jcr:name="Lexus IS350" maker="Lexus"
model="IS350" year="2008" msrp="$36,305"
mpgCity="18" mpgHighway="25" userRating="4"
valueRating="5" />
+ <car jcr:primaryType="vehix:car" jcr:name="Cadillac DTS"
vehix:maker="Cadillac" vehix:model="DTS" vehix:year="2008"
vehix:engine="3.6-liter V6" vehix:userRating="0"/>
+ <car jcr:primaryType="vehix:car" jcr:name="Bentley
Continental" vehix:maker="Bentley" vehix:model="Continental"
vehix:year="2008" vehix:msrp="$170,990" vehix:mpgCity="10"
vehix:mpgHighway="17" />
+ <car jcr:primaryType="vehix:car" jcr:name="Lexus IS350"
vehix:maker="Lexus" vehix:model="IS350" vehix:year="2008"
vehix:msrp="$36,305" vehix:mpgCity="18"
vehix:mpgHighway="25" vehix:userRating="4"
vehix:valueRating="5" />
</Luxury>
<Utility>
- <car jcr:name="Land Rover LR2" maker="Land Rover"
model="LR2" year="2008" msrp="$33,985"
userRating="4.5" valueRating="5" mpgCity="16"
mpgHighway="23" />
- <car jcr:name="Land Rover LR3" maker="Land Rover"
model="LR3" year="2008" msrp="$48,525"
userRating="5" valueRating="2" mpgCity="12"
mpgHighway="17" />
- <car jcr:name="Hummer H3" maker="Hummer"
model="H3" year="2008" msrp="$30,595"
userRating="3.5" valueRating="4" mpgCity="13"
mpgHighway="16" />
- <car jcr:name="Ford F-150" maker="Ford"
model="F-150" year="2008" msrp="$23,910"
userRating="4" valueRating="1" mpgCity="14"
mpgHighway="20" />
+ <car jcr:primaryType="vehix:car" jcr:name="Land Rover LR2"
vehix:maker="Land Rover" vehix:model="LR2" vehix:year="2008"
vehix:msrp="$33,985" vehix:userRating="4.5"
vehix:valueRating="5" vehix:mpgCity="16"
vehix:mpgHighway="23" />
+ <car jcr:primaryType="vehix:car" jcr:name="Land Rover LR3"
vehix:maker="Land Rover" vehix:model="LR3" vehix:year="2008"
vehix:msrp="$48,525" vehix:userRating="5"
vehix:valueRating="2" vehix:mpgCity="12"
vehix:mpgHighway="17" />
+ <car jcr:primaryType="vehix:car" jcr:name="Hummer H3"
vehix:maker="Hummer" vehix:model="H3" vehix:year="2008"
vehix:msrp="$30,595" vehix:userRating="3.5"
vehix:valueRating="4" vehix:mpgCity="13"
vehix:mpgHighway="16" />
+ <car jcr:primaryType="vehix:car" jcr:name="Ford F-150"
vehix:maker="Ford" vehix:model="F-150" vehix:year="2008"
vehix:msrp="$23,910" vehix:userRating="4"
vehix:valueRating="1" vehix:mpgCity="14"
vehix:mpgHighway="20" />
</Utility>
</Cars>
\ No newline at end of file