Index: dna-graph/src/main/java/org/jboss/dna/graph/Graph.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/Graph.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/Graph.java (working copy) @@ -6323,7 +6323,7 @@ public class Graph { public boolean equals( Object obj ) { if (obj instanceof Node) { Node that = (Node)obj; - return this.getLocation().equals(that.getLocation()); + return this.getLocation().isSame(that.getLocation()); } return false; } @@ -6591,7 +6591,7 @@ public class Graph { public boolean equals( Object obj ) { if (obj instanceof Node) { Node that = (Node)obj; - return this.location.equals(that.getLocation()); + return this.location.isSame(that.getLocation()); } return false; } @@ -6799,7 +6799,7 @@ public class Graph { public boolean equals( Object obj ) { if (obj instanceof Node) { Node that = (Node)obj; - return this.location.equals(that.getLocation()); + return this.location.isSame(that.getLocation()); } return false; } Index: dna-graph/src/main/java/org/jboss/dna/graph/GraphI18n.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/GraphI18n.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/GraphI18n.java (working copy) @@ -73,7 +73,7 @@ public final class GraphI18n { public static I18n unableToCreateReferenceToNodeWithoutUuid; public static I18n unableToCopyToLocationWithoutAPath; public static I18n unableToCopyToTheRoot; - public static I18n actualLocationIsNotSameAsInputLocation; + public static I18n actualLocationNotEqualToInputLocation; public static I18n actualLocationIsNotChildOfInputLocation; public static I18n actualLocationIsNotAtCorrectChildSegment; public static I18n actualLocationDoesNotHaveCorrectChildName; Index: dna-graph/src/main/java/org/jboss/dna/graph/Location.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/Location.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/Location.java (working copy) @@ -41,7 +41,8 @@ import org.jboss.dna.graph.property.Path; import org.jboss.dna.graph.property.Property; /** - * The location of a node, as specified by either its path, UUID, and/or identification properties. + * The location of a node, as specified by either its path, UUID, and/or identification properties. Hash codes are not implemented + * in this base class to allow immutable subclasses to calculate and cache the hash code during object construction. */ @Immutable public abstract class Location implements Iterable, Comparable { @@ -97,7 +98,6 @@ public abstract class Location implements Iterable, Comparable, Comparable, Comparable, Comparable, Comparable, Comparable idProperties = new ArrayList(1 + remainingIdProperties.length); Set names = new HashSet(); names.add(firstIdProperty.getName()); @@ -249,16 +250,7 @@ public abstract class Location implements Iterable, Comparable, Comparable - *
  • location A is defined with a "/x/y" path
  • - *
  • location B is defined with an identification property {id=3}
  • - *
  • location C is defined with a "/x/y/z"
  • - *
  • location D is defined with a "/x/y/z" path and an identification property {id=3}
  • - * - * Locations C and D would be considered the same, and B and D would also be considered the same. None of the other - * combinations would be considered the same. - *

    - * Note that passing a null location as a parameter will always return false. - *

    - * - * @param other the other location to compare - * @return true if the two locations represent the same location, or false otherwise - */ - public boolean isSame( Location other ) { - return isSame(other, true); - } - - /** - * Compare this location to the supplied location, and determine whether the two locations represent the same logical - * location. One location is considered the same as another location when one location is a superset of the other. For - * example, consider the following locations: - *
      - *
    • location A is defined with a "/x/y" path
    • - *
    • location B is defined with an identification property {id=3}
    • - *
    • location C is defined with a "/x/y/z"
    • - *
    • location D is defined with a "/x/y/z" path and an identification property {id=3}
    • - *
    - * Locations C and D would be considered the same, and B and D would also be considered the same. None of the other - * combinations would be considered the same. - *

    - * Note that passing a null location as a parameter will always return false. - *

    - * - * @param other the other location to compare - * @param requireSameNameSiblingIndexes true if the paths must have equivalent {@link Path.Segment#getIndex() - * same-name-sibling indexes}, or false if the same-name-siblings may be different - * @return true if the two locations represent the same location, or false otherwise - */ - public boolean isSame( Location other, - boolean requireSameNameSiblingIndexes ) { - if (other != null) { - if (this.hasPath() && other.hasPath()) { - // Paths on both, so the paths MUST match - if (requireSameNameSiblingIndexes) { - if (!this.getPath().equals(other.getPath())) return false; - } else { - Path thisPath = this.getPath(); - Path thatPath = other.getPath(); - if (thisPath.isRoot()) return thatPath.isRoot(); - if (thatPath.isRoot()) return thisPath.isRoot(); - // The parents must match ... - if (!thisPath.hasSameAncestor(thatPath)) return false; - // And the names of the last segments must match ... - if (!thisPath.getLastSegment().getName().equals(thatPath.getLastSegment().getName())) return false; - } - - // And the identification properties must match only if they exist on both - if (this.hasIdProperties() && other.hasIdProperties()) { - return this.getIdProperties().containsAll(other.getIdProperties()); - } - return true; - } - // Path only in one, so the identification properties MUST match - if (!other.hasIdProperties()) return false; - return this.getIdProperties().containsAll(other.getIdProperties()); + public boolean isSame( Location that ) { + if (that == null) return false; + if (this.hasPath()) { + if (!this.getPath().equals(that.getPath())) return false; + } else if (that.hasPath()) return false; + if (this.hasIdProperties()) { + if (that.hasIdProperties()) return this.getIdProperties().containsAll(that.getIdProperties()); + return false; } - return false; + return (!that.hasIdProperties()); } /** @@ -438,20 +367,69 @@ public abstract class Location implements Iterable, Comparable + *
  • location A is defined with a "/x/y" path
  • + *
  • location B is defined with an identification property {id=3}
  • + *
  • location C is defined with a "/x/y/z"
  • + *
  • location D is defined with a "/x/y/z" path and an identification property {id=3}
  • + * + * Locations C and D would be considered the same, and B and D would also be considered the same. None of the other + * combinations would be considered the same. + *

    + * Note that passing a null location as a parameter will always return false. + *

    + * + * @param obj the other location to compare + * @param requireSameNameSiblingIndexes true if the paths must have equivalent {@link Path.Segment#getIndex() + * same-name-sibling indexes}, or false if the same-name-siblings may be different + * @return true if the two locations represent the same location, or false otherwise + */ + public boolean equals( Object obj, + boolean requireSameNameSiblingIndexes ) { + // if (obj instanceof Location) { + // Location that = (Location)obj; + // if (this.hasPath()) { + // if (!this.getPath().equals(that.getPath())) return false; + // } else { + // if (that.hasPath()) return false; + // } + // if (this.hasIdProperties()) { + // if (!this.getIdProperties().equals(that.getIdProperties())) return + // false; + // } else { + // if (that.hasIdProperties()) return false; + // } + // return true; + // } + // return false; if (obj instanceof Location) { Location that = (Location)obj; - if (this.hasPath()) { - if (!this.getPath().equals(that.getPath())) return false; - } else { - if (that.hasPath()) return false; - } - if (this.hasIdProperties()) { - if (!this.getIdProperties().equals(that.getIdProperties())) return false; + + // if both have same path they are equal + if (requireSameNameSiblingIndexes) { + if (this.hasPath() && that.hasPath()) return (this.getPath().equals(that.getPath())); } else { - if (that.hasIdProperties()) return false; + Path thisPath = this.getPath(); + Path thatPath = that.getPath(); + if (thisPath.isRoot()) return thatPath.isRoot(); + if (thatPath.isRoot()) return thisPath.isRoot(); + // The parents must match ... + if (!thisPath.hasSameAncestor(thatPath)) return false; + // And the names of the last segments must match ... + if (!thisPath.getLastSegment().getName().equals(thatPath.getLastSegment().getName())) return false; } - return true; + + // one or both is/are missing path so check properties instead + if (this.hasIdProperties()) return (this.getIdProperties().equals(that.getIdProperties())); } + return false; } Index: dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPath.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPath.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPath.java (working copy) @@ -39,7 +39,7 @@ import org.jboss.dna.graph.property.Property; * @see Location */ @Immutable -final class LocationWithPath extends Location { +class LocationWithPath extends Location { private final Path path; private final int hashCode; @@ -79,7 +79,7 @@ final class LocationWithPath extends Location { * @see Location#getIdProperties() */ @Override - public final List getIdProperties() { + public List getIdProperties() { return null; } @@ -89,7 +89,7 @@ final class LocationWithPath extends Location { * @see Location#hasIdProperties() */ @Override - public final boolean hasIdProperties() { + public boolean hasIdProperties() { return false; } @@ -99,7 +99,7 @@ final class LocationWithPath extends Location { * @see Location#getUuid() */ @Override - public final UUID getUuid() { + public UUID getUuid() { return null; } @@ -137,7 +137,7 @@ final class LocationWithPath extends Location { @Override public Location with( Property newIdProperty ) { if (newIdProperty == null || newIdProperty.isEmpty()) return this; - return Location.create(path, newIdProperty); + return create(path, newIdProperty); } /** @@ -148,7 +148,7 @@ final class LocationWithPath extends Location { @Override public Location with( Path newPath ) { if (newPath == null || path.equals(newPath)) return this; - return Location.create(newPath); + return create(newPath); } /** @@ -159,6 +159,6 @@ final class LocationWithPath extends Location { @Override public Location with( UUID uuid ) { if (uuid == null) return this; - return Location.create(path, uuid); + return create(path, uuid); } } Index: dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndProperties.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndProperties.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndProperties.java (working copy) @@ -27,8 +27,9 @@ 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.HashCode; + import org.jboss.dna.graph.property.Path; import org.jboss.dna.graph.property.Property; import org.jboss.dna.graph.property.basic.BasicSingleValueProperty; @@ -40,13 +41,10 @@ import org.jboss.dna.graph.property.basic.BasicSingleValueProperty; * @see Location */ @Immutable -final class LocationWithPathAndProperties extends Location { +class LocationWithPathAndProperties extends LocationWithPath { - private final Path path; private final List idProperties; - private final int hashCode; - /** * Create a new location with a given path and set of identification properties. * @@ -55,25 +53,10 @@ final class LocationWithPathAndProperties extends Location { */ LocationWithPathAndProperties( Path path, List idProperties ) { - assert path != null; + super(path); assert idProperties != null; assert !idProperties.isEmpty(); - 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; } /** @@ -87,23 +70,28 @@ final class LocationWithPathAndProperties extends Location { } /** - * {@inheritDoc} + * Get the first UUID that is in one of the {@link #getIdProperties() identification properties}. * - * @see Location#hasIdProperties() + * @return the UUID for this location, or null if there is no such identification property */ @Override - public final boolean hasIdProperties() { - return idProperties.size() > 0; + public UUID getUuid() { + Property property = getIdProperty(DnaLexicon.UUID); + if (property != null && !property.isEmpty()) { + Object value = property.getFirstValue(); + if (value instanceof UUID) return (UUID)value; + } + return null; } /** * {@inheritDoc} * - * @see Location#hashCode() + * @see Location#hasIdProperties() */ @Override - public int hashCode() { - return hashCode; + public boolean hasIdProperties() { + return idProperties.size() > 0; } /** @@ -124,9 +112,9 @@ final class LocationWithPathAndProperties extends Location { } newIdProperties.add(newIdProperty); newIdProperties = Collections.unmodifiableList(newIdProperties); - return new LocationWithPathAndProperties(path, newIdProperties); + return create(getPath(), newIdProperties); } - return new LocationWithPathAndProperty(path, newIdProperty); + return create(getPath(), newIdProperty); } /** @@ -137,7 +125,7 @@ final class LocationWithPathAndProperties extends Location { @Override public Location with( Path newPath ) { if (newPath == null || newPath.equals(this.getPath())) return this; - return new LocationWithPathAndProperties(newPath, idProperties); + return create(newPath, idProperties); } /** @@ -157,6 +145,6 @@ final class LocationWithPathAndProperties extends Location { List newIdProperties = new ArrayList(idProperties.size() + 1); newIdProperties.addAll(idProperties); newIdProperties.add(newProperty); - return new LocationWithPathAndProperties(path, newIdProperties); + return create(getPath(), newIdProperties); } } Index: dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndProperty.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndProperty.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndProperty.java (working copy) @@ -24,11 +24,9 @@ package org.jboss.dna.graph; 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; @@ -41,12 +39,7 @@ import org.jboss.dna.graph.property.basic.BasicSingleValueProperty; * @see Location */ @Immutable -final class LocationWithPathAndProperty extends Location { - - private final Path path; - private final List idProperties; - - private final int hashCode; +class LocationWithPathAndProperty extends LocationWithPathAndProperties { /** * Create a new location with a given path and identification property. @@ -56,56 +49,9 @@ final class LocationWithPathAndProperty extends Location { */ LocationWithPathAndProperty( Path path, Property idProperty ) { - assert path != null; + super(path, Collections.singletonList(idProperty)); assert idProperty != null; assert !idProperty.isEmpty(); - this.path = path; - 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(this.path, idProperties); - } - - /** - * {@inheritDoc} - * - * @see Location#getPath() - */ - @Override - public final Path getPath() { - return path; - } - - /** - * {@inheritDoc} - * - * @see org.jboss.dna.graph.Location#hasPath() - */ - @Override - public final boolean hasPath() { - return true; - } - - /** - * {@inheritDoc} - * - * @see Location#getIdProperties() - */ - @Override - public final List getIdProperties() { - return idProperties; - } - - /** - * {@inheritDoc} - * - * @see Location#hasIdProperties() - */ - @Override - public final boolean hasIdProperties() { - return true; } /** @@ -116,7 +62,7 @@ final class LocationWithPathAndProperty extends Location { @Override public final Property getIdProperty( Name name ) { CheckArg.isNotNull(name, "name"); - Property property = idProperties.get(0); // this is fast + Property property = getIdProperties().get(0); // this is fast return property.getName().equals(name) ? property : null; } @@ -127,7 +73,7 @@ final class LocationWithPathAndProperty extends Location { */ @Override public UUID getUuid() { - Property property = idProperties.get(0); // this is fast + Property property = getIdProperties().get(0); // this is fast if (DnaLexicon.UUID.equals(property.getName())) { Object value = property.getFirstValue(); if (value instanceof UUID) return (UUID)value; @@ -138,14 +84,14 @@ final class LocationWithPathAndProperty extends Location { /** * {@inheritDoc} - * - * @see Location#hashCode() + * + * @see org.jboss.dna.graph.LocationWithPathAndProperties#hasIdProperties() */ @Override - public int hashCode() { - return hashCode; + public final boolean hasIdProperties() { + return true; } - + /** * {@inheritDoc} * @@ -154,11 +100,11 @@ final class LocationWithPathAndProperty extends Location { @Override public Location with( Property newIdProperty ) { if (newIdProperty == null || newIdProperty.isEmpty()) return this; - Property idProperty = idProperties.get(0); // fast + Property idProperty = getIdProperties().get(0); // fast if (newIdProperty.getName().equals(idProperty.getName())) { - return new LocationWithPathAndProperty(path, newIdProperty); + return Location.create(getPath(), newIdProperty); } - return Location.create(path, idProperty, newIdProperty); + return Location.create(getPath(), idProperty, newIdProperty); } /** @@ -168,10 +114,10 @@ final class LocationWithPathAndProperty extends Location { */ @Override public Location with( Path newPath ) { - if (newPath == null) return Location.create(idProperties); - if (path.equals(newPath)) return this; - Property idProperty = idProperties.get(0); // fast - return new LocationWithPathAndProperty(newPath, idProperty); + if (newPath == null) return Location.create(getIdProperties()); + if (getPath().equals(newPath)) return this; + Property idProperty = getIdProperties().get(0); // fast + return Location.create(newPath, idProperty); } /** @@ -181,10 +127,10 @@ final class LocationWithPathAndProperty extends Location { */ @Override public Location with( UUID uuid ) { - Property idProperty = idProperties.get(0); // fast - if (uuid == null) return Location.create(path); + Property idProperty = getIdProperties().get(0); // fast + if (uuid == null) return Location.create(getPath()); assert !DnaLexicon.UUID.equals(idProperty.getName()); Property newUuidProperty = new BasicSingleValueProperty(DnaLexicon.UUID, uuid); - return Location.create(path, idProperty, newUuidProperty); + return Location.create(getPath(), idProperty, newUuidProperty); } } Index: dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndUuid.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndUuid.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndUuid.java (working copy) @@ -23,13 +23,8 @@ */ package org.jboss.dna.graph; -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; @@ -41,12 +36,9 @@ import org.jboss.dna.graph.property.basic.BasicSingleValueProperty; * @see Location */ @Immutable -final class LocationWithPathAndUuid extends Location { +final class LocationWithPathAndUuid extends LocationWithPathAndProperty { - private final Path path; - private final List idProperties; - - private final int hashCode; + private final UUID uuid; /** * Create a new location with a given path and identification property. @@ -56,67 +48,9 @@ final class LocationWithPathAndUuid extends Location { */ LocationWithPathAndUuid( Path path, UUID uuid ) { - assert path != null; + super(path, new BasicSingleValueProperty(DnaLexicon.UUID, uuid)); assert uuid != null; - this.path = path; - this.idProperties = Collections.singletonList((Property)new BasicSingleValueProperty(DnaLexicon.UUID, uuid)); - - // 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(this.path, idProperties); - } - - /** - * {@inheritDoc} - * - * @see Location#getPath() - */ - @Override - public final Path getPath() { - return path; - } - - /** - * {@inheritDoc} - * - * @see org.jboss.dna.graph.Location#hasPath() - */ - @Override - public final boolean hasPath() { - return true; - } - - /** - * {@inheritDoc} - * - * @see Location#getIdProperties() - */ - @Override - public final List 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"); - Property property = idProperties.get(0); // this is fast - return property.getName().equals(name) ? property : null; + this.uuid = uuid; } /** @@ -126,17 +60,7 @@ final class LocationWithPathAndUuid extends Location { */ @Override public final UUID getUuid() { - return (UUID)idProperties.get(0).getFirstValue(); // this is fast, and we know this is a UUID object - } - - /** - * {@inheritDoc} - * - * @see Location#hashCode() - */ - @Override - public int hashCode() { - return hashCode; + return uuid; } /** @@ -145,13 +69,13 @@ final class LocationWithPathAndUuid extends Location { * @see Location#with(Property) */ @Override - public Location with( Property newIdProperty ) { - if (newIdProperty == null || newIdProperty.isEmpty()) return this; - Property idProperty = idProperties.get(0); // fast - if (newIdProperty.getName().equals(idProperty.getName())) { - return new LocationWithPathAndProperty(path, newIdProperty); + public Location with( Property idProperty ) { + if (idProperty == null || idProperty.isEmpty()) return this; + if (DnaLexicon.UUID.equals(idProperty.getName())) { + if (idProperty.isSingle() && uuid.equals(idProperty.getFirstValue())) return this; + return Location.create(getPath(), idProperty); } - return Location.create(path, idProperty, newIdProperty); + return Location.create(getPath(), getIdProperties().get(0), idProperty); } /** @@ -160,11 +84,10 @@ final class LocationWithPathAndUuid extends Location { * @see Location#with(Path) */ @Override - public Location with( Path newPath ) { - if (newPath == null) return Location.create(idProperties); - if (path.equals(newPath)) return this; - Property idProperty = idProperties.get(0); // fast - return new LocationWithPathAndProperty(newPath, idProperty); + public Location with( Path path ) { + if (path == null) return Location.create(uuid); + if (getPath().equals(path)) return this; + return Location.create(path, uuid); } /** @@ -174,8 +97,8 @@ final class LocationWithPathAndUuid extends Location { */ @Override public Location with( UUID uuid ) { - if (uuid == null) return Location.create(path); - if (uuid.equals(getUuid())) return this; - return new LocationWithPathAndUuid(path, uuid); + if (uuid == null) return Location.create(getPath()); + if (uuid.equals(this.uuid)) return this; + return Location.create(getPath(), uuid); } } Index: dna-graph/src/main/java/org/jboss/dna/graph/LocationWithProperties.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/LocationWithProperties.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/LocationWithProperties.java (working copy) @@ -40,7 +40,7 @@ import org.jboss.dna.graph.property.basic.BasicSingleValueProperty; * @see Location */ @Immutable -final class LocationWithProperties extends Location { +class LocationWithProperties extends Location { private final List idProperties; private final int hashCode; @@ -57,7 +57,7 @@ final class LocationWithProperties extends Location { // 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(null, idProperties); + hashCode = HashCode.compute(idProperties); } /** @@ -128,7 +128,7 @@ final class LocationWithProperties extends Location { } newIdProperties.add(newIdProperty); newIdProperties = Collections.unmodifiableList(newIdProperties); - return new LocationWithProperties(newIdProperties); + return create(newIdProperties); } /** @@ -139,7 +139,7 @@ final class LocationWithProperties extends Location { @Override public Location with( Path newPath ) { if (newPath == null) return this; - return new LocationWithPathAndProperties(newPath, idProperties); + return create(newPath, idProperties); } /** @@ -159,6 +159,6 @@ final class LocationWithProperties extends Location { List newIdProperties = new ArrayList(idProperties.size() + 1); newIdProperties.addAll(idProperties); newIdProperties.add(newProperty); - return new LocationWithProperties(newIdProperties); + return create(newIdProperties); } } Index: dna-graph/src/main/java/org/jboss/dna/graph/LocationWithProperty.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/LocationWithProperty.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/LocationWithProperty.java (working copy) @@ -29,7 +29,6 @@ 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; @@ -42,11 +41,7 @@ import org.jboss.dna.graph.property.basic.BasicSingleValueProperty; * @see Location */ @Immutable -final class LocationWithProperty extends Location { - - protected final List idProperties; - - private final int hashCode; +final class LocationWithProperty extends LocationWithProperties { /** * Create a new location with a given path and identification property. @@ -54,55 +49,9 @@ final class LocationWithProperty extends Location { * @param idProperty the identification property */ LocationWithProperty( Property idProperty ) { + super(Collections.singletonList(idProperty)); assert idProperty != null; assert !idProperty.isEmpty(); - // The path could be null - 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(null, idProperties); - } - - /** - * {@inheritDoc} - * - * @see Location#getPath() - */ - @Override - public final Path getPath() { - return null; - } - - /** - * {@inheritDoc} - * - * @see org.jboss.dna.graph.Location#hasPath() - */ - @Override - public boolean hasPath() { - return false; - } - - /** - * {@inheritDoc} - * - * @see Location#getIdProperties() - */ - @Override - public final List getIdProperties() { - return idProperties; - } - - /** - * {@inheritDoc} - * - * @see Location#hasIdProperties() - */ - @Override - public final boolean hasIdProperties() { - return true; } /** @@ -113,7 +62,7 @@ final class LocationWithProperty extends Location { @Override public final Property getIdProperty( Name name ) { CheckArg.isNotNull(name, "name"); - Property property = idProperties.get(0); // this is fast + Property property = getIdProperties().get(0); // this is fast return property.getName().equals(name) ? property : null; } @@ -124,7 +73,7 @@ final class LocationWithProperty extends Location { */ @Override public UUID getUuid() { - Property property = idProperties.get(0); // this is fast + Property property = getIdProperties().get(0); // this is fast if (DnaLexicon.UUID.equals(property.getName())) { Object value = property.getFirstValue(); if (value instanceof UUID) return (UUID)value; @@ -136,29 +85,19 @@ final class LocationWithProperty extends Location { /** * {@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; - Property idProperty = idProperties.get(0); // fast + Property idProperty = getIdProperties().get(0); // fast if (newIdProperty.getName().equals(idProperty.getName())) { return Location.create(newIdProperty); } - List newIdProperties = new ArrayList(idProperties.size() + 1); + List newIdProperties = new ArrayList(getIdProperties().size() + 1); newIdProperties.add(newIdProperty); - newIdProperties.addAll(idProperties); - return new LocationWithProperties(newIdProperties); + newIdProperties.addAll(getIdProperties()); + return Location.create(newIdProperties); } /** @@ -169,8 +108,8 @@ final class LocationWithProperty extends Location { @Override public Location with( Path newPath ) { if (newPath == null) return this; - Property idProperty = idProperties.get(0); // fast - return new LocationWithPathAndProperty(newPath, idProperty); + Property idProperty = getIdProperties().get(0); // fast + return Location.create(newPath, idProperty); } /** @@ -181,13 +120,13 @@ final class LocationWithProperty extends Location { @Override public Location with( UUID uuid ) { if (uuid == null) return this; - Property idProperty = idProperties.get(0); // fast + Property idProperty = getIdProperties().get(0); // fast if (DnaLexicon.UUID.equals(idProperty.getName())) { - return new LocationWithUuid(uuid); + return Location.create(uuid); } - List newIdProperties = new ArrayList(idProperties.size() + 1); + List newIdProperties = new ArrayList(getIdProperties().size() + 1); newIdProperties.add(new BasicSingleValueProperty(DnaLexicon.UUID, uuid)); - newIdProperties.addAll(idProperties); - return new LocationWithProperties(newIdProperties); + newIdProperties.addAll(getIdProperties()); + return Location.create(newIdProperties); } } Index: dna-graph/src/main/java/org/jboss/dna/graph/LocationWithUuid.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/LocationWithUuid.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/LocationWithUuid.java (working copy) @@ -130,7 +130,7 @@ final class LocationWithUuid extends Location { */ @Override public Location with( UUID uuid ) { - return new LocationWithUuid(uuid); + return Location.create(uuid); } /** Index: dna-graph/src/main/java/org/jboss/dna/graph/connector/federation/ProjectedNode.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/connector/federation/ProjectedNode.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/connector/federation/ProjectedNode.java (working copy) @@ -140,7 +140,7 @@ class ProxyNode extends ProjectedNode { super(locationInSource); this.projection = projection; this.federatedLocation = locationInFederated; - this.sameLocationAsOriginal = locationInSource.equals(locationInFederated); + this.sameLocationAsOriginal = locationInSource.isSame(locationInFederated); } protected ProxyNode( Projection projection, Index: dna-graph/src/main/java/org/jboss/dna/graph/observe/NetChangeObserver.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/observe/NetChangeObserver.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/observe/NetChangeObserver.java (working copy) @@ -303,7 +303,7 @@ public abstract class NetChangeObserver extends ChangeObserver { if (that == this) return true; if (this.hc != that.hc) return false; if (!this.workspaceName.equals(that.workspaceName)) return false; - if (!this.location.equals(that.location)) return false; + if (!this.location.isSame(that.location)) return false; return true; } Index: dna-graph/src/main/java/org/jboss/dna/graph/query/process/MergeJoinComponent.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/query/process/MergeJoinComponent.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/query/process/MergeJoinComponent.java (working copy) @@ -178,7 +178,7 @@ public class MergeJoinComponent extends JoinComponent { for (int i = columns.getColumnCount(); i != columns.getLocationCount(); ++i) { Location location = (Location)tuple1[i]; Location location2 = (Location)tuple2[i]; - if (!location.equals(location2)) return false; + if (!location.isSame(location2)) return false; } return true; } Index: dna-graph/src/main/java/org/jboss/dna/graph/request/BatchRequestBuilder.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/request/BatchRequestBuilder.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/request/BatchRequestBuilder.java (working copy) @@ -426,7 +426,7 @@ public class BatchRequestBuilder { // If there's a pending request ... if (pendingRequest != null) { // Compare the supplied location with that of the pending request - if (pendingRequest.location.equals(on)) { + if (pendingRequest.location.isSame(on)) { // They are the same location, so we can add the properties to the pending request ... pendingRequest.pendingProperties.put(property.getName(), property); return this; @@ -456,7 +456,7 @@ public class BatchRequestBuilder { // If there's a pending request ... if (pendingRequest != null) { // Compare the supplied location with that of the pending request - if (pendingRequest.location.equals(on)) { + if (pendingRequest.location.isSame(on)) { // They are the same location, so we can add the properties to the pending request ... for (Property property : properties) { pendingRequest.pendingProperties.put(property.getName(), property); @@ -492,7 +492,7 @@ public class BatchRequestBuilder { // If there's a pending request ... if (pendingRequest != null) { // Compare the supplied location with that of the pending request - if (pendingRequest.location.equals(on)) { + if (pendingRequest.location.isSame(on)) { // They are the same location, so we can add the properties to the pending request ... pendingRequest.pendingProperties.put(propertyName, null); return this; @@ -523,7 +523,7 @@ public class BatchRequestBuilder { // If there's a pending request ... if (pendingRequest != null) { // Compare the supplied location with that of the pending request - if (pendingRequest.location.equals(on)) { + if (pendingRequest.location.isSame(on)) { // They are the same location, so we can add the properties to the pending request ... for (Name propertyName : propertyNames) { pendingRequest.pendingProperties.put(propertyName, null); Index: dna-graph/src/main/java/org/jboss/dna/graph/request/CloneBranchRequest.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/request/CloneBranchRequest.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/request/CloneBranchRequest.java (working copy) @@ -176,8 +176,8 @@ public class CloneBranchRequest extends ChangeRequest { public void setActualLocations( Location fromLocation, Location intoLocation ) { checkNotFrozen(); - if (!from.isSame(fromLocation)) { // not same if actual is null - throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(fromLocation, from)); + if (!from.equals(fromLocation)) { // not same if actual is null + throw new IllegalArgumentException(GraphI18n.actualLocationNotEqualToInputLocation.text(fromLocation, from)); } CheckArg.isNotNull(intoLocation, "intoLocation"); assert fromLocation != null; @@ -306,8 +306,8 @@ public class CloneBranchRequest extends ChangeRequest { if (obj == this) return true; if (this.getClass().isInstance(obj)) { CloneBranchRequest that = (CloneBranchRequest)obj; - if (!this.from().equals(that.from())) return false; - if (!this.into().equals(that.into())) return false; + if (!this.from().isSame(that.from())) return false; + if (!this.into().isSame(that.into())) return false; if (!this.fromWorkspace.equals(that.fromWorkspace)) return false; if (!this.intoWorkspace.equals(that.intoWorkspace)) return false; return true; Index: dna-graph/src/main/java/org/jboss/dna/graph/request/CopyBranchRequest.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/request/CopyBranchRequest.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/request/CopyBranchRequest.java (working copy) @@ -212,8 +212,8 @@ public class CopyBranchRequest extends ChangeRequest { public void setActualLocations( Location fromLocation, Location intoLocation ) { checkNotFrozen(); - if (!from.isSame(fromLocation)) { // not same if actual is null - throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(fromLocation, from)); + if (!from.equals(fromLocation)) { // not same if actual is null + throw new IllegalArgumentException(GraphI18n.actualLocationNotEqualToInputLocation.text(fromLocation, from)); } CheckArg.isNotNull(intoLocation, "intoLocation"); assert fromLocation != null; @@ -313,8 +313,8 @@ public class CopyBranchRequest extends ChangeRequest { if (obj == this) return true; if (this.getClass().isInstance(obj)) { CopyBranchRequest that = (CopyBranchRequest)obj; - if (!this.from().equals(that.from())) return false; - if (!this.into().equals(that.into())) return false; + if (!this.from().isSame(that.from())) return false; + if (!this.into().isSame(that.into())) return false; if (!this.nodeConflictBehavior().equals(that.nodeConflictBehavior())) return false; if (!this.fromWorkspace.equals(that.fromWorkspace)) return false; if (!this.intoWorkspace.equals(that.intoWorkspace)) return false; Index: dna-graph/src/main/java/org/jboss/dna/graph/request/CreateNodeRequest.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/request/CreateNodeRequest.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/request/CreateNodeRequest.java (working copy) @@ -282,7 +282,7 @@ public class CreateNodeRequest extends ChangeRequest implements Iterable actualAddedValues, List actualRemovedValues) { checkNotFrozen(); - if (!on.isSame(actual)) { // not same if actual is null - throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, on)); + if (!on.equals(actual)) { // not same if actual is null + throw new IllegalArgumentException(GraphI18n.actualLocationNotEqualToInputLocation.text(actual, on)); } assert actual != null; if (!actual.hasPath()) { Index: dna-graph/src/main/java/org/jboss/dna/graph/request/VerifyNodeExistsRequest.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/request/VerifyNodeExistsRequest.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/request/VerifyNodeExistsRequest.java (working copy) @@ -93,8 +93,8 @@ public class VerifyNodeExistsRequest extends CacheableRequest { */ public void setActualLocationOfNode( Location actual ) { checkNotFrozen(); - if (!at.isSame(actual)) { // not same if actual is null - throw new IllegalArgumentException(GraphI18n.actualLocationIsNotSameAsInputLocation.text(actual, at)); + if (!at.equals(actual)) { // not same if actual is null + throw new IllegalArgumentException(GraphI18n.actualLocationNotEqualToInputLocation.text(actual, at)); } assert actual != null; if (!actual.hasPath()) { @@ -155,7 +155,7 @@ public class VerifyNodeExistsRequest extends CacheableRequest { if (obj == this) return true; if (this.getClass().isInstance(obj)) { VerifyNodeExistsRequest that = (VerifyNodeExistsRequest)obj; - if (!this.at().equals(that.at())) return false; + if (!this.at().isSame(that.at())) return false; if (!this.inWorkspace().equals(that.inWorkspace())) return false; return true; } Index: dna-graph/src/main/java/org/jboss/dna/graph/request/processor/RequestProcessor.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/request/processor/RequestProcessor.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/request/processor/RequestProcessor.java (working copy) @@ -38,7 +38,6 @@ import org.jboss.dna.graph.GraphI18n; import org.jboss.dna.graph.Location; import org.jboss.dna.graph.cache.CachePolicy; import org.jboss.dna.graph.connector.LockFailedException; -import org.jboss.dna.graph.connector.RepositorySourceCapabilities; import org.jboss.dna.graph.observe.Changes; import org.jboss.dna.graph.observe.Observer; import org.jboss.dna.graph.property.DateTime; @@ -549,7 +548,7 @@ public abstract class RequestProcessor { if (count > request.count()) break; if (!found) { // Set to true if we find the child we're looking for ... - found = child.equals(request.startingAfter()); + found = child.isSame(request.startingAfter()); } else { // Add the child to the block ... ++count; Index: dna-graph/src/main/java/org/jboss/dna/graph/session/GraphSession.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/session/GraphSession.java (revision 1350) +++ dna-graph/src/main/java/org/jboss/dna/graph/session/GraphSession.java (working copy) @@ -1442,7 +1442,7 @@ public class GraphSession { org.jboss.dna.graph.Node persistentNode = cache.store.getNodeAt(getLocation()); // Check the actual location ... Location actualLocation = persistentNode.getLocation(); - if (!this.location.equals(actualLocation)) { + if (!this.location.isSame(actualLocation)) { // The actual location is changed, so update it ... this.location = actualLocation; } @@ -1452,7 +1452,7 @@ public class GraphSession { // Then read the node from the store ... Subgraph subgraph = cache.store.getSubgraphOfDepth(depth).at(getLocation()); Location actualLocation = subgraph.getLocation(); - if (!this.location.equals(actualLocation)) { + if (!this.location.isSame(actualLocation)) { // The actual location is changed, so update it ... this.location = actualLocation; } @@ -2708,7 +2708,7 @@ public class GraphSession { Node that = (Node)obj; if (this.isStale() || that.isStale()) return false; if (!this.nodeId.equals(that.nodeId)) return false; - return this.location.equals(that.location); + return this.location.isSame(that.location); } return false; } Index: dna-graph/src/main/resources/org/jboss/dna/graph/GraphI18n.properties =================================================================== --- dna-graph/src/main/resources/org/jboss/dna/graph/GraphI18n.properties (revision 1350) +++ dna-graph/src/main/resources/org/jboss/dna/graph/GraphI18n.properties (working copy) @@ -61,7 +61,7 @@ unableToAddMoreRequestsToAlreadyExecutedBatch = Unable to add more requests to a unableToCreateReferenceToNodeWithoutUuid = Unable to set a reference to node {0} since it has no UUID unableToCopyToLocationWithoutAPath = Unable to copy node "{0}" to "{1}" since the desired location has no path unableToCopyToTheRoot = Unable to copy node "{0}" to "{1}" since the desired location is the root node -actualLocationIsNotSameAsInputLocation = The actual location of {0} is not the same as the current location of {1} +actualLocationNotEqualToInputLocation = The actual location of {0} is not equal to the current location of {1} actualLocationIsNotChildOfInputLocation = The actual location of {0} is not a child of the specified location {1} actualLocationIsNotAtCorrectChildSegment = The last segment of the actual location of {0} does not have the requested child segment {1} actualLocationDoesNotHaveCorrectChildName = The last segment of the actual location of {0} does not have the requested child name {1} Index: dna-graph/src/test/java/org/jboss/dna/graph/LocationTest.java =================================================================== --- dna-graph/src/test/java/org/jboss/dna/graph/LocationTest.java (revision 1350) +++ dna-graph/src/test/java/org/jboss/dna/graph/LocationTest.java (working copy) @@ -128,11 +128,11 @@ public class LocationTest { } @Test - public void locationsWithSamePathsAndDifferentPropertyAreNotEqual() { + public void locationsWithSamePathsAndDifferentPropertyAreEqual() { 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)); + assertThat("Locations created with identical paths and different property must not be equal", locationA1.equals(locationA2), is(true)); } @Test @@ -187,8 +187,8 @@ public class LocationTest { Location locationA2 = Location.create(pathA, propListABU); assertThat("Locations created with identical paths and different properties must not be equal", - locationA1, - not(locationA2)); + locationA1.equals(locationA2), + is(true)); } @Test Index: dna-graph/src/test/java/org/jboss/dna/graph/connector/test/AbstractConnectorTest.java =================================================================== --- dna-graph/src/test/java/org/jboss/dna/graph/connector/test/AbstractConnectorTest.java (revision 1350) +++ dna-graph/src/test/java/org/jboss/dna/graph/connector/test/AbstractConnectorTest.java (working copy) @@ -447,7 +447,7 @@ public abstract class AbstractConnectorTest { // Check the result has the correct location ... assertThat("The node that was read doesn't have the expected location", - result.getLocation().isSame(location, true), + result.getLocation().equals(location), is(true)); } @@ -667,7 +667,7 @@ public abstract class AbstractConnectorTest { assertThat(subgraph2, is(notNullValue())); // Shortcut ... - if (subgraph1.getLocation().equals(subgraph2.getLocation())) return; + if (subgraph1.getLocation().isSame(subgraph2.getLocation())) return; Path rootPath1 = subgraph1.getRoot().getLocation().getPath(); Path rootPath2 = subgraph2.getRoot().getLocation().getPath(); @@ -738,7 +738,7 @@ public abstract class AbstractConnectorTest { // Check the locations ... Location location1 = node1.getLocation(); Location location2 = node2.getLocation(); - assertThat(location1.isSame(location2, true), is(true)); + assertThat(location1.isSame(location2), is(true)); // Check the paths ... assertThat(location1.getPath(), is(location2.getPath())); Index: dna-graph/src/test/java/org/jboss/dna/graph/connector/test/ReadableConnectorTest.java =================================================================== --- dna-graph/src/test/java/org/jboss/dna/graph/connector/test/ReadableConnectorTest.java (revision 1350) +++ dna-graph/src/test/java/org/jboss/dna/graph/connector/test/ReadableConnectorTest.java (working copy) @@ -93,7 +93,7 @@ public abstract class ReadableConnectorTest extends AbstractConnectorTest { Node root = graph.getNodeAt("/"); for (int i = 0; i != 10; ++i) { Node anotherRoot = graph.getNodeAt("/"); - assertThat(anotherRoot.getLocation().equals(root.getLocation()), is(true)); + assertThat(anotherRoot.getLocation().isSame(root.getLocation()), is(true)); assertThat(anotherRoot.getLocation().getPath(), is(root.getLocation().getPath())); assertThat(anotherRoot.getLocation().getIdProperties(), is(root.getLocation().getIdProperties())); } @@ -117,7 +117,7 @@ public abstract class ReadableConnectorTest extends AbstractConnectorTest { } // Find the root node using the identification properties ... Node anotherRoot = graph.getNodeAt(firstProperty, additionalProperties); - assertThat(anotherRoot.getLocation().equals(root.getLocation()), is(true)); + assertThat(anotherRoot.getLocation().isSame(root.getLocation()), is(true)); assertThat(anotherRoot.getLocation().getPath(), is(root.getLocation().getPath())); assertThat(anotherRoot.getLocation().getIdProperties(), is(root.getLocation().getIdProperties())); } @@ -131,7 +131,7 @@ public abstract class ReadableConnectorTest extends AbstractConnectorTest { if (uuid != null) { // Find the root node using the identification properties ... Node anotherRoot = graph.getNodeAt(uuid); - assertThat(anotherRoot.getLocation().equals(root.getLocation()), is(true)); + assertThat(anotherRoot.getLocation().isSame(root.getLocation()), is(true)); assertThat(anotherRoot.getLocation().getPath(), is(root.getLocation().getPath())); assertThat(anotherRoot.getLocation().getIdProperties(), is(root.getLocation().getIdProperties())); assertThat(anotherRoot.getLocation().getUuid(), is(root.getLocation().getUuid())); Index: dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java (revision 1350) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java (working copy) @@ -1773,7 +1773,7 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node if (obj instanceof AbstractJcrNode) { AbstractJcrNode that = (AbstractJcrNode)obj; if (this.cache != that.cache) return false; - return this.location.equals(that.location); + return this.location.isSame(that.location); } return false; }