Author: rhauch
Date: 2009-02-23 10:55:50 -0500 (Mon, 23 Feb 2009)
New Revision: 733
Added:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/PathLocation.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/PathPropertiesLocation.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/PathPropertyLocation.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/LocationTest.java
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java
Log:
DNA-280 Create optimized versions of Location
Applied the patch to add different Location implementations, specialized for the more
frequent use cases.
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java 2009-02-20 17:09:38
UTC (rev 732)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java 2009-02-23 15:55:50
UTC (rev 733)
@@ -24,12 +24,13 @@
package org.jboss.dna.graph;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.UUID;
+
import net.jcip.annotations.Immutable;
+
import org.jboss.dna.common.text.TextEncoder;
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.common.util.HashCode;
@@ -45,12 +46,12 @@
* @author Randall Hauch
*/
@Immutable
-public class Location implements Iterable<Property> {
+public abstract class Location implements Iterable<Property> {
/**
* Simple shared iterator instance that is used when there are no properties.
*/
- private static final Iterator<Property> NO_ID_PROPERTIES_ITERATOR = new
Iterator<Property>() {
+ protected static final Iterator<Property> NO_ID_PROPERTIES_ITERATOR = new
Iterator<Property>() {
public boolean hasNext() {
return false;
}
@@ -74,7 +75,7 @@
public static Location create( Path path ) {
CheckArg.isNotNull(path, "path");
- return new Location(path, null);
+ return new PathLocation(path);
}
/**
@@ -88,7 +89,7 @@
public static Location create( UUID uuid ) {
CheckArg.isNotNull(uuid, "uuid");
Property idProperty = new BasicSingleValueProperty(DnaLexicon.UUID, uuid);
- return new Location(null, Collections.singletonList(idProperty));
+ return new PathPropertyLocation(null, idProperty);
}
/**
@@ -103,13 +104,7 @@
public static Location create( Path path,
UUID uuid ) {
CheckArg.isNotNull(uuid, "uuid");
- List<Property> idProperties = null;
- if (uuid != null) {
- Property idProperty = new BasicSingleValueProperty(DnaLexicon.UUID, uuid);
- idProperties = Collections.singletonList(idProperty);
- }
-
- return new Location(path, idProperties);
+ return new PathPropertyLocation(path, new
BasicSingleValueProperty(DnaLexicon.UUID, uuid));
}
/**
@@ -124,7 +119,7 @@
Property idProperty ) {
CheckArg.isNotNull(path, "path");
CheckArg.isNotNull(idProperty, "idProperty");
- return new Location(path, idProperty != null ?
Collections.singletonList(idProperty) : null);
+ return new PathPropertyLocation(path, idProperty);
}
/**
@@ -147,7 +142,7 @@
for (Property property : remainingIdProperties) {
idProperties.add(property);
}
- return new Location(path, Collections.unmodifiableList(idProperties));
+ return new PathPropertiesLocation(path, idProperties);
}
/**
@@ -166,7 +161,7 @@
for (Property property : idProperties) {
idPropertiesList.add(property);
}
- return new Location(path, Collections.unmodifiableList(idPropertiesList));
+ return new PathPropertiesLocation(path, idPropertiesList);
}
/**
@@ -178,7 +173,7 @@
*/
public static Location create( Property idProperty ) {
CheckArg.isNotNull(idProperty, "idProperty");
- return new Location(null, Collections.singletonList(idProperty));
+ return new PathPropertyLocation(null, idProperty);
}
/**
@@ -198,7 +193,7 @@
for (Property property : remainingIdProperties) {
idProperties.add(property);
}
- return new Location(null, Collections.unmodifiableList(idProperties));
+ return new PathPropertiesLocation(null, idProperties);
}
/**
@@ -214,7 +209,7 @@
for (Property property : idProperties) {
idPropertiesList.add(property);
}
- return new Location(null, Collections.unmodifiableList(idPropertiesList));
+ return new PathPropertiesLocation(null, idPropertiesList);
}
/**
@@ -226,89 +221,15 @@
*/
public static Location create( List<Property> idProperties ) {
CheckArg.isNotEmpty(idProperties, "idProperties");
- return new Location(null, idProperties);
+ return new PathPropertiesLocation(null, idProperties);
}
/**
- * Create a location defined by a path and multiple identification properties.
- *
- * @param path the path
- * @param idProperties the identification properties
- * @return a new <code>Location</code> with the given path and
identification properties
- * @throws IllegalArgumentException if <code>path</code> is null, or if
<code>idProperties</code> is empty
- */
- protected static Location create( Path path,
- List<Property> idProperties ) {
- CheckArg.isNotNull(path, "path");
- CheckArg.isNotEmpty(idProperties, "idProperties");
- return new Location(path, idProperties);
- }
-
- private final Path path;
- private final List<Property> idProperties;
-
- /**
- * Create a new location with a given path and set of identification properties.
- *
- * @param path the path
- * @param idProperties the identification properties
- */
- protected Location( Path path,
- List<Property> idProperties ) {
- this.path = path;
- this.idProperties = idProperties;
- }
-
- /**
- * Create a location from another but adding the supplied identification property.
The new identification property will
- * replace any existing identification property with the same name on the original.
- *
- * @param original the original location
- * @param newIdProperty the new identification property
- * @throws IllegalArgumentException if <code>original</code> is null
- */
- protected Location( Location original,
- Property newIdProperty ) {
- this.path = original.getPath();
- if (original.hasIdProperties()) {
- List<Property> originalIdProperties = original.getIdProperties();
- if (newIdProperty == null) {
- this.idProperties = original.idProperties;
- } else {
- List<Property> idProperties = new
ArrayList<Property>(originalIdProperties.size() + 1);
- for (Property property : originalIdProperties) {
- if (!newIdProperty.getName().equals(property.getName()))
idProperties.add(property);
- }
- idProperties.add(newIdProperty);
- this.idProperties = Collections.unmodifiableList(idProperties);
- }
- } else {
- this.idProperties = Collections.singletonList(newIdProperty);
- }
- }
-
- /**
- * Create a location from another but adding the supplied identification property.
The new identification property will
- * replace any existing identification property with the same name on the original.
- *
- * @param original the original location
- * @param newPath the new path for the location
- * @throws IllegalArgumentException if <code>original</code> is null
- */
- protected Location( Location original,
- Path newPath ) {
- this.path = newPath != null ? newPath : original.getPath();
- this.idProperties = original.idProperties;
- }
-
- /**
* Get the path that (at least in part) defines this location.
*
* @return the path, or null if this location is not defined with a path
*/
- public Path getPath() {
- return path;
- }
+ public abstract Path getPath();
/**
* Return whether this location is defined (at least in part) by a path.
@@ -316,7 +237,7 @@
* @return true if a {@link #getPath() path} helps define this location
*/
public boolean hasPath() {
- return path != null;
+ return getPath() != null;
}
/**
@@ -324,9 +245,7 @@
*
* @return the identification properties, or null if this location is not defined
with identification properties
*/
- public List<Property> getIdProperties() {
- return idProperties;
- }
+ public abstract List<Property> getIdProperties();
/**
* Return whether this location is defined (at least in part) with identification
properties.
@@ -334,7 +253,7 @@
* @return true if a {@link #getIdProperties() identification properties} help define
this location
*/
public boolean hasIdProperties() {
- return idProperties != null && idProperties.size() != 0;
+ return getIdProperties() != null && getIdProperties().size() != 0;
}
/**
@@ -346,8 +265,8 @@
*/
public Property getIdProperty( Name name ) {
CheckArg.isNotNull(name, "name");
- if (idProperties != null) {
- for (Property property : idProperties) {
+ if (getIdProperties() != null) {
+ for (Property property : getIdProperties()) {
if (property.getName().equals(name)) return property;
}
}
@@ -449,7 +368,7 @@
* @see java.lang.Iterable#iterator()
*/
public Iterator<Property> iterator() {
- return idProperties != null ? idProperties.iterator() :
NO_ID_PROPERTIES_ITERATOR;
+ return getIdProperties() != null ? getIdProperties().iterator() :
NO_ID_PROPERTIES_ITERATOR;
}
/**
@@ -459,7 +378,7 @@
*/
@Override
public int hashCode() {
- return HashCode.compute(path, idProperties);
+ return HashCode.compute(getPath(), getIdProperties());
}
/**
@@ -624,22 +543,14 @@
* @param newIdProperty the new identification property, which may be null
* @return the new location, or this location if the new identification property is
null or empty
*/
- public Location with( Property newIdProperty ) {
- if (newIdProperty == null || newIdProperty.isEmpty()) return this;
- return new Location(this, newIdProperty);
- }
-
+ public abstract Location with( Property newIdProperty );
/**
* Create a copy of this location that uses the supplied path.
*
* @param newPath the new path for the location
* @return the new location, or this location if the path is equal to this
location's path
*/
- public Location with( Path newPath ) {
- if (newPath == null) return this;
- if (!this.path.equals(newPath)) return new Location(this, newPath);
- return this;
- }
+ public abstract Location with( Path newPath );
/**
* Create a copy of this location that adds the supplied UUID as an identification
property. The new identification property
@@ -648,14 +559,6 @@
* @param uuid the new UUID, which may be null
* @return the new location, or this location if the new identification property is
null or empty
*/
- public Location with( UUID uuid ) {
- if (uuid == null) return this;
- Property newProperty = new BasicSingleValueProperty(DnaLexicon.UUID, uuid);
- if (this.hasIdProperties()) {
- Property existing = this.getIdProperty(DnaLexicon.UUID);
- if (existing != null && existing.equals(newProperty)) return this;
- }
- return new Location(this, newProperty);
- }
+ public abstract Location with( UUID uuid );
}
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/PathLocation.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/PathLocation.java
(rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/PathLocation.java 2009-02-23
15:55:50 UTC (rev 733)
@@ -0,0 +1,178 @@
+/*
+ * JBoss DNA (
http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.graph;
+
+import java.util.List;
+import java.util.UUID;
+
+import net.jcip.annotations.Immutable;
+
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.common.util.HashCode;
+import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.basic.BasicSingleValueProperty;
+
+/**
+ * Special location type optimized for use when only a path is specified.
+ * This class should never be directly instantiated by users of the DNA framework.
+ * Instead, use @{link Location#create} to create the correct location.
+ *
+ * @see Location
+ */
+@Immutable
+class PathLocation extends Location {
+
+ private final Path path;
+ private final int hashCode;
+
+ PathLocation(Path path) {
+ CheckArg.isNotNull(path, "path");
+
+ this.path = path;
+
+ // Paths are immutable, so PathLocations are immutable...
+ // ... so we can cache the hash code.
+ hashCode = HashCode.compute(path);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getPath()
+ */
+ @Override
+ public final Path getPath() {
+ return path;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#hasPath()
+ */
+ @Override
+ public final boolean hasPath() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getIdProperties()
+ */
+ @Override
+ public final List<Property> getIdProperties() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#hasIdProperties()
+ */
+ @Override
+ public final boolean hasIdProperties() {
+ return false;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getUuid()
+ */
+ @Override
+ public final UUID getUuid() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getString(NamespaceRegistry, TextEncoder, TextEncoder)
+ */
+ @Override
+ public String getString(NamespaceRegistry namespaceRegistry, TextEncoder encoder,
TextEncoder delimiterEncoder) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("{ ");
+ sb.append(path.getString(namespaceRegistry, encoder, delimiterEncoder));
+ sb.append(" }");
+ return sb.toString();
+ }
+
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#with(Property)
+ */
+ @Override
+ public Location with( Property newIdProperty ) {
+ if (newIdProperty == null || newIdProperty.isEmpty()) return this;
+ return Location.create(path, newIdProperty);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#with(Path)
+ */
+ @Override
+ public Location with( Path newPath ) {
+ if (newPath == null) return this;
+ if (!this.getPath().equals(newPath)) return Location.create(newPath);
+ return this;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#with(UUID)
+ */
+ @Override
+ public Location with( UUID uuid ) {
+ if (uuid == null) return this;
+ Property newProperty = new BasicSingleValueProperty(DnaLexicon.UUID, uuid);
+ if (this.hasIdProperties()) {
+ Property existing = this.getIdProperty(DnaLexicon.UUID);
+ if (existing != null && existing.equals(newProperty)) return this;
+ }
+ return Location.create(path, uuid);
+ }
+}
Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/PathLocation.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/PathPropertiesLocation.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/PathPropertiesLocation.java
(rev 0)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/PathPropertiesLocation.java 2009-02-23
15:55:50 UTC (rev 733)
@@ -0,0 +1,173 @@
+/*
+ * JBoss DNA (
http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.graph;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+import net.jcip.annotations.Immutable;
+
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.common.util.HashCode;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.basic.BasicSingleValueProperty;
+
+/**
+ * General purpose location type that supports a path and zero or more properties.
+ * This class should never be directly instantiated by users of the DNA framework.
+ * Instead, use @{link Location#create} to create the correct location.
+ *
+ * @see Location
+ */
+@Immutable
+class PathPropertiesLocation extends Location {
+
+ private final Path path;
+ private final List<Property> idProperties;
+
+ private final int hashCode;
+
+ /**
+ * Create a new location with a given path and set of identification properties.
+ *
+ * @param path the path
+ * @param idProperties the identification properties
+ */
+ PathPropertiesLocation( Path path, List<Property> idProperties ) {
+ // The path could be null
+ // CheckArg.isNotNull(path, "path");
+ // If the properties are a null, a PathLocation should be used instead.
+ CheckArg.isNotNull(idProperties, "idProperties");
+
+ this.path = path;
+ this.idProperties = Collections.unmodifiableList(idProperties);
+
+ // Paths are immutable, Properties are immutable, the idProperties list
+ // is wrapped in an unmodifiableList by the Location factory methods...
+ // ... so we can cache the hash code.
+
+ hashCode = HashCode.compute(path, idProperties);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getPath()
+ */
+ @Override
+ public final Path getPath() {
+ return path;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getIdProperties()
+ */
+ @Override
+ public final List<Property> getIdProperties() {
+ return idProperties;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#hasIdProperties()
+ */
+ @Override
+ public final boolean hasIdProperties() {
+ return idProperties.size() > 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#with(Property)
+ */
+ @Override
+ public Location with( Property newIdProperty ) {
+ if (newIdProperty == null || newIdProperty.isEmpty()) return this;
+
+ List<Property> newIdProperties;
+
+ if (hasIdProperties()) {
+ newIdProperties = new ArrayList<Property>(idProperties.size() + 1);
+ for (Property property : idProperties) {
+ if (!newIdProperty.getName().equals(property.getName()))
newIdProperties.add(property);
+ }
+ newIdProperties.add(newIdProperty);
+ newIdProperties = Collections.unmodifiableList(newIdProperties);
+ } else {
+ return Location.create(path, newIdProperty);
+ }
+
+ return new PathPropertiesLocation(path, newIdProperties);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#with(Path)
+ */
+ @Override
+ public Location with( Path newPath ) {
+ if (newPath == null) return this;
+ if (!this.getPath().equals(newPath)) return Location.create(newPath,
idProperties);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#with(UUID)
+ */
+ @Override
+ public Location with( UUID uuid ) {
+ if (uuid == null) return this;
+ Property newProperty = new BasicSingleValueProperty(DnaLexicon.UUID, uuid);
+ if (this.hasIdProperties()) {
+ Property existing = this.getIdProperty(DnaLexicon.UUID);
+ if (existing != null && existing.equals(newProperty)) return this;
+ }
+
+ List<Property> newIdProperties = new
ArrayList<Property>(idProperties.size() + 1);
+ newIdProperties.addAll(idProperties);
+ newIdProperties.add(newProperty);
+
+ return Location.create(path, newIdProperties);
+ }
+}
Property changes on:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/PathPropertiesLocation.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/PathPropertyLocation.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/PathPropertyLocation.java
(rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/PathPropertyLocation.java 2009-02-23
15:55:50 UTC (rev 733)
@@ -0,0 +1,197 @@
+/*
+ * JBoss DNA (
http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.graph;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+import net.jcip.annotations.Immutable;
+
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.common.util.HashCode;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.basic.BasicSingleValueProperty;
+
+/**
+ * General purpose location type that supports a path and a property.
+ * This class should never be directly instantiated by users of the DNA framework.
+ * Instead, use @{link Location#create} to create the correct location.
+ *
+ * @see Location
+ */
+@Immutable
+class PathPropertyLocation extends Location {
+
+ private final Path path;
+ private final Property idProperty;
+ private final List<Property> idProperties;
+
+ private final int hashCode;
+
+ /**
+ * Create a new location with a given path and identification property.
+ *
+ * @param path the path
+ * @param idProperty the identification property
+ */
+ PathPropertyLocation( Path path, Property idProperty ) {
+ // The path could be null
+ // CheckArg.isNotNull(path, "path");
+ // If the properties are a null, a PathLocation should be used instead.
+ CheckArg.isNotNull(idProperty, "idProperty");
+
+ this.path = path;
+ this.idProperty = idProperty;
+ this.idProperties = Collections.singletonList(idProperty);
+
+ // Paths are immutable, Properties are immutable, the idProperties list
+ // is wrapped in an unmodifiableList by the Location factory methods...
+ // ... so we can cache the hash code.
+
+ hashCode = HashCode.compute(path, idProperties);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getPath()
+ */
+ @Override
+ public final Path getPath() {
+ return path;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getIdProperties()
+ */
+ @Override
+ public final List<Property> getIdProperties() {
+ return idProperties;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#hasIdProperties()
+ */
+ @Override
+ public final boolean hasIdProperties() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getIdProperty(Name)
+ */
+ @Override
+ public final Property getIdProperty( Name name ) {
+ CheckArg.isNotNull(name, "name");
+ if (idProperty.getName().equals(name)) return idProperty;
+
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getUuid()
+ */
+ @Override
+ public UUID getUuid() {
+ if (DnaLexicon.UUID.equals(idProperty.getName())) {
+ Object value = idProperty.getFirstValue();
+ if (value instanceof UUID) return (UUID)value;
+ }
+ return null;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#with(Property)
+ */
+ @Override
+ public Location with( Property newIdProperty ) {
+ if (newIdProperty == null || newIdProperty.isEmpty()) return this;
+
+ // A new property with same name overrides the old property with the same name
+ if (newIdProperty.getName().equals(idProperty.getName())) return
Location.create(path, newIdProperty);
+
+ List<Property> newIdProperties = new ArrayList<Property>(2);
+ newIdProperties.add(idProperty);
+ newIdProperties.add(newIdProperty);
+
+ return Location.create(path, newIdProperties);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#with(Path)
+ */
+ @Override
+ public Location with( Path newPath ) {
+ if (newPath == null && path == null) return this;
+ if (path != null && (path.equals(newPath))) return this;
+
+ return Location.create(newPath, idProperty);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#with(UUID)
+ */
+ @Override
+ public Location with( UUID uuid ) {
+ if (uuid == null) return this;
+
+ // A new property with same name overrides the old property with the same name
+ if (idProperty.getName().equals(DnaLexicon.UUID)) return Location.create(path,
uuid);
+
+ List<Property> newIdProperties = new ArrayList<Property>(2);
+ newIdProperties.add(idProperty);
+ newIdProperties.add(new BasicSingleValueProperty(DnaLexicon.UUID, uuid));
+
+ return Location.create(path, newIdProperties);
+ }
+}
Property changes on:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/PathPropertyLocation.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/dna-graph/src/test/java/org/jboss/dna/graph/LocationTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/LocationTest.java
(rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/LocationTest.java 2009-02-23
15:55:50 UTC (rev 733)
@@ -0,0 +1,235 @@
+/*
+ * JBoss DNA (
http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.graph;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertThat;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.jboss.dna.common.text.NoOpEncoder;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.PathFactory;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.basic.BasicNamespaceRegistry;
+import org.jboss.dna.graph.property.basic.BasicSingleValueProperty;
+import org.jboss.dna.graph.property.basic.NameValueFactory;
+import org.jboss.dna.graph.property.basic.PathValueFactory;
+import org.jboss.dna.graph.property.basic.StringValueFactory;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+/**
+ * Tests <code>Location</code> class and factory constructors.
+ */
+public class LocationTest {
+
+ private static final NoOpEncoder NO_OP_ENCODER = new NoOpEncoder();
+ private static final StringValueFactory STRING_VALUE_FACTORY = new
StringValueFactory(NO_OP_ENCODER, NO_OP_ENCODER);
+ private static final NameValueFactory NAME_VALUE_FACTORY = new NameValueFactory(new
BasicNamespaceRegistry("http://www.jboss.org/dna/1.0"), NO_OP_ENCODER,
STRING_VALUE_FACTORY);
+
+ private PathFactory pathFactory = new PathValueFactory(NO_OP_ENCODER,
+ STRING_VALUE_FACTORY, NAME_VALUE_FACTORY);
+
+ private static UUID uuid = UUID.randomUUID();
+
+ private Path pathA = pathFactory.create("/A");
+ private Path pathABC = pathFactory.create("/A/B/C");
+
+ private static Property propA = new
BasicSingleValueProperty(NAME_VALUE_FACTORY.create("A"), "Value A");
+ private static Property propB = new
BasicSingleValueProperty(NAME_VALUE_FACTORY.create("B"), "Value B");
+ private static Property propU = new BasicSingleValueProperty(DnaLexicon.UUID, uuid);
+
+ private static List<Property> propListAB;
+ private static List<Property> propListABU;
+
+
+ @BeforeClass
+ public static void beforeAny() {
+ propListAB = new ArrayList<Property>();
+ propListAB.add(propA);
+ propListAB.add(propB);
+
+ propListABU = new ArrayList<Property>();
+ propListABU.add(propA);
+ propListABU.add(propB);
+ propListABU.add(propU);
+
+ }
+
+ @Test
+ public void locationsWithSamePathsAreEqual() {
+ Location locationA1 = Location.create(pathA);
+ Location locationA2 = Location.create(pathA);
+
+ assertThat("Locations created with identical paths must be equal",
locationA1, is(locationA2));
+
+ Location locationABC1 = Location.create(pathABC);
+ Location locationABC2 = Location.create(pathABC);
+
+ assertThat("Locations created with identical non-trivial paths must be
equal", locationABC1, is(locationABC2));
+ }
+
+ @Test
+ public void locationsWithSamePathsAreSame() {
+ Location locationA1 = Location.create(pathA);
+ Location locationA2 = Location.create(pathA);
+
+ assertThat("isSame must return true for locations created with identical
paths", locationA1.isSame(locationA2), is(true));
+
+ Location locationABC1 = Location.create(pathABC);
+ Location locationABC2 = Location.create(pathABC);
+
+ assertThat("isSame must return true for locations created with identical,
non-trivial paths", locationABC1.isSame(locationABC2), is(true));
+ }
+
+ @Test
+ public void locationsWithSamePathsAndSamePropertyAreNotEqual() {
+ Location locationA1 = Location.create(pathA, propA);
+ Location locationA2 = Location.create(pathA, propA);
+
+ assertThat("Locations created with identical paths and different property must
be equal", locationA1, is(locationA2));
+ }
+
+ @Test
+ public void locationsWithSamePathsAndSamePropertyAreNotSame() {
+ Location locationA1 = Location.create(pathA, propA);
+ Location locationA2 = Location.create(pathA, propA);
+
+ assertThat("isSame must return true for locations created with identical paths
and property", locationA1.isSame(locationA2), is(true));
+ }
+
+ @Test
+ public void locationsWithSamePathsAndDifferentPropertyAreNotEqual() {
+ Location locationA1 = Location.create(pathA, propA);
+ Location locationA2 = Location.create(pathA, propB);
+
+ assertThat("Locations created with identical paths and different property must
not be equal", locationA1, not(locationA2));
+ }
+
+ @Test
+ public void locationsWithSamePathsAndDifferentPropertyAreNotSame() {
+ Location locationA1 = Location.create(pathA, propA);
+ Location locationA2 = Location.create(pathA, propB);
+
+ assertThat("isSame must not return true for locations created with identical
paths and property", locationA1.isSame(locationA2), is(false));
+ }
+
+ @Test
+ public void locationsWithDifferentPathsAndSamePropertyAreNotEqual() {
+ Location locationA1 = Location.create(pathA, propA);
+ Location locationA2 = Location.create(pathABC, propA);
+
+ assertThat("Locations created with different paths and the same property must
not be equal", locationA1, not(locationA2));
+ }
+
+ @Test
+ public void locationsWithDifferentPathsAndSamePropertyAreNotSame() {
+ Location locationA1 = Location.create(pathA, propA);
+ Location locationA2 = Location.create(pathABC, propA);
+
+ assertThat("isSame must not return true for locations created with different
paths and the same property", locationA1.isSame(locationA2), is(false));
+ }
+
+ @Test
+ public void locationsWithSamePathsAndSamePropertiesAreNotEqual() {
+ Location locationA1 = Location.create(pathA, propListAB);
+ Location locationA2 = Location.create(pathA, propListAB);
+
+ assertThat("Locations created with identical paths and different properties
must be equal", locationA1, is(locationA2));
+ }
+
+ @Test
+ public void locationsWithSamePathsAndSamePropertiesAreNotSame() {
+ Location locationA1 = Location.create(pathA, propListAB);
+ Location locationA2 = Location.create(pathA, propListAB);
+
+ assertThat("isSame must return true for locations created with identical paths
and properties", locationA1.isSame(locationA2), is(true));
+ }
+
+ @Test
+ public void locationsWithSamePathsAndDifferentPropertiesAreNotEqual() {
+ Location locationA1 = Location.create(pathA, propListAB);
+ Location locationA2 = Location.create(pathA, propListABU);
+
+ assertThat("Locations created with identical paths and different properties
must not be equal", locationA1, not(locationA2));
+ }
+
+ @Test
+ public void locationsWithSamePathsAndDifferentPropertiesAreNotSame() {
+ Location locationA1 = Location.create(pathA, propListAB);
+ Location locationA2 = Location.create(pathA, propListABU);
+
+ assertThat("isSame must not return true for locations created with identical
paths and different properties", locationA1.isSame(locationA2), is(false));
+ }
+
+ @Test
+ public void locationsWithDifferentPathsAndSamePropertiesAreNotEqual() {
+ Location locationA1 = Location.create(pathA, propListAB);
+ Location locationA2 = Location.create(pathABC, propListAB);
+
+ assertThat("Locations created with identical paths and different properties
must not be equal", locationA1, not(locationA2));
+ }
+
+ @Test
+ public void locationsWithDifferentPathsAndSamePropertiesAreNotSame() {
+ Location locationA1 = Location.create(pathA, propListAB);
+ Location locationA2 = Location.create(pathABC, propListAB);
+
+ assertThat("isSame must not return true for locations created with different
paths and the same properties", locationA1.isSame(locationA2), is(false));
+ }
+
+ @Test
+ public void testTransitivityOfWithOperationForPathAndUUID() {
+ Location locationA1 = Location.create(pathA);
+ locationA1 = locationA1.with(uuid);
+
+ Location locationU1 = Location.create(uuid);
+ locationU1 = locationU1.with(pathA);
+
+ assertThat("With() operation must be transitive for equals",
locationA1.equals(locationU1), is(true));
+ assertThat("With() operation must be transitive for isSame",
locationA1.isSame(locationU1), is(true));
+ assertThat("With() operation must be transitive for getString",
locationA1.getString().equals(locationU1.getString()), is(true));
+ assertThat("With() operation must be transitive for hashCode",
locationA1.hashCode() == locationU1.hashCode(), is(true));
+ }
+
+ @Test
+ public void testTransitivityOfWithOperationForPathAndProperty() {
+ Location locationA1 = Location.create(pathA);
+ locationA1 = locationA1.with(propB);
+
+ Location locationU1 = Location.create(propB);
+ locationU1 = locationU1.with(pathA);
+
+ assertThat("With() operation must be transitive for equals",
locationA1.equals(locationU1), is(true));
+ assertThat("With() operation must be transitive for isSame",
locationA1.isSame(locationU1), is(true));
+ assertThat("With() operation must be transitive for getString",
locationA1.getString().equals(locationU1.getString()), is(true));
+ assertThat("With() operation must be transitive for hashCode",
locationA1.hashCode() == locationU1.hashCode(), is(true));
+ }
+
+}
Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/LocationTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain