Author: rhauch
Date: 2009-04-30 00:32:26 -0400 (Thu, 30 Apr 2009)
New Revision: 866
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRepository.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRequestProcessor.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CopyBranchRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CreateNodeRequest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/MoveBranchRequest.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/inmemory/InMemoryRepositoryWorkspaceTest.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/MixinTest.java
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java
trunk/docs/examples/gettingstarted/repositories/src/main/resources/aircraft.xml
trunk/docs/examples/gettingstarted/repositories/src/main/resources/cars.xml
trunk/docs/examples/gettingstarted/repositories/src/test/java/org/jboss/example/dna/repository/RepositoryClientTest.java
trunk/docs/examples/gettingstarted/repositories/src/test/java/org/jboss/example/dna/repository/RepositoryClientUsingJcrTest.java
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedWorkspace.java
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatingRequestProcessor.java
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederationI18n.java
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergePlan.java
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategy.java
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategy.java
trunk/extensions/dna-connector-federation/src/main/resources/org/jboss/dna/connector/federation/FederationI18n.properties
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatingRequestProcessorTest.java
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategyTest.java
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategyTest.java
trunk/extensions/dna-connector-federation/src/test/resources/log4j.properties
trunk/pom.xml
Log:
DNA-387 Federation connector does not support updates, which are required when using with
the JCR implementation
Added support for writes in limited scenarios (when the nodes being changed are within a
single projection), and addressed a couple of issues related to the handling of UUIDs in
the federation connector. Added more unit tests, verifying the behavior is correct. Also
corrected a few errors in CopyBranchRequest, MoveBranchRequest, and CreateNodeRequest.
Finally, the repository examples (from the Getting Started document) were corrected to use
our JCR implementation.
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRepository.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRepository.java 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRepository.java 2009-04-30
04:32:26 UTC (rev 866)
@@ -263,7 +263,13 @@
InMemoryNode node ) {
assert context != null;
assert node != null;
- assert getRoot().equals(node) != true;
+ if (getRoot().equals(node)) {
+ nodesByUuid.clear();
+ // Create the root node ...
+ InMemoryNode root = new InMemoryNode(rootNodeUuid);
+ nodesByUuid.put(root.getUuid(), root);
+ return;
+ }
InMemoryNode parent = node.getParent();
assert parent != null;
parent.getChildren().remove(node);
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRequestProcessor.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRequestProcessor.java 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRequestProcessor.java 2009-04-30
04:32:26 UTC (rev 866)
@@ -35,6 +35,7 @@
import org.jboss.dna.graph.DnaLexicon;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.GraphI18n;
+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.Path;
@@ -150,7 +151,7 @@
}
UUID uuid = null;
for (Property property : request.properties()) {
- if (property.getName().equals(DnaLexicon.UUID)) {
+ if (property.getName().equals(DnaLexicon.UUID) ||
property.getName().equals(JcrLexicon.UUID)) {
uuid =
getExecutionContext().getValueFactories().getUuidFactory().create(property.getValues().next());
break;
}
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CopyBranchRequest.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CopyBranchRequest.java 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CopyBranchRequest.java 2009-04-30
04:32:26 UTC (rev 866)
@@ -223,6 +223,7 @@
if (into.hasPath() &&
!intoLocation.getPath().getParent().equals(into.getPath())) {
throw new
IllegalArgumentException(GraphI18n.actualLocationIsNotChildOfInputLocation.text(intoLocation,
into));
}
+ this.actualFromLocation = fromLocation;
this.actualIntoLocation = intoLocation;
}
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CreateNodeRequest.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CreateNodeRequest.java 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/CreateNodeRequest.java 2009-04-30
04:32:26 UTC (rev 866)
@@ -168,12 +168,6 @@
for (Property property : properties) {
if (property != null) props.add(property);
}
- // Add in the location properties ...
- if (under.hasIdProperties()) {
- for (Property property : under.getIdProperties()) {
- if (property != null) props.add(property);
- }
- }
this.properties = Collections.unmodifiableList(props);
}
@@ -207,12 +201,6 @@
Property property = properties.next();
if (property != null) props.add(property);
}
- // Add in the location properties ...
- if (under.hasIdProperties()) {
- for (Property property : under.getIdProperties()) {
- if (property != null) props.add(property);
- }
- }
this.properties = Collections.unmodifiableList(props);
}
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/MoveBranchRequest.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/MoveBranchRequest.java 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/MoveBranchRequest.java 2009-04-30
04:32:26 UTC (rev 866)
@@ -237,6 +237,7 @@
if (!actualNewName.equals(expectedNewName)) {
throw new
IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(newLocation,
into));
}
+ this.actualOldLocation = oldLocation;
this.actualNewLocation = newLocation;
}
@@ -265,9 +266,8 @@
*/
public boolean changes( String workspace,
Path path ) {
- return this.workspaceName.equals(workspace)
- && (into.hasPath() && into.getPath().isAtOrBelow(path)
- || from.hasPath() && from.getPath().isAtOrBelow(path));
+ return this.workspaceName.equals(workspace)
+ && (into.hasPath() && into.getPath().isAtOrBelow(path) ||
from.hasPath() && from.getPath().isAtOrBelow(path));
}
/**
Modified:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/inmemory/InMemoryRepositoryWorkspaceTest.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/inmemory/InMemoryRepositoryWorkspaceTest.java 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/inmemory/InMemoryRepositoryWorkspaceTest.java 2009-04-30
04:32:26 UTC (rev 866)
@@ -94,9 +94,11 @@
assertThat(workspace.getRoot().getUuid(), is(rootUuid));
}
- @Test( expected = AssertionError.class )
- public void shouldNotAllowRootToBeRemoved() {
+ @Test
+ public void shouldAllowRootToBeRemoved() {
workspace.removeNode(context, workspace.getRoot());
+ assertThat(workspace.getRoot().getChildren().size(), is(0));
+ assertThat(workspace.getRoot().getProperties().size(), is(0));
}
@Test( expected = AssertionError.class )
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-04-29 14:31:49
UTC (rev 865)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java 2009-04-30 04:32:26
UTC (rev 866)
@@ -141,10 +141,15 @@
context);
namespaceGraph.useWorkspace(workspaceName);
- Name uriProperty = DnaLexicon.NAMESPACE_URI;
+ // Make sure the "/jcr:system" node exists ...
PathFactory pathFactory = context.getValueFactories().getPathFactory();
Path root = pathFactory.createRootPath();
- Path namespacesPath = context.getValueFactories().getPathFactory().create(root,
JcrLexicon.SYSTEM, DnaLexicon.NAMESPACES);
+ Path systemPath = pathFactory.create(root, JcrLexicon.SYSTEM);
+ Property systemPrimaryType =
context.getPropertyFactory().create(JcrLexicon.PRIMARY_TYPE, DnaLexicon.SYSTEM);
+ namespaceGraph.createIfMissing(systemPath, systemPrimaryType);
+
+ Name uriProperty = DnaLexicon.NAMESPACE_URI;
+ Path namespacesPath = pathFactory.create(systemPath, DnaLexicon.NAMESPACES);
PropertyFactory propertyFactory = context.getPropertyFactory();
Property namespaceType = propertyFactory.create(JcrLexicon.PRIMARY_TYPE,
DnaLexicon.NAMESPACE);
org.jboss.dna.graph.property.NamespaceRegistry persistentRegistry = new
GraphNamespaceRegistry(namespaceGraph,
@@ -168,9 +173,7 @@
this.queryManager = new JcrQueryManager(this.session);
if (Boolean.valueOf(repository.getOptions().get(Options.PROJECT_NODE_TYPES))) {
- Path parentOfTypeNodes =
context.getValueFactories().getPathFactory().create(root,
-
JcrLexicon.SYSTEM,
-
JcrLexicon.NODE_TYPES);
+ Path parentOfTypeNodes =
context.getValueFactories().getPathFactory().create(systemPath, JcrLexicon.NODE_TYPES);
repoTypeManager.projectOnto(this.graph, parentOfTypeNodes);
}
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/MixinTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/MixinTest.java 2009-04-29 14:31:49 UTC
(rev 865)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/MixinTest.java 2009-04-30 04:32:26 UTC
(rev 866)
@@ -115,10 +115,6 @@
// Set up the initial content ...
graph = Graph.create(source, context);
- // Make sure the path to the namespaces exists ...
- graph.create("/jcr:system"); //
.and().create("/jcr:system/dna:namespaces");
-
graph.set("jcr:primaryType").on("/jcr:system").to(DnaLexicon.SYSTEM);
-
// Stub out the connection factory ...
connectionFactory = new RepositoryConnectionFactory() {
/**
@@ -318,7 +314,9 @@
public void shouldAllowAdditionIfResidualChildNodeDoesNotConflict() throws Exception
{
graph.create("/a").and().create("/a/" + CHILD_NODE_B);
graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a").to(JcrNtLexicon.UNSTRUCTURED.getString(registry));
- graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry)).on("/a/" +
CHILD_NODE_B).to(JcrNtLexicon.UNSTRUCTURED.getString(registry));
+ graph.set(JcrLexicon.PRIMARY_TYPE.getString(registry))
+ .on("/a/" + CHILD_NODE_B)
+ .to(JcrNtLexicon.UNSTRUCTURED.getString(registry));
Node rootNode = session.getRootNode();
Node nodeA = rootNode.getNode("a");
@@ -672,4 +670,4 @@
}
-}
\ No newline at end of file
+}
Modified:
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java
===================================================================
---
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java 2009-04-30
04:32:26 UTC (rev 866)
@@ -138,6 +138,7 @@
// Load into the source manager the repository source for the configuration
repository ...
InMemoryRepositorySource configSource = new InMemoryRepositorySource();
configSource.setName("Configuration");
+ configSource.setDefaultWorkspaceName("default");
sources.addSource(configSource);
// For this example, we're using a couple of in-memory repositories
(including one for the configuration repository).
@@ -145,7 +146,7 @@
// populate these repositories here by importing from files. First do the
configuration repository ...
String location = this.userInterface.getLocationOfRepositoryFiles();
Graph config = Graph.create("Configuration", sources, context);
- config.createWorkspace().named("default");
+ config.useWorkspace("default");
config.importXmlFrom(location +
"/configRepository.xml").into("/");
// Now instantiate the Repository Service ...
@@ -295,6 +296,8 @@
children.add(name);
}
}
+ } catch (javax.jcr.ItemNotFoundException e) {
+ return false;
} catch (javax.jcr.PathNotFoundException e) {
return false;
} finally {
Modified: trunk/docs/examples/gettingstarted/repositories/src/main/resources/aircraft.xml
===================================================================
---
trunk/docs/examples/gettingstarted/repositories/src/main/resources/aircraft.xml 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/docs/examples/gettingstarted/repositories/src/main/resources/aircraft.xml 2009-04-30
04:32:26 UTC (rev 866)
@@ -24,31 +24,31 @@
~ 51 Franklin Street, Fifth Floor
~ Boston, MA 02110-1301 USA
-->
-<Aircraft
xmlns:jcr="http://www.jcp.org/jcr/1.0">
+<Aircraft
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
<Business>
- <aircraft jcr:name="Gulfstream V" maker="Gulfstream"
model="G-V" introduced="1995" range="5800nm"
cruiseSpeed="488kt" crew="2" emptyWeight="46200lb"
url="http://en.wikipedia.org/wiki/Gulfstream_V"/>
- <aircraft jcr:name="Learjet 45" maker="Learjet"
model="LJ45" introduced="1995" numberBuilt="264+"
crew="2" emptyWeight="13695lb" range="2120nm"
cruiseSpeed="457kt"
url="http://en.wikipedia.org/wiki/Learjet_45"/>
+ <nt:unstructured jcr:name="Gulfstream V"
maker="Gulfstream" model="G-V" introduced="1995"
range="5800nm" cruiseSpeed="488kt" crew="2"
emptyWeight="46200lb"
url="http://en.wikipedia.org/wiki/Gulfstream_V"/>
+ <nt:unstructured jcr:name="Learjet 45" maker="Learjet"
model="LJ45" introduced="1995" numberBuilt="264+"
crew="2" emptyWeight="13695lb" range="2120nm"
cruiseSpeed="457kt"
url="http://en.wikipedia.org/wiki/Learjet_45"/>
</Business>
<Commercial>
- <aircraft jcr:name="Boeing 777" maker="Boeing"
model="777-200LR" introduced="1995" numberBuilt="731+"
maxRange="7500nm" emptyWeight="326000lb"
cruiseSpeed="560mph"
url="http://en.wikipedia.org/wiki/Boeing_777"/>
- <aircraft jcr:name="Boeing 767" maker="Boeing"
model="767-200" introduced="1982" numberBuilt="966+"
maxRange="3950nm" emptyWeight="176650lb"
cruiseSpeed="530mph"
url="http://en.wikipedia.org/wiki/Boeing_767"/>
- <aircraft jcr:name="Boeing 787" maker="Boeing"
model="787-3" introduced="2009" range="3050nm"
emptyWeight="223000lb" cruiseSpeed="561mph"
url="http://en.wikipedia.org/wiki/Boeing_787"/>
- <aircraft jcr:name="Boeing 757" maker="Boeing"
model="757-200" introduced="1983" numberBuilt="1050"
range="3900nm" maxWeight="255000lb" cruiseSpeed="530mph"
url="http://en.wikipedia.org/wiki/Boeing_757"/>
- <aircraft jcr:name="Airbus A380" maker="Airbus"
model="A380-800" introduced="2007" numberBuilt="18"
range="8200nm" maxWeight="1235000lb" cruiseSpeed="647mph"
url="http://en.wikipedia.org/wiki/Airbus_a380"/>
- <aircraft jcr:name="Airbus A340" maker="Airbus"
model="A340-200" introduced="1993" numberBuilt="354"
range="8000nm" maxWeight="606300lb" cruiseSpeed="557mph"
url="http://en.wikipedia.org/wiki/Airbus_A-340"/>
- <aircraft jcr:name="Airbus A310" maker="Airbus"
model="A310-200" introduced="1983" numberBuilt="255"
cruiseSpeed="850km/h" emptyWeight="176312lb" range="3670nm"
url="http://en.wikipedia.org/wiki/Airbus_A-310"/>
- <aircraft jcr:name="Embraer RJ-175" maker="Embraer"
model="ERJ170-200" introduced="2004" range="3334km"
cruiseSpeed="481kt" emptyWeight="21810kg"
url="http://en.wikipedia.org/wiki/EMBRAER_170"/>
+ <nt:unstructured jcr:name="Boeing 777" maker="Boeing"
model="777-200LR" introduced="1995" numberBuilt="731+"
maxRange="7500nm" emptyWeight="326000lb"
cruiseSpeed="560mph"
url="http://en.wikipedia.org/wiki/Boeing_777"/>
+ <nt:unstructured jcr:name="Boeing 767" maker="Boeing"
model="767-200" introduced="1982" numberBuilt="966+"
maxRange="3950nm" emptyWeight="176650lb"
cruiseSpeed="530mph"
url="http://en.wikipedia.org/wiki/Boeing_767"/>
+ <nt:unstructured jcr:name="Boeing 787" maker="Boeing"
model="787-3" introduced="2009" range="3050nm"
emptyWeight="223000lb" cruiseSpeed="561mph"
url="http://en.wikipedia.org/wiki/Boeing_787"/>
+ <nt:unstructured jcr:name="Boeing 757" maker="Boeing"
model="757-200" introduced="1983" numberBuilt="1050"
range="3900nm" maxWeight="255000lb" cruiseSpeed="530mph"
url="http://en.wikipedia.org/wiki/Boeing_757"/>
+ <nt:unstructured jcr:name="Airbus A380" maker="Airbus"
model="A380-800" introduced="2007" numberBuilt="18"
range="8200nm" maxWeight="1235000lb" cruiseSpeed="647mph"
url="http://en.wikipedia.org/wiki/Airbus_a380"/>
+ <nt:unstructured jcr:name="Airbus A340" maker="Airbus"
model="A340-200" introduced="1993" numberBuilt="354"
range="8000nm" maxWeight="606300lb" cruiseSpeed="557mph"
url="http://en.wikipedia.org/wiki/Airbus_A-340"/>
+ <nt:unstructured jcr:name="Airbus A310" maker="Airbus"
model="A310-200" introduced="1983" numberBuilt="255"
cruiseSpeed="850km/h" emptyWeight="176312lb" range="3670nm"
url="http://en.wikipedia.org/wiki/Airbus_A-310"/>
+ <nt:unstructured jcr:name="Embraer RJ-175" maker="Embraer"
model="ERJ170-200" introduced="2004" range="3334km"
cruiseSpeed="481kt" emptyWeight="21810kg"
url="http://en.wikipedia.org/wiki/EMBRAER_170"/>
</Commercial>
<Vintage>
- <aircraft jcr:name="Fokker Trimotor" maker="Fokker"
model="F.VII" introduced="1925" cruiseSpeed="170km/h"
emptyWeight="3050kg" crew="2"
url="http://en.wikipedia.org/wiki/Fokker_trimotor"/>
- <aircraft jcr:name="P-38 Lightning" maker="Lockheed"
model="P-38" designedBy="Kelly Johnson" introduced="1941"
numberBuilt="10037" rateOfClimb="4750ft/min" range="1300mi"
emptyWeight="12780lb" crew="1"
url="http://en.wikipedia.org/wiki/P-38_Lightning"/>
- <aircraft jcr:name="A6M Zero" maker="Mitsubishi"
model="A6M" designedBy="Jiro Horikoshi" introduced="1940"
numberBuilt="11000" crew="1" emptyWeight="3704lb"
serviceCeiling="33000ft" maxSpeed="331mph" range="1929mi"
rateOfClimb="3100ft/min"
url="http://en.wikipedia.org/wiki/A6M_Zero"/>
- <aircraft jcr:name="Bf 109" maker="Messerschmitt"
model="Bf 109" introduced="1937"
url="http://en.wikipedia.org/wiki/BF_109"/>
- <aircraft jcr:name="Wright Flyer" maker="Wright Brothers"
introduced="1903" range="852ft" maxSpeed="30mph"
emptyWeight="605lb" crew="1"/>
+ <nt:unstructured jcr:name="Fokker Trimotor" maker="Fokker"
model="F.VII" introduced="1925" cruiseSpeed="170km/h"
emptyWeight="3050kg" crew="2"
url="http://en.wikipedia.org/wiki/Fokker_trimotor"/>
+ <nt:unstructured jcr:name="P-38 Lightning"
maker="Lockheed" model="P-38" designedBy="Kelly Johnson"
introduced="1941" numberBuilt="10037"
rateOfClimb="4750ft/min" range="1300mi"
emptyWeight="12780lb" crew="1"
url="http://en.wikipedia.org/wiki/P-38_Lightning"/>
+ <nt:unstructured jcr:name="A6M Zero" maker="Mitsubishi"
model="A6M" designedBy="Jiro Horikoshi" introduced="1940"
numberBuilt="11000" crew="1" emptyWeight="3704lb"
serviceCeiling="33000ft" maxSpeed="331mph" range="1929mi"
rateOfClimb="3100ft/min"
url="http://en.wikipedia.org/wiki/A6M_Zero"/>
+ <nt:unstructured jcr:name="Bf 109" maker="Messerschmitt"
model="Bf 109" introduced="1937"
url="http://en.wikipedia.org/wiki/BF_109"/>
+ <nt:unstructured jcr:name="Wright Flyer" maker="Wright
Brothers" introduced="1903" range="852ft"
maxSpeed="30mph" emptyWeight="605lb" crew="1"/>
</Vintage>
<Homebuilt>
- <aircraft jcr:name="Long-EZ" maker="Rutan Aircraft
Factory" model="61" emptyWeight="760lb"
fuelCapacity="200L" maxSpeed="185kt" since="1976"
range="1200nm"
url="http://en.wikipedia.org/wiki/Rutan_Long-EZ"/>
- <aircraft jcr:name="Cirrus VK-30" maker="Cirrus Design"
model="VK-30" emptyWeight="2400lb" maxLoad="1200lb"
maxSpeed="250mph" rateOfClimb="1500ft/min" range="1300mi"
url="http://en.wikipedia.org/wiki/Cirrus_VK-30"/>
- <aircraft jcr:name="Van's RV-4" maker="Van's
Aircraft" model="RV-4" introduced="1980"
emptyWeight="905lb" maxLoad="500lb" maxSpeed="200mph"
rateOfClimb="2450ft/min" range="725mi"
url="http://en.wikipedia.org/wiki/Van%27s_Aircraft_RV-4"/>
+ <nt:unstructured jcr:name="Long-EZ" maker="Rutan Aircraft
Factory" model="61" emptyWeight="760lb"
fuelCapacity="200L" maxSpeed="185kt" since="1976"
range="1200nm"
url="http://en.wikipedia.org/wiki/Rutan_Long-EZ"/>
+ <nt:unstructured jcr:name="Cirrus VK-30" maker="Cirrus
Design" model="VK-30" emptyWeight="2400lb"
maxLoad="1200lb" maxSpeed="250mph" rateOfClimb="1500ft/min"
range="1300mi"
url="http://en.wikipedia.org/wiki/Cirrus_VK-30"/>
+ <nt:unstructured jcr:name="Van's RV-4" maker="Van's
Aircraft" model="RV-4" introduced="1980"
emptyWeight="905lb" maxLoad="500lb" maxSpeed="200mph"
rateOfClimb="2450ft/min" range="725mi"
url="http://en.wikipedia.org/wiki/Van%27s_Aircraft_RV-4"/>
</Homebuilt>
</Aircraft>
\ No newline at end of file
Modified: trunk/docs/examples/gettingstarted/repositories/src/main/resources/cars.xml
===================================================================
--- trunk/docs/examples/gettingstarted/repositories/src/main/resources/cars.xml 2009-04-29
14:31:49 UTC (rev 865)
+++ trunk/docs/examples/gettingstarted/repositories/src/main/resources/cars.xml 2009-04-30
04:32:26 UTC (rev 866)
@@ -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:nt="http://www.jcp.org/jcr/nt/1.0">
<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"/>
+ <nt:unstructured jcr:name="Toyota Prius" maker="Toyota"
model="Prius" year="2008" msrp="$21,500"
userRating="4.2" valueRating="5" mpgCity="48"
mpgHighway="45"/>
+ <nt:unstructured jcr:name="Toyota Highlander"
maker="Toyota" model="Highlander" year="2008"
msrp="$34,200" userRating="4" valueRating="5"
mpgCity="27" mpgHighway="25"/>
+ <nt:unstructured jcr:name="Nissan Altima" maker="Nissan"
model="Altima" year="2008" msrp="$18,260"
mpgCity="23" 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" />
+ <nt:unstructured 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"/>
+ <nt:unstructured jcr:name="Infiniti G37" maker="Infiniti"
model="G37" year="2008" msrp="$34,900"
userRating="3.5" valueRating="4" mpgCity="18"
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" />
+ <nt:unstructured jcr:name="Cadillac DTS" maker="Cadillac"
model="DTS" year="2008" engine="3.6-liter V6"
userRating="0"/>
+ <nt:unstructured jcr:name="Bentley Continental"
maker="Bentley" model="Continental" year="2008"
msrp="$170,990" mpgCity="10" mpgHighway="17" />
+ <nt:unstructured jcr:name="Lexus IS350" maker="Lexus"
model="IS350" year="2008" msrp="$36,305"
mpgCity="18" mpgHighway="25" userRating="4"
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" />
+ <nt:unstructured jcr:name="Land Rover LR2" maker="Land
Rover" model="LR2" year="2008" msrp="$33,985"
userRating="4.5" valueRating="5" mpgCity="16"
mpgHighway="23" />
+ <nt:unstructured jcr:name="Land Rover LR3" maker="Land
Rover" model="LR3" year="2008" msrp="$48,525"
userRating="5" valueRating="2" mpgCity="12"
mpgHighway="17" />
+ <nt:unstructured jcr:name="Hummer H3" maker="Hummer"
model="H3" year="2008" msrp="$30,595"
userRating="3.5" valueRating="4" mpgCity="13"
mpgHighway="16" />
+ <nt:unstructured jcr:name="Ford F-150" maker="Ford"
model="F-150" year="2008" msrp="$23,910"
userRating="4" valueRating="1" mpgCity="14"
mpgHighway="20" />
</Utility>
</Cars>
\ No newline at end of file
Modified:
trunk/docs/examples/gettingstarted/repositories/src/test/java/org/jboss/example/dna/repository/RepositoryClientTest.java
===================================================================
---
trunk/docs/examples/gettingstarted/repositories/src/test/java/org/jboss/example/dna/repository/RepositoryClientTest.java 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/docs/examples/gettingstarted/repositories/src/test/java/org/jboss/example/dna/repository/RepositoryClientTest.java 2009-04-30
04:32:26 UTC (rev 866)
@@ -139,19 +139,32 @@
getNodeInfo("Cars", "/Cars");
assertThat(children, hasItems("Hybrid", "Sports",
"Luxury", "Utility"));
assertThat(properties.containsKey("jcr:primaryType"), is(true));
- assertThat(properties.containsKey("dna:uuid"), is(true));
- assertThat(properties.size(), is(2));
+ switch (getApi()) {
+ case DNA:
+ assertThat(properties.containsKey("dna:uuid"), is(true));
+ assertThat(properties.size(), is(2));
+ break;
+ case JCR:
+ assertThat(properties.size(), is(1));
+ break;
+ }
getNodeInfo("Cars", "/Cars/Hybrid");
assertThat(children, hasItems("Toyota Prius", "Toyota
Highlander", "Nissan Altima"));
assertThat(properties.containsKey("jcr:primaryType"), is(true));
- assertThat(properties.containsKey("dna:uuid"), is(true));
- assertThat(properties.size(), is(2));
+ switch (getApi()) {
+ case DNA:
+ assertThat(properties.containsKey("dna:uuid"), is(true));
+ assertThat(properties.size(), is(2));
+ break;
+ case JCR:
+ assertThat(properties.size(), is(1));
+ break;
+ }
getNodeInfo("Cars", "/Cars/Sports/Aston Martin DB9");
assertThat(children.size(), is(0));
assertThat(properties.containsKey("jcr:primaryType"), is(true));
- assertThat(properties.containsKey("dna:uuid"), is(true));
assertProperty("maker", "Aston Martin");
assertProperty("maker", "Aston Martin");
assertProperty("model", "DB9");
@@ -163,7 +176,15 @@
assertProperty("lengthInInches", "185.5");
assertProperty("wheelbaseInInches", "108.0");
assertProperty("engine", "5,935 cc 5.9 liters V 12");
- assertThat(properties.size(), is(12));
+ switch (getApi()) {
+ case DNA:
+ assertThat(properties.containsKey("dna:uuid"), is(true));
+ assertThat(properties.size(), is(12));
+ break;
+ case JCR:
+ assertThat(properties.size(), is(11));
+ break;
+ }
}
@Test
@@ -173,8 +194,7 @@
getNodeInfo("Aircraft", "/Aircraft");
assertThat(children, hasItems("Business", "Commercial",
"Vintage", "Homebuilt"));
assertThat(properties.containsKey("jcr:primaryType"), is(true));
- assertThat(properties.containsKey("dna:uuid"), is(true));
- assertThat(properties.size(), is(2));
+ // assertThat(properties.containsKey("dna:uuid"), is(true)); // not
referenceable in JCR
getNodeInfo("Aircraft", "/Aircraft/Commercial");
assertThat(children, hasItems("Boeing 777",
@@ -186,20 +206,18 @@
"Airbus A310",
"Embraer RJ-175"));
assertThat(properties.containsKey("jcr:primaryType"), is(true));
- assertThat(properties.containsKey("dna:uuid"), is(true));
- assertThat(properties.size(), is(2));
+ // assertThat(properties.containsKey("dna:uuid"), is(true)); // not
referenceable in JCR
getNodeInfo("Aircraft", "/Aircraft/Vintage/Wright Flyer");
assertThat(children.size(), is(0));
assertThat(properties.containsKey("jcr:primaryType"), is(true));
- assertThat(properties.containsKey("dna:uuid"), is(true));
+ // assertThat(properties.containsKey("dna:uuid"), is(true));
assertProperty("maker", "Wright Brothers");
assertProperty("introduced", "1903");
assertProperty("range", "852ft");
assertProperty("maxSpeed", "30mph");
assertProperty("emptyWeight", "605lb");
assertProperty("crew", "1");
- assertThat(properties.size(), is(8));
}
@Test
@@ -208,29 +226,20 @@
getNodeInfo("Vehicles", "/");
assertThat(children, hasItems("Vehicles", "jcr:system"));
- assertThat(properties.containsKey("dna:uuid"), is(true));
- assertThat(properties.size(), is(1));
getNodeInfo("Vehicles", "/Vehicles");
assertThat(children, hasItems("Cars", "Aircraft"));
- assertThat(properties.containsKey("dna:uuid"), is(true));
- assertThat(properties.size(), is(1));
getNodeInfo("Vehicles", "/");
assertThat(children, hasItems("Vehicles", "jcr:system"));
- assertThat(properties.containsKey("dna:uuid"), is(true));
- assertThat(properties.size(), is(1));
getNodeInfo("Vehicles", "/Vehicles/Cars/Hybrid");
assertThat(children, hasItems("Toyota Prius", "Toyota
Highlander", "Nissan Altima"));
assertThat(properties.containsKey("jcr:primaryType"), is(true));
- assertThat(properties.containsKey("dna:uuid"), is(true));
- assertThat(properties.size(), is(2));
getNodeInfo("Vehicles", "/Vehicles/Cars/Sports/Aston Martin
DB9");
assertThat(children.size(), is(0));
assertThat(properties.containsKey("jcr:primaryType"), is(true));
- assertThat(properties.containsKey("dna:uuid"), is(true));
assertProperty("maker", "Aston Martin");
assertProperty("maker", "Aston Martin");
assertProperty("model", "DB9");
@@ -242,19 +251,16 @@
assertProperty("lengthInInches", "185.5");
assertProperty("wheelbaseInInches", "108.0");
assertProperty("engine", "5,935 cc 5.9 liters V 12");
- assertThat(properties.size(), is(12));
getNodeInfo("Vehicles", "/Vehicles/Aircraft/Vintage/Wright
Flyer");
assertThat(children.size(), is(0));
assertThat(properties.containsKey("jcr:primaryType"), is(true));
- assertThat(properties.containsKey("dna:uuid"), is(true));
assertProperty("maker", "Wright Brothers");
assertProperty("introduced", "1903");
assertProperty("range", "852ft");
assertProperty("maxSpeed", "30mph");
assertProperty("emptyWeight", "605lb");
assertProperty("crew", "1");
- assertThat(properties.size(), is(8));
}
@Test
Modified:
trunk/docs/examples/gettingstarted/repositories/src/test/java/org/jboss/example/dna/repository/RepositoryClientUsingJcrTest.java
===================================================================
---
trunk/docs/examples/gettingstarted/repositories/src/test/java/org/jboss/example/dna/repository/RepositoryClientUsingJcrTest.java 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/docs/examples/gettingstarted/repositories/src/test/java/org/jboss/example/dna/repository/RepositoryClientUsingJcrTest.java 2009-04-30
04:32:26 UTC (rev 866)
@@ -39,4 +39,14 @@
protected Api getApi() {
return RepositoryClient.Api.JCR;
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.example.dna.repository.RepositoryClientTest#shouldHaveContentFromVehiclesRepository()
+ */
+ @Override
+ public void shouldHaveContentFromVehiclesRepository() throws Throwable {
+ super.shouldHaveContentFromVehiclesRepository();
+ }
}
Modified:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedWorkspace.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedWorkspace.java 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedWorkspace.java 2009-04-30
04:32:26 UTC (rev 866)
@@ -184,6 +184,16 @@
}
/**
+ * Return the unmodifiable list of projections for the source name.
+ *
+ * @param sourceName the name of the source
+ * @return the list of projections for this source, or null if there are none
+ */
+ public List<Projection> getProjectionsFor( String sourceName ) {
+ return this.projectionsBySourceName.get(sourceName);
+ }
+
+ /**
* Determine whether this workspace has a projection supplied contribution
*
* @param sourceName the name of the source
Modified:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatingRequestProcessor.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatingRequestProcessor.java 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatingRequestProcessor.java 2009-04-30
04:32:26 UTC (rev 866)
@@ -28,12 +28,14 @@
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.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
+import net.jcip.annotations.Immutable;
import net.jcip.annotations.NotThreadSafe;
import org.jboss.dna.common.i18n.I18n;
import org.jboss.dna.common.util.CheckArg;
@@ -43,6 +45,7 @@
import org.jboss.dna.connector.federation.merge.MergePlan;
import org.jboss.dna.graph.DnaLexicon;
import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.JcrLexicon;
import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.NodeConflictBehavior;
import org.jboss.dna.graph.cache.CachePolicy;
@@ -56,6 +59,7 @@
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.PropertyFactory;
import org.jboss.dna.graph.request.CloneWorkspaceRequest;
import org.jboss.dna.graph.request.CompositeRequest;
import org.jboss.dna.graph.request.CopyBranchRequest;
@@ -70,6 +74,7 @@
import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
import org.jboss.dna.graph.request.ReadNodeRequest;
import org.jboss.dna.graph.request.Request;
+import org.jboss.dna.graph.request.UnsupportedRequestException;
import org.jboss.dna.graph.request.UpdatePropertiesRequest;
import org.jboss.dna.graph.request.VerifyWorkspaceRequest;
import org.jboss.dna.graph.request.processor.RequestProcessor;
@@ -87,6 +92,7 @@
private final RepositoryConnectionFactory connectionFactory;
/** The set of all connections, including the cache connection */
private final Map<String, RepositoryConnection> connectionsBySourceName;
+ protected final PathFactory pathFactory;
private Logger logger;
/**
@@ -116,6 +122,7 @@
this.logger = context.getLogger(getClass());
this.connectionsBySourceName = new HashMap<String,
RepositoryConnection>();
this.defaultWorkspace = defaultWorkspace; // may be null
+ this.pathFactory = context.getValueFactories().getPathFactory();
}
protected DateTime getCurrentTimeInUtc() {
@@ -248,31 +255,118 @@
/**
* {@inheritDoc}
*
- * @see
org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CopyBranchRequest)
+ * @see
org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CreateNodeRequest)
*/
@Override
- public void process( CopyBranchRequest request ) {
- throw new UnsupportedOperationException();
+ public void process( CreateNodeRequest request ) {
+ FederatedWorkspace workspace = getWorkspace(request, request.inWorkspace());
+ if (workspace == null) return;
+
+ // Can push this down if and only if the entire request is within a single
federated source ...
+ SingleProjection projection = asSingleProjection(workspace, request.under(),
request);
+ if (projection == null) return;
+
+ // Push down the request ...
+ Location parentLocation = Location.create(projection.pathInSource);
+ String workspaceName = projection.projection.getWorkspaceName();
+ CreateNodeRequest sourceRequest = new CreateNodeRequest(parentLocation,
workspaceName, request.named(),
+ request.properties());
+ execute(sourceRequest, projection.projection);
+
+ // Copy/transform the results ...
+ if (sourceRequest.hasError()) {
+ request.setError(sourceRequest.getError());
+ } else {
+
request.setActualLocationOfNode(projection.convertToRepository(sourceRequest.getActualLocationOfNode()));
+ }
}
/**
* {@inheritDoc}
*
- * @see
org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CreateNodeRequest)
+ * @see
org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.DeleteBranchRequest)
*/
@Override
- public void process( CreateNodeRequest request ) {
- throw new UnsupportedOperationException();
+ public void process( DeleteBranchRequest request ) {
+ FederatedWorkspace workspace = getWorkspace(request, request.inWorkspace());
+ if (workspace == null) return;
+
+ // Can push this down if and only if the entire request is within a single
federated source ...
+ SingleProjection projection = asSingleProjection(workspace, request.at(),
request);
+ if (projection == null) return;
+
+ // Push down the request ...
+ Location sourceLocation = Location.create(projection.pathInSource);
+ String workspaceName = projection.projection.getWorkspaceName();
+ DeleteBranchRequest sourceRequest = new DeleteBranchRequest(sourceLocation,
workspaceName);
+ execute(sourceRequest, projection.projection);
+
+ // Copy/transform the results ...
+ if (sourceRequest.hasError()) {
+ request.setError(sourceRequest.getError());
+ } else {
+
request.setActualLocationOfNode(projection.convertToRepository(sourceRequest.getActualLocationOfNode()));
+ }
+
+ // Delete in the cache ...
+ DeleteBranchRequest cacheRequest = new DeleteBranchRequest(request.at(),
workspace.getCacheProjection()
+
.getWorkspaceName());
+ executeInCache(cacheRequest, workspace);
}
/**
* {@inheritDoc}
*
- * @see
org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.DeleteBranchRequest)
+ * @see
org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.CopyBranchRequest)
*/
@Override
- public void process( DeleteBranchRequest request ) {
- throw new UnsupportedOperationException();
+ public void process( CopyBranchRequest request ) {
+ FederatedWorkspace fromWorkspace = getWorkspace(request,
request.fromWorkspace());
+ if (fromWorkspace == null) return;
+ FederatedWorkspace intoWorkspace = getWorkspace(request,
request.intoWorkspace());
+ if (intoWorkspace == null) return;
+ if (!fromWorkspace.equals(intoWorkspace)) {
+ // Otherwise there wasn't a single projection with a single path ...
+ String msg =
FederationI18n.unableToPerformOperationSpanningWorkspaces.text(fromWorkspace.getName(),
+
intoWorkspace.getName());
+ request.setError(new UnsupportedRequestException(msg));
+ }
+
+ // Can push this down if and only if the entire request is within a single
federated source ...
+ SingleProjection fromProjection = asSingleProjection(fromWorkspace,
request.from(), request);
+ if (fromProjection == null) return;
+ SingleProjection intoProjection = asSingleProjection(intoWorkspace,
request.into(), request);
+ if (intoProjection == null) return;
+ if (!intoProjection.projection.equals(fromProjection.projection)) {
+ // Otherwise there wasn't a single projection with a single path ...
+ String msg =
FederationI18n.unableToPerformOperationUnlessLocationsAreFromSingleProjection.text(request.from(),
+
request.into(),
+
fromWorkspace.getName(),
+
fromProjection.projection.getRules(),
+
intoProjection.projection.getRules());
+ request.setError(new UnsupportedRequestException(msg));
+ }
+
+ // Push down the request ...
+ Location fromLocation = Location.create(fromProjection.pathInSource);
+ Location intoLocation = Location.create(intoProjection.pathInSource);
+ String workspaceName = fromProjection.projection.getWorkspaceName();
+ CopyBranchRequest sourceRequest = new CopyBranchRequest(fromLocation,
workspaceName, intoLocation, workspaceName,
+ request.desiredName(),
request.conflictBehavior());
+ execute(sourceRequest, fromProjection.projection);
+
+ // Copy/transform the results ...
+ if (sourceRequest.hasError()) {
+ request.setError(sourceRequest.getError());
+ } else {
+
request.setActualLocations(fromProjection.convertToRepository(sourceRequest.getActualLocationBefore()),
+
intoProjection.convertToRepository(sourceRequest.getActualLocationAfter()));
+ }
+
+ // Delete from the cache the parent of the new location ...
+ DeleteBranchRequest cacheRequest = new DeleteBranchRequest(request.into(),
fromWorkspace.getCacheProjection()
+
.getWorkspaceName());
+ executeInCache(cacheRequest, fromWorkspace);
}
/**
@@ -282,7 +376,43 @@
*/
@Override
public void process( MoveBranchRequest request ) {
- throw new UnsupportedOperationException();
+ FederatedWorkspace workspace = getWorkspace(request, request.inWorkspace());
+ if (workspace == null) return;
+
+ // Can push this down if and only if the entire request is within a single
federated source ...
+ SingleProjection fromProjection = asSingleProjection(workspace, request.from(),
request);
+ if (fromProjection == null) return;
+ SingleProjection intoProjection = asSingleProjection(workspace, request.into(),
request);
+ if (intoProjection == null) return;
+ if (!intoProjection.projection.equals(fromProjection.projection)) {
+ // Otherwise there wasn't a single projection with a single path ...
+ String msg =
FederationI18n.unableToPerformOperationUnlessLocationsAreFromSingleProjection.text(request.from(),
+
request.into(),
+
workspace.getName(),
+
fromProjection.projection.getRules(),
+
intoProjection.projection.getRules());
+ request.setError(new UnsupportedRequestException(msg));
+ }
+
+ // Push down the request ...
+ Location fromLocation = Location.create(fromProjection.pathInSource);
+ Location intoLocation = Location.create(intoProjection.pathInSource);
+ String workspaceName = fromProjection.projection.getWorkspaceName();
+ MoveBranchRequest sourceRequest = new MoveBranchRequest(fromLocation,
intoLocation, workspaceName, request.desiredName(),
+
request.conflictBehavior());
+ execute(sourceRequest, fromProjection.projection);
+
+ // Copy/transform the results ...
+ if (sourceRequest.hasError()) {
+ request.setError(sourceRequest.getError());
+ } else {
+
request.setActualLocations(fromProjection.convertToRepository(sourceRequest.getActualLocationBefore()),
+
intoProjection.convertToRepository(sourceRequest.getActualLocationAfter()));
+ }
+ // Delete from the cache ...
+ DeleteBranchRequest cacheRequest = new DeleteBranchRequest(request.from(),
workspace.getCacheProjection()
+
.getWorkspaceName());
+ executeInCache(cacheRequest, workspace);
}
/**
@@ -292,7 +422,31 @@
*/
@Override
public void process( UpdatePropertiesRequest request ) {
- throw new UnsupportedOperationException();
+ FederatedWorkspace workspace = getWorkspace(request, request.inWorkspace());
+ if (workspace == null) return;
+
+ // Can push this down if and only if the entire request is within a single
federated source ...
+ SingleProjection projection = asSingleProjection(workspace, request.on(),
request);
+ if (projection == null) return;
+
+ // Push down the request ...
+ Location sourceLocation = Location.create(projection.pathInSource);
+ String workspaceName = projection.projection.getWorkspaceName();
+ UpdatePropertiesRequest sourceRequest = new
UpdatePropertiesRequest(sourceLocation, workspaceName, request.properties());
+ execute(sourceRequest, projection.projection);
+
+ // Copy/transform the results ...
+ if (sourceRequest.hasError()) {
+ request.setError(sourceRequest.getError());
+ } else {
+
request.setActualLocationOfNode(projection.convertToRepository(sourceRequest.getActualLocationOfNode()));
+ }
+
+ // Update the cache ...
+ UpdatePropertiesRequest cacheRequest = new UpdatePropertiesRequest(request.on(),
workspace.getCacheProjection()
+
.getWorkspaceName(),
+
request.properties());
+ executeInCache(cacheRequest, workspace);
}
/**
@@ -305,7 +459,7 @@
FederatedWorkspace workspace = getWorkspace(request, request.workspaceName());
if (workspace != null) {
request.setActualWorkspaceName(workspace.getName());
- Location root =
Location.create(getExecutionContext().getValueFactories().getPathFactory().createRootPath());
+ Location root = Location.create(pathFactory.createRootPath());
ReadNodeRequest nodeInfo = getNode(root, workspace);
if (nodeInfo.hasError()) return;
request.setActualRootLocation(nodeInfo.getActualLocationOfNode());
@@ -353,6 +507,96 @@
throw new UnsupportedOperationException();
}
+ @Immutable
+ protected class SingleProjection {
+ protected final Projection projection;
+ protected final Path pathInSource;
+ protected final Location federatedLocation;
+
+ protected SingleProjection( Projection projection,
+ Path pathInSource,
+ Location federatedLocation ) {
+ this.projection = projection;
+ this.federatedLocation = federatedLocation;
+ this.pathInSource = pathInSource;
+ }
+
+ protected Location convertToRepository( Location sourceLocation ) {
+ assert sourceLocation != null;
+ if (sourceLocation.hasPath()) {
+ Set<Path> paths =
projection.getPathsInRepository(sourceLocation.getPath(), pathFactory);
+ assert paths.size() == 1;
+ return sourceLocation.with(paths.iterator().next());
+ }
+ return sourceLocation;
+ }
+ }
+
+ protected SingleProjection asSingleProjection( FederatedWorkspace
federatedWorkspace,
+ Location location,
+ Request request ) {
+ // Check the cache for this location ...
+ ReadNodeRequest nodeInfo = getNode(location, federatedWorkspace);
+ if (nodeInfo.hasError()) {
+ request.setError(nodeInfo.getError());
+ return null;
+ }
+ Location actualLocation = nodeInfo.getActualLocationOfNode();
+ Path pathInRepository = actualLocation.getPath();
+ assert pathInRepository != null;
+
+ // Get the merge plan for the node ...
+ MergePlan plan = getMergePlan(nodeInfo);
+ assert plan != null;
+ if (plan.getRealContributionCount() == 1) {
+ for (Contribution contribution : plan) {
+ if (contribution.isEmpty() || contribution.isPlaceholder()) continue;
+ for (Projection projection :
federatedWorkspace.getProjectionsFor(contribution.getSourceName())) {
+ Set<Path> paths = projection.getPathsInSource(pathInRepository,
pathFactory);
+ if (paths.size() == 1) {
+ return new SingleProjection(projection, paths.iterator().next(),
actualLocation);
+ }
+ }
+ }
+ }
+
+ // Otherwise there wasn't a single projection with a single path ...
+ StringBuilder projections = new StringBuilder();
+ boolean first = true;
+ for (Contribution contribution : plan) {
+ if (contribution.isPlaceholder() || contribution.isEmpty()) continue;
+ if (first) first = false;
+ else projections.append(", ");
+ for (Projection projection :
federatedWorkspace.getProjectionsFor(contribution.getSourceName())) {
+ Set<Path> paths = projection.getPathsInSource(pathInRepository,
pathFactory);
+ if (paths.size() == 1) {
+
projections.append(FederationI18n.pathInProjection.text(paths.iterator().next(),
projection.getRules()));
+ } else {
+ projections.append(FederationI18n.pathInProjection.text(paths,
projection.getRules()));
+ }
+ }
+ }
+ String msg =
FederationI18n.unableToPerformOperationUnlessLocationIsFromSingleProjection.text(location,
+
federatedWorkspace.getName(),
+
projections);
+ request.setError(new UnsupportedRequestException(msg));
+ return null;
+ }
+
+ protected void execute( Request request,
+ Projection projection ) {
+ RepositoryConnection connection = getConnection(projection);
+ connection.execute(getExecutionContext(), request);
+ // Don't need to close, as we'll close all connections when this
processor is closed
+ }
+
+ protected void executeInCache( Request request,
+ FederatedWorkspace workspace ) {
+ RepositoryConnection connection = getConnectionToCacheFor(workspace);
+ connection.execute(getExecutionContext(), request);
+ // Don't need to close, as we'll close all connections when this
processor is closed
+ }
+
/**
* Get the node information from the underlying sources or, if possible, from the
cache.
*
@@ -363,12 +607,9 @@
*/
protected ReadNodeRequest getNode( Location location,
FederatedWorkspace workspace ) throws
RepositorySourceException {
- final ExecutionContext context = getExecutionContext();
-
// Check the cache first ...
- RepositoryConnection cacheConnection = getConnectionToCacheFor(workspace);
ReadNodeRequest fromCache = new ReadNodeRequest(location,
workspace.getCacheProjection().getWorkspaceName());
- cacheConnection.execute(context, fromCache);
+ executeInCache(fromCache, workspace);
// Look at the cache results from the cache for problems, or if found a plan in
the cache look
// at the contributions. We'll be putting together the set of source names
for which we need to
@@ -395,13 +636,19 @@
Location locationToLoad = Location.create(pathToLoad);
loadContributionsFromSources(locationToLoad, workspace, null,
contributions); // sourceNames may be
// null or empty
- FederatedNode mergedNode = createFederatedNode(locationToLoad,
workspace, contributions, true);
+ FederatedNode mergedNode = createFederatedNode(locationToLoad,
workspace, fromCache, contributions, true);
if (mergedNode == null) {
// No source had a contribution ...
I18n msg = FederationI18n.nodeDoesNotExistAtPath;
fromCache.setError(new PathNotFoundException(location,
ancestor, msg.text(path, ancestor)));
return fromCache;
}
+ MergePlan mergePlan = mergedNode.getMergePlan();
+ if (mergePlan != null) {
+ Property mergePlanProperty =
getExecutionContext().getPropertyFactory().create(DnaLexicon.MERGE_PLAN,
+
(Object)mergePlan);
+ fromCache.addProperty(mergePlanProperty);
+ }
contributions.clear();
// Move to the next child along the path ...
pathToLoad = pathToLoad.getParent();
@@ -449,7 +696,7 @@
location = fromCache.at();
}
loadContributionsFromSources(location, workspace, sourceNames, contributions); //
sourceNames may be null or empty
- FederatedNode mergedNode = createFederatedNode(location, workspace,
contributions, true);
+ FederatedNode mergedNode = createFederatedNode(location, workspace, fromCache,
contributions, true);
if (mergedNode == null) {
// No source had a contribution ...
if (location.hasPath()) {
@@ -467,6 +714,7 @@
protected FederatedNode createFederatedNode( Location location,
FederatedWorkspace federatedWorkspace,
+ ReadNodeRequest fromCache,
List<Contribution> contributions,
boolean updateCache ) throws
RepositorySourceException {
assert location != null;
@@ -492,7 +740,7 @@
// Create the node, and use the existing UUID if one is found in the cache ...
ExecutionContext context = getExecutionContext();
assert context != null;
- FederatedNode mergedNode = new FederatedNode(location.with((UUID)null),
federatedWorkspace.getName());
+ FederatedNode mergedNode = new FederatedNode(location,
federatedWorkspace.getName());
// Merge the results into a single set of results ...
assert contributions.size() > 0;
@@ -502,7 +750,7 @@
}
if (updateCache) {
// Place the results into the cache ...
- updateCache(federatedWorkspace, mergedNode);
+ updateCache(federatedWorkspace, mergedNode, fromCache);
}
// And return the results ...
return mergedNode;
@@ -525,7 +773,6 @@
List<Contribution> contributions )
throws RepositorySourceException {
// At this point, there is no merge plan, so read information from the sources
...
final ExecutionContext context = getExecutionContext();
- final PathFactory pathFactory = context.getValueFactories().getPathFactory();
CachePolicy cachePolicy = federatedWorkspace.getCachePolicy();
// If the location has no path, then we have to submit a request to ALL sources
...
@@ -720,9 +967,9 @@
}
protected void updateCache( FederatedWorkspace federatedWorkspace,
- FederatedNode mergedNode ) throws
RepositorySourceException {
+ FederatedNode mergedNode,
+ ReadNodeRequest fromCache ) throws
RepositorySourceException {
final ExecutionContext context = getExecutionContext();
- final RepositoryConnection cacheConnection =
getConnectionToCacheFor(federatedWorkspace);
final Location location = mergedNode.at();
final Path path = location.getPath();
final String cacheWorkspace =
federatedWorkspace.getCacheProjection().getWorkspaceName();
@@ -733,29 +980,126 @@
// If the merged node has a merge plan, then add it to the properties if it is
not already there ...
Map<Name, Property> properties = mergedNode.getPropertiesByName();
MergePlan mergePlan = mergedNode.getMergePlan();
- if (mergePlan != null) {
+ if (mergePlan != null && !properties.containsKey(DnaLexicon.MERGE_PLAN))
{
// Record the merge plan on the merged node ...
Property mergePlanProperty =
getExecutionContext().getPropertyFactory().create(DnaLexicon.MERGE_PLAN,
(Object)mergePlan);
properties.put(mergePlanProperty.getName(), mergePlanProperty);
}
- if (path.isRoot()) {
- // Set the properties ...
- requests.add(new UpdatePropertiesRequest(location, cacheWorkspace,
properties));
- } else {
- // This is not the root node, so we need to create the node ...
+ // Make sure the UUID is being stored ...
+ PropertyFactory propertyFactory = getExecutionContext().getPropertyFactory();
+ Property uuidProperty = properties.get(DnaLexicon.UUID);
+ if (uuidProperty == null) uuidProperty = properties.get(JcrLexicon.UUID);
+ if (uuidProperty == null) {
+ UUID uuid = mergedNode.at().getUuid();
+ if (uuid == null) uuid = UUID.randomUUID();
+ uuidProperty = propertyFactory.create(DnaLexicon.UUID, uuid);
+ properties.put(uuidProperty.getName(), uuidProperty);
+ }
+
+ // Have the children changed ...
+ if (mergedNode.hasError() && !path.isRoot()) {
+ // This is not the root node, so we need to create the node (or replace it if
it exists) ...
final Location parentLocation = Location.create(path.getParent());
childName = path.getLastSegment().getName();
requests.add(new CreateNodeRequest(parentLocation, cacheWorkspace, childName,
NodeConflictBehavior.REPLACE,
mergedNode.getProperties()));
+ // logger.trace("Adding {0} to cache with properties {1}",
location, properties);
+ // Now create all of the children that this federated node knows of ...
+ for (Location child : mergedNode.getChildren()) {
+ childName = child.getPath().getLastSegment().getName();
+ requests.add(new CreateNodeRequest(location, cacheWorkspace, childName,
NodeConflictBehavior.APPEND, child));
+ // logger.trace("Caching child of {0} named {1}", location,
childName);
+ }
+ } else if (fromCache.getChildren().equals(mergedNode.getChildren())) {
+ // Just update the properties ...
+ requests.add(new UpdatePropertiesRequest(location, cacheWorkspace,
properties));
+ // logger.trace("Updating cached properties on the root to {0}",
properties);
+ } else {
+ // The children have changed, so figure out how ...
+ if (fromCache.getChildren().isEmpty()) {
+ // No children in the cache, so just update the properties of the node
...
+ requests.add(new UpdatePropertiesRequest(location, cacheWorkspace,
properties));
+ // logger.trace("Updating cached properties on {0} to {1}",
location, properties);
+
+ // And create all of the children that this federated node knows of ...
+ for (Location child : mergedNode.getChildren()) {
+ childName = child.getPath().getLastSegment().getName();
+ requests.add(new CreateNodeRequest(location, cacheWorkspace,
childName, NodeConflictBehavior.APPEND, child));
+ // logger.trace("Caching child of {0} named {1}", location,
childName);
+ }
+ } else if (mergedNode.getChildren().isEmpty()) {
+ // There were children in the cache but not in the merged node, so update
the cached properties
+ requests.add(new UpdatePropertiesRequest(location, cacheWorkspace,
properties));
+
+ // and delete all the children ...
+ for (Location child : fromCache.getChildren()) {
+ requests.add(new DeleteBranchRequest(child, cacheWorkspace));
+ // logger.trace("Removing {0} from cache", child);
+ }
+ } else {
+ // There were children in the cache and in the merged node. The easy way
is to just remove the
+ // branch from the cache, the create it again ...
+ if (path.isRoot()) {
+ requests.add(new UpdatePropertiesRequest(location, cacheWorkspace,
properties));
+ // logger.trace("Updating cached properties on {0} to {1}",
location, properties);
+
+ // and delete all the children ...
+ for (Location child : fromCache.getChildren()) {
+ requests.add(new DeleteBranchRequest(child, cacheWorkspace));
+ // logger.trace("Removing child node {0} from cache",
child);
+ }
+
+ // Now create all of the children that this federated node knows of
...
+ for (Location child : mergedNode.getChildren()) {
+ childName = child.getPath().getLastSegment().getName();
+ requests.add(new CreateNodeRequest(location, cacheWorkspace,
childName, NodeConflictBehavior.APPEND,
+ child));
+ // logger.trace("Caching child of {0} named {1}",
location, childName);
+ }
+ } else {
+ requests.add(new DeleteBranchRequest(location, cacheWorkspace));
+ // logger.trace("Replacing node {0} from cache",
location);
+
+ // This is not the root node, so we need to create the node (or
replace it if it exists) ...
+ final Location parentLocation = Location.create(path.getParent());
+ childName = path.getLastSegment().getName();
+ requests.add(new CreateNodeRequest(parentLocation, cacheWorkspace,
childName, NodeConflictBehavior.REPLACE,
+ mergedNode.getProperties()));
+ // logger.trace("Adding {0} to cache with properties {1}",
location, properties);
+ // Now create all of the children that this federated node knows of
...
+ for (Location child : mergedNode.getChildren()) {
+ childName = child.getPath().getLastSegment().getName();
+ requests.add(new CreateNodeRequest(location, cacheWorkspace,
childName, NodeConflictBehavior.APPEND,
+ child));
+ // logger.trace("Caching child of {0} named {1}",
location, childName);
+ }
+ }
+ }
}
- // Now create all of the children that this federated node knows of ...
- for (Location child : mergedNode.getChildren()) {
- childName = child.getPath().getLastSegment().getName();
- requests.add(new CreateNodeRequest(location, cacheWorkspace, childName,
NodeConflictBehavior.APPEND));
+ // Execute all the requests ...
+ final RepositoryConnection cacheConnection =
getConnectionToCacheFor(federatedWorkspace);
+ cacheConnection.execute(context, CompositeRequest.with(requests));
+
+ // If the children did not have UUIDs, then find the actual locations for each of
the cached nodes ...
+ if (requests.size() > 1) {
+ Iterator<Request> requestIter = requests.iterator();
+ requestIter.next(); // Skip the first request, which creates/updates the node
(we want children)
+ List<Location> children = mergedNode.getChildren();
+ for (int i = 0; i != children.size(); ++i) {
+ Request request = requestIter.next();
+ while (!(request instanceof CreateNodeRequest)) { // skip non-create
requests
+ request = requestIter.next();
+ }
+ Location actual =
((CreateNodeRequest)request).getActualLocationOfNode();
+ Location child = children.get(i);
+ if (!child.hasIdProperties()) {
+ assert child.getPath().equals(actual.getPath());
+ children.set(i, actual);
+ }
+ }
}
- cacheConnection.execute(context, CompositeRequest.with(requests));
}
}
Modified:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederationI18n.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederationI18n.java 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederationI18n.java 2009-04-30
04:32:26 UTC (rev 866)
@@ -43,6 +43,11 @@
public static I18n unableToAuthenticateConnectionToFederatedRepository;
public static I18n repositoryHasBeenShutDown;
public static I18n errorAddingProjectionRuleParseMethod;
+ public static I18n pathInProjection;
+ public static I18n pathsInProjection;
+ public static I18n unableToPerformOperationUnlessLocationIsFromSingleProjection;
+ public static I18n unableToPerformOperationUnlessLocationsAreFromSingleProjection;
+ public static I18n unableToPerformOperationSpanningWorkspaces;
public static I18n workspaceDoesNotExist;
public static I18n noDefaultWorkspace;
Modified:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergePlan.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergePlan.java 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergePlan.java 2009-04-30
04:32:26 UTC (rev 866)
@@ -242,6 +242,21 @@
public abstract int getContributionCount();
/**
+ * Get the number of contributions that are not placeholders or empty.
+ *
+ * @return the number of real contributions
+ */
+ public int getRealContributionCount() {
+ int count = 0;
+ for (Contribution contribution : this) {
+ if (contribution.isPlaceholder()) continue;
+ if (contribution.isEmpty()) continue;
+ ++count;
+ }
+ return count;
+ }
+
+ /**
* Get the plan annotation property with the given name. Plan annotations are custom
properties that may be set by
* MergeProcessor implementations to store custom properties on the plan. This method
does nothing if the supplied name is
* null
Modified:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategy.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategy.java 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategy.java 2009-04-30
04:32:26 UTC (rev 866)
@@ -91,26 +91,32 @@
}
if (dnaUuidProperty != null) uuidProperty = dnaUuidProperty; // use
"dna:uuid" if there is one
- // Look for the UUID property on the properties, and update the federated node
...
- if (uuidProperty != null && !uuidProperty.isEmpty()) {
- UUID uuid =
context.getValueFactories().getUuidFactory().create(uuidProperty.getFirstValue());
- uuidProperty = context.getPropertyFactory().create(DnaLexicon.UUID, uuid); //
Use the "dna:uuid" name
-
federatedNode.setActualLocationOfNode(federatedNode.at().with(uuidProperty));
+ if (federatedNode.at().getUuid() != null) {
+ federatedNode.setActualLocationOfNode(federatedNode.at());
} else {
- // Make sure there's a UUID for an identification property ...
- if (location.getUuid() == null) {
- location = location.with(UUID.randomUUID());
+ // Look for the UUID property on the properties, and update the federated
node ...
+ if (uuidProperty != null && !uuidProperty.isEmpty()) {
+ UUID uuid =
context.getValueFactories().getUuidFactory().create(uuidProperty.getFirstValue());
+ uuidProperty = context.getPropertyFactory().create(DnaLexicon.UUID,
uuid); // Use the "dna:uuid" name
+
federatedNode.setActualLocationOfNode(federatedNode.at().with(uuidProperty));
+ } else {
+ // Make sure there's a UUID for an identification property ...
+ if (location.getUuid() == null) {
+ location = location.with(UUID.randomUUID());
+ }
+ // Set the UUID as a property (it wasn't set already) ...
+ uuidProperty = location.getIdProperty(DnaLexicon.UUID);
+ assert uuidProperty != null; // there should be one!
+ federatedNode.addProperty(uuidProperty);
+ federatedNode.setActualLocationOfNode(location);
}
- // Set the UUID as a property (it wasn't set already) ...
- uuidProperty = location.getIdProperty(DnaLexicon.UUID);
- assert uuidProperty != null; // there should be one!
- federatedNode.addProperty(uuidProperty);
- federatedNode.setActualLocationOfNode(location);
}
// Assign the merge plan ...
MergePlan mergePlan = MergePlan.create(contributions);
federatedNode.setMergePlan(mergePlan);
+ Property mergePlanProperty =
context.getPropertyFactory().create(DnaLexicon.MERGE_PLAN, (Object)mergePlan);
+ federatedNode.addProperty(mergePlanProperty);
}
private boolean hasUuidValue( ExecutionContext context,
Modified:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategy.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategy.java 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategy.java 2009-04-30
04:32:26 UTC (rev 866)
@@ -110,7 +110,7 @@
if (!childNames.containsKey(childName)) {
childNames.put(childName, 1);
Path pathToChild = pathFactory.create(location.getPath(),
childName);
- federatedNode.addChild(Location.create(pathToChild));
+ federatedNode.addChild(child.with(pathToChild));
}
}
} else {
@@ -140,7 +140,7 @@
index = previousValue;
}
Path pathToChild = pathFactory.create(location.getPath(), childName,
index);
- federatedNode.addChild(Location.create(pathToChild));
+ federatedNode.addChild(child.with(pathToChild)); // keep the same
identifiers
}
// Add in the properties ...
@@ -152,7 +152,7 @@
// Record the property ...
Property existing = properties.put(property.getName(), property);
- if (existing != null) {
+ if (existing != null && !existing.equals(property)) {
// There's already an existing property, so we need to merge
them ...
Property merged = merge(existing, property,
context.getPropertyFactory(), removeDuplicateProperties);
properties.put(property.getName(), merged);
@@ -181,6 +181,8 @@
// Assign the merge plan ...
MergePlan mergePlan = MergePlan.create(contributions);
federatedNode.setMergePlan(mergePlan);
+ Property mergePlanProperty =
context.getPropertyFactory().create(DnaLexicon.MERGE_PLAN, (Object)mergePlan);
+ properties.put(mergePlanProperty.getName(), mergePlanProperty);
}
/**
Modified:
trunk/extensions/dna-connector-federation/src/main/resources/org/jboss/dna/connector/federation/FederationI18n.properties
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/resources/org/jboss/dna/connector/federation/FederationI18n.properties 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/extensions/dna-connector-federation/src/main/resources/org/jboss/dna/connector/federation/FederationI18n.properties 2009-04-30
04:32:26 UTC (rev 866)
@@ -32,6 +32,11 @@
unableToAuthenticateConnectionToFederatedRepository = Unable to authenticate
"{1}" for federated repository "{0}"
repositoryHasBeenShutDown = The "{0}" federated repository has been shut down
and may no longer be used.
errorAddingProjectionRuleParseMethod = Error while adding a parsing method for a
federation projection rule
+pathInProjection = path "{0}" in projection {1}
+pathsInProjection = paths "{0}" in projection {1}
+unableToPerformOperationUnlessLocationIsFromSingleProjection = The node "{0}"
in workspace "{1}" must be within a single projection for this operation to
succeed, but is in {2}
+unableToPerformOperationUnlessLocationsAreFromSingleProjection = The nodes
"{0}" and "{1}" in workspace "{2}" must both be within a
single projection for this operation to succeed, but come from projections "{3}"
and "{4}"
+unableToPerformOperationSpanningWorkspaces = Unable to perform operation spanning
workspaces ("{0}" and "{1}")
workspaceDoesNotExist = The "{0}" federated repository does not have a
workspace named "{1}"
noDefaultWorkspace = The "{0}" federated repository does not have a default
workspace
\ No newline at end of file
Modified:
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatingRequestProcessorTest.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatingRequestProcessorTest.java 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatingRequestProcessorTest.java 2009-04-30
04:32:26 UTC (rev 866)
@@ -41,10 +41,6 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
-import org.jboss.dna.connector.federation.FederatedWorkspace;
-import org.jboss.dna.connector.federation.FederatingRequestProcessor;
-import org.jboss.dna.connector.federation.Projection;
-import org.jboss.dna.connector.federation.ProjectionParser;
import org.jboss.dna.connector.federation.contribution.Contribution;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
@@ -55,8 +51,19 @@
import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
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.graph.property.PathFactory;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.request.CopyBranchRequest;
+import org.jboss.dna.graph.request.CreateNodeRequest;
+import org.jboss.dna.graph.request.DeleteBranchRequest;
+import org.jboss.dna.graph.request.MoveBranchRequest;
+import org.jboss.dna.graph.request.ReadAllChildrenRequest;
+import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.request.ReadPropertyRequest;
+import org.jboss.dna.graph.request.UnsupportedRequestException;
+import org.jboss.dna.graph.request.UpdatePropertiesRequest;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockitoAnnotations;
@@ -93,6 +100,7 @@
cachePolicy = new BasicCachePolicy(219L, TimeUnit.SECONDS);
cacheSource = new InMemoryRepositorySource();
cacheSource.setName("Cache");
+ cacheSource.setDefaultWorkspaceName("cacheSpace");
ProjectionParser ruleParser = ProjectionParser.getInstance();
cacheProjectionRules = ruleParser.rulesFromStrings(context, "/ =>
/cache/repo/A");
cacheProjection = new Projection(cacheSource.getName(), "cacheSpace",
cacheProjectionRules);
@@ -128,6 +136,82 @@
doReturn(cacheSource.getConnection()).when(connectionFactory).createConnection(cacheSource.getName());
}
+ protected Name name( String name ) {
+ return context.getValueFactories().getNameFactory().create(name);
+ }
+
+ protected Path path( String path ) {
+ return pathFactory.create(path);
+ }
+
+ protected Path.Segment segment( String path ) {
+ return pathFactory.createSegment(path);
+ }
+
+ protected Property property( String name,
+ Object... values ) {
+ return context.getPropertyFactory().create(name(name), values);
+ }
+
+ protected Map<Name, Property> addProperty( Map<Name, Property>
properties,
+ String name,
+ Object... values ) {
+ Property property = property(name, values);
+ properties.put(property.getName(), property);
+ return properties;
+ }
+
+ protected void assertNodeHasChildren( String path,
+ String... expectedChildSegments ) {
+ Location parent = Location.create(path(path));
+ ReadAllChildrenRequest request = new ReadAllChildrenRequest(parent,
"fedSpace");
+ executor.process(request);
+ assertThat(request.hasError(), is(false));
+ assertThat(request.getActualLocationOfNode().getPath(), is(path(path)));
+ List<Location> actualChildLocations = request.getChildren();
+ Path.Segment[] actualChildren = new Path.Segment[actualChildLocations.size()];
+ for (int i = 0; i != actualChildren.length; ++i) {
+ Path actualChildPath = actualChildLocations.get(i).getPath();
+ actualChildren[i] = actualChildPath.getLastSegment();
+ assertThat(actualChildPath.getParent(), is(path(path)));
+ }
+ Path.Segment[] expectedChildren = new
Path.Segment[expectedChildSegments.length];
+ for (int i = 0; i != expectedChildren.length; ++i) {
+ expectedChildren[i] = segment(expectedChildSegments[i]);
+ }
+ assertThat(actualChildren, is(expectedChildren));
+ }
+
+ protected void assertNodeHasProperty( String path,
+ String propertyName,
+ Object... expectedValues ) {
+ Location parent = Location.create(path(path));
+ ReadPropertyRequest request = new ReadPropertyRequest(parent,
"fedSpace", name(propertyName));
+ executor.process(request);
+ assertThat(request.hasError(), is(false));
+ assertThat(request.getActualLocationOfNode().getPath(), is(path(path)));
+ Object[] actualValues = request.getProperty().getValuesAsArray();
+ String[] actualValuesAsStrings = new String[actualValues.length];
+ for (int i = 0; i != actualValues.length; ++i) {
+ actualValuesAsStrings[i] =
context.getValueFactories().getStringFactory().create(actualValues[i]);
+ }
+ String[] expectedValuesAsStrings = new String[expectedValues.length];
+ for (int i = 0; i != expectedValues.length; ++i) {
+ expectedValuesAsStrings[i] =
context.getValueFactories().getStringFactory().create(expectedValues[i]);
+ }
+ assertThat(actualValuesAsStrings, is(expectedValuesAsStrings));
+ }
+
+ protected void assertNodeHasNoProperty( String path,
+ String propertyName ) {
+ Location parent = Location.create(path(path));
+ ReadAllPropertiesRequest request = new ReadAllPropertiesRequest(parent,
"fedSpace");
+ executor.process(request);
+ assertThat(request.hasError(), is(false));
+ assertThat(request.getActualLocationOfNode().getPath(), is(path(path)));
+ assertThat(request.getPropertiesByName().containsKey(name(propertyName)),
is(false));
+ }
+
@Test( expected = IllegalArgumentException.class )
public void shouldFailWhenExecutionContextIsNull() {
context = null;
@@ -568,9 +652,203 @@
assertThat(contributions.get(2).isExpired(nowPlus310InUtc), is(true)); // expired
by cache @ 219
}
+ /**
+ * Set up the sources such that:
+ * <ul>
+ * <li>Source 1: "{@code /a => /source/one/a}", "{@code /b
=> /source/one/b}"</li>
+ * <li>Source 2: "{@code /a => /source/two/a}"</li>
+ * <li>Source 1: "{@code / => /}"</li>
+ * </ul>
+ */
+ protected void initializeSourcesWithContent() {
+ // Set up the content of source 1
+ Graph repository1 = Graph.create(source1, context);
+ repository1.createWorkspace().named("workspace1");
+ Graph.Batch batch = repository1.batch();
+ batch.create("/source").and();
+ batch.create("/source/one").and();
+ batch.create("/source/one/a").with("desc", "source 1
node a description").and();
+ batch.create("/source/one/a/nA").with("desc", "source 1
node nA description").and();
+ batch.create("/source/one/a/nB").with("desc", "source 1
node nB description").and();
+ batch.create("/source/one/a/nC").with("desc", "source 1
node nC description").and();
+ batch.create("/source/one/b").with("desc", "source 1
node b description").and();
+ batch.create("/source/one/b/pA").with("desc", "source 1
node pA description").and();
+ batch.create("/source/one/b/pB").with("desc", "source 1
node pB description").and();
+ batch.create("/source/one/b/pC").with("desc", "source 1
node pC description").and();
+ batch.execute();
+
+ // Set up the content of source 2
+ Graph repository2 = Graph.create(source2, context);
+ repository2.createWorkspace().named("workspace2");
+ batch = repository2.batch();
+ batch.create("/source").and();
+ batch.create("/source/two").and();
+ batch.create("/source/two/a").with("desc", "source 2
node a description").and();
+ batch.create("/source/two/a/qA").with("desc", "source 2
node qA description").and();
+ batch.create("/source/two/a/qB").with("desc", "source 2
node qB description").and();
+ batch.create("/source/two/a/qC").with("desc", "source 2
node qC description").and();
+ batch.execute();
+
+ // Set up the content of source 3
+ Graph repository3 = Graph.create(source3, context);
+ repository3.createWorkspace().named("workspace3");
+ batch = repository3.batch();
+ batch.create("/x").and();
+ batch.create("/x/y").with("desc", "y
description").and();
+ batch.create("/x/y/zA").with("desc", "zA
description").and();
+ batch.create("/x/y/zB").with("desc", "zB
description").and();
+ batch.create("/x/y/zC").with("desc", "zC
description").and();
+ batch.create("/b").and();
+ batch.create("/b/by").with("desc", "by
description").and();
+ batch.create("/b/by/bzA").with("desc", "bzA
description").and();
+ batch.create("/b/by/bzB").with("desc", "bzB
description").and();
+ batch.create("/a").and();
+ batch.create("/a/ay").with("desc", "ay
description").and();
+ batch.create("/a/ay/azA").with("desc", "azA
description").and();
+ batch.create("/a/ay/azB").with("desc", "azB
description").and();
+ batch.execute();
+
+ }
+
+ @Test( expected = UnsupportedRequestException.class )
+ public void shouldNotCreateNodeIfParentIsOutsideSingleProjection() throws Throwable
{
+ initializeSourcesWithContent();
+ Location parent = Location.create(path("/a")); // source 2 or 3?
+ CreateNodeRequest request = new CreateNodeRequest(parent, "fedSpace",
name("child"));
+ executor.process(request);
+ if (request.hasError()) throw request.getError();
+ }
+
@Test
- public void shouldGetNodeUsingPath() {
+ public void shouldCreateNodeOnlyIfParentIsInsideSingleProjection() throws Throwable
{
+ initializeSourcesWithContent();
+ Location parent = Location.create(path("/a/ay")); // source 3
+ CreateNodeRequest request = new CreateNodeRequest(parent, "fedSpace",
name("child"));
+ executor.process(request);
+ assertThat(request.hasError(), is(false));
+ assertThat(request.getActualLocationOfNode().getPath(),
is(path("/a/ay/child")));
+ assertNodeHasChildren("/a/ay", "azA", "azB",
"child");
+ }
+ @Test( expected = UnsupportedRequestException.class )
+ public void shouldNotDestroyNodeIfOutsideSingleProjection() throws Throwable {
+ initializeSourcesWithContent();
+ Location location = Location.create(path("/a")); // source 2 or 3?
+ DeleteBranchRequest request = new DeleteBranchRequest(location,
"fedSpace");
+ executor.process(request);
+ if (request.hasError()) throw request.getError();
}
+ @Test
+ public void shouldDestroyNodeOnlyIfInsideSingleProjection() throws Throwable {
+ initializeSourcesWithContent();
+ assertNodeHasChildren("/a", "nA", "nB",
"nC", "qA", "qB", "qC", "ay");
+ Location location = Location.create(path("/a/ay")); // source 3
+ DeleteBranchRequest request = new DeleteBranchRequest(location,
"fedSpace");
+ executor.process(request);
+ assertThat(request.hasError(), is(false));
+ assertThat(request.getActualLocationOfNode().getPath(),
is(path("/a/ay")));
+ assertNodeHasChildren("/a", "nA", "nB",
"nC", "qA", "qB", "qC");
+ }
+
+ @Test( expected = UnsupportedRequestException.class )
+ public void shouldNotUpdateNodeIfOutsideSingleProjection() throws Throwable {
+ initializeSourcesWithContent();
+ Location location = Location.create(path("/a")); // source 2 or 3?
+ Map<Name, Property> properties = new HashMap<Name, Property>();
+ addProperty(properties, "prop1", "value1");
+ addProperty(properties, "prop2", "value2a",
"value2b");
+ UpdatePropertiesRequest request = new UpdatePropertiesRequest(location,
"fedSpace", properties);
+ executor.process(request);
+ if (request.hasError()) throw request.getError();
+ }
+
+ @Test
+ public void shouldUpdateNodeOnlyIfInsideSingleProjection() throws Throwable {
+ initializeSourcesWithContent();
+ // assertNodeHasChildren("/a", "nA", "nB",
"nC", "qA", "qB", "qC", "ay");
+ assertNodeHasProperty("/a/ay", "desc", "ay
description");
+ assertNodeHasNoProperty("/a/ay", "prop1");
+ assertNodeHasNoProperty("/a/ay", "prop2");
+ Location location = Location.create(path("/a/ay")); // source 3
+ Map<Name, Property> properties = new HashMap<Name, Property>();
+ addProperty(properties, "desc", "ay description 2");
+ addProperty(properties, "prop1", "value1");
+ addProperty(properties, "prop2", "value2a",
"value2b");
+ UpdatePropertiesRequest request = new UpdatePropertiesRequest(location,
"fedSpace", properties);
+ executor.process(request);
+ assertThat(request.hasError(), is(false));
+ assertThat(request.getActualLocationOfNode().getPath(),
is(path("/a/ay")));
+ assertNodeHasProperty("/a/ay", "desc", "ay description
2");
+ assertNodeHasProperty("/a/ay", "prop1", "value1");
+ assertNodeHasProperty("/a/ay", "prop2", "value2a",
"value2b");
+ assertNodeHasChildren("/a", "nA", "nB",
"nC", "qA", "qB", "qC", "ay");
+ }
+
+ @Test( expected = UnsupportedRequestException.class )
+ public void shouldNotMoveNodeIfParentIsOutsideSingleProjection() throws Throwable {
+ initializeSourcesWithContent();
+ Location from = Location.create(path("/a/ay")); // source 3
+ Location into = Location.create(path("/b")); // source 1 or source 3?
+ assertNodeHasChildren("/a", "nA", "nB",
"nC", "qA", "qB", "qC", "ay");
+ assertNodeHasChildren("/b", "pA", "pB",
"pC", "by");
+ MoveBranchRequest request = new MoveBranchRequest(from, into,
"fedSpace");
+ executor.process(request);
+ if (request.hasError()) throw request.getError();
+ }
+
+ @Test
+ public void shouldMoveNodeOnlyIfParentIsInsideSingleProjection() throws Throwable {
+ initializeSourcesWithContent();
+ Location from = Location.create(path("/a/ay")); // source 3
+ Location into = Location.create(path("/b/by")); // source 3
+ assertNodeHasChildren("/a", "nA", "nB",
"nC", "qA", "qB", "qC", "ay");
+ assertNodeHasChildren("/b", "pA", "pB",
"pC", "by");
+ assertNodeHasChildren("/b/by", "bzA", "bzB");
+ MoveBranchRequest request = new MoveBranchRequest(from, into,
"fedSpace");
+ executor.process(request);
+ if (request.hasError()) {
+ System.out.println(request.getError().getMessage());
+ }
+ assertThat(request.hasError(), is(false));
+ assertThat(request.getActualLocationBefore().getPath(),
is(path("/a/ay")));
+ assertThat(request.getActualLocationAfter().getPath(),
is(path("/b/by/ay")));
+ assertNodeHasChildren("/a", "nA", "nB",
"nC", "qA", "qB", "qC");
+ assertNodeHasChildren("/b/by", "bzA", "bzB",
"ay");
+ }
+
+ @Test( expected = UnsupportedRequestException.class )
+ public void shouldNotCopyNodeIfParentIsOutsideSingleProjection() throws Throwable {
+ initializeSourcesWithContent();
+ Location from = Location.create(path("/a/ay")); // source 3
+ Location into = Location.create(path("/b")); // source 1 or source 3?
+ assertNodeHasChildren("/a", "nA", "nB",
"nC", "qA", "qB", "qC", "ay");
+ assertNodeHasChildren("/b", "pA", "pB",
"pC", "by");
+ CopyBranchRequest request = new CopyBranchRequest(from, "fedSpace",
into, "fedSpace");
+ executor.process(request);
+ if (request.hasError()) throw request.getError();
+ }
+
+ @Test
+ public void shouldCopyNodeOnlyIfParentIsInsideSingleProjection() throws Throwable {
+ initializeSourcesWithContent();
+ Location from = Location.create(path("/a/ay")); // source 3
+ Location into = Location.create(path("/b/by")); // source 3
+ assertNodeHasChildren("/a", "nA", "nB",
"nC", "qA", "qB", "qC", "ay");
+ assertNodeHasChildren("/a/ay", "azA", "azB");
+ assertNodeHasChildren("/b", "pA", "pB",
"pC", "by");
+ assertNodeHasChildren("/b/by", "bzA", "bzB");
+ CopyBranchRequest request = new CopyBranchRequest(from, "fedSpace",
into, "fedSpace");
+ executor.process(request);
+ if (request.hasError()) {
+ System.out.println(request.getError().getMessage());
+ }
+ assertThat(request.hasError(), is(false));
+ assertThat(request.getActualLocationBefore().getPath(),
is(path("/a/ay")));
+ assertThat(request.getActualLocationAfter().getPath(),
is(path("/b/by/ay")));
+ assertNodeHasChildren("/a", "nA", "nB",
"nC", "qA", "qB", "qC", "ay");
+ assertNodeHasChildren("/b/by", "bzA", "bzB",
"ay");
+ assertNodeHasChildren("/b/by/ay", "azA", "azB");
+ }
+
}
Modified:
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategyTest.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategyTest.java 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategyTest.java 2009-04-30
04:32:26 UTC (rev 866)
@@ -104,6 +104,7 @@
stub(contribution.getProperties()).toReturn(properties.values().iterator());
strategy.merge(node, contributions, context);
properties.put(DnaLexicon.UUID,
node.getPropertiesByName().get(DnaLexicon.UUID));
+ properties.put(DnaLexicon.MERGE_PLAN,
node.getPropertiesByName().get(DnaLexicon.MERGE_PLAN));
assertThat(node.getPropertiesByName(), is(properties));
}
Modified:
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategyTest.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategyTest.java 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategyTest.java 2009-04-30
04:32:26 UTC (rev 866)
@@ -88,8 +88,9 @@
public void shouldCombinePropertiesFromOneContribution() {
addContribution("source1").setProperty("p1", "p1
value");
strategy.merge(node, contributions, context);
- assertThat(node.getProperties().size(), is(2));
+ assertThat(node.getProperties().size(), is(3));
assertThat(node.getPropertiesByName().get(DnaLexicon.UUID), is(notNullValue()));
+ assertThat(node.getPropertiesByName().get(DnaLexicon.MERGE_PLAN),
is(notNullValue()));
assertThat(node.getPropertiesByName().get(name("p1")),
is(property("p1", "p1 value")));
}
@@ -122,8 +123,9 @@
addContribution("source1").setProperty("p1", "p1
value");
addContribution("source2").setProperty("p2", "p2
value");
strategy.merge(node, contributions, context);
- assertThat(node.getProperties().size(), is(3));
+ assertThat(node.getProperties().size(), is(4));
assertThat(node.getPropertiesByName().get(DnaLexicon.UUID), is(notNullValue()));
+ assertThat(node.getPropertiesByName().get(DnaLexicon.MERGE_PLAN),
is(notNullValue()));
assertThat(node.getPropertiesByName().get(name("p1")),
is(property("p1", "p1 value")));
assertThat(node.getPropertiesByName().get(name("p2")),
is(property("p2", "p2 value")));
}
@@ -133,8 +135,9 @@
addContribution("source1").setProperty("p1", "p1
value").setProperty("p12", "1", "2", "3");
addContribution("source2").setProperty("p2", "p2
value").setProperty("p12", "3", "4");
strategy.merge(node, contributions, context);
- assertThat(node.getProperties().size(), is(4));
+ assertThat(node.getProperties().size(), is(5));
assertThat(node.getPropertiesByName().get(DnaLexicon.UUID), is(notNullValue()));
+ assertThat(node.getPropertiesByName().get(DnaLexicon.MERGE_PLAN),
is(notNullValue()));
assertThat(node.getPropertiesByName().get(name("p1")),
is(property("p1", "p1 value")));
assertThat(node.getPropertiesByName().get(name("p2")),
is(property("p2", "p2 value")));
assertThat(node.getPropertiesByName().get(name("p12")),
is(property("p12", "1", "2", "3",
"4")));
@@ -145,7 +148,8 @@
addContribution("source1").setProperty("p1", "p1
value").setProperty("p12", "1", "2", "3");
addContribution("source2").setProperty("p2", "p2
value").setProperty("p12", "3", "4");
strategy.merge(node, contributions, context);
- assertThat(node.getProperties().size(), is(4));
+ assertThat(node.getProperties().size(), is(5));
+ assertThat(node.getPropertiesByName().get(DnaLexicon.MERGE_PLAN),
is(notNullValue()));
assertThat(node.getPropertiesByName().get(DnaLexicon.UUID), is(notNullValue()));
for (Contribution contribution : contributions) {
Iterator<Property> iter = contribution.getProperties();
@@ -173,8 +177,9 @@
addContribution("source1").setProperty("p1", "p1
value").setProperty("p12", "1", "2", "3");
addContribution("source2").setProperty("p2", "p2
value").setProperty("p12", 3, 4);
strategy.merge(node, contributions, context);
- assertThat(node.getProperties().size(), is(4));
+ assertThat(node.getProperties().size(), is(5));
assertThat(node.getPropertiesByName().get(DnaLexicon.UUID), is(notNullValue()));
+ assertThat(node.getPropertiesByName().get(DnaLexicon.MERGE_PLAN),
is(notNullValue()));
assertThat(node.getPropertiesByName().get(name("p1")),
is(property("p1", "p1 value")));
assertThat(node.getPropertiesByName().get(name("p2")),
is(property("p2", "p2 value")));
assertThat(node.getPropertiesByName().get(name("p12")),
is(property("p12", "1", "2", "3", 4)));
Modified: trunk/extensions/dna-connector-federation/src/test/resources/log4j.properties
===================================================================
---
trunk/extensions/dna-connector-federation/src/test/resources/log4j.properties 2009-04-29
14:31:49 UTC (rev 865)
+++
trunk/extensions/dna-connector-federation/src/test/resources/log4j.properties 2009-04-30
04:32:26 UTC (rev 866)
@@ -9,7 +9,7 @@
# Set up the default logging to be INFO level, then override specific units
log4j.logger.org.jboss.dna=INFO
-log4j.logger.org.jboss.dna.connector.federation.executor=INFO
+log4j.logger.org.jboss.dna.connector.federation=TRACE
# Jackrabbit logging
log4j.logger.org.apache.jackrabbit=WARN, stdout
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2009-04-29 14:31:49 UTC (rev 865)
+++ trunk/pom.xml 2009-04-30 04:32:26 UTC (rev 866)
@@ -135,7 +135,7 @@
<module>extensions/dna-common-jdbc</module>
<module>extensions/dna-connector-jdbc-metadata</module>
<module>dna-integration-tests</module>
- <!--module>docs/examples/gettingstarted</module-->
+ <module>docs/examples/gettingstarted</module>
</modules>
<profiles>