Author: rhauch
Date: 2008-09-17 18:56:29 -0400 (Wed, 17 Sep 2008)
New Revision: 531
Added:
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/contribution/PlaceholderContribution.java
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/MergeStrategy.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/test/java/org/jboss/dna/connector/federation/merge/strategy/
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
Removed:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergeStrategy.java
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/OneContributionMergeStrategy.java
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/SimpleMergeStrategy.java
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/OneContributionMergeStrategyTest.java
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/SimpleMergeStrategyTest.java
Modified:
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java
trunk/docs/examples/gettingstarted/repositories/src/test/java/org/jboss/example/dna/repository/RepositoryClientTest.java
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/Contribution.java
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java
Log:
DNA-222 - Create Getting Started example application for repositories
http://jira.jboss.com/jira/browse/DNA-222
More testing with several fixes. DNA-225 is still an issue.
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 2008-09-17
22:56:21 UTC (rev 530)
+++
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java 2008-09-17
22:56:29 UTC (rev 531)
@@ -32,6 +32,7 @@
import javax.jcr.NodeIterator;
import javax.jcr.PropertyIterator;
import javax.jcr.Session;
+import javax.jcr.Value;
import javax.naming.NamingException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
@@ -258,13 +259,26 @@
pathToNode = pathToNode.replaceAll("^/+", "");
// Get the node by path ...
Node root = session.getRootNode();
- Node node = root.getNode(pathToNode);
+ Node node = root;
+ if (pathToNode.length() != 0) {
+ if (!pathToNode.endsWith("]")) pathToNode = pathToNode
+ "[1]";
+ node = pathToNode.equals("") ? root :
root.getNode(pathToNode);
+ }
// Now populate the properties and children ...
if (properties != null) {
for (PropertyIterator iter = node.getProperties();
iter.hasNext();) {
javax.jcr.Property property = iter.nextProperty();
- Object[] values = property.getDefinition().isMultiple() ?
property.getValues() : new Object[] {property.getValue()};
+ Object[] values = null;
+ if (property.getDefinition().isMultiple()) {
+ Value[] jcrValues = property.getValues();
+ values = new String[jcrValues.length];
+ for (int i = 0; i < jcrValues.length; i++) {
+ values[i] = jcrValues[i].getString();
+ }
+ } else {
+ values = new Object[] {property.getValue().getString()};
+ }
properties.put(property.getName(), values);
}
}
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 2008-09-17
22:56:21 UTC (rev 530)
+++
trunk/docs/examples/gettingstarted/repositories/src/test/java/org/jboss/example/dna/repository/RepositoryClientTest.java 2008-09-17
22:56:29 UTC (rev 531)
@@ -32,7 +32,6 @@
import java.util.Map;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoAnnotations.Mock;
@@ -44,6 +43,7 @@
private RepositoryClient client;
private Map<String, Object[]> properties;
+ private Map<String, Object> uuids;
private List<String> children;
@Mock
private UserInterface userInterface;
@@ -51,6 +51,7 @@
@Before
public void beforeEach() {
MockitoAnnotations.initMocks(this);
+ uuids = new HashMap<String, Object>();
properties = new HashMap<String, Object[]>();
children = new ArrayList<String>();
client = new RepositoryClient();
@@ -74,6 +75,22 @@
assertThat(actualValues, is(values));
}
+ protected void getNodeInfo( String source,
+ String path ) throws Throwable {
+ properties.clear();
+ children.clear();
+ assertThat(client.getNodeInfo(source, path, properties, children), is(true));
+ // Record the UUID of the node ...
+ final Object uuid = properties.get("dna:uuid");
+ final String key = source + "\n" + path;
+ final Object existingUuid = uuids.get(key);
+ if (existingUuid != null) {
+ assertThat(uuid, is(existingUuid));
+ } else {
+ uuids.put(key, uuid);
+ }
+ }
+
@Test
public void shouldStartupWithoutError() throws Exception {
client.startRepositories();
@@ -89,23 +106,20 @@
@Test
public void shouldHaveContentFromConfigurationRepository() throws Throwable {
client.startRepositories();
- assertThat(client.getNodeInfo("Configuration", "/dna:system",
properties, children), is(true));
+
+ getNodeInfo("Configuration", "/dna:system");
assertThat(children, hasItems("dna:sources",
"dna:federatedRepositories"));
assertThat(properties.containsKey("jcr:primaryType"), is(true));
assertThat(properties.containsKey("dna:uuid"), is(true));
assertThat(properties.size(), is(2));
- properties.clear();
- children.clear();
- assertThat(client.getNodeInfo("Configuration",
"/dna:system/dna:sources", properties, children), is(true));
+ getNodeInfo("Configuration", "/dna:system/dna:sources");
assertThat(children, hasItems("SourceA", "SourceB",
"SourceC", "SourceD"));
assertThat(properties.containsKey("jcr:primaryType"), is(true));
assertThat(properties.containsKey("dna:uuid"), is(true));
assertThat(properties.size(), is(2));
- properties.clear();
- children.clear();
- assertThat(client.getNodeInfo("Configuration",
"/dna:system/dna:sources/SourceA", properties, children), is(true));
+ getNodeInfo("Configuration",
"/dna:system/dna:sources/SourceA");
assertThat(children.size(), is(0));
assertThat(properties.containsKey("jcr:primaryType"), is(true));
assertThat(properties.containsKey("dna:uuid"), is(true));
@@ -116,25 +130,22 @@
}
@Test
- public void shouldLoadCarsRepository() throws Throwable {
+ public void shouldHaveContentFromCarsRepository() throws Throwable {
client.startRepositories();
- assertThat(client.getNodeInfo("Cars", "/Cars", properties,
children), is(true));
+
+ 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));
- properties.clear();
- children.clear();
- assertThat(client.getNodeInfo("Cars", "/Cars/Hybrid",
properties, children), is(true));
+ 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));
- properties.clear();
- children.clear();
- assertThat(client.getNodeInfo("Cars", "/Cars/Sports/Aston Martin
DB9", properties, children), is(true));
+ 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));
@@ -153,17 +164,16 @@
}
@Test
- public void shouldLoadAircraftRepository() throws Throwable {
+ public void shouldHaveContentFromAircraftRepository() throws Throwable {
client.startRepositories();
- assertThat(client.getNodeInfo("Aircraft", "/Aircraft",
properties, children), is(true));
+
+ 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));
- properties.clear();
- children.clear();
- assertThat(client.getNodeInfo("Aircraft",
"/Aircraft/Commercial", properties, children), is(true));
+ getNodeInfo("Aircraft", "/Aircraft/Commercial");
assertThat(children, hasItems("Boeing 777",
"Boeing 767",
"Boeing 787",
@@ -176,9 +186,7 @@
assertThat(properties.containsKey("dna:uuid"), is(true));
assertThat(properties.size(), is(2));
- properties.clear();
- children.clear();
- assertThat(client.getNodeInfo("Aircraft",
"/Aircraft/Vintage/Wright Flyer", properties, children), is(true));
+ 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));
@@ -191,41 +199,32 @@
assertThat(properties.size(), is(8));
}
- @Ignore
@Test
- public void shouldLoadVehiclesRepository() throws Throwable {
+ public void shouldHaveContentFromVehiclesRepository() throws Throwable {
client.startRepositories();
- assertThat(client.getNodeInfo("Vehicles", "/", properties,
children), is(true));
+
+ getNodeInfo("Vehicles", "/");
assertThat(children, hasItems("Vehicles"));
assertThat(properties.containsKey("dna:uuid"), is(true));
assertThat(properties.size(), is(1));
- properties.clear();
- children.clear();
- assertThat(client.getNodeInfo("Vehicles", "/Vehicles",
properties, children), is(true));
+ getNodeInfo("Vehicles", "/Vehicles");
assertThat(children, hasItems("Cars", "Aircraft"));
- assertThat(properties.containsKey("jcr:primaryType"), is(false));
assertThat(properties.containsKey("dna:uuid"), is(true));
assertThat(properties.size(), is(1));
- properties.clear();
- children.clear();
- assertThat(client.getNodeInfo("Vehicles", "/", properties,
children), is(true));
+ getNodeInfo("Vehicles", "/");
assertThat(children, hasItems("Vehicles"));
assertThat(properties.containsKey("dna:uuid"), is(true));
assertThat(properties.size(), is(1));
- properties.clear();
- children.clear();
- assertThat(client.getNodeInfo("Vehicles",
"/Vehicles/Cars/Hybrid", properties, children), is(true));
+ 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));
- properties.clear();
- children.clear();
- assertThat(client.getNodeInfo("Vehicles",
"/Vehicles/Cars/Sports/Aston Martin DB9", properties, children), is(true));
+ 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));
@@ -242,9 +241,7 @@
assertProperty("engine", "5,935 cc 5.9 liters V 12");
assertThat(properties.size(), is(12));
- properties.clear();
- children.clear();
- assertThat(client.getNodeInfo("Vehicles",
"/Vehicles/Aircraft/Vintage/Wright Flyer", properties, children), is(true));
+ 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));
@@ -262,4 +259,14 @@
client.startRepositories();
assertThat(client.getNodeInfo("Cars", "/Cars/Sports/Non Existant
Car", properties, children), is(false));
}
+
+ @Test
+ public void shouldBeAbleToExecuteTestsRepeatedly() throws Throwable {
+ for (int i = 0; i != 10; ++i) {
+ shouldHaveContentFromConfigurationRepository();
+ shouldHaveContentFromCarsRepository();
+ shouldHaveContentFromAircraftRepository();
+ // shouldHaveContentFromVehiclesRepository();
+ }
+ }
}
Added:
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
(rev 0)
+++
trunk/docs/examples/gettingstarted/repositories/src/test/java/org/jboss/example/dna/repository/RepositoryClientUsingJcrTest.java 2008-09-17
22:56:29 UTC (rev 531)
@@ -0,0 +1,40 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.example.dna.repository;
+
+import org.jboss.example.dna.repository.RepositoryClient.Api;
+
+/**
+ * @author Randall Hauch
+ */
+public class RepositoryClientUsingJcrTest extends RepositoryClientTest {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.example.dna.repository.RepositoryClientTest#getApi()
+ */
+ @Override
+ protected Api getApi() {
+ return RepositoryClient.Api.JCR;
+ }
+}
Property changes on:
trunk/docs/examples/gettingstarted/repositories/src/test/java/org/jboss/example/dna/repository/RepositoryClientUsingJcrTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/Contribution.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/Contribution.java 2008-09-17
22:56:21 UTC (rev 530)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/Contribution.java 2008-09-17
22:56:29 UTC (rev 531)
@@ -23,6 +23,7 @@
import java.io.Serializable;
import java.util.Collection;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
@@ -179,6 +180,46 @@
}
/**
+ * Create a placeholder contribution of a single child from the named source.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ * @param pathInSource the path in the source for this contributed information; may
not be null
+ * @param expirationTime the time (in UTC) after which this contribution should be
considered expired, or null if there is no
+ * expiration time
+ * @param child the child from the source; may not be null or empty
+ * @return the contribution
+ */
+ public static Contribution createPlaceholder( String sourceName,
+ Path pathInSource,
+ DateTime expirationTime,
+ Segment child ) {
+ if (child == null) {
+ return new EmptyContribution(sourceName, expirationTime);
+ }
+ return new PlaceholderContribution(sourceName, pathInSource, expirationTime,
Collections.singletonList(child));
+ }
+
+ /**
+ * Create a placeholder contribution of the supplied properties and children from the
named source.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ * @param pathInSource the path in the source for this contributed information; may
not be null
+ * @param expirationTime the time (in UTC) after which this contribution should be
considered expired, or null if there is no
+ * expiration time
+ * @param children the children from the source; may not be null or empty
+ * @return the contribution
+ */
+ public static Contribution createPlaceholder( String sourceName,
+ Path pathInSource,
+ DateTime expirationTime,
+ List<Segment> children ) {
+ if (children == null || children.isEmpty()) {
+ return new EmptyContribution(sourceName, expirationTime);
+ }
+ return new PlaceholderContribution(sourceName, pathInSource, expirationTime,
children);
+ }
+
+ /**
* This is the first version of this class. See the documentation of
BasicMergePlan.serialVersionUID.
*/
private static final long serialVersionUID = 1L;
@@ -299,6 +340,16 @@
}
/**
+ * Determine whether this contribution is considered a placeholder necessary solely
because the same source has contributions
+ * at or below the children.
+ *
+ * @return true if a placeholder contribution, or false otherwise
+ */
+ public boolean isPlaceholder() {
+ return false;
+ }
+
+ /**
* {@inheritDoc}
* <p>
* This implementation returns the hash code of the {@link #getSourceName() source
name}, and is compatible with the
Added:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/PlaceholderContribution.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/PlaceholderContribution.java
(rev 0)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/PlaceholderContribution.java 2008-09-17
22:56:29 UTC (rev 531)
@@ -0,0 +1,67 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.connector.federation.contribution;
+
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.spi.graph.DateTime;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.Path.Segment;
+
+/**
+ * A placeholder contribution needed because of a source's contribution below the
specified children.
+ *
+ * @author Randall Hauch
+ */
+@Immutable
+public class PlaceholderContribution extends MultiChildContribution {
+
+ /**
+ * This is the first version of this class. See the documentation of
MergePlan.serialVersionUID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Create a contribution of children from the source with the supplied name.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ * @param pathInSource the path in the source for this contributed information; may
not be null
+ * @param expirationTime the time (in UTC) after which this contribution should be
considered expired, or null if there is no
+ * expiration time
+ * @param children the children from the source; may not be null or empty
+ */
+ public PlaceholderContribution( String sourceName,
+ Path pathInSource,
+ DateTime expirationTime,
+ Iterable<Segment> children ) {
+ super(sourceName, pathInSource, expirationTime, children);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#isPlaceholder()
+ */
+ @Override
+ public boolean isPlaceholder() {
+ return true;
+ }
+}
Property changes on:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/PlaceholderContribution.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java 2008-09-17
22:56:21 UTC (rev 530)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java 2008-09-17
22:56:29 UTC (rev 531)
@@ -40,9 +40,9 @@
import org.jboss.dna.connector.federation.contribution.Contribution;
import org.jboss.dna.connector.federation.merge.FederatedNode;
import org.jboss.dna.connector.federation.merge.MergePlan;
-import org.jboss.dna.connector.federation.merge.MergeStrategy;
-import org.jboss.dna.connector.federation.merge.OneContributionMergeStrategy;
-import org.jboss.dna.connector.federation.merge.SimpleMergeStrategy;
+import org.jboss.dna.connector.federation.merge.strategy.MergeStrategy;
+import org.jboss.dna.connector.federation.merge.strategy.OneContributionMergeStrategy;
+import org.jboss.dna.connector.federation.merge.strategy.SimpleMergeStrategy;
import org.jboss.dna.spi.DnaLexicon;
import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.cache.CachePolicy;
@@ -315,7 +315,7 @@
Path pathToLoad = path.getParent();
while (!pathToLoad.equals(lowestExistingAncestor)) {
loadContributionsFromSources(pathToLoad, null, contributions); //
sourceNames may be null or empty
- FederatedNode mergedNode = createFederatedNode(pathToLoad,
contributions, true);
+ FederatedNode mergedNode = createFederatedNode(null, pathToLoad,
contributions, true);
if (mergedNode == null) {
// No source had a contribution ...
I18n msg = FederationI18n.nodeDoesNotExistAtPath;
@@ -361,7 +361,7 @@
// Get the contributions from the sources given their names ...
loadContributionsFromSources(path, sourceNames, contributions); // sourceNames
may be null or empty
- FederatedNode mergedNode = createFederatedNode(path, contributions, true);
+ FederatedNode mergedNode = createFederatedNode(fromCache, path, contributions,
true);
if (mergedNode == null) {
// No source had a contribution ...
Path ancestor = path.getParent();
@@ -372,7 +372,8 @@
return mergedNode;
}
- protected FederatedNode createFederatedNode( Path path,
+ protected FederatedNode createFederatedNode( BasicGetNodeCommand fromCache,
+ Path path,
List<Contribution> contributions,
boolean updateCache ) throws
RepositorySourceException {
@@ -394,11 +395,21 @@
}
}
- // Merge the results into a single set of results ...
- FederatedNode mergedNode = new FederatedNode(path, UUID.randomUUID());
+ // Create the node, and use the existing UUID if one is found in the cache ...
ExecutionContext context = getExecutionContext();
- assert contributions.size() > 0;
assert context != null;
+ UUID uuid = null;
+ if (fromCache != null) {
+ Property uuidProperty =
fromCache.getPropertiesByName().get(DnaLexicon.UUID);
+ if (uuidProperty != null && !uuidProperty.isEmpty()) {
+ uuid =
context.getValueFactories().getUuidFactory().create(uuidProperty.getValues().next());
+ }
+ }
+ if (uuid == null) uuid = UUID.randomUUID();
+ FederatedNode mergedNode = new FederatedNode(path, uuid);
+
+ // Merge the results into a single set of results ...
+ assert contributions.size() > 0;
mergingStrategy.merge(mergedNode, contributions, context);
if (mergedNode.getCachePolicy() == null) {
mergedNode.setCachePolicy(defaultCachePolicy);
@@ -455,7 +466,7 @@
if (path.isAncestorOf(topLevelPath)) {
assert topLevelPath.size() > path.size();
Path.Segment child = topLevelPath.getSegment(path.size());
- contribution = Contribution.create(source, path,
expirationTime, null, child);
+ contribution = Contribution.createPlaceholder(source, path,
expirationTime, child);
}
break;
}
@@ -470,7 +481,7 @@
}
}
if (children.size() > 0) {
- contribution = Contribution.create(source, path,
expirationTime, null, children);
+ contribution = Contribution.createPlaceholder(source, path,
expirationTime, children);
}
}
}
@@ -549,37 +560,4 @@
}
cacheConnection.execute(context, intoCache);
}
-
- /**
- * Determine if the supplied plan is considered current
- *
- * @param path the path of the node at which (or below which) the merge plan applies
- * @param plan the merge plan
- * @return true if the merge plan is current, or false if it needs to be (at least
partially) rebuilt
- */
- protected boolean isCurrent( Path path,
- MergePlan plan ) {
- // First check the time ...
- DateTime now = getCurrentTimeInUtc();
- if (plan.isExpired(now)) return false;
-
- // Does the plan have any contributions from sources that don't exist ?
- for (Contribution contribution : plan) {
- if (!sourceNames.contains(contribution.getSourceName())) return false;
- }
- //
- // // Determine if any new source projections exists that aren't part of the
plan ...
- // for (String sourceName : sourceNames) {
- // if (plan.isSource(sourceName)) continue;
- // // The source is new ... see whether there are any regions that apply ...
- // // for (FederatedRegion region : this.regionsBySourceName.get(sourceName)) {
- // // // If the region's path is not at/above the path, the region
doesn't matter
- // // if (!region.appliesTo(path)) continue;
- // // // The region applies to the path ...
- // // return false;
- // // }
- // }
- return true;
- }
-
}
Deleted:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergeStrategy.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergeStrategy.java 2008-09-17
22:56:21 UTC (rev 530)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergeStrategy.java 2008-09-17
22:56:29 UTC (rev 531)
@@ -1,44 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
-package org.jboss.dna.connector.federation.merge;
-
-import java.util.List;
-import org.jboss.dna.connector.federation.contribution.Contribution;
-import org.jboss.dna.spi.ExecutionContext;
-
-/**
- * @author Randall Hauch
- */
-public interface MergeStrategy {
-
- /**
- * Merge the contributions into a single
- *
- * @param federatedNode the federated node into which the contributions are to be
merged; never null
- * @param contributions the contributions to the node; never null, never empty, and
never containing nulls
- * @param context the context in which this operation is to be performed; never null
- */
- public void merge( FederatedNode federatedNode,
- List<Contribution> contributions,
- ExecutionContext context );
-
-}
Deleted:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/OneContributionMergeStrategy.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/OneContributionMergeStrategy.java 2008-09-17
22:56:21 UTC (rev 530)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/OneContributionMergeStrategy.java 2008-09-17
22:56:29 UTC (rev 531)
@@ -1,118 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
-package org.jboss.dna.connector.federation.merge;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.connector.federation.contribution.Contribution;
-import org.jboss.dna.spi.ExecutionContext;
-import org.jboss.dna.spi.graph.Name;
-import org.jboss.dna.spi.graph.Property;
-import org.jboss.dna.spi.graph.UuidFactory;
-import org.jboss.dna.spi.graph.ValueFormatException;
-import org.jboss.dna.spi.graph.Path.Segment;
-
-/**
- * A merge strategy that is optimized for merging when there is a single contribution.
- *
- * @author Randall Hauch
- */
-@ThreadSafe
-public class OneContributionMergeStrategy implements MergeStrategy {
-
- public static final boolean DEFAULT_REUSE_UUID_FROM_CONTRIBUTION = true;
-
- private boolean useUuidFromContribution = DEFAULT_REUSE_UUID_FROM_CONTRIBUTION;
-
- /**
- * @return reuseUuidFromContribution
- */
- public boolean isContributionUuidUsedForFederatedNode() {
- return useUuidFromContribution;
- }
-
- /**
- * @param useUuidFromContribution Sets useUuidFromContribution to the specified
value.
- */
- public void setContributionUuidUsedForFederatedNode( boolean useUuidFromContribution
) {
- this.useUuidFromContribution = useUuidFromContribution;
- }
-
- /**
- * {@inheritDoc}
- * <p>
- * This method only uses the one and only one non-null {@link Contribution} in the
<code>contributions</code>.
- * </p>
- *
- * @see
org.jboss.dna.connector.federation.merge.MergeStrategy#merge(org.jboss.dna.connector.federation.merge.FederatedNode,
- * java.util.List, org.jboss.dna.spi.ExecutionContext)
- */
- public void merge( FederatedNode federatedNode,
- List<Contribution> contributions,
- ExecutionContext context ) {
- assert federatedNode != null;
- assert context != null;
- assert contributions != null;
- assert contributions.size() > 0;
- Contribution contribution = contributions.get(0);
- assert contribution != null;
- final boolean findUuid = isContributionUuidUsedForFederatedNode();
- // Copy the children ...
- List<Segment> children = federatedNode.getChildren();
- children.clear();
- Iterator<Segment> childIterator = contribution.getChildren();
- while (childIterator.hasNext()) {
- Segment child = childIterator.next();
- children.add(child);
- }
- // Copy the properties ...
- Map<Name, Property> properties = federatedNode.getPropertiesByName();
- properties.clear();
- UUID uuid = null;
- UuidFactory uuidFactory = null;
- Iterator<Property> propertyIterator = contribution.getProperties();
- while (propertyIterator.hasNext()) {
- Property property = propertyIterator.next();
- properties.put(property.getName(), property);
- if (findUuid && uuid == null &&
property.getName().getLocalName().equals("uuid") && property.isSingle())
{
- if (uuidFactory == null) uuidFactory =
context.getValueFactories().getUuidFactory();
- try {
- uuid = uuidFactory.create(property.getValues().next());
- } catch (ValueFormatException e) {
- // Ignore conversion exceptions
- }
- }
- }
- // If we found a single "uuid" property whose value is a valid UUID ..
- if (uuid != null) {
- // then set the UUID on the federated node ...
- federatedNode.setUuid(uuid);
- }
- // Assign the merge plan ...
- MergePlan mergePlan = MergePlan.create(contributions);
- federatedNode.setMergePlan(mergePlan);
- }
-
-}
Deleted:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/SimpleMergeStrategy.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/SimpleMergeStrategy.java 2008-09-17
22:56:21 UTC (rev 530)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/SimpleMergeStrategy.java 2008-09-17
22:56:29 UTC (rev 531)
@@ -1,275 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
-package org.jboss.dna.connector.federation.merge;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.UUID;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.connector.federation.contribution.Contribution;
-import org.jboss.dna.spi.ExecutionContext;
-import org.jboss.dna.spi.graph.IoException;
-import org.jboss.dna.spi.graph.Name;
-import org.jboss.dna.spi.graph.Path;
-import org.jboss.dna.spi.graph.PathFactory;
-import org.jboss.dna.spi.graph.Property;
-import org.jboss.dna.spi.graph.PropertyFactory;
-import org.jboss.dna.spi.graph.UuidFactory;
-import org.jboss.dna.spi.graph.ValueComparators;
-import org.jboss.dna.spi.graph.Path.Segment;
-
-/**
- * This merge strategy simply merges all of the contributions' properties and
combines the children according to the order of the
- * contributions. No children are merged, and all properties are used (except if they are
deemed to be duplicates of the property
- * in other contributions).
- *
- * @author Randall Hauch
- */
-@ThreadSafe
-public class SimpleMergeStrategy implements MergeStrategy {
-
- private boolean removeDuplicateProperties = true;
-
- /**
- * @return removeDuplicateProperties
- */
- public boolean isRemoveDuplicateProperties() {
- return removeDuplicateProperties;
- }
-
- /**
- * @param removeDuplicateProperties Sets removeDuplicateProperties to the specified
value.
- */
- public void setRemoveDuplicateProperties( boolean removeDuplicateProperties ) {
- this.removeDuplicateProperties = removeDuplicateProperties;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.connector.federation.merge.MergeStrategy#merge(org.jboss.dna.connector.federation.merge.FederatedNode,
- * java.util.List, org.jboss.dna.spi.ExecutionContext)
- */
- public void merge( FederatedNode federatedNode,
- List<Contribution> contributions,
- ExecutionContext context ) {
- assert federatedNode != null;
- assert context != null;
- assert contributions != null;
- assert contributions.size() > 0;
- PathFactory pathFactory = context.getValueFactories().getPathFactory();
- // Prepare the federated node ...
- List<Segment> children = federatedNode.getChildren();
- children.clear();
- Map<Name, Integer> childNames = new HashMap<Name, Integer>();
- Map<Name, Property> properties = federatedNode.getPropertiesByName();
- properties.clear();
- UUID uuid = null;
- UuidFactory uuidFactory = null;
- final boolean removeDuplicateProperties = isRemoveDuplicateProperties();
- // Iterate over the set of contributions (in order) ...
- for (Contribution contribution : contributions) {
- // Copy the children ...
- int childListIndex = 0;
- Iterator<Segment> childIterator = contribution.getChildren();
- while (childIterator.hasNext()) {
- Segment child = childIterator.next();
- int index = Path.NO_INDEX;
- Integer previous = childNames.put(child.getName(), 1);
- if (previous != null) {
- int previousValue = previous.intValue();
- if (previousValue == 1) {
- // If the previous value was 1, then go back and look for the
child that has no index but that should ...
- // Walk backwards, just in case the previous same-name-sibling is
closer to the end
- for (int i = children.size() - 1; i >= 0; --i) {
- Path.Segment childSegment = children.get(i);
- if (childSegment.getName().equals(child.getName())) {
- children.set(i,
pathFactory.createSegment(child.getName(), 1));
- break;
- }
- }
- }
- // Add the previous value back in ...
- childNames.put(child.getName(), ++previousValue);
- index = previousValue;
- }
- children.add(pathFactory.createSegment(child.getName(), index));
- ++childListIndex;
- }
-
- // Copy the properties ...
- Iterator<Property> propertyIterator = contribution.getProperties();
- while (propertyIterator.hasNext()) {
- Property property = propertyIterator.next();
- Property existing = properties.put(property.getName(), property);
- if (existing != null) {
- // 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);
- }
-
- if (uuid == null &&
property.getName().getLocalName().equals("uuid") && property.isSingle())
{
- if (uuidFactory == null) uuidFactory =
context.getValueFactories().getUuidFactory();
- try {
- uuid = uuidFactory.create(property.getValues().next());
- } catch (IoException e) {
- // Ignore conversion exceptions
- assert uuid == null;
- }
- }
- }
- }
- // If we found a single "uuid" property whose value is a valid UUID ..
- if (uuid != null) {
- // then set the UUID on the federated node ...
- federatedNode.setUuid(uuid);
- }
- // Assign the merge plan ...
- MergePlan mergePlan = MergePlan.create(contributions);
- federatedNode.setMergePlan(mergePlan);
- }
-
- /**
- * Merge the values from the two properties with the same name, returning a new
property with the newly merged values.
- * <p>
- * The current algorithm merges the values by concatenating the values from
<code>property1</code> and <code>property2</code>,
- * and if <code>removeDuplicates</code> is true any values in
<code>property2</code> that are identical to values found in
- * <code>property1</code> are skipped.
- * </p>
- *
- * @param property1 the first property; may not be null, and must have the same
{@link Property#getName() name} as
- * <code>property2</code>
- * @param property2 the second property; may not be null, and must have the same
{@link Property#getName() name} as
- * <code>property1</code>
- * @param factory the property factory, used to create the result
- * @param removeDuplicates true if this method removes any values in the second
property that duplicate values found in the
- * first property.
- * @return the property that contains the same {@link Property#getName() name} as the
input properties, but with values that
- * are merged from both of the input properties
- */
- protected Property merge( Property property1,
- Property property2,
- PropertyFactory factory,
- boolean removeDuplicates ) {
- assert property1 != null;
- assert property2 != null;
- assert property1.getName().equals(property2.getName());
- if (property1.isEmpty()) return property2;
- if (property2.isEmpty()) return property1;
-
- // If they are both single-valued, then we can use a more efficient algorithm
...
- if (property1.isSingle() && property2.isSingle()) {
- Object value1 = property1.getValues().next();
- Object value2 = property2.getValues().next();
- if (removeDuplicates &&
ValueComparators.OBJECT_COMPARATOR.compare(value1, value2) == 0) return property1;
- return factory.create(property1.getName(), new Object[] {value1, value2});
- }
-
- // One or both properties are multi-valued, so use an algorithm that works with
in all cases ...
- if (!removeDuplicates) {
- Iterator<?> valueIterator = new DualIterator(property1.getValues(),
property2.getValues());
- return factory.create(property1.getName(), valueIterator);
- }
-
- // First copy all the values from property 1 ...
- Object[] values = new Object[property1.size() + property2.size()];
- int index = 0;
- for (Object property1Value : property1) {
- values[index++] = property1Value;
- }
- assert index == property1.size();
- // Now add any values of property2 that don't match a value in property1 ...
- for (Object property2Value : property2) {
- // Brute force, go through the values of property1 and compare ...
- boolean matched = false;
- for (Object property1Value : property1) {
- if (ValueComparators.OBJECT_COMPARATOR.compare(property1Value,
property2Value) == 0) {
- // The values are the same ...
- matched = true;
- break;
- }
- }
- if (!matched) values[index++] = property2Value;
- }
- if (index != values.length) {
- Object[] newValues = new Object[index];
- System.arraycopy(values, 0, newValues, 0, index);
- values = newValues;
- }
- return factory.create(property1.getName(), values);
- }
-
- protected static class DualIterator implements Iterator<Object> {
-
- private final Iterator<?>[] iterators;
- private Iterator<?> current;
- private int index = 0;
-
- protected DualIterator( Iterator<?>... iterators ) {
- assert iterators != null;
- assert iterators.length > 0;
- this.iterators = iterators;
- this.current = this.iterators[0];
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.util.Iterator#hasNext()
- */
- public boolean hasNext() {
- if (this.current != null) return this.current.hasNext();
- return false;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.util.Iterator#next()
- */
- public Object next() {
- while (this.current != null) {
- if (this.current.hasNext()) return this.current.next();
- // Get the next iterator ...
- if (++this.index < iterators.length) {
- this.current = this.iterators[this.index];
- } else {
- this.current = null;
- }
- }
- throw new NoSuchElementException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.util.Iterator#remove()
- */
- public void remove() {
- throw new UnsupportedOperationException();
- }
-
- }
-}
Copied:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/MergeStrategy.java
(from rev 522,
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergeStrategy.java)
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/MergeStrategy.java
(rev 0)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/MergeStrategy.java 2008-09-17
22:56:29 UTC (rev 531)
@@ -0,0 +1,45 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.connector.federation.merge.strategy;
+
+import java.util.List;
+import org.jboss.dna.connector.federation.contribution.Contribution;
+import org.jboss.dna.connector.federation.merge.FederatedNode;
+import org.jboss.dna.spi.ExecutionContext;
+
+/**
+ * @author Randall Hauch
+ */
+public interface MergeStrategy {
+
+ /**
+ * Merge the contributions into a single
+ *
+ * @param federatedNode the federated node into which the contributions are to be
merged; never null
+ * @param contributions the contributions to the node; never null, never empty, and
never containing nulls
+ * @param context the context in which this operation is to be performed; never null
+ */
+ public void merge( FederatedNode federatedNode,
+ List<Contribution> contributions,
+ ExecutionContext context );
+
+}
Property changes on:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/MergeStrategy.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Copied:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategy.java
(from rev 522,
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/OneContributionMergeStrategy.java)
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategy.java
(rev 0)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategy.java 2008-09-17
22:56:29 UTC (rev 531)
@@ -0,0 +1,128 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.connector.federation.merge.strategy;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.connector.federation.contribution.Contribution;
+import org.jboss.dna.connector.federation.merge.FederatedNode;
+import org.jboss.dna.connector.federation.merge.MergePlan;
+import org.jboss.dna.spi.DnaLexicon;
+import org.jboss.dna.spi.ExecutionContext;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Property;
+import org.jboss.dna.spi.graph.UuidFactory;
+import org.jboss.dna.spi.graph.ValueFormatException;
+import org.jboss.dna.spi.graph.Path.Segment;
+
+/**
+ * A merge strategy that is optimized for merging when there is a single contribution.
+ *
+ * @author Randall Hauch
+ */
+@ThreadSafe
+public class OneContributionMergeStrategy implements MergeStrategy {
+
+ public static final boolean DEFAULT_REUSE_UUID_FROM_CONTRIBUTION = true;
+
+ private boolean useUuidFromContribution = DEFAULT_REUSE_UUID_FROM_CONTRIBUTION;
+
+ /**
+ * @return reuseUuidFromContribution
+ */
+ public boolean isContributionUuidUsedForFederatedNode() {
+ return useUuidFromContribution;
+ }
+
+ /**
+ * @param useUuidFromContribution Sets useUuidFromContribution to the specified
value.
+ */
+ public void setContributionUuidUsedForFederatedNode( boolean useUuidFromContribution
) {
+ this.useUuidFromContribution = useUuidFromContribution;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This method only uses the one and only one non-null {@link Contribution} in the
<code>contributions</code>.
+ * </p>
+ *
+ * @see
org.jboss.dna.connector.federation.merge.strategy.MergeStrategy#merge(org.jboss.dna.connector.federation.merge.FederatedNode,
+ * java.util.List, org.jboss.dna.spi.ExecutionContext)
+ */
+ public void merge( FederatedNode federatedNode,
+ List<Contribution> contributions,
+ ExecutionContext context ) {
+ assert federatedNode != null;
+ assert context != null;
+ assert contributions != null;
+ assert contributions.size() > 0;
+ Contribution contribution = contributions.get(0);
+ assert contribution != null;
+ final boolean findUuid = isContributionUuidUsedForFederatedNode();
+ // Copy the children ...
+ List<Segment> children = federatedNode.getChildren();
+ children.clear();
+ Iterator<Segment> childIterator = contribution.getChildren();
+ while (childIterator.hasNext()) {
+ Segment child = childIterator.next();
+ children.add(child);
+ }
+ // Copy the properties ...
+ Map<Name, Property> properties = federatedNode.getPropertiesByName();
+ properties.clear();
+ UUID uuid = null;
+ UuidFactory uuidFactory = null;
+ Iterator<Property> propertyIterator = contribution.getProperties();
+ while (propertyIterator.hasNext()) {
+ Property property = propertyIterator.next();
+ if (findUuid && uuid == null &&
property.getName().getLocalName().equals("uuid")) {
+ if (property.isSingle()) {
+ if (uuidFactory == null) uuidFactory =
context.getValueFactories().getUuidFactory();
+ try {
+ uuid = uuidFactory.create(property.getValues().next());
+ } catch (ValueFormatException e) {
+ // Ignore conversion exceptions
+ }
+ }
+ } else {
+ properties.put(property.getName(), property);
+ }
+ }
+ // If we found a single "uuid" property whose value is a valid UUID ..
+ if (uuid != null) {
+ // then set the UUID on the federated node ...
+ federatedNode.setUuid(uuid);
+ }
+ // Set the UUID as a property ...
+ Property uuidProperty = context.getPropertyFactory().create(DnaLexicon.UUID,
federatedNode.getUuid());
+ properties.put(uuidProperty.getName(), uuidProperty);
+
+ // Assign the merge plan ...
+ MergePlan mergePlan = MergePlan.create(contributions);
+ federatedNode.setMergePlan(mergePlan);
+ }
+
+}
Property changes on:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategy.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Copied:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategy.java
(from rev 522,
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/SimpleMergeStrategy.java)
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategy.java
(rev 0)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategy.java 2008-09-17
22:56:29 UTC (rev 531)
@@ -0,0 +1,285 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.connector.federation.merge.strategy;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.UUID;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.connector.federation.contribution.Contribution;
+import org.jboss.dna.connector.federation.merge.FederatedNode;
+import org.jboss.dna.connector.federation.merge.MergePlan;
+import org.jboss.dna.spi.DnaLexicon;
+import org.jboss.dna.spi.ExecutionContext;
+import org.jboss.dna.spi.graph.IoException;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.PathFactory;
+import org.jboss.dna.spi.graph.Property;
+import org.jboss.dna.spi.graph.PropertyFactory;
+import org.jboss.dna.spi.graph.UuidFactory;
+import org.jboss.dna.spi.graph.ValueComparators;
+import org.jboss.dna.spi.graph.Path.Segment;
+
+/**
+ * This merge strategy simply merges all of the contributions' properties and
combines the children according to the order of the
+ * contributions. No children are merged, and all properties are used (except if they are
deemed to be duplicates of the property
+ * in other contributions).
+ *
+ * @author Randall Hauch
+ */
+@ThreadSafe
+public class SimpleMergeStrategy implements MergeStrategy {
+
+ private boolean removeDuplicateProperties = true;
+
+ /**
+ * @return removeDuplicateProperties
+ */
+ public boolean isRemoveDuplicateProperties() {
+ return removeDuplicateProperties;
+ }
+
+ /**
+ * @param removeDuplicateProperties Sets removeDuplicateProperties to the specified
value.
+ */
+ public void setRemoveDuplicateProperties( boolean removeDuplicateProperties ) {
+ this.removeDuplicateProperties = removeDuplicateProperties;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.connector.federation.merge.strategy.MergeStrategy#merge(org.jboss.dna.connector.federation.merge.FederatedNode,
+ * java.util.List, org.jboss.dna.spi.ExecutionContext)
+ */
+ public void merge( FederatedNode federatedNode,
+ List<Contribution> contributions,
+ ExecutionContext context ) {
+ assert federatedNode != null;
+ assert context != null;
+ assert contributions != null;
+ assert contributions.size() > 0;
+ PathFactory pathFactory = context.getValueFactories().getPathFactory();
+ // Prepare the federated node ...
+ List<Segment> children = federatedNode.getChildren();
+ children.clear();
+ Map<Name, Integer> childNames = new HashMap<Name, Integer>();
+ Map<Name, Property> properties = federatedNode.getPropertiesByName();
+ properties.clear();
+ UUID uuid = null;
+ UuidFactory uuidFactory = null;
+ final boolean removeDuplicateProperties = isRemoveDuplicateProperties();
+ // Iterate over the set of contributions (in order) ...
+ for (Contribution contribution : contributions) {
+ // If the contribution is a placeholder contribution, then the children
should be merged into other children ...
+ if (contribution.isPlaceholder()) {
+ // Iterate over the children and add only if there is not already one
...
+ Iterator<Segment> childIterator = contribution.getChildren();
+ while (childIterator.hasNext()) {
+ Segment child = childIterator.next();
+ if (!childNames.containsKey(child)) {
+ childNames.put(child.getName(), 1);
+ children.add(pathFactory.createSegment(child.getName()));
+ }
+ }
+
+ } else {
+ // Copy the children ...
+ Iterator<Segment> childIterator = contribution.getChildren();
+ while (childIterator.hasNext()) {
+ Segment child = childIterator.next();
+ int index = Path.NO_INDEX;
+ Integer previous = childNames.put(child.getName(), 1);
+ if (previous != null) {
+ int previousValue = previous.intValue();
+ // Correct the index in the child name map ...
+ childNames.put(child.getName(), ++previousValue);
+ index = previousValue;
+ }
+ children.add(pathFactory.createSegment(child.getName(), index));
+ }
+
+ // Copy the properties ...
+ Iterator<Property> propertyIterator =
contribution.getProperties();
+ while (propertyIterator.hasNext()) {
+ Property property = propertyIterator.next();
+ // Skip the "uuid" property on all root nodes ...
+ if (federatedNode.getPath().isRoot() &&
property.getName().getLocalName().equals("uuid")) continue;
+ Property existing = properties.put(property.getName(), property);
+ if (existing != null) {
+ // 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);
+ }
+
+ if (uuid == null &&
property.getName().getLocalName().equals("uuid") && property.isSingle())
{
+ if (uuidFactory == null) uuidFactory =
context.getValueFactories().getUuidFactory();
+ try {
+ uuid = uuidFactory.create(property.getValues().next());
+ } catch (IoException e) {
+ // Ignore conversion exceptions
+ assert uuid == null;
+ }
+ }
+ }
+ }
+ }
+ // If we found a single "uuid" property whose value is a valid UUID ..
+ if (uuid != null) {
+ // then set the UUID on the federated node ...
+ federatedNode.setUuid(uuid);
+ }
+ // Set the UUID as a property ...
+ Property uuidProperty = context.getPropertyFactory().create(DnaLexicon.UUID,
federatedNode.getUuid());
+ properties.put(uuidProperty.getName(), uuidProperty);
+
+ // Assign the merge plan ...
+ MergePlan mergePlan = MergePlan.create(contributions);
+ federatedNode.setMergePlan(mergePlan);
+ }
+
+ /**
+ * Merge the values from the two properties with the same name, returning a new
property with the newly merged values.
+ * <p>
+ * The current algorithm merges the values by concatenating the values from
<code>property1</code> and <code>property2</code>,
+ * and if <code>removeDuplicates</code> is true any values in
<code>property2</code> that are identical to values found in
+ * <code>property1</code> are skipped.
+ * </p>
+ *
+ * @param property1 the first property; may not be null, and must have the same
{@link Property#getName() name} as
+ * <code>property2</code>
+ * @param property2 the second property; may not be null, and must have the same
{@link Property#getName() name} as
+ * <code>property1</code>
+ * @param factory the property factory, used to create the result
+ * @param removeDuplicates true if this method removes any values in the second
property that duplicate values found in the
+ * first property.
+ * @return the property that contains the same {@link Property#getName() name} as the
input properties, but with values that
+ * are merged from both of the input properties
+ */
+ protected Property merge( Property property1,
+ Property property2,
+ PropertyFactory factory,
+ boolean removeDuplicates ) {
+ assert property1 != null;
+ assert property2 != null;
+ assert property1.getName().equals(property2.getName());
+ if (property1.isEmpty()) return property2;
+ if (property2.isEmpty()) return property1;
+
+ // If they are both single-valued, then we can use a more efficient algorithm
...
+ if (property1.isSingle() && property2.isSingle()) {
+ Object value1 = property1.getValues().next();
+ Object value2 = property2.getValues().next();
+ if (removeDuplicates &&
ValueComparators.OBJECT_COMPARATOR.compare(value1, value2) == 0) return property1;
+ return factory.create(property1.getName(), new Object[] {value1, value2});
+ }
+
+ // One or both properties are multi-valued, so use an algorithm that works with
in all cases ...
+ if (!removeDuplicates) {
+ Iterator<?> valueIterator = new DualIterator(property1.getValues(),
property2.getValues());
+ return factory.create(property1.getName(), valueIterator);
+ }
+
+ // First copy all the values from property 1 ...
+ Object[] values = new Object[property1.size() + property2.size()];
+ int index = 0;
+ for (Object property1Value : property1) {
+ values[index++] = property1Value;
+ }
+ assert index == property1.size();
+ // Now add any values of property2 that don't match a value in property1 ...
+ for (Object property2Value : property2) {
+ // Brute force, go through the values of property1 and compare ...
+ boolean matched = false;
+ for (Object property1Value : property1) {
+ if (ValueComparators.OBJECT_COMPARATOR.compare(property1Value,
property2Value) == 0) {
+ // The values are the same ...
+ matched = true;
+ break;
+ }
+ }
+ if (!matched) values[index++] = property2Value;
+ }
+ if (index != values.length) {
+ Object[] newValues = new Object[index];
+ System.arraycopy(values, 0, newValues, 0, index);
+ values = newValues;
+ }
+ return factory.create(property1.getName(), values);
+ }
+
+ protected static class DualIterator implements Iterator<Object> {
+
+ private final Iterator<?>[] iterators;
+ private Iterator<?> current;
+ private int index = 0;
+
+ protected DualIterator( Iterator<?>... iterators ) {
+ assert iterators != null;
+ assert iterators.length > 0;
+ this.iterators = iterators;
+ this.current = this.iterators[0];
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Iterator#hasNext()
+ */
+ public boolean hasNext() {
+ if (this.current != null) return this.current.hasNext();
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Iterator#next()
+ */
+ public Object next() {
+ while (this.current != null) {
+ if (this.current.hasNext()) return this.current.next();
+ // Get the next iterator ...
+ if (++this.index < iterators.length) {
+ this.current = this.iterators[this.index];
+ } else {
+ this.current = null;
+ }
+ }
+ throw new NoSuchElementException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Iterator#remove()
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+}
Property changes on:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategy.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Deleted:
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/OneContributionMergeStrategyTest.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/OneContributionMergeStrategyTest.java 2008-09-17
22:56:21 UTC (rev 530)
+++
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/OneContributionMergeStrategyTest.java 2008-09-17
22:56:29 UTC (rev 531)
@@ -1,205 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
-package org.jboss.dna.connector.federation.merge;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNot.not;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.stub;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import org.jboss.dna.connector.federation.contribution.Contribution;
-import org.jboss.dna.spi.ExecutionContext;
-import org.jboss.dna.spi.connector.BasicExecutionContext;
-import org.jboss.dna.spi.graph.Name;
-import org.jboss.dna.spi.graph.Path;
-import org.jboss.dna.spi.graph.Property;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoAnnotations.Mock;
-
-/**
- * @author Randall Hauch
- */
-public class OneContributionMergeStrategyTest {
-
- private OneContributionMergeStrategy strategy;
- private List<Contribution> contributions;
- private ExecutionContext context;
- private FederatedNode node;
- private Map<Name, Property> properties;
- private List<Path.Segment> children;
- @Mock
- private Contribution contribution;
-
- @Before
- public void beforeEach() throws Exception {
- MockitoAnnotations.initMocks(this);
- Path path = mock(Path.class);
- node = new FederatedNode(path, UUID.randomUUID());
- strategy = new OneContributionMergeStrategy();
- contributions = new LinkedList<Contribution>();
- contributions.add(contribution);
- context = new BasicExecutionContext();
- context.getNamespaceRegistry().register("dna",
"http://www.jboss.org/dna/something");
- context.getNamespaceRegistry().register("jcr",
"http://www.jcr.org");
- stub(contribution.getSourceName()).toReturn("source name");
- children = new LinkedList<Path.Segment>();
- for (int i = 0; i != 10; ++i) {
-
children.add(context.getValueFactories().getPathFactory().createSegment("a" +
i));
- }
- properties = new HashMap<Name, Property>();
- for (int i = 0; i != 10; ++i) {
- Name propertyName =
context.getValueFactories().getNameFactory().create("property" + i);
- properties.put(propertyName,
context.getPropertyFactory().create(propertyName, "value"));
- }
- }
-
- @Test
- public void shouldMergeTheChildrenFromTheFirstContribution() {
- stub(contribution.getChildren()).toReturn(children.iterator());
- stub(contribution.getProperties()).toReturn(properties.values().iterator());
- strategy.merge(node, contributions, context);
- assertThat(node.getChildren(), is(children));
- }
-
- @Test
- public void shouldMergeThePropertiesFromTheFirstContribution() {
- stub(contribution.getChildren()).toReturn(children.iterator());
- stub(contribution.getProperties()).toReturn(properties.values().iterator());
- stub(contribution.getProperties()).toReturn(properties.values().iterator());
- strategy.merge(node, contributions, context);
- assertThat(node.getPropertiesByName(), is(properties));
- }
-
- @Test
- public void shouldCreateMergePlanInTheFederatedNode() {
- stub(contribution.getChildren()).toReturn(children.iterator());
- stub(contribution.getProperties()).toReturn(properties.values().iterator());
- strategy.merge(node, contributions, context);
- MergePlan mergePlan = node.getMergePlan();
- assertThat(mergePlan.getContributionFrom(contribution.getSourceName()),
is(sameInstance(contribution)));
- assertThat(mergePlan.getContributionCount(), is(1));
- }
-
- @Test
- public void
shouldSetTheUuidOnTheNodeIfThereIsASingleValuedPropertyNamedUuidWithValueThatConvertsToUuidInstance()
{
- // Test the "dna:uuid" property ...
- Name uuidName =
context.getValueFactories().getNameFactory().create("dna:uuid");
- UUID uuid = UUID.randomUUID();
- Property uuidProperty = context.getPropertyFactory().create(uuidName, uuid);
- properties.put(uuidProperty.getName(), uuidProperty);
- stub(contribution.getChildren()).toReturn(children.iterator());
- stub(contribution.getProperties()).toReturn(properties.values().iterator());
- assertThat(node.getUuid(), is(not(uuid)));
- strategy.merge(node, contributions, context);
- assertThat(node.getUuid(), is(uuid));
- properties.remove(uuidProperty.getName());
-
- // Test the "jcr:uuid" property ...
- uuidName =
context.getValueFactories().getNameFactory().create("jcr:uuid");
- uuid = UUID.randomUUID();
- uuidProperty = context.getPropertyFactory().create(uuidName, uuid);
- properties.put(uuidProperty.getName(), uuidProperty);
- stub(contribution.getChildren()).toReturn(children.iterator());
- stub(contribution.getProperties()).toReturn(properties.values().iterator());
- assertThat(node.getUuid(), is(not(uuid)));
- strategy.merge(node, contributions, context);
- assertThat(node.getUuid(), is(uuid));
- properties.remove(uuidProperty.getName());
-
- // Test the "uuid" property ...
- uuidName =
context.getValueFactories().getNameFactory().create("uuid");
- uuid = UUID.randomUUID();
- uuidProperty = context.getPropertyFactory().create(uuidName, uuid);
- properties.put(uuidProperty.getName(), uuidProperty);
- stub(contribution.getChildren()).toReturn(children.iterator());
- stub(contribution.getProperties()).toReturn(properties.values().iterator());
- assertThat(node.getUuid(), is(not(uuid)));
- strategy.merge(node, contributions, context);
- assertThat(node.getUuid(), is(uuid));
- properties.remove(uuidProperty.getName());
-
- // Test the "uuid" property whose value is a String ...
- uuidName =
context.getValueFactories().getNameFactory().create("uuid");
- uuid = UUID.randomUUID();
- uuidProperty = context.getPropertyFactory().create(uuidName, uuid.toString());
- properties.put(uuidProperty.getName(), uuidProperty);
- stub(contribution.getChildren()).toReturn(children.iterator());
- stub(contribution.getProperties()).toReturn(properties.values().iterator());
- assertThat(node.getUuid(), is(not(uuid)));
- strategy.merge(node, contributions, context);
- assertThat(node.getUuid(), is(uuid));
- properties.remove(uuidProperty.getName());
- }
-
- @Test
- public void shouldNotSetTheUuidOnTheNodeIfThereIsNoPropertyNamedUuid() {
- // Test the "dna:uuid" property ...
- Name uuidName =
context.getValueFactories().getNameFactory().create("dna:uuid");
- UUID uuid = UUID.randomUUID();
- Property uuidProperty = context.getPropertyFactory().create(uuidName, uuid);
- properties.put(uuidProperty.getName(), uuidProperty);
- stub(contribution.getChildren()).toReturn(children.iterator());
- stub(contribution.getProperties()).toReturn(properties.values().iterator());
- assertThat(node.getUuid(), is(not(uuid)));
- strategy.merge(node, contributions, context);
- assertThat(node.getUuid(), is(uuid));
- properties.remove(uuidProperty.getName());
- }
-
- @Test
- public void shouldNotSetTheUuidOnTheNodeIfThereIsAMultiValuedPropertyNamedUuid() {
- final UUID originalUuid = node.getUuid();
- // Test the "dna:uuid" property ...
- Name uuidName =
context.getValueFactories().getNameFactory().create("dna:uuid");
- Property uuidProperty = context.getPropertyFactory().create(uuidName,
- UUID.randomUUID(),
- UUID.randomUUID(),
- UUID.randomUUID());
- properties.put(uuidProperty.getName(), uuidProperty);
- stub(contribution.getChildren()).toReturn(children.iterator());
- stub(contribution.getProperties()).toReturn(properties.values().iterator());
- strategy.merge(node, contributions, context);
- assertThat(node.getUuid(), is(originalUuid));
- }
-
- @Test
- public void
shouldNotSetTheUuidOnTheNodeIfThereIsASingleValuedPropertyNamedUuidWithValueThatDoesNotConvertToUuidInstance()
{
- final UUID originalUuid = node.getUuid();
- // Test the "dna:uuid" property ...
- Name uuidName =
context.getValueFactories().getNameFactory().create("dna:uuid");
- Property uuidProperty = context.getPropertyFactory().create(uuidName, 3.33d);
- properties.put(uuidProperty.getName(), uuidProperty);
- stub(contribution.getChildren()).toReturn(children.iterator());
- stub(contribution.getProperties()).toReturn(properties.values().iterator());
- strategy.merge(node, contributions, context);
- assertThat(node.getUuid(), is(originalUuid));
- }
-
-}
Deleted:
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/SimpleMergeStrategyTest.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/SimpleMergeStrategyTest.java 2008-09-17
22:56:21 UTC (rev 530)
+++
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/SimpleMergeStrategyTest.java 2008-09-17
22:56:29 UTC (rev 531)
@@ -1,297 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
-package org.jboss.dna.connector.federation.merge;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.stub;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import org.hamcrest.Matcher;
-import org.jboss.dna.common.collection.IsIteratorContaining;
-import org.jboss.dna.connector.federation.contribution.Contribution;
-import org.jboss.dna.spi.ExecutionContext;
-import org.jboss.dna.spi.connector.BasicExecutionContext;
-import org.jboss.dna.spi.graph.Name;
-import org.jboss.dna.spi.graph.Path;
-import org.jboss.dna.spi.graph.Property;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-/**
- * @author Randall Hauch
- */
-public class SimpleMergeStrategyTest {
-
- private SimpleMergeStrategy strategy;
- private List<Contribution> contributions;
- private ExecutionContext context;
- private FederatedNode node;
-
- @Before
- public void beforeEach() throws Exception {
- MockitoAnnotations.initMocks(this);
- Path path = mock(Path.class);
- node = new FederatedNode(path, UUID.randomUUID());
- strategy = new SimpleMergeStrategy();
- contributions = new LinkedList<Contribution>();
- context = new BasicExecutionContext();
- context.getNamespaceRegistry().register("dna",
"http://www.jboss.org/dna/something");
- context.getNamespaceRegistry().register("jcr",
"http://www.jcr.org");
- }
-
- @Test
- public void shouldAddChildrenFromOneContribution() {
- addContribution("source1").addChildren("childA",
"childB[1]", "childB[2]");
- strategy.merge(node, contributions, context);
- assertThat(node.getChildren(), hasSegments("childA",
"childB[1]", "childB[2]"));
- }
-
- @Test
- public void shouldCombinePropertiesFromOneContribution() {
- addContribution("source1").setProperty("p1", "p1
value");
- strategy.merge(node, contributions, context);
- assertThat(node.getProperties().size(), is(1));
- assertThat(node.getPropertiesByName().get(name("p1")),
is(property("p1", "p1 value")));
- }
-
- @Test
- public void
shouldAddChildrenFromMultipleContributionsInOrderAndShouldNotChangeSameNameSiblingIndexesWhenChildrenDoNotShareNamesWithChildrenFromDifferentContributions()
{
- addContribution("source1").addChildren("childA",
"childB[1]", "childB[2]");
- addContribution("source2").addChildren("childX",
"childY[1]", "childY[2]");
- strategy.merge(node, contributions, context);
- assertThat(node.getChildren(), hasSegments("childA",
"childB[1]", "childB[2]", "childX", "childY[1]",
"childY[2]"));
- }
-
- @Test
- public void
shouldAddChildrenFromMultipleContributionsInOrderAndShouldChangeSameNameSiblingIndexesWhenChildrenDoShareNamesWithChildrenFromDifferentContributions()
{
- addContribution("source1").addChildren("childA",
"childB[1]", "childB[2]");
- addContribution("source2").addChildren("childX",
"childB", "childY");
- addContribution("source3").addChildren("childX",
"childB");
- strategy.merge(node, contributions, context);
- assertThat(node.getChildren(), hasSegments("childA",
- "childB[1]",
- "childB[2]",
- "childX[1]",
- "childB[3]",
- "childY",
- "childX[2]",
- "childB[4]"));
- }
-
- @Test
- public void
shouldCombinePropertiesFromMultipleContributionsAndRemoveNoValuesWhenNoContributionsContainSameProperty()
{
- addContribution("source1").setProperty("p1", "p1
value");
- addContribution("source2").setProperty("p2", "p2
value");
- strategy.merge(node, contributions, context);
- assertThat(node.getProperties().size(), is(2));
- assertThat(node.getPropertiesByName().get(name("p1")),
is(property("p1", "p1 value")));
- assertThat(node.getPropertiesByName().get(name("p2")),
is(property("p2", "p2 value")));
- }
-
- @Test
- public void
shouldCombinePropertiesFromMultipleContributionsAndRemoveDuplicateValuesWhenContributionsContainSameProperty()
{
- 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(3));
- 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")));
- }
-
- @Test
- public void
shouldCombinePropertiesFromMultipleContributionsAndMaintainAllValuesForEveryProperty() {
- 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(3));
- for (Contribution contribution : contributions) {
- Iterator<Property> iter = contribution.getProperties();
- while (iter.hasNext()) {
- Property contributionProperty = iter.next();
- Property mergedProperty =
node.getPropertiesByName().get(contributionProperty.getName());
- assertThat(mergedProperty, is(notNullValue()));
- // Make sure that the merged property has each value ...
- for (Object contributedValue : contributionProperty.getValuesAsArray())
{
- boolean foundValue = false;
- for (Object mergedValue : mergedProperty.getValuesAsArray()) {
- if (mergedValue.equals(contributedValue)) {
- foundValue = true;
- break;
- }
- }
- assertThat(foundValue, is(true));
- }
- }
- }
- }
-
- @Test
- public void
shouldCombinePropertiesFromMultipleContributionsWhenPropertyValuesAreOfDifferentPropertyTypes()
{
- 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(3));
- 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)));
- }
-
- @Test
- public void shouldCreateMergePlanWhenMergingContributions() {
- addContribution("source1").addChildren("childA",
"childB[1]", "childB[2]").setProperty("p1", "p1
value");
- addContribution("source2").addChildren("childX",
"childB", "childY").setProperty("p2", "p2
value");
- strategy.merge(node, contributions, context);
- assertThat(node.getMergePlan(), is(notNullValue()));
- assertThat(node.getMergePlan().getContributionCount(), is(2));
- assertThat(node.getMergePlan().getContributionFrom("source1"),
is(sameInstance(contributions.get(0))));
- assertThat(node.getMergePlan().getContributionFrom("source2"),
is(sameInstance(contributions.get(1))));
- }
-
- @Test
- public void shouldCorrectlyBuildMockUsingContributionBuilder() {
- assertThat(contributions.size(), is(0));
- addContribution("source1").addChildren("childA",
"childB[1]", "childB[2]").setProperty("p1", "p1
value");
- assertThat(contributions.size(), is(1));
- assertThat(contributions.get(0).getChildren(),
hasSegmentIterator("childA", "childB[1]", "childB[2]"));
- }
-
- protected Matcher<List<Path.Segment>> hasSegments( String... segment ) {
- List<Path.Segment> segments = new ArrayList<Path.Segment>();
- for (String seg : segment) {
-
segments.add(context.getValueFactories().getPathFactory().createSegment(seg));
- }
- return equalTo(segments);
- }
-
- protected Matcher<Iterator<Path.Segment>> hasSegmentIterator( String...
segment ) {
- Path.Segment[] segments = new Path.Segment[segment.length];
- int index = 0;
- for (String seg : segment) {
- segments[index++] =
context.getValueFactories().getPathFactory().createSegment(seg);
- }
- return IsIteratorContaining.hasItems(segments);
- }
-
- protected Name name( String name ) {
- return context.getValueFactories().getNameFactory().create(name);
- }
-
- protected Property property( String name,
- Object... values ) {
- return context.getPropertyFactory().create(name(name), values);
- }
-
- protected ContributionBuilder addContribution( String sourceName ) {
- ContributionBuilder builder = new ContributionBuilder(context, sourceName,
contributions);
- contributions.add(builder.getMock());
- return builder;
- }
-
- protected class ContributionBuilder {
- protected final Contribution mockContribution;
- protected final ExecutionContext context;
- protected final Map<Name, Property> properties = new HashMap<Name,
Property>();
- protected final List<Path.Segment> children = new
ArrayList<Path.Segment>();
-
- protected ContributionBuilder( ExecutionContext context,
- String name,
- List<Contribution> contributions ) {
- this.context = context;
- this.mockContribution = Mockito.mock(Contribution.class);
- stub(mockContribution.getSourceName()).toReturn(name);
- stub(mockContribution.getChildren()).toAnswer(new
Answer<Iterator<Path.Segment>>() {
- public Iterator<Path.Segment> answer( InvocationOnMock invocation )
throws Throwable {
- return ContributionBuilder.this.children.iterator();
- }
- });
- stub(mockContribution.getChildrenCount()).toAnswer(new
Answer<Integer>() {
- public Integer answer( InvocationOnMock invocation ) throws Throwable {
- return ContributionBuilder.this.children.size();
- }
- });
- stub(mockContribution.getProperties()).toAnswer(new
Answer<Iterator<Property>>() {
- public Iterator<Property> answer( InvocationOnMock invocation )
throws Throwable {
- return ContributionBuilder.this.properties.values().iterator();
- }
- });
- stub(mockContribution.getPropertyCount()).toAnswer(new
Answer<Integer>() {
- public Integer answer( InvocationOnMock invocation ) throws Throwable {
- return ContributionBuilder.this.properties.size();
- }
- });
- }
-
- public Contribution getMock() {
- return this.mockContribution;
- }
-
- public ContributionBuilder addChildren( String... segmentNamesForChildren ) {
- for (String childSegmentName : segmentNamesForChildren) {
-
children.add(context.getValueFactories().getPathFactory().createSegment(childSegmentName));
- }
- return this;
- }
-
- public ContributionBuilder addChildren( Name... segmentNamesForChildren ) {
- for (Name childSegmentName : segmentNamesForChildren) {
-
children.add(context.getValueFactories().getPathFactory().createSegment(childSegmentName));
- }
- return this;
- }
-
- public ContributionBuilder addChildren( Path.Segment... segmentNamesForChildren )
{
- for (Path.Segment childSegmentName : segmentNamesForChildren) {
- children.add(childSegmentName);
- }
- return this;
- }
-
- public ContributionBuilder setProperty( String name,
- Object... values ) {
- Name propertyName =
context.getValueFactories().getNameFactory().create(name);
- Property property = context.getPropertyFactory().create(propertyName,
values);
- stub(mockContribution.getProperty(propertyName)).toReturn(property);
- if (values != null && values.length > 0) {
- properties.put(propertyName, property);
- } else {
- properties.remove(propertyName);
- }
- return this;
- }
- }
-
-}
Copied:
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategyTest.java
(from rev 522,
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/OneContributionMergeStrategyTest.java)
===================================================================
---
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategyTest.java
(rev 0)
+++
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategyTest.java 2008-09-17
22:56:29 UTC (rev 531)
@@ -0,0 +1,209 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.connector.federation.merge.strategy;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.stub;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.jboss.dna.connector.federation.contribution.Contribution;
+import org.jboss.dna.connector.federation.merge.FederatedNode;
+import org.jboss.dna.connector.federation.merge.MergePlan;
+import org.jboss.dna.spi.DnaLexicon;
+import org.jboss.dna.spi.ExecutionContext;
+import org.jboss.dna.spi.connector.BasicExecutionContext;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.Property;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoAnnotations.Mock;
+
+/**
+ * @author Randall Hauch
+ */
+public class OneContributionMergeStrategyTest {
+
+ private OneContributionMergeStrategy strategy;
+ private List<Contribution> contributions;
+ private ExecutionContext context;
+ private FederatedNode node;
+ private Map<Name, Property> properties;
+ private List<Path.Segment> children;
+ @Mock
+ private Contribution contribution;
+
+ @Before
+ public void beforeEach() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ Path path = mock(Path.class);
+ node = new FederatedNode(path, UUID.randomUUID());
+ strategy = new OneContributionMergeStrategy();
+ contributions = new LinkedList<Contribution>();
+ contributions.add(contribution);
+ context = new BasicExecutionContext();
+ context.getNamespaceRegistry().register("dna",
"http://www.jboss.org/dna/something");
+ context.getNamespaceRegistry().register("jcr",
"http://www.jcr.org");
+ stub(contribution.getSourceName()).toReturn("source name");
+ children = new LinkedList<Path.Segment>();
+ for (int i = 0; i != 10; ++i) {
+
children.add(context.getValueFactories().getPathFactory().createSegment("a" +
i));
+ }
+ properties = new HashMap<Name, Property>();
+ for (int i = 0; i != 10; ++i) {
+ Name propertyName =
context.getValueFactories().getNameFactory().create("property" + i);
+ properties.put(propertyName,
context.getPropertyFactory().create(propertyName, "value"));
+ }
+ }
+
+ @Test
+ public void shouldMergeTheChildrenFromTheFirstContribution() {
+ stub(contribution.getChildren()).toReturn(children.iterator());
+ stub(contribution.getProperties()).toReturn(properties.values().iterator());
+ strategy.merge(node, contributions, context);
+ assertThat(node.getChildren(), is(children));
+ }
+
+ @Test
+ public void shouldMergeThePropertiesFromTheFirstContribution() {
+ stub(contribution.getChildren()).toReturn(children.iterator());
+ stub(contribution.getProperties()).toReturn(properties.values().iterator());
+ stub(contribution.getProperties()).toReturn(properties.values().iterator());
+ strategy.merge(node, contributions, context);
+ properties.put(DnaLexicon.UUID,
node.getPropertiesByName().get(DnaLexicon.UUID));
+ assertThat(node.getPropertiesByName(), is(properties));
+ }
+
+ @Test
+ public void shouldCreateMergePlanInTheFederatedNode() {
+ stub(contribution.getChildren()).toReturn(children.iterator());
+ stub(contribution.getProperties()).toReturn(properties.values().iterator());
+ strategy.merge(node, contributions, context);
+ MergePlan mergePlan = node.getMergePlan();
+ assertThat(mergePlan.getContributionFrom(contribution.getSourceName()),
is(sameInstance(contribution)));
+ assertThat(mergePlan.getContributionCount(), is(1));
+ }
+
+ @Test
+ public void
shouldSetTheUuidOnTheNodeIfThereIsASingleValuedPropertyNamedUuidWithValueThatConvertsToUuidInstance()
{
+ // Test the "dna:uuid" property ...
+ Name uuidName =
context.getValueFactories().getNameFactory().create("dna:uuid");
+ UUID uuid = UUID.randomUUID();
+ Property uuidProperty = context.getPropertyFactory().create(uuidName, uuid);
+ properties.put(uuidProperty.getName(), uuidProperty);
+ stub(contribution.getChildren()).toReturn(children.iterator());
+ stub(contribution.getProperties()).toReturn(properties.values().iterator());
+ assertThat(node.getUuid(), is(not(uuid)));
+ strategy.merge(node, contributions, context);
+ assertThat(node.getUuid(), is(uuid));
+ properties.remove(uuidProperty.getName());
+
+ // Test the "jcr:uuid" property ...
+ uuidName =
context.getValueFactories().getNameFactory().create("jcr:uuid");
+ uuid = UUID.randomUUID();
+ uuidProperty = context.getPropertyFactory().create(uuidName, uuid);
+ properties.put(uuidProperty.getName(), uuidProperty);
+ stub(contribution.getChildren()).toReturn(children.iterator());
+ stub(contribution.getProperties()).toReturn(properties.values().iterator());
+ assertThat(node.getUuid(), is(not(uuid)));
+ strategy.merge(node, contributions, context);
+ assertThat(node.getUuid(), is(uuid));
+ properties.remove(uuidProperty.getName());
+
+ // Test the "uuid" property ...
+ uuidName =
context.getValueFactories().getNameFactory().create("uuid");
+ uuid = UUID.randomUUID();
+ uuidProperty = context.getPropertyFactory().create(uuidName, uuid);
+ properties.put(uuidProperty.getName(), uuidProperty);
+ stub(contribution.getChildren()).toReturn(children.iterator());
+ stub(contribution.getProperties()).toReturn(properties.values().iterator());
+ assertThat(node.getUuid(), is(not(uuid)));
+ strategy.merge(node, contributions, context);
+ assertThat(node.getUuid(), is(uuid));
+ properties.remove(uuidProperty.getName());
+
+ // Test the "uuid" property whose value is a String ...
+ uuidName =
context.getValueFactories().getNameFactory().create("uuid");
+ uuid = UUID.randomUUID();
+ uuidProperty = context.getPropertyFactory().create(uuidName, uuid.toString());
+ properties.put(uuidProperty.getName(), uuidProperty);
+ stub(contribution.getChildren()).toReturn(children.iterator());
+ stub(contribution.getProperties()).toReturn(properties.values().iterator());
+ assertThat(node.getUuid(), is(not(uuid)));
+ strategy.merge(node, contributions, context);
+ assertThat(node.getUuid(), is(uuid));
+ properties.remove(uuidProperty.getName());
+ }
+
+ @Test
+ public void shouldNotSetTheUuidOnTheNodeIfThereIsNoPropertyNamedUuid() {
+ // Test the "dna:uuid" property ...
+ Name uuidName =
context.getValueFactories().getNameFactory().create("dna:uuid");
+ UUID uuid = UUID.randomUUID();
+ Property uuidProperty = context.getPropertyFactory().create(uuidName, uuid);
+ properties.put(uuidProperty.getName(), uuidProperty);
+ stub(contribution.getChildren()).toReturn(children.iterator());
+ stub(contribution.getProperties()).toReturn(properties.values().iterator());
+ assertThat(node.getUuid(), is(not(uuid)));
+ strategy.merge(node, contributions, context);
+ assertThat(node.getUuid(), is(uuid));
+ properties.remove(uuidProperty.getName());
+ }
+
+ @Test
+ public void shouldNotSetTheUuidOnTheNodeIfThereIsAMultiValuedPropertyNamedUuid() {
+ final UUID originalUuid = node.getUuid();
+ // Test the "dna:uuid" property ...
+ Name uuidName =
context.getValueFactories().getNameFactory().create("dna:uuid");
+ Property uuidProperty = context.getPropertyFactory().create(uuidName,
+ UUID.randomUUID(),
+ UUID.randomUUID(),
+ UUID.randomUUID());
+ properties.put(uuidProperty.getName(), uuidProperty);
+ stub(contribution.getChildren()).toReturn(children.iterator());
+ stub(contribution.getProperties()).toReturn(properties.values().iterator());
+ strategy.merge(node, contributions, context);
+ assertThat(node.getUuid(), is(originalUuid));
+ }
+
+ @Test
+ public void
shouldNotSetTheUuidOnTheNodeIfThereIsASingleValuedPropertyNamedUuidWithValueThatDoesNotConvertToUuidInstance()
{
+ final UUID originalUuid = node.getUuid();
+ // Test the "dna:uuid" property ...
+ Name uuidName =
context.getValueFactories().getNameFactory().create("dna:uuid");
+ Property uuidProperty = context.getPropertyFactory().create(uuidName, 3.33d);
+ properties.put(uuidProperty.getName(), uuidProperty);
+ stub(contribution.getChildren()).toReturn(children.iterator());
+ stub(contribution.getProperties()).toReturn(properties.values().iterator());
+ strategy.merge(node, contributions, context);
+ assertThat(node.getUuid(), is(originalUuid));
+ }
+
+}
Property changes on:
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/OneContributionMergeStrategyTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Copied:
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategyTest.java
(from rev 522,
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/SimpleMergeStrategyTest.java)
===================================================================
---
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategyTest.java
(rev 0)
+++
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategyTest.java 2008-09-17
22:56:29 UTC (rev 531)
@@ -0,0 +1,304 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.connector.federation.merge.strategy;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.stub;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.hamcrest.Matcher;
+import org.jboss.dna.common.collection.IsIteratorContaining;
+import org.jboss.dna.connector.federation.contribution.Contribution;
+import org.jboss.dna.connector.federation.merge.FederatedNode;
+import org.jboss.dna.spi.DnaLexicon;
+import org.jboss.dna.spi.ExecutionContext;
+import org.jboss.dna.spi.connector.BasicExecutionContext;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.Property;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+/**
+ * @author Randall Hauch
+ */
+public class SimpleMergeStrategyTest {
+
+ private SimpleMergeStrategy strategy;
+ private List<Contribution> contributions;
+ private ExecutionContext context;
+ private FederatedNode node;
+
+ @Before
+ public void beforeEach() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ Path path = mock(Path.class);
+ node = new FederatedNode(path, UUID.randomUUID());
+ strategy = new SimpleMergeStrategy();
+ contributions = new LinkedList<Contribution>();
+ context = new BasicExecutionContext();
+ context.getNamespaceRegistry().register("dna",
"http://www.jboss.org/dna/something");
+ context.getNamespaceRegistry().register("jcr",
"http://www.jcr.org");
+ }
+
+ @Test
+ public void shouldAddChildrenFromOneContribution() {
+ addContribution("source1").addChildren("childA",
"childB[1]", "childB[2]");
+ strategy.merge(node, contributions, context);
+ assertThat(node.getChildren(), hasSegments("childA",
"childB[1]", "childB[2]"));
+ }
+
+ @Test
+ public void shouldCombinePropertiesFromOneContribution() {
+ addContribution("source1").setProperty("p1", "p1
value");
+ strategy.merge(node, contributions, context);
+ assertThat(node.getProperties().size(), is(2));
+ assertThat(node.getPropertiesByName().get(DnaLexicon.UUID), is(notNullValue()));
+ assertThat(node.getPropertiesByName().get(name("p1")),
is(property("p1", "p1 value")));
+ }
+
+ @Test
+ public void
shouldAddChildrenFromMultipleContributionsInOrderAndShouldNotChangeSameNameSiblingIndexesWhenChildrenDoNotShareNamesWithChildrenFromDifferentContributions()
{
+ addContribution("source1").addChildren("childA",
"childB[1]", "childB[2]");
+ addContribution("source2").addChildren("childX",
"childY[1]", "childY[2]");
+ strategy.merge(node, contributions, context);
+ assertThat(node.getChildren(), hasSegments("childA",
"childB[1]", "childB[2]", "childX", "childY[1]",
"childY[2]"));
+ }
+
+ @Test
+ public void
shouldAddChildrenFromMultipleContributionsInOrderAndShouldChangeSameNameSiblingIndexesWhenChildrenDoShareNamesWithChildrenFromDifferentContributions()
{
+ addContribution("source1").addChildren("childA",
"childB[1]", "childB[2]");
+ addContribution("source2").addChildren("childX",
"childB", "childY");
+ addContribution("source3").addChildren("childX",
"childB");
+ strategy.merge(node, contributions, context);
+ assertThat(node.getChildren(), hasSegments("childA",
+ "childB[1]",
+ "childB[2]",
+ "childX[1]",
+ "childB[3]",
+ "childY",
+ "childX[2]",
+ "childB[4]"));
+ }
+
+ @Test
+ public void
shouldCombinePropertiesFromMultipleContributionsAndRemoveNoValuesWhenNoContributionsContainSameProperty()
{
+ 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.getPropertiesByName().get(DnaLexicon.UUID), is(notNullValue()));
+ assertThat(node.getPropertiesByName().get(name("p1")),
is(property("p1", "p1 value")));
+ assertThat(node.getPropertiesByName().get(name("p2")),
is(property("p2", "p2 value")));
+ }
+
+ @Test
+ public void
shouldCombinePropertiesFromMultipleContributionsAndRemoveDuplicateValuesWhenContributionsContainSameProperty()
{
+ 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.getPropertiesByName().get(DnaLexicon.UUID), 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")));
+ }
+
+ @Test
+ public void
shouldCombinePropertiesFromMultipleContributionsAndMaintainAllValuesForEveryProperty() {
+ 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.getPropertiesByName().get(DnaLexicon.UUID), is(notNullValue()));
+ for (Contribution contribution : contributions) {
+ Iterator<Property> iter = contribution.getProperties();
+ while (iter.hasNext()) {
+ Property contributionProperty = iter.next();
+ Property mergedProperty =
node.getPropertiesByName().get(contributionProperty.getName());
+ assertThat(mergedProperty, is(notNullValue()));
+ // Make sure that the merged property has each value ...
+ for (Object contributedValue : contributionProperty.getValuesAsArray())
{
+ boolean foundValue = false;
+ for (Object mergedValue : mergedProperty.getValuesAsArray()) {
+ if (mergedValue.equals(contributedValue)) {
+ foundValue = true;
+ break;
+ }
+ }
+ assertThat(foundValue, is(true));
+ }
+ }
+ }
+ }
+
+ @Test
+ public void
shouldCombinePropertiesFromMultipleContributionsWhenPropertyValuesAreOfDifferentPropertyTypes()
{
+ 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.getPropertiesByName().get(DnaLexicon.UUID), 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)));
+ }
+
+ @Test
+ public void shouldCreateMergePlanWhenMergingContributions() {
+ addContribution("source1").addChildren("childA",
"childB[1]", "childB[2]").setProperty("p1", "p1
value");
+ addContribution("source2").addChildren("childX",
"childB", "childY").setProperty("p2", "p2
value");
+ strategy.merge(node, contributions, context);
+ assertThat(node.getMergePlan(), is(notNullValue()));
+ assertThat(node.getMergePlan().getContributionCount(), is(2));
+ assertThat(node.getMergePlan().getContributionFrom("source1"),
is(sameInstance(contributions.get(0))));
+ assertThat(node.getMergePlan().getContributionFrom("source2"),
is(sameInstance(contributions.get(1))));
+ }
+
+ @Test
+ public void shouldCorrectlyBuildMockUsingContributionBuilder() {
+ assertThat(contributions.size(), is(0));
+ addContribution("source1").addChildren("childA",
"childB[1]", "childB[2]").setProperty("p1", "p1
value");
+ assertThat(contributions.size(), is(1));
+ assertThat(contributions.get(0).getChildren(),
hasSegmentIterator("childA", "childB[1]", "childB[2]"));
+ }
+
+ protected Matcher<List<Path.Segment>> hasSegments( String... segment ) {
+ List<Path.Segment> segments = new ArrayList<Path.Segment>();
+ for (String seg : segment) {
+
segments.add(context.getValueFactories().getPathFactory().createSegment(seg));
+ }
+ return equalTo(segments);
+ }
+
+ protected Matcher<Iterator<Path.Segment>> hasSegmentIterator( String...
segment ) {
+ Path.Segment[] segments = new Path.Segment[segment.length];
+ int index = 0;
+ for (String seg : segment) {
+ segments[index++] =
context.getValueFactories().getPathFactory().createSegment(seg);
+ }
+ return IsIteratorContaining.hasItems(segments);
+ }
+
+ protected Name name( String name ) {
+ return context.getValueFactories().getNameFactory().create(name);
+ }
+
+ protected Property property( String name,
+ Object... values ) {
+ return context.getPropertyFactory().create(name(name), values);
+ }
+
+ protected ContributionBuilder addContribution( String sourceName ) {
+ ContributionBuilder builder = new ContributionBuilder(context, sourceName,
contributions);
+ contributions.add(builder.getMock());
+ return builder;
+ }
+
+ protected class ContributionBuilder {
+ protected final Contribution mockContribution;
+ protected final ExecutionContext context;
+ protected final Map<Name, Property> properties = new HashMap<Name,
Property>();
+ protected final List<Path.Segment> children = new
ArrayList<Path.Segment>();
+
+ protected ContributionBuilder( ExecutionContext context,
+ String name,
+ List<Contribution> contributions ) {
+ this.context = context;
+ this.mockContribution = Mockito.mock(Contribution.class);
+ stub(mockContribution.getSourceName()).toReturn(name);
+ stub(mockContribution.getChildren()).toAnswer(new
Answer<Iterator<Path.Segment>>() {
+ public Iterator<Path.Segment> answer( InvocationOnMock invocation )
throws Throwable {
+ return ContributionBuilder.this.children.iterator();
+ }
+ });
+ stub(mockContribution.getChildrenCount()).toAnswer(new
Answer<Integer>() {
+ public Integer answer( InvocationOnMock invocation ) throws Throwable {
+ return ContributionBuilder.this.children.size();
+ }
+ });
+ stub(mockContribution.getProperties()).toAnswer(new
Answer<Iterator<Property>>() {
+ public Iterator<Property> answer( InvocationOnMock invocation )
throws Throwable {
+ return ContributionBuilder.this.properties.values().iterator();
+ }
+ });
+ stub(mockContribution.getPropertyCount()).toAnswer(new
Answer<Integer>() {
+ public Integer answer( InvocationOnMock invocation ) throws Throwable {
+ return ContributionBuilder.this.properties.size();
+ }
+ });
+ }
+
+ public Contribution getMock() {
+ return this.mockContribution;
+ }
+
+ public ContributionBuilder addChildren( String... segmentNamesForChildren ) {
+ for (String childSegmentName : segmentNamesForChildren) {
+
children.add(context.getValueFactories().getPathFactory().createSegment(childSegmentName));
+ }
+ return this;
+ }
+
+ public ContributionBuilder addChildren( Name... segmentNamesForChildren ) {
+ for (Name childSegmentName : segmentNamesForChildren) {
+
children.add(context.getValueFactories().getPathFactory().createSegment(childSegmentName));
+ }
+ return this;
+ }
+
+ public ContributionBuilder addChildren( Path.Segment... segmentNamesForChildren )
{
+ for (Path.Segment childSegmentName : segmentNamesForChildren) {
+ children.add(childSegmentName);
+ }
+ return this;
+ }
+
+ public ContributionBuilder setProperty( String name,
+ Object... values ) {
+ Name propertyName =
context.getValueFactories().getNameFactory().create(name);
+ Property property = context.getPropertyFactory().create(propertyName,
values);
+ stub(mockContribution.getProperty(propertyName)).toReturn(property);
+ if (values != null && values.length > 0) {
+ properties.put(propertyName, property);
+ } else {
+ properties.remove(propertyName);
+ }
+ return this;
+ }
+ }
+
+}
Property changes on:
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/strategy/SimpleMergeStrategyTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain