Author: rhauch
Date: 2009-07-13 16:37:53 -0400 (Mon, 13 Jul 2009)
New Revision: 1107
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/map/MapRequestProcessor.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/session/GraphSession.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/session/GraphSessionTest.java
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/JcrContentHandler.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNode.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/ImportExportTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java
Log:
DNA-479 Workspace import does not work
Resolved a number of issues, including how the SessionCache forwards down desired UUIDs or
identification properties to the GraphSession when creating new nodes. There still are 4
TCK import test cases that fail, so the DocumentViewImportTest and SerializationTest are
still commented out.
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/map/MapRequestProcessor.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/map/MapRequestProcessor.java 2009-07-13
15:07:52 UTC (rev 1106)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/map/MapRequestProcessor.java 2009-07-13
20:37:53 UTC (rev 1107)
@@ -88,7 +88,7 @@
MapWorkspace workspace = getWorkspace(request, request.inWorkspace());
MapNode node = getTargetNode(workspace, request, request.of());
if (node == null) return;
- Location actualLocation = getActualLocation(request.of().getPath(), node);
+ Location actualLocation = getActualLocation(request.of(), node);
Path path = actualLocation.getPath();
// Get the names of the children ...
List<MapNode> children = node.getChildren();
@@ -107,7 +107,7 @@
MapNode node = getTargetNode(workspace, request, request.at());
if (node == null) return;
// Get the properties of the node ...
- Location actualLocation = getActualLocation(request.at().getPath(), node);
+ Location actualLocation = getActualLocation(request.at(), node);
request.addProperty(propertyFactory.create(DnaLexicon.UUID, node.getUuid()));
for (Property property : node.getProperties().values()) {
request.addProperty(property);
@@ -140,7 +140,7 @@
request.desiredSegment(),
request.removeExisting());
Path newPath =
getExecutionContext().getValueFactories().getPathFactory().create(newParentPath,
newNode.getName());
- Location oldLocation = getActualLocation(request.from().getPath(), node);
+ Location oldLocation = getActualLocation(request.from(), node);
Location newLocation = Location.create(newPath, newNode.getUuid());
request.setActualLocations(oldLocation, newLocation);
recordChange(request);
@@ -165,7 +165,7 @@
MapNode newParent = newWorkspace.getNode(newParentPath);
MapNode newNode = workspace.copyNode(getExecutionContext(), node, newWorkspace,
newParent, desiredName, true);
Path newPath =
getExecutionContext().getValueFactories().getPathFactory().create(newParentPath,
newNode.getName());
- Location oldLocation = getActualLocation(request.from().getPath(), node);
+ Location oldLocation = getActualLocation(request.from(), node);
Location newLocation = Location.create(newPath, newNode.getUuid());
request.setActualLocations(oldLocation, newLocation);
recordChange(request);
@@ -243,7 +243,7 @@
node.getProperties().put(propName, property);
}
}
- Location actualLocation = getActualLocation(path, node);
+ Location actualLocation = getActualLocation(Location.create(path), node);
request.setActualLocationOfNode(actualLocation);
recordChange(request);
}
@@ -260,7 +260,7 @@
MapNode node = getTargetNode(workspace, request, request.at());
if (node == null) return;
workspace.removeNode(getExecutionContext(), node);
- Location actualLocation = getActualLocation(request.at().getPath(), node);
+ Location actualLocation = getActualLocation(request.at(), node);
request.setActualLocationOfNode(actualLocation);
recordChange(request);
}
@@ -301,7 +301,7 @@
workspace.moveNode(getExecutionContext(), node, request.desiredName(), workspace,
newParent, beforeNode);
assert node.getParent() == newParent;
Path newPath =
getExecutionContext().getValueFactories().getPathFactory().create(newParentPath,
node.getName());
- Location oldLocation = getActualLocation(request.from().getPath(), node);
+ Location oldLocation = getActualLocation(request.from(), node);
Location newLocation = Location.create(newPath, node.getUuid());
request.setActualLocations(oldLocation, newLocation);
recordChange(request);
@@ -329,7 +329,7 @@
node.getProperties().put(propName, property);
}
}
- Location actualLocation = getActualLocation(request.on().getPath(), node);
+ Location actualLocation = getActualLocation(request.on(), node);
request.setActualLocationOfNode(actualLocation);
recordChange(request);
}
@@ -452,8 +452,9 @@
}
}
- protected Location getActualLocation( Path path,
+ protected Location getActualLocation( Location location,
MapNode node ) {
+ Path path = location.getPath();
if (path == null) {
// Find the path on the node ...
LinkedList<Path.Segment> segments = new
LinkedList<Path.Segment>();
@@ -465,6 +466,11 @@
}
path = pathFactory.createAbsolutePath(segments);
}
+ // If there is a UUID in the location, it should match the node's.
+ assert location.getUuid() == null || location.getUuid().equals(node.getUuid());
+ if (location.hasIdProperties()) {
+ return location.with(path);
+ }
return Location.create(path, node.getUuid());
}
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-13
15:07:52 UTC (rev 1106)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/session/GraphSession.java 2009-07-13
20:37:53 UTC (rev 1107)
@@ -275,7 +275,8 @@
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
+ Node<Payload, PropertyPayload> result = id != null ? nodes.get(id) : null;
// if found, the user should have read
+ // privilege since it was
// already in the cache
if (result == null || result.isStale()) {
assert path != null;
@@ -667,6 +668,7 @@
root.childrenByName = null;
root.expirationTime = Long.MAX_VALUE;
root.changedBelow = false;
+ root.payload = null;
}
}
@@ -781,13 +783,11 @@
// LinkedList<Request> oldRequests = this.requests;
this.requests = new LinkedList<Request>();
this.requestBuilder = new BatchRequestBuilder(this.requests);
- operations = store.batch(this.requestBuilder);
+ this.operations = store.batch(this.requestBuilder);
- // Remove all the cached items that have been changed or deleted ...
+ // Remove all the cached items ...
this.root.clearChanges();
-
- // Remove all the changed and deleted infos ...
- changeDependencies.clear();
+ this.root.unload();
}
/**
@@ -874,6 +874,7 @@
// Remove all the cached, changed or deleted items that were just saved ...
node.clearChanges();
+ node.unload();
}
protected Node<Payload, PropertyPayload> createNode( Node<Payload,
PropertyPayload> parent,
@@ -925,7 +926,7 @@
protected void recordUnloaded( final Node<Payload, PropertyPayload> node ) {
if (node.isLoaded() && node.getChildrenCount() > 0) {
// Walk the branch and remove all nodes from the map of all nodes ...
- node.onLoadedNodes(new NodeVisitor<Payload, PropertyPayload>() {
+ node.onCachedNodes(new NodeVisitor<Payload, PropertyPayload>() {
@SuppressWarnings( "synthetic-access" )
@Override
public boolean visit( Node<Payload, PropertyPayload> unloaded ) {
@@ -2204,44 +2205,63 @@
}
/**
- * 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.
+ * 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 property a property for the new node
+ * @param properties the (non-identification) properties for the new node
* @return the new child node
- * @throws IllegalArgumentException if the name or identification property is
null
+ * @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 property ) {
+ Property... properties ) {
CheckArg.isNotNull(name, "name");
- CheckArg.isNotNull(property, "property");
- return doCreateChild(name, property, null);
+ CheckArg.isNotNull(properties, "properties");
+ return doCreateChild(name, null, properties);
}
/**
+ * Create a new child node with the supplied name and multiple initial
identification properties. The same-name-sibling
+ * index will be determined based upon the existing children.
+ *
+ * @param name the name of the new child node
+ * @param idProperties the 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,
+ Collection<Property>
idProperties ) {
+ CheckArg.isNotNull(name, "name");
+ CheckArg.isNotEmpty(idProperties, "idProperties");
+ return doCreateChild(name, idProperties, 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
+ * @param idProperties the identification properties for the new node
+ * @param remainingProperties the remaining (non-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,
+ Collection<Property>
idProperties,
Property...
remainingProperties ) {
CheckArg.isNotNull(name, "name");
- CheckArg.isNotNull(firstProperty, "firstProperty");
- return doCreateChild(name, firstProperty, remainingProperties);
+ CheckArg.isNotEmpty(idProperties, "idProperties");
+ return doCreateChild(name, idProperties, remainingProperties);
}
private Node<Payload, PropertyPayload> doCreateChild( Name name,
- Property firstProperty,
+ Collection<Property>
idProperties,
Property[]
remainingProperties ) throws ValidationException {
assert !isStale();
@@ -2255,22 +2275,24 @@
// 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);
+ Location newChild = idProperties != null && !idProperties.isEmpty() ?
Location.create(newPath, idProperties) : 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);
- }
+ if (idProperties != null) {
+ for (Property idProp : idProperties) {
+ PropertyInfo<PropertyPayload> info = new
PropertyInfo<PropertyPayload>(idProp, idProp.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);
@@ -2671,6 +2693,10 @@
queue.add(this);
while (!queue.isEmpty()) {
Node<Payload, PropertyPayload> node = queue.poll();
+ if (!node.isLoaded()) {
+ visitor.visit(node);
+ continue;
+ }
// Get an iterator over the children *before* we visit the node
Iterator<Node<Payload, PropertyPayload>> iter =
node.getChildren().iterator();
// Visit this node ...
Modified:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java 2009-07-13
15:07:52 UTC (rev 1106)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java 2009-07-13
20:37:53 UTC (rev 1107)
@@ -113,9 +113,20 @@
@Test
public void shouldAddChildrenAndSettingProperties() {
-
graph.batch().set("propA").to("valueA").on("/").and().create("/a").with("propB",
"valueB").and("propC",
"valueC").and().create("/b").with("propD",
-
"valueD").and("propE",
-
"valueE").and().execute();
+ graph.batch()
+ .set("propA")
+ .to("valueA")
+ .on("/")
+ .and()
+ .create("/a")
+ .with("propB", "valueB")
+ .and("propC", "valueC")
+ .and()
+ .create("/b")
+ .with("propD", "valueD")
+ .and("propE", "valueE")
+ .and()
+ .execute();
// Now look up the root node ...
Node root = graph.getNodeAt("/");
assertThat(root, is(notNullValue()));
@@ -867,13 +878,21 @@
graph.create("/newUuids").and();
// Copy once to get the UUID into the default workspace
-
//graph.copy("/node1/node1/node1").failingIfUuidsMatch().fromWorkspace(workspaceName).to("/newUuids/node1");
-
graph.clone("/node1/node1/node1").fromWorkspace(workspaceName).as(name("node1")).into("/newUuids").failingIfAnyUuidsMatch();
+ //
graph.copy("/node1/node1/node1").failingIfUuidsMatch().fromWorkspace(workspaceName).to("/newUuids/node1");
+ graph.clone("/node1/node1/node1")
+ .fromWorkspace(workspaceName)
+ .as(name("node1"))
+ .into("/newUuids")
+ .failingIfAnyUuidsMatch();
try {
// Copy again to get the exception since the UUID is already in the default
workspace
//
graph.copy("/node1/node1").failingIfUuidsMatch().fromWorkspace(workspaceName).to("/newUuids/shouldNotWork");
-
graph.clone("/node1/node1/node1").fromWorkspace(workspaceName).as(name("shouldNotWork")).into("/newUuids").failingIfAnyUuidsMatch();
+ graph.clone("/node1/node1/node1")
+ .fromWorkspace(workspaceName)
+ .as(name("shouldNotWork"))
+ .into("/newUuids")
+ .failingIfAnyUuidsMatch();
fail("Should not be able to copy a node into a workspace if another node
with the "
+ "same UUID already exists in the workspace and UUID behavior is
failingIfUuidsMatch");
} catch (UuidAlreadyExistsException ex) {
@@ -905,20 +924,28 @@
graph.create("/newUuids").and();
// Copy once to get the UUID into the default workspace
//
graph.copy("/node1").replacingExistingNodesWithSameUuids().fromWorkspace(workspaceName).to("/newUuids/node1");
-
graph.clone("/node1").fromWorkspace(workspaceName).as(name("node1")).into("/newUuids").replacingExistingNodesWithSameUuids();
-
+ graph.clone("/node1")
+ .fromWorkspace(workspaceName)
+ .as(name("node1"))
+ .into("/newUuids")
+ .replacingExistingNodesWithSameUuids();
+
// Make sure that the node wasn't moved by the clone
graph.useWorkspace(workspaceName);
graph.getNodeAt("/node1");
graph.useWorkspace(defaultWorkspaceName);
-
+
// Create a new child node that in the target workspace that has no corresponding
node in the source workspace
graph.create("/newUuids/node1/shouldBeRemoved");
-
+
// Copy again to test the behavior now that the UUIDs are already in the default
workspace
// This should remove /newUuids/node1/shouldBeRemoved
//
graph.copy("/node1").replacingExistingNodesWithSameUuids().fromWorkspace(workspaceName).to("/newUuids/otherNode");
-
graph.clone("/node1").fromWorkspace(workspaceName).as(name("otherNode")).into("/newUuids").replacingExistingNodesWithSameUuids();
+ graph.clone("/node1")
+ .fromWorkspace(workspaceName)
+ .as(name("otherNode"))
+ .into("/newUuids")
+ .replacingExistingNodesWithSameUuids();
/*
* Focus on testing node structure, since shouldCopyNodeWithChildren tests that
properties get copied
@@ -929,11 +956,10 @@
try {
graph.getNodeAt("/newUuids/node1/shouldBeRemoved");
fail("/newUuids/node1/shouldBeRemoved should no longer exist after the
copy-with-remove-conflicting-uuids operation");
- }
- catch (PathNotFoundException pnfe) {
+ } catch (PathNotFoundException pnfe) {
// Expected
}
-
+
Subgraph target =
graph.getSubgraphOfDepth(3).at("/newUuids/otherNode");
assertThat(target, is(notNullValue()));
assertThat(target.getNode(".").getChildren(),
hasChildren(segment("node1"), segment("node2"),
segment("node3")));
@@ -969,14 +995,18 @@
graph.create("/segmentTestUuids").and();
// Copy once to get the UUID into the default workspace
graph.clone("/node1").fromWorkspace(workspaceName).as(name("node1")).into("/segmentTestUuids").failingIfAnyUuidsMatch();
-
+
// Create a new child node that in the target workspace that has no corresponding
node in the source workspace
PropertyFactory propFactory = context.getPropertyFactory();
graph.create("/segmentTestUuids/node1",
propFactory.create(name("identifier"), "backup copy")).and();
// Copy again to test the behavior now that the UUIDs are already in the default
workspace
// This should remove /newUuids/node1/shouldBeRemoved
-
graph.clone("/node1").fromWorkspace(workspaceName).as(segment("node1[1]")).into("/segmentTestUuids").replacingExistingNodesWithSameUuids();
+ graph.clone("/node1")
+ .fromWorkspace(workspaceName)
+ .as(segment("node1[1]"))
+ .into("/segmentTestUuids")
+ .replacingExistingNodesWithSameUuids();
/*
* Focus on testing node structure, since shouldCopyNodeWithChildren tests that
properties get copied
@@ -984,8 +1014,9 @@
// /newUuids/node1 should have been removed when the new node was added with the
same UUID
assertThat(graph.getNodeAt("/segmentTestUuids").getChildren(),
hasChildren(segment("node1"), segment("node1[2]")));
assertThat(graph.getNodeAt("/segmentTestUuids/node1[1]").getProperty("identifier"),
is(nullValue()));
-
assertThat(graph.getNodeAt("/segmentTestUuids/node1[2]").getProperty("identifier").getFirstValue().toString(),
is("backup copy"));
-
+
assertThat(graph.getNodeAt("/segmentTestUuids/node1[2]").getProperty("identifier").getFirstValue().toString(),
+ is("backup copy"));
+
Subgraph target =
graph.getSubgraphOfDepth(3).at("/segmentTestUuids/node1[1]");
assertThat(target, is(notNullValue()));
assertThat(target.getNode(".").getChildren(),
hasChildren(segment("node1"), segment("node2"),
segment("node3")));
@@ -1019,7 +1050,7 @@
Object value = values[i];
assertThat(value, is(instanceOf(Reference.class)));
Reference ref = (Reference)value;
- assertThat(graph.resolve(ref), is(graph.getNodeAt(toNodePath[i])));
+ assertThat(graph.resolve(ref).getLocation().getPath(),
is(graph.getNodeAt(toNodePath[i]).getLocation().getPath()));
}
}
Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/session/GraphSessionTest.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/session/GraphSessionTest.java 2009-07-13
15:07:52 UTC (rev 1106)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/session/GraphSessionTest.java 2009-07-13
20:37:53 UTC (rev 1107)
@@ -446,7 +446,7 @@
// 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.isStale(), is(true));
assertThat(cars.isLoaded(), is(false));
assertThat(root.isStale(), is(false)); // not touched during saves
@@ -454,6 +454,7 @@
sports = cache.findNodeWith(path("/Cars/Utility/Sports"));
assertConnectionsUsed(1);
utility = cache.findNodeWith(path("/Cars/Utility"));
+ cars = cache.findNodeWith(path("/Cars"));
assertNoMoreConnectionsUsed();
assertChildren(cars, "Hybrid", "Luxury",
"Utility");
@@ -567,11 +568,12 @@
// 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.isStale(), is(true));
assertThat(cars.isLoaded(), is(false));
assertThat(root.isStale(), is(false)); // not touched during saves
// Now the state should reflect our changes ...
+ cars = cache.findNodeWith(path("/Cars"));
assertChildren(cars, "Hybrid", "Utility", "Sports",
"Luxury");
// Now there should be no changes ...
@@ -607,6 +609,7 @@
assertConnectionsUsed(2); // 1 to load children required by validation, 1 to
perform save
// Now the state should reflect our changes ...
+ cars = cache.findNodeWith(path("/Cars"));
assertChildren(cars, "Hybrid", "Experimental",
"Sports", "Luxury", "Utility", "Experimental[2]",
"Experimental[3]");
// Now there should be no changes ...
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-13 15:07:52
UTC (rev 1106)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-07-13 20:37:53
UTC (rev 1107)
@@ -243,18 +243,7 @@
* @throws RepositoryException if there is an exception
*/
public final boolean isNodeType( Name nodeTypeName ) throws RepositoryException {
- JcrNodeType nodeType = getPrimaryNodeType();
- if (nodeType.isNodeType(nodeTypeName)) {
- return true;
- }
- JcrNodeTypeManager nodeTypes = session().nodeTypeManager();
- for (Name mixinTypeName : getMixinTypeNames()) {
- JcrNodeType mixinType = nodeTypes.getNodeType(mixinTypeName);
- if (mixinType.isNodeType(nodeTypeName)) {
- return true;
- }
- }
- return false;
+ return cache.isNodeType(nodeInfo(), nodeTypeName);
}
/**
@@ -505,7 +494,10 @@
* @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(nodeId, location.getPath(), propertyName);
+ Property property = cache.findJcrProperty(nodeId, location.getPath(),
propertyName);
+ // Must be referenceable in order to return this property ...
+ if (property != null && JcrLexicon.UUID.equals(propertyName) &&
!isReferenceable()) return null;
+ return property;
}
/**
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-13
15:07:52 UTC (rev 1106)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java 2009-07-13
20:37:53 UTC (rev 1107)
@@ -92,10 +92,16 @@
}
final org.jboss.dna.graph.property.Property property() throws RepositoryException {
+ if (propertyInfo() == null) {
+ int x = 0;
+ }
return propertyInfo().getProperty();
}
JcrValue createValue( Object value ) throws RepositoryException {
+ if (value == null) {
+ int x = 0;
+ }
return new JcrValue(context().getValueFactories(), this.cache,
payload().getPropertyType(), value);
}
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-13
15:07:52 UTC (rev 1106)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java 2009-07-13
20:37:53 UTC (rev 1107)
@@ -125,7 +125,11 @@
}
assert cache != null;
- this.currentNode = cache.findJcrNode(null, parentPath);
+ try {
+ this.currentNode = cache.findJcrNode(null, parentPath);
+ } catch (ItemNotFoundException e) {
+ throw new PathNotFoundException(e.getLocalizedMessage(), e);
+ }
this.jcrValueFactory = session.getValueFactory();
this.nodeTypes = session.nodeTypeManager();
this.jcrNamespaceRegistry = session.workspace().getNamespaceRegistry();
@@ -342,6 +346,7 @@
String typeName =
currentProps.get(primaryTypeName).get(0).getString();
AbstractJcrNode newNode =
parentNode.editor().createChild(nameFor(currentNodeName), uuid, nameFor(typeName));
+ SessionCache.NodeEditor newNodeEditor = newNode.editor();
for (Map.Entry<String, List<Value>> entry :
currentProps.entrySet()) {
if (entry.getKey().equals(primaryTypeName)) {
@@ -351,7 +356,7 @@
if (entry.getKey().equals(mixinTypesName)) {
for (Value value : entry.getValue()) {
JcrNodeType mixinType = nodeTypeFor(value.getString());
- newNode.editor().addMixin(mixinType);
+ newNodeEditor.addMixin(mixinType);
}
continue;
}
@@ -363,11 +368,11 @@
List<Value> values = entry.getValue();
if (values.size() == 1) {
- newNode.editor().setProperty(nameFor(entry.getKey()),
(JcrValue)values.get(0));
+ newNodeEditor.setProperty(nameFor(entry.getKey()),
(JcrValue)values.get(0));
} else {
- newNode.editor().setProperty(nameFor(entry.getKey()),
- values.toArray(new
Value[values.size()]),
- PropertyType.UNDEFINED);
+ newNodeEditor.setProperty(nameFor(entry.getKey()),
+ values.toArray(new
Value[values.size()]),
+ PropertyType.UNDEFINED);
}
}
@@ -448,10 +453,12 @@
if (uuid != null) {
try {
+ // Deal with any existing node ...
AbstractJcrNode existingNodeWithUuid =
cache().findJcrNode(Location.create(uuid));
switch (uuidBehavior) {
case
ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING:
- existingNodeWithUuid.editor().destroy();
+ parentNode = existingNodeWithUuid.getParent();
+ existingNodeWithUuid.remove();
break;
case ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW:
uuid = UUID.randomUUID();
@@ -460,18 +467,19 @@
if
(existingNodeWithUuid.path().isAtOrAbove(parentStack.firstElement().path())) {
throw new ConstraintViolationException();
}
- existingNodeWithUuid.editor().destroy();
+ existingNodeWithUuid.remove();
break;
case ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW:
throw new ItemExistsException();
}
} catch (ItemNotFoundException e) {
- // don't care
+ // there wasn't an existing item, so just continue
}
}
name = DOCUMENT_VIEW_NAME_DECODER.decode(name);
AbstractJcrNode currentNode =
parentNode.editor().createChild(nameFor(name), uuid, nameFor(primaryTypeName));
+ SessionCache.NodeEditor currentNodeEditor = currentNode.editor();
for (int i = 0; i < atts.getLength(); i++) {
if (JcrContentHandler.this.primaryTypeName.equals(atts.getQName(i)))
{
@@ -480,7 +488,7 @@
if (mixinTypesName.equals(atts.getQName(i))) {
JcrNodeType mixinType = nodeTypeFor(atts.getValue(i));
- currentNode.editor().addMixin(mixinType);
+ currentNodeEditor.addMixin(mixinType);
continue;
}
@@ -493,7 +501,7 @@
// 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.editor().setProperty(nameFor(propertyName),
(JcrValue)valueFor(value, PropertyType.STRING));
+ currentNodeEditor.setProperty(nameFor(propertyName),
(JcrValue)valueFor(value, PropertyType.STRING));
}
parentStack.push(currentNode);
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-13 15:07:52 UTC
(rev 1106)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNode.java 2009-07-13 20:37:53 UTC
(rev 1107)
@@ -94,6 +94,6 @@
* @see javax.jcr.Item#remove()
*/
public void remove() throws RepositoryException {
- editorForParent().destroyChild(nodeInfo());
+ editor().destroy();
}
}
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-13 15:07:52 UTC
(rev 1106)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-07-13 20:37:53 UTC
(rev 1107)
@@ -49,6 +49,7 @@
import javax.jcr.ValueFormatException;
import javax.jcr.Workspace;
import javax.jcr.nodetype.ConstraintViolationException;
+import net.jcip.annotations.Immutable;
import net.jcip.annotations.NotThreadSafe;
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.graph.ExecutionContext;
@@ -62,9 +63,11 @@
import org.jboss.dna.graph.property.PathFactory;
import org.jboss.dna.graph.property.ValueFactories;
import org.jboss.dna.graph.property.basic.LocalNamespaceRegistry;
+import org.jboss.dna.graph.session.GraphSession;
import org.jboss.dna.jcr.JcrContentHandler.EnclosingSAXException;
import org.jboss.dna.jcr.JcrContentHandler.SaveMode;
import org.jboss.dna.jcr.JcrNamespaceRegistry.Behavior;
+import org.jboss.dna.jcr.SessionCache.JcrPropertyPayload;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
@@ -812,4 +815,43 @@
public void save() throws RepositoryException {
cache.save();
}
+
+ /**
+ * Get a snapshot of the current session state. This snapshot is immutable and will
not reflect any future state changes in
+ * the session.
+ *
+ * @return the snapshot; never null
+ */
+ public Snapshot getSnapshot() {
+ return new Snapshot(cache.graphSession().getRoot().getSnapshot(false));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return getSnapshot().toString();
+ }
+
+ @Immutable
+ public class Snapshot {
+ private final GraphSession.StructureSnapshot<JcrPropertyPayload>
rootSnapshot;
+
+ protected Snapshot( GraphSession.StructureSnapshot<JcrPropertyPayload>
snapshot ) {
+ this.rootSnapshot = snapshot;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return rootSnapshot.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-13 15:07:52
UTC (rev 1106)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-07-13 20:37:53
UTC (rev 1107)
@@ -362,13 +362,13 @@
try {
graphSession.save();
} catch (ValidationException e) {
- throw new ConstraintViolationException(e.getLocalizedMessage(),
e.getCause());
+ throw new ConstraintViolationException(e.getLocalizedMessage(), e);
} catch (InvalidStateException e) {
- throw new InvalidItemStateException(e.getLocalizedMessage(), e.getCause());
+ throw new InvalidItemStateException(e.getLocalizedMessage(), e);
} catch (RepositorySourceException e) {
- throw new RepositoryException(e.getLocalizedMessage(), e.getCause());
+ throw new RepositoryException(e.getLocalizedMessage(), e);
} catch (AccessControlException e) {
- throw new AccessDeniedException(e.getMessage(), e.getCause());
+ throw new AccessDeniedException(e.getMessage(), e);
}
}
@@ -393,13 +393,13 @@
assert node != null;
graphSession.save(node);
} catch (ValidationException e) {
- throw new ConstraintViolationException(e.getLocalizedMessage(),
e.getCause());
+ throw new ConstraintViolationException(e.getLocalizedMessage(), e);
} catch (InvalidStateException e) {
- throw new InvalidItemStateException(e.getLocalizedMessage(), e.getCause());
+ throw new InvalidItemStateException(e.getLocalizedMessage(), e);
} catch (RepositorySourceException e) {
- throw new RepositoryException(e.getLocalizedMessage(), e.getCause());
+ throw new RepositoryException(e.getLocalizedMessage(), e);
} catch (AccessControlException e) {
- throw new AccessDeniedException(e.getMessage(), e.getCause());
+ throw new AccessDeniedException(e.getMessage(), e);
}
}
@@ -420,11 +420,11 @@
try {
return graphSession.findNodeWith(id, absolutePath);
} catch (org.jboss.dna.graph.property.PathNotFoundException e) {
- throw new ItemNotFoundException(e.getMessage(), e.getCause());
+ throw new ItemNotFoundException(e.getMessage(), e);
} catch (RepositorySourceException e) {
- throw new RepositoryException(e.getMessage(), e.getCause());
+ throw new RepositoryException(e.getMessage(), e);
} catch (AccessControlException e) {
- throw new AccessDeniedException(e.getMessage(), e.getCause());
+ throw new AccessDeniedException(e.getMessage(), e);
}
}
@@ -451,11 +451,11 @@
try {
return graphSession.findNodeRelativeTo(referenceNode, relativePath);
} catch (org.jboss.dna.graph.property.PathNotFoundException e) {
- throw new PathNotFoundException(e.getMessage(), e.getCause());
+ throw new PathNotFoundException(e.getMessage(), e);
} catch (RepositorySourceException e) {
- throw new RepositoryException(e.getMessage(), e.getCause());
+ throw new RepositoryException(e.getMessage(), e);
} catch (AccessControlException e) {
- throw new AccessDeniedException(e.getMessage(), e.getCause());
+ throw new AccessDeniedException(e.getMessage(), e);
}
}
@@ -484,11 +484,11 @@
try {
return graphSession.findNodeWith(location).getPayload().getJcrNode();
} catch (org.jboss.dna.graph.property.PathNotFoundException e) {
- throw new ItemNotFoundException(e.getMessage(), e.getCause());
+ throw new ItemNotFoundException(e.getMessage(), e);
} catch (RepositorySourceException e) {
- throw new RepositoryException(e.getMessage(), e.getCause());
+ throw new RepositoryException(e.getMessage(), e);
} catch (AccessControlException e) {
- throw new AccessDeniedException(e.getMessage(), e.getCause());
+ throw new AccessDeniedException(e.getMessage(), e);
}
}
@@ -535,11 +535,11 @@
// 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());
+ throw new PathNotFoundException(e.getMessage(), e);
} catch (RepositorySourceException e) {
- throw new RepositoryException(e.getMessage(), e.getCause());
+ throw new RepositoryException(e.getMessage(), e);
} catch (AccessControlException e) {
- throw new AccessDeniedException(e.getMessage(), e.getCause());
+ throw new AccessDeniedException(e.getMessage(), e);
}
}
@@ -562,6 +562,7 @@
Node<JcrNodePayload, JcrPropertyPayload> node = findNode(id,
absolutePath);
PropertyInfo<JcrPropertyPayload> propertyInfo =
node.getProperty(propertyName);
if (propertyInfo != null) {
+ if (propertyName.equals(JcrLexicon.UUID) && !isReferenceable(node))
return null;
return propertyInfo.getPayload().getJcrProperty();
}
return null;
@@ -585,17 +586,18 @@
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.equals(JcrLexicon.UUID) &&
!isReferenceable(node)) continue;
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());
+ throw new PathNotFoundException(e.getMessage(), e);
} catch (RepositorySourceException e) {
- throw new RepositoryException(e.getMessage(), e.getCause());
+ throw new RepositoryException(e.getMessage(), e);
} catch (AccessControlException e) {
- throw new AccessDeniedException(e.getMessage(), e.getCause());
+ throw new AccessDeniedException(e.getMessage(), e);
}
}
@@ -655,11 +657,11 @@
parent = graphSession.findNodeRelativeTo(fromNode,
relativePath.getParent());
}
} catch (org.jboss.dna.graph.property.PathNotFoundException e) {
- throw new ItemNotFoundException(e.getMessage(), e.getCause());
+ throw new ItemNotFoundException(e.getMessage(), e);
} catch (RepositorySourceException e) {
- throw new RepositoryException(e.getMessage(), e.getCause());
+ throw new RepositoryException(e.getMessage(), e);
} catch (AccessControlException e) {
- throw new AccessDeniedException(e.getMessage(), e.getCause());
+ throw new AccessDeniedException(e.getMessage(), e);
}
// JSR-170 doesn't allow children and proeprties to have the same name, but
this is relaxed in JSR-283.
@@ -695,6 +697,37 @@
}
/**
+ * Determine whether the 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
javax.jcr.Node#isNodeType(String)
+ * equivalent in the JCR API}.
+ *
+ * @param node the node to be evaluated
+ * @param nodeType 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( Node<JcrNodePayload, JcrPropertyPayload>
node,
+ Name nodeType ) throws RepositoryException {
+ Name primaryTypeName = node.getPayload().getPrimaryTypeName();
+ JcrNodeType primaryType = nodeTypes().getNodeType(primaryTypeName);
+ if (primaryType.isNodeType(nodeType)) {
+ return true;
+ }
+ JcrNodeTypeManager nodeTypes = session().nodeTypeManager();
+ for (Name mixinTypeName : node.getPayload().getMixinTypeNames()) {
+ JcrNodeType mixinType = nodeTypes.getNodeType(mixinTypeName);
+ if (mixinType.isNodeType(nodeType)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean isReferenceable( Node<JcrNodePayload, JcrPropertyPayload> node )
throws RepositoryException {
+ return isNodeType(node, JcrMixLexicon.REFERENCEABLE);
+ }
+
+ /**
* Obtain an {@link NodeEditor editor} that can be used to manipulate the properties
or children on the node identified by the
* 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
@@ -939,11 +972,11 @@
node.setProperty(dnaProp, definition.isMultiple(), propPayload);
return jcrProp;
} catch (ValidationException e) {
- throw new ConstraintViolationException(e.getMessage(), e.getCause());
+ throw new ConstraintViolationException(e.getMessage(), e);
} catch (RepositorySourceException e) {
- throw new RepositoryException(e.getMessage(), e.getCause());
+ throw new RepositoryException(e.getMessage(), e);
} catch (AccessControlException e) {
- throw new AccessDeniedException(e.getMessage(), e.getCause());
+ throw new AccessDeniedException(e.getMessage(), e);
}
}
@@ -1118,11 +1151,11 @@
node.setProperty(dnaProp, definition.isMultiple(), propPayload);
return jcrProp;
} catch (ValidationException e) {
- throw new ConstraintViolationException(e.getMessage(), e.getCause());
+ throw new ConstraintViolationException(e.getMessage(), e);
} catch (RepositorySourceException e) {
- throw new RepositoryException(e.getMessage(), e.getCause());
+ throw new RepositoryException(e.getMessage(), e);
} catch (AccessControlException e) {
- throw new AccessDeniedException(e.getMessage(), e.getCause());
+ throw new AccessDeniedException(e.getMessage(), e);
}
}
@@ -1138,11 +1171,11 @@
try {
return node.removeProperty(name) != null;
} catch (ValidationException e) {
- throw new ConstraintViolationException(e.getMessage(), e.getCause());
+ throw new ConstraintViolationException(e.getMessage(), e);
} catch (RepositorySourceException e) {
- throw new RepositoryException(e.getMessage(), e.getCause());
+ throw new RepositoryException(e.getMessage(), e);
} catch (AccessControlException e) {
- throw new AccessDeniedException(e.getMessage(), e.getCause());
+ throw new AccessDeniedException(e.getMessage(), e);
}
}
@@ -1161,11 +1194,11 @@
try {
node.orderChildBefore(childToBeMoved, before);
} catch (ValidationException e) {
- throw new ConstraintViolationException(e.getMessage(), e.getCause());
+ throw new ConstraintViolationException(e.getMessage(), e);
} catch (RepositorySourceException e) {
- throw new RepositoryException(e.getMessage(), e.getCause());
+ throw new RepositoryException(e.getMessage(), e);
} catch (AccessControlException e) {
- throw new AccessDeniedException(e.getMessage(), e.getCause());
+ throw new AccessDeniedException(e.getMessage(), e);
}
}
@@ -1222,11 +1255,11 @@
}
return existingChild;
} catch (ValidationException e) {
- throw new ConstraintViolationException(e.getMessage(), e.getCause());
+ throw new ConstraintViolationException(e.getMessage(), e);
} catch (RepositorySourceException e) {
- throw new RepositoryException(e.getMessage(), e.getCause());
+ throw new RepositoryException(e.getMessage(), e);
} catch (AccessControlException e) {
- throw new AccessDeniedException(e.getMessage(), e.getCause());
+ throw new AccessDeniedException(e.getMessage(), e);
}
}
@@ -1292,9 +1325,9 @@
setProperty(JcrLexicon.UUID, value, false);
}
} catch (RepositorySourceException e) {
- throw new RepositoryException(e.getMessage(), e.getCause());
+ throw new RepositoryException(e.getMessage(), e);
} catch (AccessControlException e) {
- throw new AccessDeniedException(e.getMessage(), e.getCause());
+ throw new AccessDeniedException(e.getMessage(), e);
}
}
@@ -1386,12 +1419,16 @@
// Now add the "jcr:uuid" property if and only if referenceable
...
Node<JcrNodePayload, JcrPropertyPayload> result = null;
- if (primaryType.isNodeType(JcrMixLexicon.REFERENCEABLE)) {
+ boolean isReferenceable =
primaryType.isNodeType(JcrMixLexicon.REFERENCEABLE);
+ Property uuidProperty = null;
+ if (desiredUuid != null || isReferenceable) {
if (desiredUuid == null) {
desiredUuid = UUID.randomUUID();
}
- Property uuidProperty = propertyFactory.create(JcrLexicon.UUID,
desiredUuid);
- result = node.createChild(name, uuidProperty, primaryTypeProp,
nodeDefinitionProp);
+ uuidProperty = propertyFactory.create(JcrLexicon.UUID, desiredUuid);
+ }
+ if (uuidProperty != null) {
+ result = node.createChild(name, Collections.singleton(uuidProperty),
primaryTypeProp, nodeDefinitionProp);
} else {
result = node.createChild(name, primaryTypeProp,
nodeDefinitionProp);
}
@@ -1400,11 +1437,11 @@
// Finally, return the jcr node ...
return (JcrNode)result.getPayload().getJcrNode();
} catch (ValidationException e) {
- throw new ConstraintViolationException(e.getMessage(), e.getCause());
+ throw new ConstraintViolationException(e.getMessage(), e);
} catch (RepositorySourceException e) {
- throw new RepositoryException(e.getMessage(), e.getCause());
+ throw new RepositoryException(e.getMessage(), e);
} catch (AccessControlException e) {
- throw new AccessDeniedException(e.getMessage(), e.getCause());
+ throw new AccessDeniedException(e.getMessage(), e);
}
}
@@ -1423,7 +1460,7 @@
try {
child.destroy();
} catch (AccessControlException e) {
- throw new AccessDeniedException(e.getMessage(), e.getCause());
+ throw new AccessDeniedException(e.getMessage(), e);
}
return true;
}
@@ -1439,7 +1476,7 @@
try {
node.destroy();
} catch (AccessControlException e) {
- throw new AccessDeniedException(e.getMessage(), e.getCause());
+ throw new AccessDeniedException(e.getMessage(), e);
}
return true;
}
@@ -2337,7 +2374,15 @@
Set<JcrNodeDefinition> satisfiedChildNodes = new
HashSet<JcrNodeDefinition>();
Set<JcrPropertyDefinition> satisfiedProperties = new
HashSet<JcrPropertyDefinition>();
+ // Is this node referenceable ...
+ boolean referenceable = false;
+ try {
+ referenceable = isReferenceable(node);
+ } catch (RepositoryException e) {
+ throw new ValidationException(e.getLocalizedMessage());
+ }
for
(org.jboss.dna.graph.session.GraphSession.PropertyInfo<JcrPropertyPayload> property
: node.getProperties()) {
+ if (property.getName().equals(JcrLexicon.UUID) && !referenceable)
continue;
JcrPropertyPayload propPayload = property.getPayload();
JcrPropertyDefinition definition =
findBestPropertyDefintion(primaryTypeName,
mixinTypeNames,
@@ -2447,13 +2492,13 @@
// Now update the property infos for the two mandatory properties ...
JcrNodeType ntBase = nodeTypes().getNodeType(JcrNtLexicon.BASE);
assert ntBase != null;
- primaryTypeInfo = createPropertyInfo(parent.getPayload(),
+ primaryTypeInfo = createPropertyInfo(child.getPayload(),
primaryTypeInfo.getProperty(),
ntBase.allPropertyDefinitions(JcrLexicon.PRIMARY_TYPE).iterator().next(),
PropertyType.NAME,
primaryTypeInfo);
properties.put(primaryTypeInfo.getName(), primaryTypeInfo);
- nodeDefnInfo = createPropertyInfo(parent.getPayload(),
+ nodeDefnInfo = createPropertyInfo(child.getPayload(),
nodeDefnInfo.getProperty(),
ntBase.allPropertyDefinitions(DnaIntLexicon.NODE_DEFINITON).iterator().next(),
PropertyType.STRING,
@@ -2465,7 +2510,7 @@
if (uuidInfo != null) {
JcrNodeType mixRef =
nodeTypes().getNodeType(JcrMixLexicon.REFERENCEABLE);
assert mixRef != null;
- uuidInfo = createPropertyInfo(parent.getPayload(),
+ uuidInfo = createPropertyInfo(child.getPayload(),
uuidInfo.getProperty(),
mixRef.allPropertyDefinitions(JcrLexicon.UUID).iterator().next(),
PropertyType.STRING,
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/ImportExportTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/ImportExportTest.java 2009-07-13
15:07:52 UTC (rev 1106)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/ImportExportTest.java 2009-07-13
20:37:53 UTC (rev 1107)
@@ -114,7 +114,8 @@
String targetPath,
ExportType useSystemView,
boolean skipBinary,
- boolean noRecurse ) throws Exception {
+ boolean noRecurse,
+ boolean useWorkspace ) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if (useSystemView == ExportType.SYSTEM) {
@@ -125,11 +126,17 @@
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
- session.importXML(targetPath, bais, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
+ if (useWorkspace) {
+ // import via workspace ...
+ session.getWorkspace().importXML(targetPath, bais,
ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
+ } else {
+ // import via session ...
+ session.importXML(targetPath, bais,
ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
+ }
}
@Test
- public void shouldImportExportEscapedXmlCharactersInSystemView() throws Exception {
+ public void shouldImportExportEscapedXmlCharactersInSystemViewUsingSession() throws
Exception {
String testName = "importExportEscapedXmlCharacters";
Node rootNode = session.getRootNode();
Node sourceNode = rootNode.addNode(testName + "Source",
"nt:unstructured");
@@ -140,15 +147,34 @@
assertThat(sourceNode.getProperty("badcharacters").getString(),
is(BAD_CHARACTER_STRING));
sourceNode.addNode(BAD_CHARACTER_STRING);
- testImportExport(sourceNode.getPath(), targetNode.getPath(), ExportType.SYSTEM,
false, false);
+ testImportExport(sourceNode.getPath(), targetNode.getPath(), ExportType.SYSTEM,
false, false, false);
Node newSourceNode = targetNode.getNode(testName + "Source");
newSourceNode.getNode(BAD_CHARACTER_STRING);
assertThat(newSourceNode.getProperty("badcharacters").getString(),
is(BAD_CHARACTER_STRING));
}
+ @Test
+ public void shouldImportExportEscapedXmlCharactersInSystemViewUsingWorkspace() throws
Exception {
+ String testName = "importExportEscapedXmlCharacters";
+ Node rootNode = session.getRootNode();
+ Node sourceNode = rootNode.addNode(testName + "Source",
"nt:unstructured");
+ Node targetNode = rootNode.addNode(testName + "Target",
"nt:unstructured");
+
+ // Test data
+ sourceNode.setProperty("badcharacters", BAD_CHARACTER_STRING);
+ assertThat(sourceNode.getProperty("badcharacters").getString(),
is(BAD_CHARACTER_STRING));
+ sourceNode.addNode(BAD_CHARACTER_STRING);
+ session.save();
+
+ testImportExport(sourceNode.getPath(), targetNode.getPath(), ExportType.SYSTEM,
false, false, true);
+ Node newSourceNode = targetNode.getNode(testName + "Source");
+ newSourceNode.getNode(BAD_CHARACTER_STRING);
+ assertThat(newSourceNode.getProperty("badcharacters").getString(),
is(BAD_CHARACTER_STRING));
+ }
+
@Ignore( "JR TCK is broken" )
@Test
- public void shouldImportExportEscapedXmlCharactersInDocumentView() throws Exception
{
+ public void shouldImportExportEscapedXmlCharactersInDocumentViewUsingSession() throws
Exception {
String testName = "importExportEscapedXmlCharacters";
Node rootNode = session.getRootNode();
Node sourceNode = rootNode.addNode(testName + "Source",
"nt:unstructured");
@@ -159,7 +185,7 @@
assertThat(sourceNode.getProperty("badcharacters").getString(),
is(BAD_CHARACTER_STRING));
sourceNode.addNode(BAD_CHARACTER_STRING);
- testImportExport(sourceNode.getPath(), targetNode.getPath(), ExportType.DOCUMENT,
false, false);
+ testImportExport(sourceNode.getPath(), targetNode.getPath(), ExportType.DOCUMENT,
false, false, false);
Node newSourceNode = targetNode.getNode(testName + "Source");
newSourceNode.getNode(BAD_CHARACTER_STRING);
assertThat(newSourceNode.getProperty("badcharacters").getString(),
is(BAD_CHARACTER_STRING));
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-13
15:07:52 UTC (rev 1106)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/SessionCacheTest.java 2009-07-13
20:37:53 UTC (rev 1107)
@@ -26,6 +26,7 @@
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.junit.Assert.fail;
@@ -40,6 +41,7 @@
import java.util.UUID;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.Value;
import javax.jcr.ValueFormatException;
import org.jboss.dna.graph.Location;
@@ -255,6 +257,56 @@
assertThat(hybrid.hasNode("child"), is(true));
}
+ @Test
+ public void shouldNotExposeUuidPropertyOnNonReferenceableNodes() throws Exception {
+ AbstractJcrNode highlander = cache.findJcrNode(null,
path("/Cars/Hybrid/Toyota Highlander"));
+ assertNotReferenceable(highlander);
+ }
+
+ @Test
+ public void shouldExposeUuidPropertyOnReferenceableNodes() throws Exception {
+ AbstractJcrNode hybrid = cache.findJcrNode(null,
path("/Cars/Hybrid"));
+ hybrid.addMixin("mix:referenceable"); // we don't have any
referenceable nodes in our tests
+ assertReferenceable(hybrid);
+ }
+
+ @Test
+ public void
shouldExposeUuidPropertyOnlyWhenNonReferenceableNodeTransitionsToReferenceable() throws
Exception {
+ AbstractJcrNode highlander = cache.findJcrNode(null,
path("/Cars/Hybrid/Toyota Highlander"));
+ assertNotReferenceable(highlander);
+ highlander.addMixin("mix:referenceable");
+ assertReferenceable(highlander);
+ }
+
+ protected void assertNotReferenceable( AbstractJcrNode node ) throws
RepositoryException {
+ assertThat(node.isReferenceable(), is(false));
+ try {
+ node.getUUID();
+ fail("should not return UUID if the node is not referenceable");
+ } catch (UnsupportedRepositoryOperationException e) {
+ // expected
+ }
+ // Should not have a "jcr:uuid" property ...
+ assertThat(node.hasProperty(JcrLexicon.UUID), is(false));
+ assertThat(node.getProperty(JcrLexicon.UUID), is(nullValue()));
+ }
+
+ protected void assertReferenceable( AbstractJcrNode node ) throws RepositoryException
{
+ assertThat(node.isReferenceable(), is(true));
+ String uuidValue = null;
+ try {
+ uuidValue = node.getUUID();
+ assertThat(uuidValue, is(notNullValue()));
+ } catch (UnsupportedOperationException e) {
+ fail("should return UUID if the node is referenceable");
+ }
+ // Should have a "jcr:uuid" property ...
+ assertThat(node.hasProperty(JcrLexicon.UUID), is(true));
+ javax.jcr.Property uuidProp = node.getProperty(JcrLexicon.UUID);
+ assertThat(uuidProp, is(notNullValue()));
+ assertThat(uuidProp.getString(), is(uuidValue));
+ }
+
protected void assertProperty( AbstractJcrProperty property,
javax.jcr.Node node,
String name,