Author: rhauch
Date: 2008-12-08 11:53:45 -0500 (Mon, 08 Dec 2008)
New Revision: 668
Added:
trunk/dna-common/src/main/java/org/jboss/dna/common/collection/ImmutableAppendedList.java
trunk/dna-common/src/test/java/org/jboss/dna/common/collection/ImmutableAppendedListTest.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/AbstractPath.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/ChildPath.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/RootPath.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/AbstractPathTest.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathOldTest.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathTest.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/ChildPathTest.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/RootPathTest.java
Removed:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathTest.java
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Path.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicPath.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicPathSegment.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/PathValueFactory.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositorySourceLoadHarness.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/SimpleRepository.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathSegmentTest.java
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/Projection.java
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/MultiChildContributionTest.java
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/MultiPropertyContributionTest.java
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/NodeContributionTest.java
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/OneChildContributionTest.java
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/OnePropertyContributionTest.java
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/ThreePropertyContributionTest.java
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/TwoChildContributionTest.java
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/TwoPropertyContributionTest.java
trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java
trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerTest.java
Log:
DNA-250 - Creating a path from a parent path and a segment is not fast
Added new specialized implementations of Path, including RootPath and ChildPath.
ChildPath is much more efficient when creating paths based upon an existing parent path.
Also cleaned up and corrected some Path documentation, and added unit tests. Created a
new utility class that implements List that appends (virtually) a single element to an
already immutable list. This is useful when having to create a List (e.g., of
Path.Segment objects) based upon an existing List but with a single additional element.
Added:
trunk/dna-common/src/main/java/org/jboss/dna/common/collection/ImmutableAppendedList.java
===================================================================
---
trunk/dna-common/src/main/java/org/jboss/dna/common/collection/ImmutableAppendedList.java
(rev 0)
+++
trunk/dna-common/src/main/java/org/jboss/dna/common/collection/ImmutableAppendedList.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -0,0 +1,456 @@
+/*
+ * 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.common.collection;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.CheckArg;
+
+/**
+ * An immutable {@link List} that consists of a single element appended to another
existing {@link List}. The result is a list
+ * that contains all of the elements in the parent list as well as the last appended
element, but while reusing the existing
+ * parent list and without having to create a copy of the parent list.
+ *
+ * @author Randall Hauch
+ * @param <T> the type of element
+ */
+@Immutable
+public class ImmutableAppendedList<T> implements List<T> {
+
+ private final List<T> parent;
+ private final T element;
+ private final int size;
+ private transient int hc;
+
+ /**
+ * Create an instance using the supplied parent list and an element to be virtually
appended to the parent. Note that the
+ * parent must be immutable (though this is not checked).
+ *
+ * @param parent the parent list
+ * @param element the child element (may be null)
+ * @throws IllegalArgumentException if the reference to the parent list is null
+ */
+ public ImmutableAppendedList( List<T> parent,
+ T element ) {
+ CheckArg.isNotNull(parent, "parent");
+ this.parent = parent;
+ this.element = element;
+ this.size = parent.size() + 1;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#contains(java.lang.Object)
+ */
+ public boolean contains( Object o ) {
+ return element == o || (element != null && element.equals(o)) ||
parent.contains(o);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#containsAll(java.util.Collection)
+ */
+ public boolean containsAll( Collection<?> c ) {
+ Iterator<?> e = c.iterator();
+ while (e.hasNext()) {
+ if (!contains(e.next())) return false;
+ }
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#get(int)
+ */
+ public T get( int index ) {
+ if (index == (size - 1)) return element;
+ return parent.get(index);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#indexOf(java.lang.Object)
+ */
+ public int indexOf( Object o ) {
+ int index = parent.indexOf(o);
+ if (index == -1) {
+ return (element == o || (element != null && element.equals(o))) ?
(size - 1) : -1;
+ }
+ return -1;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#isEmpty()
+ */
+ public boolean isEmpty() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#iterator()
+ */
+ @SuppressWarnings( "synthetic-access" )
+ public Iterator<T> iterator() {
+ final Iterator<T> parentIterator = parent.iterator();
+ return new Iterator<T>() {
+ boolean finished = false;
+
+ public boolean hasNext() {
+ return parentIterator.hasNext() || !finished;
+ }
+
+ public T next() {
+ if (parentIterator.hasNext()) return parentIterator.next();
+ if (finished) throw new NoSuchElementException();
+ finished = true;
+ return element;
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#lastIndexOf(java.lang.Object)
+ */
+ public int lastIndexOf( Object o ) {
+ if (element == o || (element != null && element.equals(o))) return size -
1;
+ return parent.lastIndexOf(o);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#listIterator()
+ */
+ public ListIterator<T> listIterator() {
+ return listIterator(0);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#listIterator(int)
+ */
+ @SuppressWarnings( "synthetic-access" )
+ public ListIterator<T> listIterator( final int index ) {
+ return new ListIterator<T>() {
+ int cursor = index;
+
+ public boolean hasNext() {
+ return cursor < size;
+ }
+
+ public T next() {
+ try {
+ T next = get(cursor);
+ cursor++;
+ return next;
+ } catch (IndexOutOfBoundsException e) {
+ throw new NoSuchElementException();
+ }
+ }
+
+ public boolean hasPrevious() {
+ return cursor != 0;
+ }
+
+ public int nextIndex() {
+ return cursor;
+ }
+
+ public T previous() {
+ try {
+ int i = cursor - 1;
+ T previous = get(i);
+ cursor = i;
+ return previous;
+ } catch (IndexOutOfBoundsException e) {
+ throw new NoSuchElementException();
+ }
+ }
+
+ public int previousIndex() {
+ return cursor - 1;
+ }
+
+ public void set( T o ) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void add( T o ) {
+ throw new UnsupportedOperationException();
+ }
+
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#size()
+ */
+ public int size() {
+ return size;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#subList(int, int)
+ */
+ public List<T> subList( int fromIndex,
+ int toIndex ) {
+ if (fromIndex == 0 && toIndex == size) {
+ // The bounds are the same as this list, so just return this list ...
+ return this;
+ }
+ if (toIndex == size || fromIndex == (size - 1)) {
+ // The only list is the last element ...
+ return Collections.singletonList(element);
+ }
+ if (toIndex < size) {
+ // It is all within the range of the parent's list, so simply delegate
+ return parent.subList(fromIndex, toIndex);
+ }
+ // Otherwise, the sublist starts within the parent list and ends with the last
element.
+ // So, create a sublist starting at the 'fromIndex' until the end of the
parent list ...
+ List<T> sublist = parent.subList(fromIndex, toIndex - 1); // will catch
out-of-bounds errors
+ // And wrap with another immutable appended list to add the last element ...
+ return new ImmutableAppendedList<T>(sublist, element);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#toArray()
+ */
+ public Object[] toArray() {
+ Object[] result = new Object[size];
+ int i = 0;
+ for (T e : parent) {
+ result[i++] = e;
+ }
+ result[i] = element;
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#toArray(T[])
+ */
+ @SuppressWarnings( "unchecked" )
+ public <X> X[] toArray( X[] a ) {
+ if (a.length < size) a =
(X[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
+ a = parent.toArray(a);
+ a[size - 1] = (X)element;
+ return a;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ if (hc == 0) {
+ int hashCode = 1;
+ for (T element : this) {
+ hashCode = 31 * hashCode + (element == null ? 0 : element.hashCode());
+ }
+ hc = hashCode;
+ }
+ return hc;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof List) {
+ List<?> that = (List<?>)obj;
+ if (this.size() != that.size()) return false;
+ Iterator<?> thisIter = this.iterator();
+ Iterator<?> thatIter = that.iterator();
+ while (thisIter.hasNext()) {
+ Object thisValue = thisIter.next();
+ Object thatValue = thatIter.next();
+ if (thisValue == null) {
+ if (thatValue != null) return false;
+ // assert thatValue == null;
+ } else {
+ if (!thisValue.equals(thatValue)) return false;
+ }
+ }
+ return true;
+ }
+ return super.equals(obj);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("[");
+
+ Iterator<T> i = iterator();
+ boolean hasNext = i.hasNext();
+ while (hasNext) {
+ T o = i.next();
+ buf.append(o == this ? "(this Collection)" : String.valueOf(o));
+ hasNext = i.hasNext();
+ if (hasNext) buf.append(", ");
+ }
+
+ buf.append("]");
+ return buf.toString();
+ }
+
+ //
----------------------------------------------------------------------------------------------------------------
+ // Methods that modify are not supported
+ //
----------------------------------------------------------------------------------------------------------------
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#add(int, Object)
+ */
+ public void add( int index,
+ T element ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#add(Object)
+ */
+ public boolean add( T o ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#addAll(java.util.Collection)
+ */
+ public boolean addAll( Collection<? extends T> c ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#addAll(int, java.util.Collection)
+ */
+ public boolean addAll( int index,
+ Collection<? extends T> c ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#clear()
+ */
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#remove(java.lang.Object)
+ */
+ public boolean remove( Object o ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#remove(int)
+ */
+ public T remove( int index ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#removeAll(java.util.Collection)
+ */
+ public boolean removeAll( Collection<?> c ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#retainAll(java.util.Collection)
+ */
+ public boolean retainAll( Collection<?> c ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.List#set(int, java.lang.Object)
+ */
+ public T set( int index,
+ T element ) {
+ throw new UnsupportedOperationException();
+ }
+
+}
Added:
trunk/dna-common/src/test/java/org/jboss/dna/common/collection/ImmutableAppendedListTest.java
===================================================================
---
trunk/dna-common/src/test/java/org/jboss/dna/common/collection/ImmutableAppendedListTest.java
(rev 0)
+++
trunk/dna-common/src/test/java/org/jboss/dna/common/collection/ImmutableAppendedListTest.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -0,0 +1,286 @@
+/*
+ * 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.common.collection;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.hasItems;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class ImmutableAppendedListTest {
+
+ private List<String> list;
+ private List<String> parent;
+ private String[] data;
+
+ @Before
+ public void beforeEach() {
+ data = new String[] {"a", "b", "c", "d",
"e"};
+ parent = new ArrayList<String>(5);
+ for (int i = 0; i != 4; ++i) {
+ parent.add(data[i]);
+ }
+ list = new ImmutableAppendedList<String>(parent, data[4]);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowCreatingWithNullParentList() {
+ list = new ImmutableAppendedList<String>(null, data[4]);
+ }
+
+ @Test
+ public void shouldAllowCreatingWithEmptyParentList() {
+ data = new String[] {data[0], data[1]};
+ parent = Collections.singletonList(data[0]);
+ list = new ImmutableAppendedList<String>(parent, data[1]);
+ assertThat(list, hasItems(data));
+ assertThat(list.size(), is(parent.size() + 1));
+ assertThat(list.toArray(), is((Object[])data));
+ assertThat(list.toArray(new String[list.size()]), is(data));
+ assertThat(list.toArray(new String[list.size() - 1]), is(data)); // too small
+ assertThat(list.isEmpty(), is(false));
+ }
+
+ @Test
+ public void shouldAllowCreatingAppendedListWithNullForFinalElement() {
+ data[4] = null;
+ list = new ImmutableAppendedList<String>(parent, data[4]);
+ assertThat(list, hasItems(data));
+ }
+
+ @Test
+ public void shouldHaveSizeOfParentPlusOne() {
+ assertThat(list.size(), is(parent.size() + 1));
+ }
+
+ @Test
+ public void shouldConvertToArrayContainingAllValues() {
+ assertThat(list.toArray(), is((Object[])data));
+ }
+
+ @Test
+ public void shouldConvertToSuppliedArrayContainingAllValues() {
+ assertThat(list.toArray(new String[list.size()]), is(data));
+ }
+
+ @Test
+ public void shouldConvertToTooSmallSuppliedArrayContainingAllValues() {
+ assertThat(list.toArray(new String[list.size() - 1]), is(data));
+ }
+
+ @Test
+ public void shouldIterateOverAllValues() {
+ Iterator<String> iter = list.iterator();
+ int i = 0;
+ while (iter.hasNext()) {
+ assertThat(iter.next(), is(data[i++]));
+ }
+ }
+
+ @Test
+ public void shouldIterateOverAllValuesUsingListIterator() {
+ List<String> copy = new ArrayList<String>(list);
+ assertThat(copy.size(), is(list.size()));
+ ListIterator<String> listIter = list.listIterator();
+ ListIterator<String> copyIter = copy.listIterator();
+ for (int i = 0; i != 3; ++i) {
+ assertThat(listIter.hasPrevious(), is(false));
+ assertThat(copyIter.hasPrevious(), is(false));
+ while (listIter.hasNext()) {
+ assertThat(listIter.next(), is(copyIter.next()));
+ }
+ assertThat(listIter.hasNext(), is(false));
+ assertThat(copyIter.hasNext(), is(false));
+ while (listIter.hasPrevious()) {
+ assertThat(listIter.previous(), is(copyIter.previous()));
+ }
+ }
+ assertThat(listIter.hasPrevious(), is(false));
+ assertThat(copyIter.hasPrevious(), is(false));
+ }
+
+ @Test
+ public void shouldIterateBackwardsOverAllValuesUsingListIterator() {
+ List<String> copy = new ArrayList<String>(list);
+ assertThat(copy.size(), is(list.size()));
+ ListIterator<String> listIter = list.listIterator(list.size());
+ ListIterator<String> copyIter = copy.listIterator(copy.size());
+ assertThat(listIter.hasNext(), is(false));
+ assertThat(copyIter.hasNext(), is(false));
+ while (listIter.hasPrevious()) {
+ assertThat(listIter.previous(), is(copyIter.previous()));
+ }
+ assertThat(listIter.hasPrevious(), is(false));
+ assertThat(copyIter.hasPrevious(), is(false));
+ }
+
+ @Test( expected = UnsupportedOperationException.class )
+ public void shouldNotAllowAddingAnElement() {
+ list.add(null);
+ }
+
+ @Test( expected = UnsupportedOperationException.class )
+ public void shouldNotAllowAddingAnElementByIndex() {
+ list.add(0, null);
+ }
+
+ @Test( expected = UnsupportedOperationException.class )
+ public void shouldNotAllowAddingACollection() {
+ list.addAll(parent);
+ }
+
+ @Test( expected = UnsupportedOperationException.class )
+ public void shouldNotAllowAddingACollectionWithIndex() {
+ list.addAll(1, parent);
+ }
+
+ @Test( expected = UnsupportedOperationException.class )
+ public void shouldNotAllowRemovingAnElement() {
+ list.remove(null);
+ }
+
+ @Test( expected = UnsupportedOperationException.class )
+ public void shouldNotAllowRemovingAnElementByIndex() {
+ list.remove(0);
+ }
+
+ @Test( expected = UnsupportedOperationException.class )
+ public void shouldNotAllowRemovingAllElementsInACollection() {
+ list.removeAll(null);
+ }
+
+ @Test( expected = UnsupportedOperationException.class )
+ public void shouldNotAllowRetainingAllElementsInACollection() {
+ list.retainAll(null);
+ }
+
+ @Test( expected = UnsupportedOperationException.class )
+ public void shouldNotAllowSettingElementByIndex() {
+ list.set(0, null);
+ }
+
+ @Test( expected = UnsupportedOperationException.class )
+ public void shouldNotAllowClearingList() {
+ list.clear();
+ }
+
+ @Test
+ public void shouldReturnSameHashCodeMultipleTimes() {
+ int hc = list.hashCode();
+ for (int i = 0; i != 100; ++i) {
+ assertThat(list.hashCode(), is(hc));
+ }
+ }
+
+ @Test
+ public void shouldReturnSameHashCodeAsEquivalentArrayList() {
+ List<String> copy = new ArrayList<String>(list);
+ assertThat(list.hashCode(), is(copy.hashCode()));
+ }
+
+ @Test
+ public void shouldBeEqualToEquivalentArrayList() {
+ List<String> copy = new ArrayList<String>(list);
+ assertThat(list.equals(copy), is(true));
+ }
+
+ @Test
+ public void shouldHaveToStringThatIsTheSameAsEquivalentArrayList() {
+ List<String> copy = new ArrayList<String>(list);
+ assertThat(list.toString(), is(copy.toString()));
+ }
+
+ @Test
+ public void shouldFindLastIndexOfEachValue() {
+ for (int i = 0; i != data.length; ++i) {
+ String value = data[i];
+ int lastIndex = list.lastIndexOf(value);
+ assertThat(lastIndex, is(i));
+ }
+ }
+
+ @Test
+ public void shouldNotFindLastIndexOfValuesThatAreNotInList() {
+ assertThat(list.lastIndexOf("not found"), is(-1));
+ assertThat(list.lastIndexOf(null), is(-1));
+ }
+
+ @Test
+ public void shouldFindIndexOfEachValue() {
+ for (int i = 0; i != data.length; ++i) {
+ String value = data[i];
+ int lastIndex = list.lastIndexOf(value);
+ assertThat(lastIndex, is(i));
+ }
+ }
+
+ @Test
+ public void shouldNotFindIndexOfValuesThatAreNotInList() {
+ assertThat(list.lastIndexOf("not found"), is(-1));
+ assertThat(list.lastIndexOf(null), is(-1));
+ }
+
+ @Test
+ public void shouldGetValuesByIndex() {
+ for (int i = 0; i != data.length; ++i) {
+ String expectedValue = data[i];
+ String actualValue = list.get(i);
+ assertThat(actualValue, is(expectedValue));
+ }
+ }
+
+ @Test
+ public void shouldContainEachValue() {
+ for (int i = 0; i != data.length; ++i) {
+ String value = data[i];
+ assertThat(list.contains(value), is(true));
+ }
+ }
+
+ @Test
+ public void shouldNotContainValuesThatAreNotInList() {
+ assertThat(list.contains("not found"), is(false));
+ assertThat(list.contains(null), is(false));
+ }
+
+ @Test
+ public void shouldContainAllValuesInDuplicateCollection() {
+ List<String> copy = new ArrayList<String>(list);
+ assertThat(list.containsAll(copy), is(true));
+ assertThat(copy.containsAll(list), is(true));
+ }
+
+ @Test
+ public void shouldNeverBeEmpty() {
+ assertThat(list.isEmpty(), is(false));
+ }
+
+}
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 2008-12-08 16:20:36
UTC (rev 667)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java 2008-12-08 16:53:45
UTC (rev 668)
@@ -396,7 +396,8 @@
} else {
Path thisPath = this.getPath();
Path thatPath = other.getPath();
- if (thisPath.isRoot() && thatPath.isRoot()) return true;
+ 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 ...
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Path.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Path.java 2008-12-08
16:20:36 UTC (rev 667)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/Path.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -360,7 +360,8 @@
public boolean isNormalized();
/**
- * Get a normalized path with as many ".." segments and all "."
resolved.
+ * Get a normalized path with as many ".." segments and all "."
resolved. The relative path ".", however, will return itself
+ * as the normalized path, since it cannot be resolved any further.
*
* @return the normalized path, or this object if this path is already normalized
* @throws InvalidPathException if the normalized form would result in a path with
negative length (e.g., "/a/../../..")
@@ -409,7 +410,7 @@
* Return the path to the parent, or this path if it is the {@link #isRoot() root}.
This is an efficient operation that does
* not require copying any data.
*
- * @return the parent path, or this path if it is already the root
+ * @return the parent path, or this null if it is already the root
*/
public Path getParent();
@@ -543,12 +544,12 @@
* prefixes and the supplied encoder to encode characters in each of the path
segments.
*
* @param namespaceRegistry the namespace registry that should be used to obtain the
prefix for the
- * {@link Name#getNamespaceUri() namespace URIs} in the segment {@link
Segment#getName() names}
+ * {@link Name#getNamespaceUri() namespace URIs} in the segment {@link
Segment#getName() names}, or null if the
+ * namespace registry should not be used
* @param encoder the encoder to use for encoding the {@link Name#getLocalName()
local part} and
* {@link Name#getNamespaceUri() namespace prefix} of each {@link
Path#getSegmentsList() segment}, or null if the
* {@link #DEFAULT_ENCODER default encoder} should be used
* @return the encoded string
- * @throws IllegalArgumentException if the namespace registry is null
* @see #getString(NamespaceRegistry)
* @see #getString(NamespaceRegistry, TextEncoder, TextEncoder)
*/
Added:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/AbstractPath.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/AbstractPath.java
(rev 0)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/AbstractPath.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -0,0 +1,519 @@
+/*
+ * 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.graph.properties.basic;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import org.jboss.dna.common.CommonI18n;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.properties.InvalidPathException;
+import org.jboss.dna.graph.properties.NamespaceRegistry;
+import org.jboss.dna.graph.properties.Path;
+
+/**
+ * An abstract foundation for different {@link Path} implementations. This class does not
manage any of the {@link Path}'s state,
+ * but it does provide implementations for most of the methods based upon a few abstract
methods. For example, any implementaton
+ * that requires the {@link Path.Segment path's segments} are written to use the
{@link #iterator()}, since that is likely more
+ * efficient for the majority of implementations.
+ *
+ * @author Randall Hauch
+ */
+public abstract class AbstractPath implements Path {
+
+ /**
+ * The initial serializable version. Version {@value}
+ */
+ private static final long serialVersionUID = 1L;
+
+ public static final Path SELF_PATH = new
BasicPath(Collections.singletonList(Path.SELF_SEGMENT), false);
+
+ private transient String cachedStringPath;
+ private transient int hc = 0;
+
+ protected boolean isNormalized( List<Segment> segments ) {
+ for (Segment segment : segments) {
+ if (segment.isSelfReference() || segment.isParentReference()) return false;
+ }
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#getCanonicalPath()
+ */
+ public Path getCanonicalPath() {
+ if (!this.isAbsolute()) {
+ String msg = GraphI18n.pathIsNotAbsolute.text(this);
+ throw new InvalidPathException(msg);
+ }
+ if (this.isNormalized()) return this;
+ return this.getNormalizedPath();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Path getCommonAncestor( Path that ) {
+ CheckArg.isNotNull(that, "that");
+ if (that.isRoot()) return that;
+ Path normalizedPath = this.getNormalizedPath();
+ int lastIndex = 0;
+ Iterator<Segment> thisIter = normalizedPath.iterator();
+ Iterator<Segment> thatIter = that.getNormalizedPath().iterator();
+ while (thisIter.hasNext() && thatIter.hasNext()) {
+ Segment thisSeg = thisIter.next();
+ Segment thatSeg = thatIter.next();
+ if (thisSeg.equals(thatSeg)) {
+ ++lastIndex;
+ } else {
+ break;
+ }
+ }
+ if (lastIndex == 0) return RootPath.INSTANCE;
+ return normalizedPath.subpath(0, lastIndex);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Path.Segment getLastSegment() {
+ return this.getSegmentsList().get(size() - 1);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#getParent()
+ */
+ public Path getParent() {
+ return getAncestor(1);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Segment getSegment( int index ) {
+ CheckArg.isNonNegative(index, "index");
+ return this.getSegmentsList().get(index);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Segment[] getSegmentsArray() {
+ // By default, make a new array every time since arrays are mutable, and use the
iterator
+ // since that is probably more efficient than creating a list ...
+ Segment[] result = new Path.Segment[size()];
+ int i = 0;
+ for (Segment segment : this) {
+ result[i] = segment;
+ ++i;
+ }
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Path getNormalizedPath() {
+ if (this.isNormalized()) return this;
+ LinkedList<Segment> newSegments = new LinkedList<Segment>();
+ for (Segment segment : this) {
+ if (segment.isSelfReference()) continue;
+ if (segment.isParentReference()) {
+ if (newSegments.isEmpty()) {
+ if (this.isAbsolute()) {
+ throw new
InvalidPathException(CommonI18n.pathCannotBeNormalized.text(this));
+ }
+ } else if (!newSegments.getLast().isParentReference()) {
+ newSegments.removeLast();
+ continue;
+ }
+ }
+ newSegments.add(segment);
+ }
+ if (newSegments.isEmpty()) {
+ if (this.isAbsolute()) return RootPath.INSTANCE;
+ // Otherwise relative and it had contained nothing but self references ...
+ return SELF_PATH;
+ }
+ return new BasicPath(newSegments, this.isAbsolute());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getString() {
+ return doGetString(null, DEFAULT_ENCODER, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getString( TextEncoder encoder ) {
+ return doGetString(null, encoder, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getString( NamespaceRegistry namespaceRegistry ) {
+ CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
+ return doGetString(namespaceRegistry, null, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getString( NamespaceRegistry namespaceRegistry,
+ TextEncoder encoder ) {
+ CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
+ return doGetString(namespaceRegistry, encoder, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.properties.Path#getString(org.jboss.dna.graph.properties.NamespaceRegistry,
+ * org.jboss.dna.common.text.TextEncoder,
org.jboss.dna.common.text.TextEncoder)
+ */
+ public String getString( NamespaceRegistry namespaceRegistry,
+ TextEncoder encoder,
+ TextEncoder delimiterEncoder ) {
+ return doGetString(namespaceRegistry, encoder, delimiterEncoder);
+ }
+
+ /**
+ * Method that creates the string representation. This method works two different
ways depending upon whether the namespace
+ * registry is provided.
+ *
+ * @param namespaceRegistry
+ * @param encoder
+ * @param delimiterEncoder
+ * @return this path as a string
+ */
+ protected String doGetString( NamespaceRegistry namespaceRegistry,
+ TextEncoder encoder,
+ TextEncoder delimiterEncoder ) {
+ if (encoder == null) encoder = DEFAULT_ENCODER;
+ if (encoder == DEFAULT_ENCODER && cachedStringPath != null &&
delimiterEncoder == null) return cachedStringPath;
+ final String delimiter = delimiterEncoder != null ?
delimiterEncoder.encode(DELIMITER_STR) : DELIMITER_STR;
+
+ // Since the segments are immutable, this code need not be synchronized because
concurrent threads
+ // may just compute the same value (with no harm done)
+ StringBuilder sb = new StringBuilder();
+ if (this.isAbsolute()) sb.append(delimiter);
+ boolean first = true;
+ for (Segment segment : this) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append(delimiter);
+ }
+ assert segment != null;
+ sb.append(segment.getString(namespaceRegistry, encoder, delimiterEncoder));
+ }
+ String result = sb.toString();
+ // Save the result to the internal string if this the default encoder is used.
+ // This is not synchronized, but it's okay
+ if (encoder == DEFAULT_ENCODER && cachedStringPath == null &&
delimiterEncoder == null) cachedStringPath = result;
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasSameAncestor( Path that ) {
+ CheckArg.isNotNull(that, "that");
+ if (that.size() != this.size()) return false;
+ if (this.size() == 1) return true; // both nodes are just under the root
+ for (int i = this.size() - 2; i >= 0; --i) {
+ Path.Segment thisSegment = this.getSegment(i);
+ Path.Segment thatSegment = that.getSegment(i);
+ if (!thisSegment.equals(thatSegment)) return false;
+ }
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isAncestorOf( Path decendant ) {
+ CheckArg.isNotNull(decendant, "that");
+ if (this == decendant) return false;
+ if (this.size() >= decendant.size()) return false;
+
+ Iterator<Path.Segment> thisIter = this.iterator();
+ Iterator<Path.Segment> thatIter = decendant.iterator();
+ while (thisIter.hasNext()) {
+ Path.Segment thisSeg = thisIter.next();
+ Path.Segment thatSeg = thatIter.next();
+ if (!thisSeg.equals(thatSeg)) return false;
+ }
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.properties.Path#isAtOrBelow(org.jboss.dna.graph.properties.Path)
+ */
+ public boolean isAtOrBelow( Path other ) {
+ CheckArg.isNotNull(other, "other");
+ if (this == other) return true;
+ if (other.isRoot()) return true;
+ Iterator<Segment> thisIter = iterator();
+ Iterator<Segment> thatIter = other.iterator();
+ while (thisIter.hasNext() && thatIter.hasNext()) {
+ if (!thisIter.next().equals(thatIter.next())) return false;
+ }
+ if (thatIter.hasNext()) return false; // The other still has segments, but this
doesn't
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.properties.Path#isAtOrAbove(org.jboss.dna.graph.properties.Path)
+ */
+ public boolean isAtOrAbove( Path other ) {
+ CheckArg.isNotNull(other, "other");
+ if (this == other) return true;
+ Iterator<Segment> thisIter = iterator();
+ Iterator<Segment> thatIter = other.iterator();
+ while (thisIter.hasNext() && thatIter.hasNext()) {
+ if (!thisIter.next().equals(thatIter.next())) return false;
+ }
+ if (thisIter.hasNext()) return false; // This still has segments, but other
doesn't
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isDecendantOf( Path ancestor ) {
+ CheckArg.isNotNull(ancestor, "ancestor");
+ return ancestor.isAncestorOf(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSameAs( Path other ) {
+ return other != null && this.compareTo(other) == 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Iterator<Segment> iterator() {
+ return getSegmentsList().iterator();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Path relativeTo( Path startingPath ) {
+ CheckArg.isNotNull(startingPath, "to");
+ if (!this.isAbsolute()) {
+ String msg = GraphI18n.pathIsNotAbsolute.text(this);
+ throw new InvalidPathException(msg);
+ }
+ if (!startingPath.isAbsolute()) {
+ String msg = GraphI18n.pathIsNotAbsolute.text(startingPath);
+ throw new InvalidPathException(msg);
+ }
+
+ // Count the number of segments up to the common ancestor (relative path is what
remains) ...
+ int lengthOfCommonAncestor = 0;
+ Iterator<Segment> thisIter = this.getNormalizedPath().iterator();
+ Iterator<Segment> toIter = startingPath.getNormalizedPath().iterator();
+ while (thisIter.hasNext() && toIter.hasNext()) {
+ Segment thisSeg = thisIter.next();
+ Segment toSeg = toIter.next();
+ if (thisSeg.equals(toSeg)) {
+ ++lengthOfCommonAncestor;
+ } else {
+ break;
+ }
+ }
+ // Create the relative path, starting with parent references to the common
ancestor ...
+ int numberOfParentReferences = startingPath.size() - lengthOfCommonAncestor;
+ List<Segment> relativeSegments = new ArrayList<Segment>();
+ for (int i = 0; i != numberOfParentReferences; ++i) {
+ relativeSegments.add(Path.PARENT_SEGMENT);
+ }
+ // Add the segments of this path from the common ancestor ...
+ for (int i = lengthOfCommonAncestor; i < this.size(); ++i) {
+ relativeSegments.add(getSegment(i));
+ }
+ if (relativeSegments.isEmpty()) {
+ relativeSegments.add(Path.SELF_SEGMENT);
+ }
+ return new BasicPath(relativeSegments, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Path resolve( Path relativePath ) {
+ CheckArg.isNotNull(relativePath, "relative path");
+ if (!this.isAbsolute()) {
+ String msg = GraphI18n.pathIsNotAbsolute.text(this);
+ throw new InvalidPathException(msg);
+ }
+ if (relativePath.isAbsolute()) {
+ String msg = GraphI18n.pathIsNotRelative.text(relativePath);
+ throw new InvalidPathException(msg);
+ }
+ // If the relative path is the self or parent reference ...
+ relativePath = relativePath.getNormalizedPath();
+ if (relativePath.size() == 1) {
+ Segment onlySegment = relativePath.getSegment(0);
+ if (onlySegment.isSelfReference()) return this;
+ if (onlySegment.isParentReference()) return this.getParent();
+ }
+ List<Segment> segments = new ArrayList<Segment>(this.size() +
relativePath.size());
+ for (Segment segment : this) {
+ segments.add(segment);
+ }
+ for (Segment segment : relativePath) {
+ segments.add(segment);
+ }
+ return new BasicPath(segments, true).getNormalizedPath();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Path resolveAgainst( Path absolutePath ) {
+ CheckArg.isNotNull(absolutePath, "absolute path");
+ return absolutePath.resolve(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Path subpath( int beginIndex ) {
+ return subpath(beginIndex, size());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Path subpath( int beginIndex,
+ int endIndex ) {
+ CheckArg.isNonNegative(beginIndex, "beginIndex");
+ CheckArg.isNonNegative(endIndex, "endIndex");
+ int size = size();
+ if (beginIndex == 0) {
+ if (endIndex == 0) return RootPath.INSTANCE;
+ if (endIndex == size) return this;
+ }
+ if (beginIndex >= size) {
+ throw new IndexOutOfBoundsException(
+
GraphI18n.unableToCreateSubpathBeginIndexGreaterThanOrEqualToSize.text(beginIndex,
+
size));
+ }
+ if (beginIndex > endIndex) {
+ throw new IndexOutOfBoundsException(
+
GraphI18n.unableToCreateSubpathBeginIndexGreaterThanOrEqualToEndingIndex.text(beginIndex,
+
endIndex));
+ }
+ // This reuses the same list, so it's pretty efficient ...
+ return new BasicPath(createSegmentsSubList(beginIndex, endIndex),
this.isAbsolute());
+ }
+
+ protected List<Segment> createSegmentsSubList( int validBeginIndex,
+ int validEndIndex ) {
+ return this.getSegmentsList().subList(validBeginIndex, validEndIndex);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ if (hc == 0) {
+ int hashCode = 1;
+ for (Segment segment : this) {
+ hashCode = 31 * hashCode + segment.hashCode();
+ }
+ hc = hashCode;
+ }
+ return hc;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof Path) {
+ Path that = (Path)obj;
+ if (this.size() != that.size()) return false;
+ if (this.hashCode() != that.hashCode()) return false;
+ Iterator<Segment> thisIter = this.iterator();
+ Iterator<Segment> thatIter = that.iterator();
+ while (thisIter.hasNext()) {
+ Segment thisSegment = thisIter.next();
+ Segment thatSegment = thatIter.next();
+ if (!thisSegment.equals(thatSegment)) return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int compareTo( Path that ) {
+ if (this == that) return 0;
+ Iterator<Segment> thisIter = getSegmentsList().iterator();
+ Iterator<Segment> thatIter = that.iterator();
+ while (thisIter.hasNext() && thatIter.hasNext()) {
+ Segment thisSegment = thisIter.next();
+ Segment thatSegment = thatIter.next();
+ int diff = thisSegment.compareTo(thatSegment);
+ if (diff != 0) return diff;
+ }
+ if (thisIter.hasNext()) return 1;
+ if (thatIter.hasNext()) return -1;
+ return 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return getString(Path.URL_ENCODER);
+ }
+}
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicPath.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicPath.java 2008-12-08
16:20:36 UTC (rev 667)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicPath.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -21,19 +21,13 @@
*/
package org.jboss.dna.graph.properties.basic;
-import java.util.ArrayList;
import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedList;
import java.util.List;
import net.jcip.annotations.Immutable;
-import org.jboss.dna.common.CommonI18n;
import org.jboss.dna.common.text.Inflector;
-import org.jboss.dna.common.text.TextEncoder;
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.graph.GraphI18n;
import org.jboss.dna.graph.properties.InvalidPathException;
-import org.jboss.dna.graph.properties.NamespaceRegistry;
import org.jboss.dna.graph.properties.Path;
/**
@@ -43,24 +37,24 @@
* @author John Verhaeg
*/
@Immutable
-public class BasicPath implements Path {
+public class BasicPath extends AbstractPath {
/**
+ * The initial serializable version. Version {@value}
*/
- private static final long serialVersionUID = 8488295345524209746L;
+ private static final long serialVersionUID = 1L;
private static final List<Segment> EMPTY_SEGMENTS = Collections.emptyList();
- public static final Path ROOT = new BasicPath(EMPTY_SEGMENTS, true);
-
public static final Path EMPTY_RELATIVE = new BasicPath(EMPTY_SEGMENTS, false);
public static final Path SELF_PATH = new
BasicPath(Collections.singletonList(Path.SELF_SEGMENT), false);
+ public static final Path PARENT_PATH = new
BasicPath(Collections.singletonList(Path.PARENT_SEGMENT), false);
+
private final List<Segment> segments;
private final boolean absolute;
private final boolean normalized;
- private transient String path;
/**
* @param segments the segments
@@ -68,37 +62,20 @@
*/
public BasicPath( List<Segment> segments,
boolean absolute ) {
- CheckArg.isNotNull(segments, "segments");
- this.segments = segments.isEmpty() ? EMPTY_SEGMENTS :
Collections.unmodifiableList(segments);
+ assert segments != null;
+ this.segments = Collections.unmodifiableList(segments);
this.absolute = absolute;
this.normalized = isNormalized(this.segments);
}
- protected boolean isNormalized( List<Segment> segments ) {
- for (Segment segment : segments) {
- if (segment.isSelfReference() || segment.isParentReference()) return false;
- }
- return true;
- }
-
/**
* {@inheritDoc}
*/
- public Path getParent() {
- if (this.isRoot()) return null;
- if (this.segments.size() == 1) return this.isAbsolute() ? ROOT : EMPTY_RELATIVE;
- return subpath(0, this.segments.size() - 1);
- }
-
- /**
- * {@inheritDoc}
- */
public Path getAncestor( int degree ) {
CheckArg.isNonNegative(degree, "degree");
if (degree == 0) return this;
- if (this.isRoot()) return null;
int endIndex = this.segments.size() - degree;
- if (endIndex == 0) return this.isAbsolute() ? ROOT : EMPTY_RELATIVE;
+ if (endIndex == 0) return this.isAbsolute() ? RootPath.INSTANCE : null;
if (endIndex < 0) {
String msg = GraphI18n.pathAncestorDegreeIsInvalid.text(this.getString(),
Inflector.getInstance().ordinalize(degree));
throw new InvalidPathException(msg);
@@ -109,91 +86,6 @@
/**
* {@inheritDoc}
*/
- public Path getCanonicalPath() {
- if (!this.isAbsolute()) {
- String msg = GraphI18n.pathIsNotAbsolute.text(this);
- throw new InvalidPathException(msg);
- }
- if (this.isNormalized()) return this;
- return this.getNormalizedPath();
- }
-
- /**
- * {@inheritDoc}
- */
- public Path getCommonAncestor( Path that ) {
- if (that == null) return null;
- if (this.isRoot() || that.isRoot()) return ROOT;
- Path normalizedPath = this.getNormalizedPath();
- int lastIndex = 0;
- Iterator<Segment> thisIter = normalizedPath.iterator();
- Iterator<Segment> thatIter = that.getNormalizedPath().iterator();
- while (thisIter.hasNext() && thatIter.hasNext()) {
- Segment thisSeg = thisIter.next();
- Segment thatSeg = thatIter.next();
- if (thisSeg.equals(thatSeg)) {
- ++lastIndex;
- } else {
- break;
- }
- }
- if (lastIndex == 0) return ROOT;
- return normalizedPath.subpath(0, lastIndex);
- }
-
- /**
- * {@inheritDoc}
- */
- public Path.Segment getLastSegment() {
- if (this.isRoot()) return null;
- return this.segments.get(size() - 1);
- }
-
- /**
- * {@inheritDoc}
- */
- public Path getNormalizedPath() {
- if (this.isNormalized()) return this; // ROOT is normalized already
- LinkedList<Segment> newSegments = new LinkedList<Segment>();
- for (Segment segment : segments) {
- if (segment.isSelfReference()) continue;
- if (segment.isParentReference()) {
- if (newSegments.isEmpty()) {
- if (this.isAbsolute()) {
- throw new
InvalidPathException(CommonI18n.pathCannotBeNormalized.text(this));
- }
- } else if (!newSegments.getLast().isParentReference()) {
- newSegments.removeLast();
- continue;
- }
- }
- newSegments.add(segment);
- }
- if (newSegments.isEmpty()) {
- if (this.isAbsolute()) return ROOT;
- // Otherwise relative and it had contained nothing but self references ...
- return SELF_PATH;
- }
- return new BasicPath(newSegments, this.isAbsolute());
- }
-
- /**
- * {@inheritDoc}
- */
- public Segment getSegment( int index ) {
- return this.segments.get(index);
- }
-
- /**
- * {@inheritDoc}
- */
- public Segment[] getSegmentsArray() {
- return this.segments.toArray(new Path.Segment[this.segments.size()]);
- }
-
- /**
- * {@inheritDoc}
- */
public List<Segment> getSegmentsList() {
return this.segments;
}
@@ -201,102 +93,6 @@
/**
* {@inheritDoc}
*/
- public String getString() {
- return doGetString(null, DEFAULT_ENCODER, null);
- }
-
- /**
- * {@inheritDoc}
- */
- public String getString( TextEncoder encoder ) {
- return doGetString(null, encoder, null);
- }
-
- /**
- * {@inheritDoc}
- */
- public String getString( NamespaceRegistry namespaceRegistry ) {
- CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
- return doGetString(namespaceRegistry, null, null);
- }
-
- /**
- * {@inheritDoc}
- */
- public String getString( NamespaceRegistry namespaceRegistry,
- TextEncoder encoder ) {
- CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
- return doGetString(namespaceRegistry, encoder, null);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.graph.properties.Path#getString(org.jboss.dna.graph.properties.NamespaceRegistry,
- * org.jboss.dna.common.text.TextEncoder,
org.jboss.dna.common.text.TextEncoder)
- */
- public String getString( NamespaceRegistry namespaceRegistry,
- TextEncoder encoder,
- TextEncoder delimiterEncoder ) {
- return doGetString(namespaceRegistry, encoder, delimiterEncoder);
- }
-
- /**
- * Method that creates the string representation. This method works two different
ways depending upon whether the namespace
- * registry is provided.
- *
- * @param namespaceRegistry
- * @param encoder
- * @param delimiterEncoder
- * @return this path as a string
- */
- protected String doGetString( NamespaceRegistry namespaceRegistry,
- TextEncoder encoder,
- TextEncoder delimiterEncoder ) {
- if (encoder == null) encoder = DEFAULT_ENCODER;
- if (encoder == DEFAULT_ENCODER && this.path != null &&
delimiterEncoder == null) return this.path;
- final String delimiter = delimiterEncoder != null ?
delimiterEncoder.encode(DELIMITER_STR) : DELIMITER_STR;
-
- // Since the segments are immutable, this code need not be synchronized because
concurrent threads
- // may just compute the same value (with no harm done)
- StringBuilder sb = new StringBuilder();
- if (this.isAbsolute()) sb.append(delimiter);
- boolean first = true;
- for (Segment segment : this.segments) {
- if (first) {
- first = false;
- } else {
- sb.append(delimiter);
- }
- assert segment != null;
- sb.append(segment.getString(namespaceRegistry, encoder, delimiterEncoder));
- }
- String result = sb.toString();
- // Save the result to the internal string if this the default encoder is used.
- // This is not synchronized, but it's okay
- if (encoder == DEFAULT_ENCODER && this.path == null &&
delimiterEncoder == null) this.path = result;
- return result;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean hasSameAncestor( Path that ) {
- if (that == null) return false;
- if (this.isRoot() && that.isRoot()) return true;
- if (that.size() != this.size()) return false;
- if (this.size() == 1) return true; // both nodes are just under the root
- for (int i = this.size() - 2; i >= 0; --i) {
- Path.Segment thisSegment = this.getSegment(i);
- Path.Segment thatSegment = that.getSegment(i);
- if (!thisSegment.equals(thatSegment)) return false;
- }
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
public boolean isAbsolute() {
return this.absolute;
}
@@ -304,66 +100,6 @@
/**
* {@inheritDoc}
*/
- public boolean isAncestorOf( Path decendant ) {
- if (decendant == null) return false;
- if (this == decendant) return false;
- if (this.size() >= decendant.size()) return false;
-
- Iterator<Path.Segment> thisIter = this.iterator();
- Iterator<Path.Segment> thatIter = decendant.iterator();
- while (thisIter.hasNext()) {
- Path.Segment thisSeg = thisIter.next();
- Path.Segment thatSeg = thatIter.next();
- if (!thisSeg.equals(thatSeg)) return false;
- }
- return true;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.graph.properties.Path#isAtOrBelow(org.jboss.dna.graph.properties.Path)
- */
- public boolean isAtOrBelow( Path other ) {
- if (other == null) return false;
- if (this == other) return true;
- Iterator<Segment> thisIter = this.segments.iterator();
- Iterator<Segment> thatIter = other.iterator();
- while (thisIter.hasNext() && thatIter.hasNext()) {
- if (!thisIter.next().equals(thatIter.next())) return false;
- }
- if (thatIter.hasNext()) return false; // The other still has segments, but this
doesn't
- return true;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see
org.jboss.dna.graph.properties.Path#isAtOrAbove(org.jboss.dna.graph.properties.Path)
- */
- public boolean isAtOrAbove( Path other ) {
- if (other == null) return false;
- if (this == other) return true;
- Iterator<Segment> thisIter = this.segments.iterator();
- Iterator<Segment> thatIter = other.iterator();
- while (thisIter.hasNext() && thatIter.hasNext()) {
- if (!thisIter.next().equals(thatIter.next())) return false;
- }
- if (thisIter.hasNext()) return false; // This still has segments, but other
doesn't
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean isDecendantOf( Path ancestor ) {
- if (ancestor == null) return false;
- return ancestor.isAncestorOf(this);
- }
-
- /**
- * {@inheritDoc}
- */
public boolean isNormalized() {
return this.normalized;
}
@@ -372,191 +108,14 @@
* {@inheritDoc}
*/
public boolean isRoot() {
- return this == ROOT || this.segments.isEmpty();
+ return false;
}
/**
* {@inheritDoc}
*/
- public boolean isSameAs( Path other ) {
- return other != null && this.compareTo(other) == 0;
- }
-
- /**
- * {@inheritDoc}
- */
- public Iterator<Segment> iterator() {
- return this.segments.iterator();
- }
-
- /**
- * {@inheritDoc}
- */
- public Path relativeTo( Path startingPath ) {
- CheckArg.isNotNull(startingPath, "to");
- if (!this.isAbsolute()) {
- String msg = GraphI18n.pathIsNotAbsolute.text(this);
- throw new InvalidPathException(msg);
- }
- if (!startingPath.isAbsolute()) {
- String msg = GraphI18n.pathIsNotAbsolute.text(startingPath);
- throw new InvalidPathException(msg);
- }
-
- // Count the number of segments up to the common ancestor (relative path is what
remains) ...
- int lengthOfCommonAncestor = 0;
- Iterator<Segment> thisIter = this.getNormalizedPath().iterator();
- Iterator<Segment> toIter = startingPath.getNormalizedPath().iterator();
- while (thisIter.hasNext() && toIter.hasNext()) {
- Segment thisSeg = thisIter.next();
- Segment toSeg = toIter.next();
- if (thisSeg.equals(toSeg)) {
- ++lengthOfCommonAncestor;
- } else {
- break;
- }
- }
- // Create the relative path, starting with parent references to the common
ancestor ...
- int numberOfParentReferences = startingPath.size() - lengthOfCommonAncestor;
- List<Segment> relativeSegments = new ArrayList<Segment>();
- for (int i = 0; i != numberOfParentReferences; ++i) {
- relativeSegments.add(Path.PARENT_SEGMENT);
- }
- // Add the segments of this path from the common ancestor ...
- for (int i = lengthOfCommonAncestor; i < this.size(); ++i) {
- relativeSegments.add(this.segments.get(i));
- }
- if (relativeSegments.isEmpty()) {
- relativeSegments.add(Path.SELF_SEGMENT);
- }
- return new BasicPath(relativeSegments, false);
- }
-
- /**
- * {@inheritDoc}
- */
- public Path resolve( Path relativePath ) {
- CheckArg.isNotNull(relativePath, "relative path");
- if (!this.isAbsolute()) {
- String msg = GraphI18n.pathIsAlreadyAbsolute.text(this.path);
- throw new InvalidPathException(msg);
- }
- if (relativePath.isAbsolute()) {
- String msg = GraphI18n.pathIsNotRelative.text(relativePath);
- throw new InvalidPathException(msg);
- }
- // If the relative path is the self or parent reference ...
- relativePath = relativePath.getNormalizedPath();
- if (relativePath.size() == 1) {
- Segment onlySegment = relativePath.getSegment(0);
- if (onlySegment.isSelfReference()) return this;
- if (onlySegment.isParentReference()) return this.getParent();
- }
- List<Segment> segments = new ArrayList<Segment>(this.size() +
relativePath.size());
- segments.addAll(this.segments);
- segments.addAll(relativePath.getSegmentsList());
- return new BasicPath(segments, true).getNormalizedPath();
- }
-
- /**
- * {@inheritDoc}
- */
- public Path resolveAgainst( Path absolutePath ) {
- CheckArg.isNotNull(absolutePath, "absolute path");
- return absolutePath.resolve(this);
- }
-
- /**
- * {@inheritDoc}
- */
public int size() {
return this.segments.size();
}
- /**
- * {@inheritDoc}
- */
- public Path subpath( int beginIndex ) {
- if (beginIndex == 0) return this;
- int size = size();
- if (beginIndex >= size) {
- throw new IndexOutOfBoundsException(
-
GraphI18n.unableToCreateSubpathBeginIndexGreaterThanOrEqualToSize.text(beginIndex,
-
size));
- }
- if (size == 0) return ROOT;
- return new BasicPath(this.segments.subList(beginIndex, size),
this.isAbsolute());
- }
-
- /**
- * {@inheritDoc}
- */
- public Path subpath( int beginIndex,
- int endIndex ) {
- int size = size();
- if (beginIndex == 0) {
- if (endIndex == 0) return ROOT;
- if (endIndex == size) return this;
- }
- if (beginIndex >= size) {
- throw new IndexOutOfBoundsException(
-
GraphI18n.unableToCreateSubpathBeginIndexGreaterThanOrEqualToSize.text(beginIndex,
-
size));
- }
- if (beginIndex > endIndex) {
- throw new IndexOutOfBoundsException(
-
GraphI18n.unableToCreateSubpathBeginIndexGreaterThanOrEqualToEndingIndex.text(beginIndex,
-
endIndex));
- }
- // This reuses the same list, so it's pretty efficient ...
- return new BasicPath(this.segments.subList(beginIndex, endIndex),
this.isAbsolute());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int hashCode() {
- return this.segments.hashCode();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean equals( Object obj ) {
- if (obj == this) return true;
- if (obj instanceof Path) {
- Path that = (Path)obj;
- return this.segments.equals(that.getSegmentsList());
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- public int compareTo( Path that ) {
- if (this == that) return 0;
- Iterator<Segment> thisIter = this.segments.iterator();
- Iterator<Segment> thatIter = that.iterator();
- while (thisIter.hasNext() && thatIter.hasNext()) {
- Segment thisSegment = thisIter.next();
- Segment thatSegment = thatIter.next();
- int diff = thisSegment.compareTo(thatSegment);
- if (diff != 0) return diff;
- }
- if (thisIter.hasNext()) return 1;
- if (thatIter.hasNext()) return -1;
- return 0;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String toString() {
- return getString(Path.URL_ENCODER);
- }
-
}
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicPathSegment.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicPathSegment.java 2008-12-08
16:20:36 UTC (rev 667)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/BasicPathSegment.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -23,7 +23,6 @@
import net.jcip.annotations.Immutable;
import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.graph.properties.Name;
import org.jboss.dna.graph.properties.NamespaceRegistry;
import org.jboss.dna.graph.properties.Path;
@@ -57,8 +56,8 @@
*/
public BasicPathSegment( Name name,
int index ) {
- CheckArg.isNotNull(name, "name");
- CheckArg.isNotLessThan(index, Path.NO_INDEX, "index");
+ assert name != null;
+ assert index >= Path.NO_INDEX;
this.name = name;
this.index = (this.isSelfReference() || this.isParentReference()) ? Path.NO_INDEX
: index;
}
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/ChildPath.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/ChildPath.java
(rev 0)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/ChildPath.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -0,0 +1,261 @@
+/*
+ * 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.graph.properties.basic;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import org.jboss.dna.common.collection.ImmutableAppendedList;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.properties.Path;
+
+/**
+ * Implementation of a {@link Path} that has the information for the last segment but
that points to another Path for the parent
+ * information.
+ *
+ * @author Randall Hauch
+ */
+public class ChildPath extends AbstractPath {
+
+ /**
+ * The serializable version. Version {@value}
+ */
+ private static final long serialVersionUID = 1L;
+
+ private final Path parent;
+ private final Path.Segment child;
+ private final int size;
+ private transient List<Segment> cachedSegmentList;
+
+ public ChildPath( Path parent,
+ Path.Segment child ) {
+ assert parent != null;
+ assert child != null;
+ this.parent = parent;
+ this.child = child;
+ this.size = this.parent.size() + 1;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#getAncestor(int)
+ */
+ public Path getAncestor( int degree ) {
+ CheckArg.isNonNegative(degree, "degree");
+ if (degree == 0) return this;
+ if (degree == 1) return parent;
+ return parent.getAncestor(degree - 1);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#getLastSegment()
+ */
+ @Override
+ public Segment getLastSegment() {
+ return child;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#getParent()
+ */
+ @Override
+ public Path getParent() {
+ return parent;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#getSegment(int)
+ */
+ @Override
+ public Segment getSegment( int index ) {
+ if (index == (size - 1)) return child;
+ return parent.getSegment(index - 1);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#getSegmentsList()
+ */
+ public List<Segment> getSegmentsList() {
+ if (cachedSegmentList == null) {
+ // No need to synchronize, since this is idempotent and thus the list will be
as well
+ List<Segment> segments = null;
+ if (parent.isRoot()) {
+ segments = Collections.singletonList(child); // already immutable
+ } else if (size < 4) {
+ segments = new ArrayList<Segment>(size);
+ for (Segment segment : parent) {
+ segments.add(segment);
+ }
+ segments.add(child);
+ segments = Collections.unmodifiableList(segments);
+ } else {
+ segments = new
ImmutableAppendedList<Segment>(parent.getSegmentsList(), child);
+ }
+ cachedSegmentList = segments;
+ }
+ return cachedSegmentList;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.properties.Path#hasSameAncestor(org.jboss.dna.graph.properties.Path)
+ */
+ @Override
+ public boolean hasSameAncestor( Path that ) {
+ CheckArg.isNotNull(that, "that");
+ if (parent.equals(that.getParent())) return true;
+ return super.hasSameAncestor(that);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#isAbsolute()
+ */
+ public boolean isAbsolute() {
+ return parent.isAbsolute();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.properties.Path#isAtOrBelow(org.jboss.dna.graph.properties.Path)
+ */
+ @Override
+ public boolean isAtOrBelow( Path other ) {
+ if (this == other || parent == other) return true;
+ return super.isAtOrBelow(other);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.properties.Path#isDecendantOf(org.jboss.dna.graph.properties.Path)
+ */
+ @Override
+ public boolean isDecendantOf( Path ancestor ) {
+ if (parent == ancestor) return true; // same instance
+ return parent.isAtOrBelow(ancestor);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#isNormalized()
+ */
+ public boolean isNormalized() {
+ if (child.isParentReference() || child.isSelfReference()) return false;
+ return parent.isNormalized();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#isRoot()
+ */
+ public boolean isRoot() {
+ if (child.isParentReference()) return parent.isRoot();
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#iterator()
+ */
+ @Override
+ @SuppressWarnings( "synthetic-access" )
+ public Iterator<Segment> iterator() {
+ if (parent.isRoot()) {
+ return new Iterator<Segment>() {
+ boolean finished = false;
+
+ public boolean hasNext() {
+ return !finished;
+ }
+
+ public Segment next() {
+ if (finished) throw new NoSuchElementException();
+ finished = true;
+ return ChildPath.this.child;
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ final Iterator<Segment> parentIterator = parent.iterator();
+ return new Iterator<Segment>() {
+ boolean finished = false;
+
+ public boolean hasNext() {
+ return parentIterator.hasNext() || !finished;
+ }
+
+ public Segment next() {
+ if (parentIterator.hasNext()) return parentIterator.next();
+ if (finished) throw new NoSuchElementException();
+ finished = true;
+ return ChildPath.this.child;
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#size()
+ */
+ public int size() {
+ return size;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#subpath(int, int)
+ */
+ @Override
+ public Path subpath( int beginIndex,
+ int endIndex ) {
+ if (beginIndex == 0 && endIndex == (size - 1)) return parent;
+ return super.subpath(beginIndex, endIndex);
+ }
+
+}
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/PathValueFactory.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/PathValueFactory.java 2008-12-08
16:20:36 UTC (rev 667)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/PathValueFactory.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -104,7 +104,7 @@
* @see org.jboss.dna.graph.properties.PathFactory#createRootPath()
*/
public Path createRootPath() {
- return BasicPath.ROOT;
+ return RootPath.INSTANCE;
}
/**
@@ -124,8 +124,11 @@
int length = trimmedValue.length();
boolean absolute = false;
if (length == 0) {
- return BasicPath.ROOT;
+ return BasicPath.EMPTY_RELATIVE;
}
+ if (Path.DELIMITER_STR.equals(trimmedValue)) return RootPath.INSTANCE;
+ if (Path.SELF.equals(trimmedValue)) return BasicPath.SELF_PATH;
+ if (Path.PARENT.equals(trimmedValue)) return BasicPath.PARENT_PATH;
// Remove the leading delimiter ...
if (trimmedValue.charAt(0) == Path.DELIMITER) {
@@ -139,7 +142,7 @@
length = trimmedValue.length();
}
if (length == 0) {
- return BasicPath.ROOT;
+ return RootPath.INSTANCE;
}
// Parse the path into its segments ...
@@ -161,6 +164,10 @@
segments.add(createSegment(segment, decoder));
}
+ if (absolute && segments.size() == 1) {
+ // Special case of a single-segment name ...
+ return new ChildPath(RootPath.INSTANCE, segments.get(0));
+ }
// Create a path constructed from the supplied segments ...
return new BasicPath(segments, absolute);
}
@@ -259,9 +266,7 @@
public Path create( Name value ) {
if (value == null) return null;
try {
- List<Path.Segment> segments = new ArrayList<Path.Segment>(1);
- segments.add(new BasicPathSegment(value));
- return new BasicPath(segments, true);
+ return new ChildPath(RootPath.INSTANCE, new BasicPathSegment(value));
} catch (IllegalArgumentException e) {
throw new ValueFormatException(value, getPropertyType(), e);
}
@@ -278,7 +283,7 @@
* {@inheritDoc}
*/
public Path createAbsolutePath( Name... segmentNames ) {
- if (segmentNames == null || segmentNames.length == 0) return BasicPath.ROOT;
+ if (segmentNames == null || segmentNames.length == 0) return RootPath.INSTANCE;
List<Segment> segments = new
ArrayList<Segment>(segmentNames.length);
for (Name segmentName : segmentNames) {
if (segmentName == null) {
@@ -286,6 +291,10 @@
}
segments.add(new BasicPathSegment(segmentName));
}
+ if (segments.size() == 1) {
+ // Special case of a single-segment name ...
+ return new ChildPath(RootPath.INSTANCE, segments.get(0));
+ }
return new BasicPath(segments, true);
}
@@ -293,7 +302,7 @@
* {@inheritDoc}
*/
public Path createAbsolutePath( Segment... segments ) {
- if (segments == null || segments.length == 0) return BasicPath.ROOT;
+ if (segments == null || segments.length == 0) return RootPath.INSTANCE;
List<Segment> segmentsList = new
ArrayList<Segment>(segments.length);
for (Segment segment : segments) {
if (segment == null) {
@@ -301,6 +310,10 @@
}
segmentsList.add(segment);
}
+ if (segmentsList.size() == 1) {
+ // Special case of a single-segment name ...
+ return new ChildPath(RootPath.INSTANCE, segmentsList.get(0));
+ }
return new BasicPath(segmentsList, true);
}
@@ -317,7 +330,11 @@
}
segmentsList.add(segment);
}
- if (segmentsList.isEmpty()) return BasicPath.ROOT;
+ if (segmentsList.isEmpty()) return RootPath.INSTANCE;
+ if (segmentsList.size() == 1) {
+ // Special case of a single-segment name ...
+ return new ChildPath(RootPath.INSTANCE, segmentsList.get(0));
+ }
return new BasicPath(segmentsList, true);
}
@@ -397,8 +414,12 @@
return new BasicPath(childPath.getSegmentsList(), parentPath.isAbsolute());
}
List<Segment> segments = new ArrayList<Segment>(parentPath.size() +
childPath.size());
- segments.addAll(parentPath.getSegmentsList());
- segments.addAll(childPath.getSegmentsList());
+ for (Segment seg : parentPath) {
+ segments.add(seg);
+ }
+ for (Segment seg : childPath) {
+ segments.add(seg);
+ }
return new BasicPath(segments, parentPath.isAbsolute());
}
@@ -410,10 +431,7 @@
int index ) {
CheckArg.isNotNull(parentPath, "parent path");
CheckArg.isNotNull(segmentName, "segment name");
- List<Segment> segments = new ArrayList<Segment>(parentPath.size() +
1);
- segments.addAll(parentPath.getSegmentsList());
- segments.add(new BasicPathSegment(segmentName, index));
- return new BasicPath(segments, parentPath.isAbsolute());
+ return new ChildPath(parentPath, new BasicPathSegment(segmentName, index));
}
/**
@@ -423,6 +441,9 @@
Name... segmentNames ) {
CheckArg.isNotNull(parentPath, "parent path");
if (segmentNames == null || segmentNames.length == 0) return parentPath;
+ if (segmentNames.length == 1 && segmentNames[0] != null) {
+ return new ChildPath(parentPath, new BasicPathSegment(segmentNames[0]));
+ }
List<Segment> segments = new ArrayList<Segment>(parentPath.size() +
1);
segments.addAll(parentPath.getSegmentsList());
@@ -441,7 +462,10 @@
public Path create( Path parentPath,
Segment... segments ) {
CheckArg.isNotNull(parentPath, "parent path");
- if (segments == null || segments.length == 0) return BasicPath.ROOT;
+ if (segments == null || segments.length == 0) return RootPath.INSTANCE;
+ if (segments.length == 1 && segments[0] != null) {
+ return new ChildPath(parentPath, segments[0]);
+ }
List<Segment> segmentsList = new ArrayList<Segment>(parentPath.size()
+ 1);
segmentsList.addAll(parentPath.getSegmentsList());
@@ -471,7 +495,8 @@
}
segmentsList.add(segment);
}
- if (segmentsList.isEmpty()) return BasicPath.ROOT;
+ if (segmentsList.isEmpty()) return RootPath.INSTANCE;
+ if (segmentsList.size() == 0) return new ChildPath(parentPath,
segmentsList.get(0));
return new BasicPath(segmentsList, parentPath.isAbsolute());
}
@@ -482,9 +507,27 @@
*/
public Path create( Path parentPath,
String subpath ) {
- // Create a relative path for the subpath ...
+ CheckArg.isNotNull(subpath, "subpath");
+ subpath = subpath.trim();
+ boolean singleChild = subpath.indexOf(Path.DELIMITER) == -1;
+ if (!singleChild && subpath.startsWith("./")) {
+ if (subpath.length() == 2) return parentPath; // self reference
+ // Remove the leading parent reference and try again to see if single child
...
+ subpath = subpath.substring(2);
+ singleChild = subpath.indexOf(Path.DELIMITER) == -1;
+ }
+ if (singleChild) {
+ try {
+ Path.Segment childSegment = createSegment(subpath);
+ return new ChildPath(parentPath, childSegment);
+ } catch (IllegalArgumentException t) {
+ // Catch and eat, letting the slower implementation catch anything ...
+ }
+ }
+ // It is a subpath with more than one segment, so create a relative path for the
subpath ...
Path relativeSubpath = create(subpath);
return create(parentPath, relativeSubpath);
+
}
/**
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/RootPath.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/RootPath.java
(rev 0)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/properties/basic/RootPath.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -0,0 +1,393 @@
+/*
+ * 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.graph.properties.basic;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.Inflector;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.properties.InvalidPathException;
+import org.jboss.dna.graph.properties.NamespaceRegistry;
+import org.jboss.dna.graph.properties.Path;
+
+/**
+ * Optimized implementation of {@link Path} that serves as the root path.
+ *
+ * @author Randall Hauch
+ */
+@Immutable
+public class RootPath extends AbstractPath {
+
+ /**
+ * The serializable version. Version {@value}
+ */
+ private static final long serialVersionUID = 1L;
+
+ public static final Path INSTANCE = new RootPath();
+
+ private static final Path.Segment[] EMPTY_SEGMENT_ARRAY = new Path.Segment[] {};
+ private static final List<Path.Segment> EMPTY_SEGMENT_LIST =
Collections.emptyList();
+
+ private RootPath() {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#getAncestor(int)
+ */
+ public Path getAncestor( int degree ) {
+ CheckArg.isNonNegative(degree, "degree");
+ if (degree == 0) {
+ return this;
+ }
+ String msg = GraphI18n.pathAncestorDegreeIsInvalid.text(this.getString(),
Inflector.getInstance().ordinalize(degree));
+ throw new InvalidPathException(msg);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#getCanonicalPath()
+ */
+ @Override
+ public Path getCanonicalPath() {
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.properties.Path#getCommonAncestor(org.jboss.dna.graph.properties.Path)
+ */
+ @Override
+ public Path getCommonAncestor( Path that ) {
+ CheckArg.isNotNull(that, "that");
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#getLastSegment()
+ */
+ @Override
+ public Segment getLastSegment() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#getNormalizedPath()
+ */
+ @Override
+ public Path getNormalizedPath() {
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.properties.basic.AbstractPath#resolve(org.jboss.dna.graph.properties.Path)
+ */
+ @Override
+ public Path resolve( Path relativePath ) {
+ CheckArg.isNotNull(relativePath, "relative path");
+ if (relativePath.isAbsolute()) {
+ String msg = GraphI18n.pathIsNotRelative.text(relativePath);
+ throw new InvalidPathException(msg);
+ }
+ // Make an absolute path out of the supplied relative path ...
+ return new BasicPath(relativePath.getSegmentsList(), true).getNormalizedPath();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#getParent()
+ */
+ @Override
+ public Path getParent() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#getSegment(int)
+ */
+ @Override
+ public Segment getSegment( int index ) {
+ CheckArg.isNonNegative(index, "index");
+ EMPTY_SEGMENT_LIST.get(index); // throws IndexOutOfBoundsException
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#getSegmentsArray()
+ */
+ @Override
+ public Segment[] getSegmentsArray() {
+ // Can return the same array every time, since it's empty ...
+ return EMPTY_SEGMENT_ARRAY;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#getSegmentsList()
+ */
+ public List<Segment> getSegmentsList() {
+ return EMPTY_SEGMENT_LIST;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#getString()
+ */
+ @Override
+ public String getString() {
+ return Path.DELIMITER_STR;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.properties.Path#getString(org.jboss.dna.common.text.TextEncoder)
+ */
+ @Override
+ public String getString( TextEncoder encoder ) {
+ return Path.DELIMITER_STR;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.properties.Path#getString(org.jboss.dna.graph.properties.NamespaceRegistry)
+ */
+ @Override
+ public String getString( NamespaceRegistry namespaceRegistry ) {
+ CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
+ return Path.DELIMITER_STR;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.properties.Path#getString(org.jboss.dna.graph.properties.NamespaceRegistry,
+ * org.jboss.dna.common.text.TextEncoder)
+ */
+ @Override
+ public String getString( NamespaceRegistry namespaceRegistry,
+ TextEncoder encoder ) {
+ CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry");
+ return Path.DELIMITER_STR;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.properties.Path#getString(org.jboss.dna.graph.properties.NamespaceRegistry,
+ * org.jboss.dna.common.text.TextEncoder,
org.jboss.dna.common.text.TextEncoder)
+ */
+ @Override
+ public String getString( NamespaceRegistry namespaceRegistry,
+ TextEncoder encoder,
+ TextEncoder delimiterEncoder ) {
+ return (delimiterEncoder == null) ? DELIMITER_STR :
delimiterEncoder.encode(DELIMITER_STR);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.properties.Path#hasSameAncestor(org.jboss.dna.graph.properties.Path)
+ */
+ @Override
+ public boolean hasSameAncestor( Path that ) {
+ CheckArg.isNotNull(that, "that");
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#isAbsolute()
+ */
+ public boolean isAbsolute() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.properties.Path#isAncestorOf(org.jboss.dna.graph.properties.Path)
+ */
+ @Override
+ public boolean isAncestorOf( Path decendant ) {
+ CheckArg.isNotNull(decendant, "decendant");
+ return !decendant.isRoot();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.properties.Path#isAtOrAbove(org.jboss.dna.graph.properties.Path)
+ */
+ @Override
+ public boolean isAtOrAbove( Path other ) {
+ CheckArg.isNotNull(other, "other");
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.properties.Path#isAtOrBelow(org.jboss.dna.graph.properties.Path)
+ */
+ @Override
+ public boolean isAtOrBelow( Path other ) {
+ CheckArg.isNotNull(other, "other");
+ return other.isRoot();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.properties.Path#isDecendantOf(org.jboss.dna.graph.properties.Path)
+ */
+ @Override
+ public boolean isDecendantOf( Path ancestor ) {
+ CheckArg.isNotNull(ancestor, "ancestor");
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#isNormalized()
+ */
+ public boolean isNormalized() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#isRoot()
+ */
+ public boolean isRoot() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.properties.Path#isSameAs(org.jboss.dna.graph.properties.Path)
+ */
+ @Override
+ public boolean isSameAs( Path other ) {
+ CheckArg.isNotNull(other, "other");
+ return other.isRoot();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#iterator()
+ */
+ @Override
+ public Iterator<Segment> iterator() {
+ return EMPTY_SEGMENT_LIST.iterator();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#size()
+ */
+ public int size() {
+ return 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#subpath(int)
+ */
+ @Override
+ public Path subpath( int beginIndex ) {
+ CheckArg.isNonNegative(beginIndex, "beginIndex");
+ if (beginIndex == 0) return this;
+ EMPTY_SEGMENT_LIST.get(1); // throws IndexOutOfBoundsException
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.properties.Path#subpath(int, int)
+ */
+ @Override
+ public Path subpath( int beginIndex,
+ int endIndex ) {
+ CheckArg.isNonNegative(beginIndex, "beginIndex");
+ CheckArg.isNonNegative(endIndex, "endIndex");
+ if (endIndex >= 1) {
+ EMPTY_SEGMENT_LIST.get(endIndex); // throws IndexOutOfBoundsException
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ @Override
+ public int compareTo( Path other ) {
+ return other.isRoot() ? 0 : -1;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof Path) {
+ Path that = (Path)obj;
+ return that.isRoot();
+ }
+ return false;
+ }
+
+}
Modified:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositorySourceLoadHarness.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositorySourceLoadHarness.java 2008-12-08
16:20:36 UTC (rev 667)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/RepositorySourceLoadHarness.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -35,7 +35,7 @@
import org.jboss.dna.common.util.Logger;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.properties.basic.BasicPath;
+import org.jboss.dna.graph.properties.basic.RootPath;
import org.jboss.dna.graph.requests.ReadNodeRequest;
/**
@@ -215,7 +215,7 @@
if (i % 2 == 0) {
Thread.yield();
}
- connection.execute(context, new ReadNodeRequest(new
Location(BasicPath.ROOT)));
+ connection.execute(context, new ReadNodeRequest(new
Location(RootPath.INSTANCE)));
int int2 = random(this.hashCode() ^ (int)System.nanoTime() + i);
total += Math.min(Math.abs(Math.max(int1, int2) + int1 * int2 / 3),
count);
}
Modified:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/SimpleRepository.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/SimpleRepository.java 2008-12-08
16:20:36 UTC (rev 667)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connectors/SimpleRepository.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -39,7 +39,7 @@
import org.jboss.dna.graph.properties.PathFactory;
import org.jboss.dna.graph.properties.Property;
import org.jboss.dna.graph.properties.PropertyFactory;
-import org.jboss.dna.graph.properties.basic.BasicPath;
+import org.jboss.dna.graph.properties.basic.RootPath;
/**
* A very simple repository that maintains properties for nodes identified by a path, and
computes the children based upon the set
@@ -81,7 +81,7 @@
// throw new IllegalArgumentException("Repository \"" +
repositoryName + "\" already exists and may not be recreated");
// }
// Create a root node ...
- data.putIfAbsent(BasicPath.ROOT, new HashMap<Name, Property>());
+ data.putIfAbsent(RootPath.INSTANCE, new HashMap<Name, Property>());
}
/**
Added:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/AbstractPathTest.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/AbstractPathTest.java
(rev 0)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/AbstractPathTest.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -0,0 +1,232 @@
+/*
+ * 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.graph.properties.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.stub;
+import java.util.Iterator;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.graph.properties.InvalidPathException;
+import org.jboss.dna.graph.properties.NamespaceRegistry;
+import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.properties.Path.Segment;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public abstract class AbstractPathTest {
+
+ protected Path path;
+
+ @Before
+ public void beforeEach() {
+ }
+
+ @Test
+ public void shouldReturnNoAncestorForRoot() {
+ if (path.isRoot()) assertThat(path.getParent(), nullValue());
+ }
+
+ @Test
+ public void shouldReturnRootForAnyAncestorExactDegreeFromRoot() {
+ assertThat(path.getAncestor(path.size()).isRoot(), is(true));
+ }
+
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotAllowAncestorDegreeLargerThanSize() {
+ path.getAncestor(path.size() + 1);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowNegativeAncestorDegree() {
+ path.getAncestor(-1);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowGettingAncestorOfNullPath() {
+ path.getCommonAncestor(null);
+ }
+
+ @Test
+ public void shouldNotConsiderNodeToBeAncestorOfItself() {
+ assertThat(path.isAncestorOf(path), is(false));
+ }
+
+ @Test
+ public void shouldNotConsiderNodeToBeDecendantOfItself() {
+ assertThat(path.isDecendantOf(path), is(false));
+ }
+
+ @Test
+ public void shouldConsiderANodeToHaveSameAncestorAsItself() {
+ assertThat(path.hasSameAncestor(path), is(true));
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailForSameAncestorOfNullPath() {
+ path.hasSameAncestor(null);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailForDecendantOfNullPath() {
+ path.isDecendantOf(null);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailForAtOrAboveNullPath() {
+ path.isAtOrAbove(null);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailForAtOrBelowNullPath() {
+ path.isAtOrBelow(null);
+ }
+
+ @Test
+ public void shouldConsiderNodeToBeAtOrAboveItself() {
+ assertThat(path.isAtOrAbove(path), is(true));
+ }
+
+ @Test
+ public void shouldConsiderNodeToBeAtOrBelowItself() {
+ assertThat(path.isAtOrBelow(path), is(true));
+ }
+
+ @Test
+ public void shouldReturnNullForLastSegmentOfRoot() {
+ if (path.isRoot()) {
+ assertThat(path.getLastSegment(), is(nullValue()));
+ }
+ }
+
+ @Test
+ public void shouldNeverReturnNullForLastSegmentOfNonRoot() {
+ if (!path.isRoot()) {
+ assertThat(path.getLastSegment(), is(notNullValue()));
+ }
+ }
+
+ @Test
+ public void shouldReturnNonNullIteratorOverSegments() {
+ assertThat(path.iterator(), is(notNullValue()));
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldFailToReturnSegmentAtIndexEqualToSize() {
+ path.getSegment(path.size());
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailToReturnSegmentAtNegativeIndex() {
+ path.getSegment(-1);
+ }
+
+ @Test
+ public void shouldReturnNonNullSegmentsArray() {
+ assertThat(path.getSegmentsArray(), is(notNullValue()));
+ }
+
+ @Test
+ public void shouldReturnNonNullSegmentsList() {
+ assertThat(path.getSegmentsList(), is(notNullValue()));
+ }
+
+ @Test( expected = UnsupportedOperationException.class )
+ public void shouldReturnImmutableSegmentsList() {
+ path.getSegmentsList().add(null);
+ }
+
+ @Test( expected = UnsupportedOperationException.class )
+ public void shouldReturnImmutableSegmentsIterator() {
+ Iterator<Segment> iter = path.iterator();
+ if (iter.hasNext()) {
+ iter.remove();
+ }
+ }
+
+ @Test
+ public void shouldAlwaysReturnNonNullStringForGetString() {
+ assertThat(path.getString(), is(notNullValue()));
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowNullNamespaceRegistry() {
+ path.getString((NamespaceRegistry)null);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowNullNamespaceRegistryWithNonNullTextEncoder() {
+ TextEncoder encoder = mock(TextEncoder.class);
+ path.getString((NamespaceRegistry)null, encoder);
+ }
+
+ @Test
+ public void shouldReturnSelfForSubpathStartingAtZero() {
+ assertThat(path.subpath(0), is(sameInstance(path)));
+ assertThat(path.subpath(0, path.size()), is(sameInstance(path)));
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowSubpathStartingAtNegativeNumber() {
+ path.subpath(-1);
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldNotAllowSubpathStartingAtIndexEqualToSize() {
+ if (path.isRoot()) path.subpath(1);
+ path.subpath(path.size());
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldNotAllowSubpathEndingAtMoreThanSize() {
+ path.subpath(0, path.size() + 1);
+ }
+
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotFindRelativePathToAnotherRelativePath() {
+ Path other = mock(Path.class);
+ stub(other.isAbsolute()).toReturn(false);
+ path.relativeTo(other);
+ }
+
+ @Test
+ public void shouldAlwaysConsiderPathEqualToItself() {
+ Path other = mock(Path.class);
+ stub(other.isRoot()).toReturn(true);
+ assertThat(path.compareTo(path), is(0));
+ assertThat(path.equals(path), is(true));
+ }
+
+ @Test
+ public void shouldAlwaysReturnNonNullToString() {
+ assertThat(path.toString(), is(notNullValue()));
+ }
+
+}
Copied:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathOldTest.java
(from rev 658,
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathTest.java)
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathOldTest.java
(rev 0)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathOldTest.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -0,0 +1,952 @@
+/*
+ * 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.graph.properties.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.jboss.dna.graph.properties.basic.IsPathContaining.hasSegments;
+import static org.junit.Assert.assertThat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.jboss.dna.common.text.Jsr283Encoder;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.graph.DnaLexicon;
+import org.jboss.dna.graph.properties.InvalidPathException;
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.properties.ValueFormatException;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class BasicPathOldTest {
+
+ public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
+ public static final Path ROOT = RootPath.INSTANCE;
+
+ private BasicNamespaceRegistry namespaceRegistry;
+ private String validNamespaceUri;
+ private Path path;
+ private Path path2;
+ private Path.Segment[] validSegments;
+ private List<Path.Segment> validSegmentsList;
+ private Name[] validSegmentNames;
+ private String validNamespacePrefix;
+ private PathValueFactory pathFactory;
+
+ @Before
+ public void beforeEach() {
+ validNamespacePrefix = DnaLexicon.Namespace.PREFIX;
+ validNamespaceUri = DnaLexicon.Namespace.URI;
+ validSegmentNames = new Name[] {new BasicName(validNamespaceUri, "a"),
new BasicName(validNamespaceUri, "b"),
+ new BasicName(validNamespaceUri, "c")};
+ validSegments = new Path.Segment[] {new BasicPathSegment(validSegmentNames[0]),
+ new BasicPathSegment(validSegmentNames[1]), new
BasicPathSegment(validSegmentNames[1])};
+ validSegmentsList = new ArrayList<Path.Segment>();
+ for (Path.Segment segment : validSegments) {
+ validSegmentsList.add(segment);
+ }
+ path = new BasicPath(validSegmentsList, true);
+ namespaceRegistry = new BasicNamespaceRegistry();
+ namespaceRegistry.register(validNamespacePrefix, validNamespaceUri);
+ StringValueFactory stringValueFactory = new
StringValueFactory(Path.DEFAULT_DECODER, Path.DEFAULT_ENCODER);
+ NameValueFactory nameValueFactory = new NameValueFactory(namespaceRegistry,
Path.DEFAULT_DECODER, stringValueFactory);
+ pathFactory = new PathValueFactory(Path.DEFAULT_DECODER, stringValueFactory,
nameValueFactory);
+ }
+
+ @Test
+ public void shouldCreateAbsolutePathFromListOfValidSegments() {
+ path = new BasicPath(validSegmentsList, true);
+ assertThat(path.isAbsolute(), is(true));
+ assertThat(path.isNormalized(), is(true));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
+
+ @Test
+ public void shouldCreateRelativePathFromListOfValidSegments() {
+ path = new BasicPath(validSegmentsList, false);
+ assertThat(path.isAbsolute(), is(false));
+ assertThat(path.isNormalized(), is(true));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
+
+ @Test
+ public void shouldCreateAbsolutePathWithParentSegment() {
+ validSegmentsList.add(Path.PARENT_SEGMENT);
+ path = new BasicPath(validSegmentsList, true);
+ assertThat(path.isAbsolute(), is(true));
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
+
+ @Test
+ public void shouldCreateRelativePathWithParentSegment() {
+ validSegmentsList.add(Path.PARENT_SEGMENT);
+ path = new BasicPath(validSegmentsList, false);
+ assertThat(path.isAbsolute(), is(false));
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
+
+ @Test
+ public void shouldCreateAbsolutePathWithSelfSegment() {
+ validSegmentsList.add(Path.SELF_SEGMENT);
+ path = new BasicPath(validSegmentsList, true);
+ assertThat(path.isAbsolute(), is(true));
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
+
+ @Test
+ public void shouldCreateRelativePathWithSelfSegment() {
+ validSegmentsList.add(Path.SELF_SEGMENT);
+ path = new BasicPath(validSegmentsList, false);
+ assertThat(path.isAbsolute(), is(false));
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
+
+ @Test
+ public void shouldCreatePathWithNoNamespacePrefixes() {
+ path = pathFactory.create("/a/b/c/");
+ assertThat(path.size(), is(3));
+ assertThat(path, hasSegments(pathFactory, "a", "b",
"c"));
+ }
+
+ @Test
+ public void shouldConstructRelativePath() {
+ assertThat(pathFactory.create("a/b/c").isAbsolute(), is(false));
+ assertThat(pathFactory.create("a/b/c").isNormalized(), is(true));
+ assertThat(pathFactory.create("a/b/c").size(), is(3));
+ assertThat(pathFactory.create("a/b/c").getString(namespaceRegistry),
is("a/b/c"));
+ }
+
+ @Test
+ public void shouldConstructRelativePathToSelf() {
+ assertThat(pathFactory.create(".").isAbsolute(), is(false));
+ assertThat(pathFactory.create(".").size(), is(1));
+ assertThat(pathFactory.create("."), hasSegments(pathFactory,
Path.SELF));
+
+ assertThat(pathFactory.create("./").isAbsolute(), is(false));
+ assertThat(pathFactory.create("./").size(), is(1));
+ assertThat(pathFactory.create("./"), hasSegments(pathFactory,
Path.SELF));
+ }
+
+ @Test
+ public void shouldConstructRelativePathToParent() {
+ assertThat(pathFactory.create("..").isAbsolute(), is(false));
+ assertThat(pathFactory.create("..").size(), is(1));
+ assertThat(pathFactory.create(".."), hasSegments(pathFactory,
Path.PARENT));
+
+ assertThat(pathFactory.create("../").isAbsolute(), is(false));
+ assertThat(pathFactory.create("../").size(), is(1));
+ assertThat(pathFactory.create("../"), hasSegments(pathFactory,
Path.PARENT));
+ }
+
+ @Test
+ public void shouldConstructRootPathFromStringWithSingleDelimiter() {
+ assertThat(pathFactory.create("/"), is(ROOT));
+ assertThat(pathFactory.create("/").isRoot(), is(true));
+ }
+
+ @Test( expected = ValueFormatException.class )
+ public void shouldNotConstructPathWithSuccessiveDelimiters() {
+ pathFactory.create("///a/b///c//d//");
+ }
+
+ @Test( expected = ValueFormatException.class )
+ public void shouldNotConstructPathWithOnlyDelimiters() {
+ pathFactory.create("///");
+ }
+
+ @Test
+ public void
shouldConstructPathFromStringAndShouldIgnoreLeadingAndTrailingWhitespace() {
+ assertThat(pathFactory.create(" \t / \t").toString(),
is("/"));
+ }
+
+ @Test
+ public void shouldConstructRelativePathIfSuppliedPathHasNoLeadingDelimiter() {
+ assertThat(pathFactory.create("a"), hasSegments(pathFactory,
"a"));
+ }
+
+ @Test
+ public void shouldHaveSizeThatReflectsNumberOfSegments() {
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
+
+ @Test
+ public void shouldIterateOverAllSegmentsReturnedByList() {
+ Iterator<Path.Segment> expectedIter = validSegmentsList.iterator();
+ for (Path.Segment segment : path) {
+ assertThat(segment, is(expectedIter.next()));
+ }
+
+ expectedIter = path.getSegmentsList().iterator();
+ for (Path.Segment segment : path) {
+ assertThat(segment, is(expectedIter.next()));
+ }
+ }
+
+ @Test
+ public void shouldReturnNoAncestorForRoot() {
+ assertThat(RootPath.INSTANCE.getParent(), nullValue());
+ }
+
+ @Test
+ public void shouldReturnAncestorForNodeOtherThanRoot() {
+ assertThat(path.getParent(), is(pathFactory.create("/dna:a/dna:b")));
+ assertThat(path.getParent().getParent(),
is(pathFactory.create("/dna:a")));
+ assertThat(path.getParent().getParent().getParent(), is(ROOT));
+ }
+
+ @Test
+ public void shouldReturnNthDegreeAncestor() {
+ assertThat(path.getAncestor(1),
is(pathFactory.create("/dna:a/dna:b")));
+ assertThat(path.getAncestor(2), is(pathFactory.create("/dna:a")));
+ assertThat(path.getAncestor(3), is(ROOT));
+ }
+
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotAllowAncestorDegreeLargerThanSize() {
+ path.getAncestor(path.size() + 1);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowNegativeAncestorDegree() {
+ path.getAncestor(-1);
+ }
+
+ @Test
+ public void shouldReturnRootForAnyAncestorExactDegreeFromRoot() {
+ assertThat(path.getAncestor(path.size()), is(ROOT));
+ assertThat(ROOT.getAncestor(0), is(ROOT));
+ }
+
+ @Test
+ public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodeAndRoot() {
+ assertThat(path.getCommonAncestor(ROOT), is(ROOT));
+ assertThat(ROOT.getCommonAncestor(path), is(ROOT));
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldReturnNullForLowestCommonAncestorWithNullPath() {
+ path.getCommonAncestor(null);
+ }
+
+ @Test
+ public void shouldFindLowestCommonAncestorBetweenTwoNonRootNodesOnCommonBranch() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path common = pathFactory.create("/a");
+ assertThat(path1.getCommonAncestor(path2), is(common));
+
+ path1 = pathFactory.create("/a/b/c");
+ path2 = pathFactory.create("/a/b/c/d");
+ common = path1;
+ assertThat(path1.getCommonAncestor(path2), is(common));
+
+ path1 = pathFactory.create("/a/b/c/x/y/");
+ path2 = pathFactory.create("/a/b/c/d/e/f/");
+ common = pathFactory.create("/a/b/c");
+ assertThat(path1.getCommonAncestor(path2), is(common));
+ }
+
+ @Test
+ public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodesOnSeparateBrances() {
+ Path path1 = pathFactory.create("/x/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path common = ROOT;
+ assertThat(path1.getCommonAncestor(path2), is(common));
+ }
+
+ @Test
+ public void shouldConsiderNodeToBeAncestorOfEveryDecendantNode() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ Path common = pathFactory.create("/a");
+ assertThat(common.isAncestorOf(path1), is(true));
+ assertThat(common.isAncestorOf(path2), is(true));
+ assertThat(common.isAncestorOf(path3), is(false));
+
+ assertThat(path1.getParent().isAncestorOf(path1), is(true));
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.getAncestor(i).isAncestorOf(path1), is(true));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.getAncestor(i).isAncestorOf(path2), is(true));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.getAncestor(i).isAncestorOf(path3), is(true));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.getAncestor(i).isAncestorOf(path4), is(true));
+ }
+ }
+
+ @Test
+ public void shouldConsiderNodeToBeDecendantOfEveryAncestorNode() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ Path common = pathFactory.create("/a");
+ assertThat(path1.isDecendantOf(common), is(true));
+ assertThat(path2.isDecendantOf(common), is(true));
+ assertThat(path3.isDecendantOf(common), is(false));
+
+ assertThat(path1.getParent().isAncestorOf(path1), is(true));
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.isDecendantOf(path1.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.isDecendantOf(path2.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.isDecendantOf(path3.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.isDecendantOf(path4.getAncestor(i)), is(true));
+ }
+ }
+
+ @Test
+ public void shouldNotConsiderNodeToBeAncestorOfItself() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ assertThat(path1.isAncestorOf(path1), is(false));
+ assertThat(path2.isAncestorOf(path2), is(false));
+ assertThat(path3.isAncestorOf(path3), is(false));
+ assertThat(ROOT.isAncestorOf(ROOT), is(false));
+ }
+
+ @Test
+ public void shouldNotConsiderNodeToBeDecendantOfItself() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ assertThat(path1.isDecendantOf(path1), is(false));
+ assertThat(path2.isDecendantOf(path2), is(false));
+ assertThat(path3.isDecendantOf(path3), is(false));
+ assertThat(ROOT.isDecendantOf(ROOT), is(false));
+ }
+
+ @Test
+ public void shouldNotConsiderRootToBeDecendantOfAnyNode() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path common = pathFactory.create("/a");
+ assertThat(ROOT.isDecendantOf(path1), is(false));
+ assertThat(ROOT.isDecendantOf(path2), is(false));
+ assertThat(ROOT.isDecendantOf(path3), is(false));
+ assertThat(ROOT.isDecendantOf(common), is(false));
+ }
+
+ @Test
+ public void shouldConsiderRootToBeAncestorOfAnyNode() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path common = pathFactory.create("/a");
+ assertThat(ROOT.isAncestorOf(path1), is(true));
+ assertThat(ROOT.isAncestorOf(path2), is(true));
+ assertThat(ROOT.isAncestorOf(path3), is(true));
+ assertThat(ROOT.isAncestorOf(common), is(true));
+ }
+
+ @Test
+ public void shouldNotConsiderRootToBeAncestorOfItself() {
+ assertThat(ROOT.isAncestorOf(ROOT), is(false));
+ }
+
+ @Test
+ public void shouldNotConsiderRootToBeDecendantOfItself() {
+ assertThat(ROOT.isDecendantOf(ROOT), is(false));
+ }
+
+ @Test
+ public void shouldConsiderTwoRootNodesToHaveSameAncestor() {
+ assertThat(ROOT.hasSameAncestor(ROOT), is(true));
+ }
+
+ @Test
+ public void shouldConsiderTwoNotRootSiblingNodesToHaveSameAncestor() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/y/c");
+ assertThat(path1.hasSameAncestor(path2), is(true));
+
+ path1 = pathFactory.create("/a/z");
+ path2 = pathFactory.create("/a/c");
+ assertThat(path1.hasSameAncestor(path2), is(true));
+
+ path1 = pathFactory.create("/z");
+ path2 = pathFactory.create("/c");
+ assertThat(path1.hasSameAncestor(path2), is(true));
+ }
+
+ @Test
+ public void shouldNotConsiderTwoNonSiblingNodesToHaveSameAncestor() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/x/c");
+ assertThat(path1.hasSameAncestor(path2), is(false));
+
+ path1 = pathFactory.create("/a/z");
+ path2 = pathFactory.create("/b/c");
+ assertThat(path1.hasSameAncestor(path2), is(false));
+
+ path1 = pathFactory.create("/z");
+ path2 = pathFactory.create("/a/c");
+ assertThat(path1.hasSameAncestor(path2), is(false));
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailForSameAncestorOfNullPath() {
+ path.hasSameAncestor(null);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailForDecendantOfNullPath() {
+ path.isDecendantOf(null);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailForAtOrAboveNullPath() {
+ path.isAtOrAbove(null);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailForAtOrBelowNullPath() {
+ path.isAtOrBelow(null);
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldFailToReturnSegmentAtIndexGreatherThanSize() {
+ path.getSegment(path.size() + 1);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailToReturnSegmentAtNegativeIndex() {
+ path.getSegment(-1);
+ }
+
+ @Test
+ public void shouldConsiderNodeToBeAtOrAboveItself() {
+ assertThat(path.isAtOrAbove(path), is(true));
+ }
+
+ @Test
+ public void shouldConsiderNodeToBeAtOrBelowItself() {
+ assertThat(path.isAtOrBelow(path), is(true));
+ }
+
+ @Test
+ public void shouldConsiderAncestorToBeAtOrAboveTheDecendant() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.getAncestor(i).isAtOrAbove(path1), is(true));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.getAncestor(i).isAtOrAbove(path2), is(true));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.getAncestor(i).isAtOrAbove(path3), is(true));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.getAncestor(i).isAtOrAbove(path4), is(true));
+ }
+ }
+
+ @Test
+ public void shouldConsiderDecendantToBeAtOrBelowTheAncestor() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.isAtOrBelow(path1.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.isAtOrBelow(path2.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.isAtOrBelow(path3.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.isAtOrBelow(path4.getAncestor(i)), is(true));
+ }
+ }
+
+ @Test
+ public void shouldNotConsiderAncestorToBeAtOrBelowTheDecendant() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.getAncestor(i).isAtOrBelow(path1), is(false));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.getAncestor(i).isAtOrBelow(path2), is(false));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.getAncestor(i).isAtOrBelow(path3), is(false));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.getAncestor(i).isAtOrBelow(path4), is(false));
+ }
+ }
+
+ @Test
+ public void shouldNotConsiderDecendantToBeAtOrAboveTheAncestor() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.isAtOrAbove(path1.getAncestor(i)), is(false));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.isAtOrAbove(path2.getAncestor(i)), is(false));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.isAtOrAbove(path3.getAncestor(i)), is(false));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.isAtOrAbove(path4.getAncestor(i)), is(false));
+ }
+ }
+
+ @Test
+ public void shouldReturnNullForLastSegmentOfRoot() {
+ assertThat(ROOT.getLastSegment(), is(nullValue()));
+ }
+
+ @Test
+ public void shouldReturnLastSegmentOfNonRootPath() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x");
+ assertThat(path1.getLastSegment().getName().getLocalName(), is("z"));
+ assertThat(path2.getLastSegment().getName().getLocalName(), is("c"));
+ assertThat(path3.getLastSegment().getName().getLocalName(), is("c"));
+ assertThat(path4.getLastSegment().getName().getLocalName(), is("x"));
+ }
+
+ @Test
+ public void shouldNormalizePathWithSelfAndParentReferences() {
+ path = pathFactory.create("/a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a",
"b"));
+ assertThat(path.getNormalizedPath().isAbsolute(), is(true));
+ assertThat(path.getNormalizedPath().isNormalized(), is(true));
+
+ path = pathFactory.create("a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a",
"b"));
+ assertThat(path.getNormalizedPath().isAbsolute(), is(false));
+ assertThat(path.getNormalizedPath().isNormalized(), is(true));
+ }
+
+ @Test
+ public void shouldAlreadyBeNormalizedIfPathContainsNoParentOrSelfReferences() {
+ assertThat(pathFactory.create("/a/b/c/d/e").isNormalized(), is(true));
+ assertThat(pathFactory.create("a/b/c/d/e").isNormalized(), is(true));
+ assertThat(pathFactory.create("a").isNormalized(), is(true));
+ assertThat(pathFactory.create("/a").isNormalized(), is(true));
+ assertThat(ROOT.isNormalized(), is(true));
+ }
+
+ @Test
+ public void shouldNotBeNormalizedIfPathContainsParentOrSelfReferences() {
+ assertThat(pathFactory.create("/a/b/c/../d/./e/../..").isNormalized(),
is(false));
+ assertThat(pathFactory.create("a/b/c/../d/./e/../..").isNormalized(),
is(false));
+ assertThat(pathFactory.create("a/b/c/./d").isNormalized(), is(false));
+ assertThat(pathFactory.create("/a/b/c/../d").isNormalized(),
is(false));
+ assertThat(pathFactory.create(".").isNormalized(), is(false));
+ assertThat(pathFactory.create("/.").isNormalized(), is(false));
+ }
+
+ @Test( expected = InvalidPathException.class )
+ public void
shouldFailToReturnNormalizedPathIfPathContainsReferencesToParentsAboveRoot() {
+ path = pathFactory.create("/a/../../../..");
+ assertThat(path.isNormalized(), is(false));
+ path.getNormalizedPath();
+ }
+
+ @Test
+ public void
shouldReturnRootPathAsTheNormalizedPathForAnAbsolutePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved()
{
+ // "/a/../b/../c/.." => "/"
+ path = pathFactory.create("/a/../b/../c/../");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), is(ROOT));
+ }
+
+ @Test
+ public void
shouldReturnSelfPathAsTheNormalizedPathForARelativePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved()
{
+ // "a/../b/../c/.." => "."
+ path = pathFactory.create("a/../b/../c/../");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath().size(), is(1));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "."));
+ }
+
+ @Test
+ public void
shouldNotHaveAnyParentOrSelfReferencesInTheNormalizedPathOfAnAbsolutePath() {
+ path = pathFactory.create("/a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a",
"b"));
+ assertThat(path.getNormalizedPath().isAbsolute(), is(true));
+ assertThat(path.getNormalizedPath().isNormalized(), is(true));
+ }
+
+ @Test
+ public void shouldNotHaveAnyParentReferencesInTheNormalizedPathOfARelativePath() {
+ path = pathFactory.create("a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a",
"b"));
+ assertThat(path.getNormalizedPath().isAbsolute(), is(false));
+ assertThat(path.getNormalizedPath().isNormalized(), is(true));
+ }
+
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotComputeCanonicalPathOfNodeThatIsNotAbsolute() {
+ pathFactory.create("a/b/c/../d/./e/../..").getCanonicalPath();
+ }
+
+ @Test
+ public void shouldReturnNormalizedPathForTheCanonicalPathOfAbsolutePath() {
+ path = pathFactory.create("/a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.isAbsolute(), is(true));
+ assertThat(path.getCanonicalPath(), hasSegments(pathFactory, "a",
"b"));
+ assertThat(path.getCanonicalPath().isAbsolute(), is(true));
+ assertThat(path.getCanonicalPath().isNormalized(), is(true));
+ }
+
+ @Test
+ public void shouldReturnSameSegmentsInIteratorAndArrayAndList() {
+ testSegmentsByIteratorAndListAndArray("/a/b/c/../d/./e/../..",
"a", "b", "c", "..", "d", ".",
"e", "..", "..");
+ testSegmentsByIteratorAndListAndArray("/a/b/c", "a",
"b", "c");
+ testSegmentsByIteratorAndListAndArray("a/b/c/../d/./e/../..",
"a", "b", "c", "..", "d", ".",
"e", "..", "..");
+ testSegmentsByIteratorAndListAndArray("a/b/c", "a",
"b", "c");
+ testSegmentsByIteratorAndListAndArray("");
+ testSegmentsByIteratorAndListAndArray(ROOT.getString());
+ }
+
+ public void testSegmentsByIteratorAndListAndArray( String pathStr,
+ String... expectedSegmentStrings )
{
+ path = pathFactory.create(pathStr);
+ assertThat(expectedSegmentStrings.length, is(path.size()));
+ Path.Segment[] segmentArray = path.getSegmentsArray();
+ List<Path.Segment> segmentList = path.getSegmentsList();
+ assertThat(segmentArray.length, is(path.size()));
+ assertThat(segmentList.size(), is(path.size()));
+ Iterator<Path.Segment> iter = path.iterator();
+ Iterator<Path.Segment> listIter = segmentList.iterator();
+ for (int i = 0; i != path.size(); ++i) {
+ Path.Segment expected =
pathFactory.createSegment(expectedSegmentStrings[i]);
+ assertThat(path.getSegment(i), is(expected));
+ assertThat(segmentArray[i], is(expected));
+ assertThat(segmentList.get(i), is(expected));
+ assertThat(iter.next(), is(expected));
+ assertThat(listIter.next(), is(expected));
+ }
+ assertThat(iter.hasNext(), is(false));
+ assertThat(listIter.hasNext(), is(false));
+ }
+
+ @Test
+ public void shouldGetStringWithNamespaceUrisIfNoNamespaceRegistryIsProvided() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.getString(NO_OP_ENCODER),
+
is("/{http://www.jboss.org/dna}a/{}b/{http://www.jboss.org/dna}c/../...);
+ }
+
+ @Test
+ public void
shouldGetStringWithNamespacePrefixesForAllNamesIfNamespaceRegistryIsProvided() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER),
is("/dna:a/b/dna:c/../d/./dna:e/../.."));
+ namespaceRegistry.register("dna2", validNamespaceUri);
+ assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER),
is("/dna2:a/b/dna2:c/../d/./dna2:e/../.."));
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailToReturnSubpathIfStartingIndexIsNegative() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(-1);
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void
shouldFailToReturnSubpathWithoutEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(path.size() + 1);
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void
shouldFailToReturnSubpathWithEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(path.size() + 1, path.size() + 2);
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldFailToReturnSubpathIfEndingIndexIsSmallerThanStartingIndex() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(2, 1);
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldFailToReturnSubpathIfEndingIndexIsEqualToOrLargerThanSize() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(2, path.size() + 1);
+ }
+
+ @Test
+ public void shouldReturnRootAsSubpathIfStartingIndexAndEndingIndexAreBothZero() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.subpath(0, 0), is(ROOT));
+ }
+
+ @Test
+ public void shouldReturnSubpathIfValidStartingIndexAndNoEndingIndexAreProvided() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a",
"b", "dna:c", "..", "d", ".",
"dna:e", "..", ".."));
+ assertThat(path.subpath(0), is(path));
+ assertThat(path.subpath(0), is(sameInstance(path)));
+ assertThat(path.subpath(1), hasSegments(pathFactory, "b",
"dna:c", "..", "d", ".", "dna:e",
"..", ".."));
+ assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c",
"..", "d", ".", "dna:e", "..",
".."));
+ assertThat(path.subpath(3), hasSegments(pathFactory, "..",
"d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(4), hasSegments(pathFactory, "d",
".", "dna:e", "..", ".."));
+ assertThat(path.subpath(5), hasSegments(pathFactory, ".",
"dna:e", "..", ".."));
+ assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e",
"..", ".."));
+ assertThat(path.subpath(7), hasSegments(pathFactory, "..",
".."));
+ assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
+
+ path = pathFactory.create("dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a",
"b", "dna:c", "..", "d", ".",
"dna:e", "..", ".."));
+ assertThat(path.subpath(0), is(path));
+ assertThat(path.subpath(0), is(sameInstance(path)));
+ assertThat(path.subpath(1), hasSegments(pathFactory, "b",
"dna:c", "..", "d", ".", "dna:e",
"..", ".."));
+ assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c",
"..", "d", ".", "dna:e", "..",
".."));
+ assertThat(path.subpath(3), hasSegments(pathFactory, "..",
"d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(4), hasSegments(pathFactory, "d",
".", "dna:e", "..", ".."));
+ assertThat(path.subpath(5), hasSegments(pathFactory, ".",
"dna:e", "..", ".."));
+ assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e",
"..", ".."));
+ assertThat(path.subpath(7), hasSegments(pathFactory, "..",
".."));
+ assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
+ }
+
+ @Test
+ public void shouldReturnSubpathIfValidStartingIndexAndEndingIndexAreProvided() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.subpath(0, path.size()), hasSegments(pathFactory,
+ "dna:a",
+ "b",
+ "dna:c",
+ "..",
+ "d",
+ ".",
+ "dna:e",
+ "..",
+ ".."));
+ assertThat(path.subpath(0, path.size()), is(path));
+ assertThat(path.subpath(0, path.size()), is(sameInstance(path)));
+ assertThat(path.subpath(1, path.size()), hasSegments(pathFactory, "b",
"dna:c", "..", "d", ".", "dna:e",
"..", ".."));
+ assertThat(path.subpath(2, path.size()), hasSegments(pathFactory,
"dna:c", "..", "d", ".", "dna:e",
"..", ".."));
+ assertThat(path.subpath(3, path.size()), hasSegments(pathFactory, "..",
"d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(4, path.size()), hasSegments(pathFactory, "d",
".", "dna:e", "..", ".."));
+ assertThat(path.subpath(5, path.size()), hasSegments(pathFactory, ".",
"dna:e", "..", ".."));
+ assertThat(path.subpath(6, path.size()), hasSegments(pathFactory,
"dna:e", "..", ".."));
+ assertThat(path.subpath(7, path.size()), hasSegments(pathFactory, "..",
".."));
+ assertThat(path.subpath(8, path.size()), hasSegments(pathFactory,
".."));
+
+ assertThat(path.subpath(0, 2), hasSegments(pathFactory, "dna:a",
"b"));
+ assertThat(path.subpath(1, 2), hasSegments(pathFactory, "b"));
+ assertThat(path.subpath(1, 5), hasSegments(pathFactory, "b",
"dna:c", "..", "d"));
+ assertThat(path.subpath(2, 5), hasSegments(pathFactory, "dna:c",
"..", "d"));
+ assertThat(path.subpath(3, 5), hasSegments(pathFactory, "..",
"d"));
+ }
+
+ @Test
+ public void shouldFindRelativePaths() {
+ path = pathFactory.create("/a/b/c/d");
+ assertThat(path.relativeTo(pathFactory.create("/a/e/f")),
is(pathFactory.create("../../b/c/d")));
+ assertThat(path.relativeTo(pathFactory.create("/e/f")),
is(pathFactory.create("../../a/b/c/d")));
+
+ }
+
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotAllowFindingRelativePathsFromRelativePaths() {
+ path = pathFactory.create("a/b/c/d");
+ path.relativeTo(pathFactory.create("/e/f"));
+
+ }
+
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotResolveRelativePathToAnotherRelativePath() {
+ path = pathFactory.create("/a/b/c/d");
+ path.relativeTo(pathFactory.create("e/f"));
+
+ }
+
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotResolveRelativePathUsingAnAbsolutePath() {
+ path = pathFactory.create("/a/b/c/d");
+ path.resolve(pathFactory.create("/e/f"));
+ }
+
+ @Test
+ public void shouldResolveRelativePathToAbsolutePath() {
+ path = pathFactory.create("/a/b/c/d");
+ path2 = path.resolve(pathFactory.create("../../e/f"));
+ assertThat(path2, is(pathFactory.create("/a/b/e/f")));
+ assertThat(path2.isAbsolute(), is(true));
+ assertThat(path2.isNormalized(), is(true));
+ }
+
+ @Test
+ public void shouldOrderPathsCorrectly() {
+ List<Path> paths = new ArrayList<Path>();
+ paths.add(pathFactory.create("/a"));
+ paths.add(pathFactory.create("/a/b"));
+ paths.add(pathFactory.create("/a/b/alpha"));
+ paths.add(pathFactory.create("/a/b/beta"));
+ paths.add(pathFactory.create("/a/b/dna:mixinTypes"));
+ paths.add(pathFactory.create("/a/b/dna:name"));
+ paths.add(pathFactory.create("/a/b/dna:primaryType"));
+ paths.add(pathFactory.create("/a/c[1]"));
+ paths.add(pathFactory.create("/a/c[1]/alpha"));
+ paths.add(pathFactory.create("/a/c[1]/beta"));
+ paths.add(pathFactory.create("/a/c[1]/dna:mixinTypes"));
+ paths.add(pathFactory.create("/a/c[1]/dna:name"));
+ paths.add(pathFactory.create("/a/c[1]/dna:primaryType"));
+ paths.add(pathFactory.create("/a/c[2]"));
+ paths.add(pathFactory.create("/a/c[2]/alpha"));
+ paths.add(pathFactory.create("/a/c[2]/beta"));
+ paths.add(pathFactory.create("/a/c[2]/dna:mixinTypes"));
+ paths.add(pathFactory.create("/a/c[2]/dna:name"));
+ paths.add(pathFactory.create("/a/c[2]/dna:primaryType"));
+
+ // Randomize the list of paths, so we have something to sort ...
+ List<Path> randomizedPaths = new ArrayList<Path>(paths);
+ Collections.shuffle(randomizedPaths);
+ assertThat(randomizedPaths, is(not(paths)));
+
+ // Sort ...
+ Collections.sort(randomizedPaths);
+ assertThat(randomizedPaths, is(paths));
+ }
+
+ @Test
+ public void shouldGetNormalizedPathOfSelfShouldBeSame() {
+ assertThat(pathFactory.create(".").getNormalizedPath(),
is(pathFactory.create(".")));
+ assertThat(pathFactory.create("./").getNormalizedPath(),
is(pathFactory.create(".")));
+ assertThat(pathFactory.create("./././").getNormalizedPath(),
is(pathFactory.create(".")));
+ }
+
+ @Test
+ public void shouldGetNormalizedPathWithParentReferences() {
+ assertThat(pathFactory.create("..").getNormalizedPath(),
is(pathFactory.create("..")));
+ assertThat(pathFactory.create("../").getNormalizedPath(),
is(pathFactory.create("../")));
+ assertThat(pathFactory.create("../../../../../..").getNormalizedPath(),
is(pathFactory.create("../../../../../..")));
+ }
+
+ @Test
+ public void shouldGetRelativePathUsingSelf() {
+ path = pathFactory.create("/a/b/c/d/e/f");
+ assertThat(path.resolve(pathFactory.create(".")),
is(sameInstance(path)));
+ assertThat(path.resolve(pathFactory.create("././.")),
is(sameInstance(path)));
+ }
+
+ @Test
+ public void shouldResolveRelativePathToParent() {
+ path = pathFactory.create("/a/b/c/d/e/f");
+ assertThat(path.resolve(pathFactory.create("..")),
is(path.getParent()));
+ assertThat(path.resolve(pathFactory.create("..")),
hasSegments(pathFactory, "a", "b", "c", "d",
"e"));
+ }
+
+ @Test
+ public void shouldResolveRelativePaths() {
+ path = pathFactory.create("/a/b/c/d/e/f");
+ assertThat(path.resolve(pathFactory.create("../../../../../..")),
is(sameInstance(ROOT)));
+ assertThat(path.resolve(pathFactory.create("../..")),
is(path.getParent().getParent()));
+ assertThat(path.resolve(pathFactory.create("../..")),
hasSegments(pathFactory, "a", "b", "c", "d"));
+ assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")),
is(path.getParent()));
+ assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")),
hasSegments(pathFactory, "a", "b", "c", "d",
"e"));
+ assertThat(path.resolve(pathFactory.create("../x")),
hasSegments(pathFactory, "a", "b", "c", "d",
"e", "x"));
+ }
+
+ public void shouldResolveNonAbsolutePaths() {
+ path = pathFactory.create("a/b/c");
+ assertThat(path, hasSegments(pathFactory, "a", "b",
"c"));
+ }
+
+ @Test
+ public void shouldConvertPathToString() {
+ TextEncoder encoder = new Jsr283Encoder();
+ TextEncoder delimEncoder = new TextEncoder() {
+ public String encode( String text ) {
+ if ("/".equals(text)) return "\\/";
+ if (":".equals(text)) return "\\:";
+ if ("{".equals(text)) return "\\{";
+ if ("}".equals(text)) return "\\}";
+ return text;
+ }
+ };
+ Path path = pathFactory.create("a/b/c");
+ assertThat(path.getString(namespaceRegistry), is("a/b/c"));
+ assertThat(path.getString(namespaceRegistry, encoder), is("a/b/c"));
+ assertThat(path.getString(namespaceRegistry, encoder, delimEncoder),
is("a\\/b\\/c"));
+
+ path = pathFactory.create("/a/b/c");
+ assertThat(path.getString(namespaceRegistry), is("/a/b/c"));
+ assertThat(path.getString(namespaceRegistry, encoder), is("/a/b/c"));
+ assertThat(path.getString(namespaceRegistry, encoder, delimEncoder),
is("\\/a\\/b\\/c"));
+
+ path = pathFactory.create("/dna:a/b/c");
+ assertThat(path.getString(encoder), is("/{" +
encoder.encode(DnaLexicon.Namespace.URI) + "}a/{}b/{}c"));
+ assertThat(path.getString(null, encoder, delimEncoder), is("\\/\\{" +
encoder.encode(DnaLexicon.Namespace.URI)
+ +
"\\}a\\/\\{\\}b\\/\\{\\}c"));
+ assertThat(path.getString(namespaceRegistry), is("/dna:a/b/c"));
+ assertThat(path.getString(namespaceRegistry, encoder),
is("/dna:a/b/c"));
+ assertThat(path.getString(namespaceRegistry, encoder, delimEncoder),
is("\\/dna\\:a\\/b\\/c"));
+ }
+}
Property changes on:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathOldTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathSegmentTest.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathSegmentTest.java 2008-12-08
16:20:36 UTC (rev 667)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathSegmentTest.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -58,11 +58,6 @@
this.factory = new PathValueFactory(Path.DEFAULT_DECODER, stringValueFactory,
nameFactory);
}
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowNegativeIndex() {
- new BasicPathSegment(validName, -2);
- }
-
@Test
public void shouldConsiderEqualTwoSegmentsWithSameNameAndIndex() {
segment = new BasicPathSegment(validName);
Deleted:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathTest.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathTest.java 2008-12-08
16:20:36 UTC (rev 667)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathTest.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -1,933 +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.graph.properties.basic;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNot.not;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
-import static org.jboss.dna.graph.properties.basic.IsPathContaining.hasSegments;
-import static org.junit.Assert.assertThat;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import org.jboss.dna.common.text.Jsr283Encoder;
-import org.jboss.dna.common.text.TextEncoder;
-import org.jboss.dna.graph.DnaLexicon;
-import org.jboss.dna.graph.properties.InvalidPathException;
-import org.jboss.dna.graph.properties.Name;
-import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.ValueFormatException;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- * @author John Verhaeg
- */
-public class BasicPathTest {
-
- public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
- public static final Path ROOT = BasicPath.ROOT;
-
- private BasicNamespaceRegistry namespaceRegistry;
- private String validNamespaceUri;
- private Path path;
- private Path path2;
- private Path.Segment[] validSegments;
- private List<Path.Segment> validSegmentsList;
- private Name[] validSegmentNames;
- private String validNamespacePrefix;
- private PathValueFactory pathFactory;
-
- @Before
- public void beforeEach() {
- validNamespacePrefix = DnaLexicon.Namespace.PREFIX;
- validNamespaceUri = DnaLexicon.Namespace.URI;
- validSegmentNames = new Name[] {new BasicName(validNamespaceUri, "a"),
new BasicName(validNamespaceUri, "b"),
- new BasicName(validNamespaceUri, "c")};
- validSegments = new Path.Segment[] {new BasicPathSegment(validSegmentNames[0]),
- new BasicPathSegment(validSegmentNames[1]), new
BasicPathSegment(validSegmentNames[1])};
- validSegmentsList = new ArrayList<Path.Segment>();
- for (Path.Segment segment : validSegments) {
- validSegmentsList.add(segment);
- }
- path = new BasicPath(validSegmentsList, true);
- namespaceRegistry = new BasicNamespaceRegistry();
- namespaceRegistry.register(validNamespacePrefix, validNamespaceUri);
- StringValueFactory stringValueFactory = new
StringValueFactory(Path.DEFAULT_DECODER, Path.DEFAULT_ENCODER);
- NameValueFactory nameValueFactory = new NameValueFactory(namespaceRegistry,
Path.DEFAULT_DECODER, stringValueFactory);
- pathFactory = new PathValueFactory(Path.DEFAULT_DECODER, stringValueFactory,
nameValueFactory);
- }
-
- @Test
- public void shouldCreateAbsolutePathFromListOfValidSegments() {
- path = new BasicPath(validSegmentsList, true);
- assertThat(path.isAbsolute(), is(true));
- assertThat(path.isNormalized(), is(true));
- assertThat(path.getSegmentsList(), is(validSegmentsList));
- assertThat(path.size(), is(validSegmentsList.size()));
- }
-
- @Test
- public void shouldCreateRelativePathFromListOfValidSegments() {
- path = new BasicPath(validSegmentsList, false);
- assertThat(path.isAbsolute(), is(false));
- assertThat(path.isNormalized(), is(true));
- assertThat(path.getSegmentsList(), is(validSegmentsList));
- assertThat(path.size(), is(validSegmentsList.size()));
- }
-
- @Test
- public void shouldCreateAbsolutePathWithParentSegment() {
- validSegmentsList.add(Path.PARENT_SEGMENT);
- path = new BasicPath(validSegmentsList, true);
- assertThat(path.isAbsolute(), is(true));
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getSegmentsList(), is(validSegmentsList));
- assertThat(path.size(), is(validSegmentsList.size()));
- }
-
- @Test
- public void shouldCreateRelativePathWithParentSegment() {
- validSegmentsList.add(Path.PARENT_SEGMENT);
- path = new BasicPath(validSegmentsList, false);
- assertThat(path.isAbsolute(), is(false));
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getSegmentsList(), is(validSegmentsList));
- assertThat(path.size(), is(validSegmentsList.size()));
- }
-
- @Test
- public void shouldCreateAbsolutePathWithSelfSegment() {
- validSegmentsList.add(Path.SELF_SEGMENT);
- path = new BasicPath(validSegmentsList, true);
- assertThat(path.isAbsolute(), is(true));
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getSegmentsList(), is(validSegmentsList));
- assertThat(path.size(), is(validSegmentsList.size()));
- }
-
- @Test
- public void shouldCreateRelativePathWithSelfSegment() {
- validSegmentsList.add(Path.SELF_SEGMENT);
- path = new BasicPath(validSegmentsList, false);
- assertThat(path.isAbsolute(), is(false));
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getSegmentsList(), is(validSegmentsList));
- assertThat(path.size(), is(validSegmentsList.size()));
- }
-
- @Test
- public void shouldCreatePathWithNoNamespacePrefixes() {
- path = pathFactory.create("/a/b/c/");
- assertThat(path.size(), is(3));
- assertThat(path, hasSegments(pathFactory, "a", "b",
"c"));
- }
-
- @Test
- public void shouldConstructRelativePath() {
- assertThat(pathFactory.create("a/b/c").isAbsolute(), is(false));
- assertThat(pathFactory.create("a/b/c").isNormalized(), is(true));
- assertThat(pathFactory.create("a/b/c").size(), is(3));
- assertThat(pathFactory.create("a/b/c").getString(namespaceRegistry),
is("a/b/c"));
- }
-
- @Test
- public void shouldConstructRelativePathToSelf() {
- assertThat(pathFactory.create(".").isAbsolute(), is(false));
- assertThat(pathFactory.create(".").size(), is(1));
- assertThat(pathFactory.create("."), hasSegments(pathFactory,
Path.SELF));
-
- assertThat(pathFactory.create("./").isAbsolute(), is(false));
- assertThat(pathFactory.create("./").size(), is(1));
- assertThat(pathFactory.create("./"), hasSegments(pathFactory,
Path.SELF));
- }
-
- @Test
- public void shouldConstructRelativePathToParent() {
- assertThat(pathFactory.create("..").isAbsolute(), is(false));
- assertThat(pathFactory.create("..").size(), is(1));
- assertThat(pathFactory.create(".."), hasSegments(pathFactory,
Path.PARENT));
-
- assertThat(pathFactory.create("../").isAbsolute(), is(false));
- assertThat(pathFactory.create("../").size(), is(1));
- assertThat(pathFactory.create("../"), hasSegments(pathFactory,
Path.PARENT));
- }
-
- @Test
- public void shouldConstructRootPathFromStringWithSingleDelimiter() {
- assertThat(pathFactory.create("/"), is(ROOT));
- assertThat(pathFactory.create("/").isRoot(), is(true));
- }
-
- @Test( expected = ValueFormatException.class )
- public void shouldNotConstructPathWithSuccessiveDelimiters() {
- pathFactory.create("///a/b///c//d//");
- }
-
- @Test( expected = ValueFormatException.class )
- public void shouldNotConstructPathWithOnlyDelimiters() {
- pathFactory.create("///");
- }
-
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotConstructPathFromNullList() {
- new BasicPath(null, true);
- }
-
- @Test
- public void
shouldConstructPathFromStringAndShouldIgnoreLeadingAndTrailingWhitespace() {
- assertThat(pathFactory.create(" \t / \t").toString(),
is("/"));
- }
-
- @Test
- public void shouldConstructRelativePathIfSuppliedPathHasNoLeadingDelimiter() {
- assertThat(pathFactory.create("a"), hasSegments(pathFactory,
"a"));
- }
-
- @Test
- public void shouldHaveSizeThatReflectsNumberOfSegments() {
- assertThat(path.size(), is(validSegmentsList.size()));
- }
-
- @Test
- public void shouldIterateOverAllSegmentsReturnedByList() {
- Iterator<Path.Segment> expectedIter = validSegmentsList.iterator();
- for (Path.Segment segment : path) {
- assertThat(segment, is(expectedIter.next()));
- }
-
- expectedIter = path.getSegmentsList().iterator();
- for (Path.Segment segment : path) {
- assertThat(segment, is(expectedIter.next()));
- }
- }
-
- @Test
- public void shouldReturnNoAncestorForRoot() {
- assertThat(BasicPath.ROOT.getParent(), nullValue());
- }
-
- @Test
- public void shouldReturnAncestorForNodeOtherThanRoot() {
- assertThat(path.getParent(), is(pathFactory.create("/dna:a/dna:b")));
- assertThat(path.getParent().getParent(),
is(pathFactory.create("/dna:a")));
- assertThat(path.getParent().getParent().getParent(), is(ROOT));
- }
-
- @Test
- public void shouldReturnNthDegreeAncestor() {
- assertThat(path.getAncestor(1),
is(pathFactory.create("/dna:a/dna:b")));
- assertThat(path.getAncestor(2), is(pathFactory.create("/dna:a")));
- assertThat(path.getAncestor(3), is(ROOT));
- }
-
- @Test( expected = InvalidPathException.class )
- public void shouldNotAllowAncestorDegreeLargerThanSize() {
- path.getAncestor(path.size() + 1);
- }
-
- @Test( expected = IllegalArgumentException.class )
- public void shouldNotAllowNegativeAncestorDegree() {
- path.getAncestor(-1);
- }
-
- @Test
- public void shouldReturnRootForAnyAncestorExactDegreeFromRoot() {
- assertThat(path.getAncestor(path.size()), is(ROOT));
- assertThat(ROOT.getAncestor(0), is(ROOT));
- }
-
- @Test
- public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodeAndRoot() {
- assertThat(path.getCommonAncestor(ROOT), is(ROOT));
- assertThat(ROOT.getCommonAncestor(path), is(ROOT));
- }
-
- @Test
- public void shouldReturnNullForLowestCommonAncestorWithNullPath() {
- assertThat(path.getCommonAncestor(null), is(nullValue()));
- }
-
- @Test
- public void shouldFindLowestCommonAncestorBetweenTwoNonRootNodesOnCommonBranch() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path common = pathFactory.create("/a");
- assertThat(path1.getCommonAncestor(path2), is(common));
-
- path1 = pathFactory.create("/a/b/c");
- path2 = pathFactory.create("/a/b/c/d");
- common = path1;
- assertThat(path1.getCommonAncestor(path2), is(common));
-
- path1 = pathFactory.create("/a/b/c/x/y/");
- path2 = pathFactory.create("/a/b/c/d/e/f/");
- common = pathFactory.create("/a/b/c");
- assertThat(path1.getCommonAncestor(path2), is(common));
- }
-
- @Test
- public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodesOnSeparateBrances() {
- Path path1 = pathFactory.create("/x/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path common = ROOT;
- assertThat(path1.getCommonAncestor(path2), is(common));
- }
-
- @Test
- public void shouldConsiderNodeToBeAncestorOfEveryDecendantNode() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
- Path common = pathFactory.create("/a");
- assertThat(common.isAncestorOf(path1), is(true));
- assertThat(common.isAncestorOf(path2), is(true));
- assertThat(common.isAncestorOf(path3), is(false));
-
- assertThat(path1.getParent().isAncestorOf(path1), is(true));
- for (int i = 1; i < path1.size(); ++i) {
- assertThat(path1.getAncestor(i).isAncestorOf(path1), is(true));
- }
- for (int i = 1; i < path2.size(); ++i) {
- assertThat(path2.getAncestor(i).isAncestorOf(path2), is(true));
- }
- for (int i = 1; i < path3.size(); ++i) {
- assertThat(path3.getAncestor(i).isAncestorOf(path3), is(true));
- }
- for (int i = 1; i < path4.size(); ++i) {
- assertThat(path4.getAncestor(i).isAncestorOf(path4), is(true));
- }
- }
-
- @Test
- public void shouldConsiderNodeToBeDecendantOfEveryAncestorNode() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
- Path common = pathFactory.create("/a");
- assertThat(path1.isDecendantOf(common), is(true));
- assertThat(path2.isDecendantOf(common), is(true));
- assertThat(path3.isDecendantOf(common), is(false));
-
- assertThat(path1.getParent().isAncestorOf(path1), is(true));
- for (int i = 1; i < path1.size(); ++i) {
- assertThat(path1.isDecendantOf(path1.getAncestor(i)), is(true));
- }
- for (int i = 1; i < path2.size(); ++i) {
- assertThat(path2.isDecendantOf(path2.getAncestor(i)), is(true));
- }
- for (int i = 1; i < path3.size(); ++i) {
- assertThat(path3.isDecendantOf(path3.getAncestor(i)), is(true));
- }
- for (int i = 1; i < path4.size(); ++i) {
- assertThat(path4.isDecendantOf(path4.getAncestor(i)), is(true));
- }
- }
-
- @Test
- public void shouldNotConsiderNodeToBeAncestorOfItself() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- assertThat(path1.isAncestorOf(path1), is(false));
- assertThat(path2.isAncestorOf(path2), is(false));
- assertThat(path3.isAncestorOf(path3), is(false));
- assertThat(ROOT.isAncestorOf(ROOT), is(false));
- }
-
- @Test
- public void shouldNotConsiderNodeToBeDecendantOfItself() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- assertThat(path1.isDecendantOf(path1), is(false));
- assertThat(path2.isDecendantOf(path2), is(false));
- assertThat(path3.isDecendantOf(path3), is(false));
- assertThat(ROOT.isDecendantOf(ROOT), is(false));
- }
-
- @Test
- public void shouldNotConsiderRootToBeDecendantOfAnyNode() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path common = pathFactory.create("/a");
- assertThat(ROOT.isDecendantOf(path1), is(false));
- assertThat(ROOT.isDecendantOf(path2), is(false));
- assertThat(ROOT.isDecendantOf(path3), is(false));
- assertThat(ROOT.isDecendantOf(common), is(false));
- }
-
- @Test
- public void shouldConsiderRootToBeAncestorOfAnyNode() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path common = pathFactory.create("/a");
- assertThat(ROOT.isAncestorOf(path1), is(true));
- assertThat(ROOT.isAncestorOf(path2), is(true));
- assertThat(ROOT.isAncestorOf(path3), is(true));
- assertThat(ROOT.isAncestorOf(common), is(true));
- }
-
- @Test
- public void shouldNotConsiderRootToBeAncestorOfItself() {
- assertThat(ROOT.isAncestorOf(ROOT), is(false));
- }
-
- @Test
- public void shouldNotConsiderRootToBeDecendantOfItself() {
- assertThat(ROOT.isDecendantOf(ROOT), is(false));
- }
-
- @Test
- public void shouldConsiderTwoRootNodesToHaveSameAncestor() {
- assertThat(ROOT.hasSameAncestor(ROOT), is(true));
- }
-
- @Test
- public void shouldConsiderTwoNotRootSiblingNodesToHaveSameAncestor() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/y/c");
- assertThat(path1.hasSameAncestor(path2), is(true));
-
- path1 = pathFactory.create("/a/z");
- path2 = pathFactory.create("/a/c");
- assertThat(path1.hasSameAncestor(path2), is(true));
-
- path1 = pathFactory.create("/z");
- path2 = pathFactory.create("/c");
- assertThat(path1.hasSameAncestor(path2), is(true));
- }
-
- @Test
- public void shouldNotConsiderTwoNonSiblingNodesToHaveSameAncestor() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/x/c");
- assertThat(path1.hasSameAncestor(path2), is(false));
-
- path1 = pathFactory.create("/a/z");
- path2 = pathFactory.create("/b/c");
- assertThat(path1.hasSameAncestor(path2), is(false));
-
- path1 = pathFactory.create("/z");
- path2 = pathFactory.create("/a/c");
- assertThat(path1.hasSameAncestor(path2), is(false));
- }
-
- @Test
- public void shouldNeverBeDecendantOfNullPath() {
- assertThat(path.isDecendantOf(null), is(false));
- assertThat(ROOT.isDecendantOf(null), is(false));
- }
-
- @Test
- public void shouldConsiderNodeToBeAtOrAboveItself() {
- assertThat(path.isAtOrAbove(path), is(true));
- }
-
- @Test
- public void shouldConsiderNodeToBeAtOrBelowItself() {
- assertThat(path.isAtOrBelow(path), is(true));
- }
-
- @Test
- public void shouldConsiderAncestorToBeAtOrAboveTheDecendant() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
- for (int i = 1; i < path1.size(); ++i) {
- assertThat(path1.getAncestor(i).isAtOrAbove(path1), is(true));
- }
- for (int i = 1; i < path2.size(); ++i) {
- assertThat(path2.getAncestor(i).isAtOrAbove(path2), is(true));
- }
- for (int i = 1; i < path3.size(); ++i) {
- assertThat(path3.getAncestor(i).isAtOrAbove(path3), is(true));
- }
- for (int i = 1; i < path4.size(); ++i) {
- assertThat(path4.getAncestor(i).isAtOrAbove(path4), is(true));
- }
- }
-
- @Test
- public void shouldConsiderDecendantToBeAtOrBelowTheAncestor() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
- for (int i = 1; i < path1.size(); ++i) {
- assertThat(path1.isAtOrBelow(path1.getAncestor(i)), is(true));
- }
- for (int i = 1; i < path2.size(); ++i) {
- assertThat(path2.isAtOrBelow(path2.getAncestor(i)), is(true));
- }
- for (int i = 1; i < path3.size(); ++i) {
- assertThat(path3.isAtOrBelow(path3.getAncestor(i)), is(true));
- }
- for (int i = 1; i < path4.size(); ++i) {
- assertThat(path4.isAtOrBelow(path4.getAncestor(i)), is(true));
- }
- }
-
- @Test
- public void shouldNotConsiderAncestorToBeAtOrBelowTheDecendant() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
- for (int i = 1; i < path1.size(); ++i) {
- assertThat(path1.getAncestor(i).isAtOrBelow(path1), is(false));
- }
- for (int i = 1; i < path2.size(); ++i) {
- assertThat(path2.getAncestor(i).isAtOrBelow(path2), is(false));
- }
- for (int i = 1; i < path3.size(); ++i) {
- assertThat(path3.getAncestor(i).isAtOrBelow(path3), is(false));
- }
- for (int i = 1; i < path4.size(); ++i) {
- assertThat(path4.getAncestor(i).isAtOrBelow(path4), is(false));
- }
- }
-
- @Test
- public void shouldNotConsiderDecendantToBeAtOrAboveTheAncestor() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
- for (int i = 1; i < path1.size(); ++i) {
- assertThat(path1.isAtOrAbove(path1.getAncestor(i)), is(false));
- }
- for (int i = 1; i < path2.size(); ++i) {
- assertThat(path2.isAtOrAbove(path2.getAncestor(i)), is(false));
- }
- for (int i = 1; i < path3.size(); ++i) {
- assertThat(path3.isAtOrAbove(path3.getAncestor(i)), is(false));
- }
- for (int i = 1; i < path4.size(); ++i) {
- assertThat(path4.isAtOrAbove(path4.getAncestor(i)), is(false));
- }
- }
-
- @Test
- public void shouldReturnNullForLastSegmentOfRoot() {
- assertThat(ROOT.getLastSegment(), is(nullValue()));
- }
-
- @Test
- public void shouldReturnLastSegmentOfNonRootPath() {
- Path path1 = pathFactory.create("/a/y/z");
- Path path2 = pathFactory.create("/a/b/c");
- Path path3 = pathFactory.create("/x/b/c");
- Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x");
- assertThat(path1.getLastSegment().getName().getLocalName(), is("z"));
- assertThat(path2.getLastSegment().getName().getLocalName(), is("c"));
- assertThat(path3.getLastSegment().getName().getLocalName(), is("c"));
- assertThat(path4.getLastSegment().getName().getLocalName(), is("x"));
- }
-
- @Test
- public void shouldNormalizePathWithSelfAndParentReferences() {
- path = pathFactory.create("/a/b/c/../d/./e/../..");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a",
"b"));
- assertThat(path.getNormalizedPath().isAbsolute(), is(true));
- assertThat(path.getNormalizedPath().isNormalized(), is(true));
-
- path = pathFactory.create("a/b/c/../d/./e/../..");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a",
"b"));
- assertThat(path.getNormalizedPath().isAbsolute(), is(false));
- assertThat(path.getNormalizedPath().isNormalized(), is(true));
- }
-
- @Test
- public void shouldAlreadyBeNormalizedIfPathContainsNoParentOrSelfReferences() {
- assertThat(pathFactory.create("/a/b/c/d/e").isNormalized(), is(true));
- assertThat(pathFactory.create("a/b/c/d/e").isNormalized(), is(true));
- assertThat(pathFactory.create("a").isNormalized(), is(true));
- assertThat(pathFactory.create("/a").isNormalized(), is(true));
- assertThat(ROOT.isNormalized(), is(true));
- }
-
- @Test
- public void shouldNotBeNormalizedIfPathContainsParentOrSelfReferences() {
- assertThat(pathFactory.create("/a/b/c/../d/./e/../..").isNormalized(),
is(false));
- assertThat(pathFactory.create("a/b/c/../d/./e/../..").isNormalized(),
is(false));
- assertThat(pathFactory.create("a/b/c/./d").isNormalized(), is(false));
- assertThat(pathFactory.create("/a/b/c/../d").isNormalized(),
is(false));
- assertThat(pathFactory.create(".").isNormalized(), is(false));
- assertThat(pathFactory.create("/.").isNormalized(), is(false));
- }
-
- @Test( expected = InvalidPathException.class )
- public void
shouldFailToReturnNormalizedPathIfPathContainsReferencesToParentsAboveRoot() {
- path = pathFactory.create("/a/../../../..");
- assertThat(path.isNormalized(), is(false));
- path.getNormalizedPath();
- }
-
- @Test
- public void
shouldReturnRootPathAsTheNormalizedPathForAnAbsolutePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved()
{
- // "/a/../b/../c/.." => "/"
- path = pathFactory.create("/a/../b/../c/../");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getNormalizedPath(), is(ROOT));
- }
-
- @Test
- public void
shouldReturnSelfPathAsTheNormalizedPathForARelativePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved()
{
- // "a/../b/../c/.." => "."
- path = pathFactory.create("a/../b/../c/../");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getNormalizedPath().size(), is(1));
- assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "."));
- }
-
- @Test
- public void
shouldNotHaveAnyParentOrSelfReferencesInTheNormalizedPathOfAnAbsolutePath() {
- path = pathFactory.create("/a/b/c/../d/./e/../..");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a",
"b"));
- assertThat(path.getNormalizedPath().isAbsolute(), is(true));
- assertThat(path.getNormalizedPath().isNormalized(), is(true));
- }
-
- @Test
- public void shouldNotHaveAnyParentReferencesInTheNormalizedPathOfARelativePath() {
- path = pathFactory.create("a/b/c/../d/./e/../..");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a",
"b"));
- assertThat(path.getNormalizedPath().isAbsolute(), is(false));
- assertThat(path.getNormalizedPath().isNormalized(), is(true));
- }
-
- @Test( expected = InvalidPathException.class )
- public void shouldNotComputeCanonicalPathOfNodeThatIsNotAbsolute() {
- pathFactory.create("a/b/c/../d/./e/../..").getCanonicalPath();
- }
-
- @Test
- public void shouldReturnNormalizedPathForTheCanonicalPathOfAbsolutePath() {
- path = pathFactory.create("/a/b/c/../d/./e/../..");
- assertThat(path.isNormalized(), is(false));
- assertThat(path.isAbsolute(), is(true));
- assertThat(path.getCanonicalPath(), hasSegments(pathFactory, "a",
"b"));
- assertThat(path.getCanonicalPath().isAbsolute(), is(true));
- assertThat(path.getCanonicalPath().isNormalized(), is(true));
- }
-
- @Test
- public void shouldReturnSameSegmentsInIteratorAndArrayAndList() {
- testSegmentsByIteratorAndListAndArray("/a/b/c/../d/./e/../..",
"a", "b", "c", "..", "d", ".",
"e", "..", "..");
- testSegmentsByIteratorAndListAndArray("/a/b/c", "a",
"b", "c");
- testSegmentsByIteratorAndListAndArray("a/b/c/../d/./e/../..",
"a", "b", "c", "..", "d", ".",
"e", "..", "..");
- testSegmentsByIteratorAndListAndArray("a/b/c", "a",
"b", "c");
- testSegmentsByIteratorAndListAndArray("");
- testSegmentsByIteratorAndListAndArray(ROOT.getString());
- }
-
- public void testSegmentsByIteratorAndListAndArray( String pathStr,
- String... expectedSegmentStrings )
{
- path = pathFactory.create(pathStr);
- assertThat(expectedSegmentStrings.length, is(path.size()));
- Path.Segment[] segmentArray = path.getSegmentsArray();
- List<Path.Segment> segmentList = path.getSegmentsList();
- assertThat(segmentArray.length, is(path.size()));
- assertThat(segmentList.size(), is(path.size()));
- Iterator<Path.Segment> iter = path.iterator();
- Iterator<Path.Segment> listIter = segmentList.iterator();
- for (int i = 0; i != path.size(); ++i) {
- Path.Segment expected =
pathFactory.createSegment(expectedSegmentStrings[i]);
- assertThat(path.getSegment(i), is(expected));
- assertThat(segmentArray[i], is(expected));
- assertThat(segmentList.get(i), is(expected));
- assertThat(iter.next(), is(expected));
- assertThat(listIter.next(), is(expected));
- }
- assertThat(iter.hasNext(), is(false));
- assertThat(listIter.hasNext(), is(false));
- }
-
- @Test
- public void shouldGetStringWithNamespaceUrisIfNoNamespaceRegistryIsProvided() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- assertThat(path.getString(NO_OP_ENCODER),
-
is("/{http://www.jboss.org/dna}a/{}b/{http://www.jboss.org/dna}c/../...);
- }
-
- @Test
- public void
shouldGetStringWithNamespacePrefixesForAllNamesIfNamespaceRegistryIsProvided() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER),
is("/dna:a/b/dna:c/../d/./dna:e/../.."));
- namespaceRegistry.register("dna2", validNamespaceUri);
- assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER),
is("/dna2:a/b/dna2:c/../d/./dna2:e/../.."));
- }
-
- @Test( expected = IndexOutOfBoundsException.class )
- public void shouldFailToReturnSubpathIfStartingIndexIsNegative() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- path.subpath(-1);
- }
-
- @Test( expected = IndexOutOfBoundsException.class )
- public void
shouldFailToReturnSubpathWithoutEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- path.subpath(path.size() + 1);
- }
-
- @Test( expected = IndexOutOfBoundsException.class )
- public void
shouldFailToReturnSubpathWithEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- path.subpath(path.size() + 1, path.size() + 2);
- }
-
- @Test( expected = IndexOutOfBoundsException.class )
- public void shouldFailToReturnSubpathIfEndingIndexIsSmallerThanStartingIndex() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- path.subpath(2, 1);
- }
-
- @Test( expected = IndexOutOfBoundsException.class )
- public void shouldFailToReturnSubpathIfEndingIndexIsEqualToOrLargerThanSize() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- path.subpath(2, path.size() + 1);
- }
-
- @Test
- public void shouldReturnRootAsSubpathIfStartingIndexAndEndingIndexAreBothZero() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- assertThat(path.subpath(0, 0), is(ROOT));
- }
-
- @Test
- public void shouldReturnSubpathIfValidStartingIndexAndNoEndingIndexAreProvided() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a",
"b", "dna:c", "..", "d", ".",
"dna:e", "..", ".."));
- assertThat(path.subpath(0), is(path));
- assertThat(path.subpath(0), is(sameInstance(path)));
- assertThat(path.subpath(1), hasSegments(pathFactory, "b",
"dna:c", "..", "d", ".", "dna:e",
"..", ".."));
- assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c",
"..", "d", ".", "dna:e", "..",
".."));
- assertThat(path.subpath(3), hasSegments(pathFactory, "..",
"d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(4), hasSegments(pathFactory, "d",
".", "dna:e", "..", ".."));
- assertThat(path.subpath(5), hasSegments(pathFactory, ".",
"dna:e", "..", ".."));
- assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e",
"..", ".."));
- assertThat(path.subpath(7), hasSegments(pathFactory, "..",
".."));
- assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
-
- path = pathFactory.create("dna:a/b/dna:c/../d/./dna:e/../..");
- assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a",
"b", "dna:c", "..", "d", ".",
"dna:e", "..", ".."));
- assertThat(path.subpath(0), is(path));
- assertThat(path.subpath(0), is(sameInstance(path)));
- assertThat(path.subpath(1), hasSegments(pathFactory, "b",
"dna:c", "..", "d", ".", "dna:e",
"..", ".."));
- assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c",
"..", "d", ".", "dna:e", "..",
".."));
- assertThat(path.subpath(3), hasSegments(pathFactory, "..",
"d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(4), hasSegments(pathFactory, "d",
".", "dna:e", "..", ".."));
- assertThat(path.subpath(5), hasSegments(pathFactory, ".",
"dna:e", "..", ".."));
- assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e",
"..", ".."));
- assertThat(path.subpath(7), hasSegments(pathFactory, "..",
".."));
- assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
- }
-
- @Test
- public void shouldReturnSubpathIfValidStartingIndexAndEndingIndexAreProvided() {
- path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
- assertThat(path.subpath(0, path.size()), hasSegments(pathFactory,
- "dna:a",
- "b",
- "dna:c",
- "..",
- "d",
- ".",
- "dna:e",
- "..",
- ".."));
- assertThat(path.subpath(0, path.size()), is(path));
- assertThat(path.subpath(0, path.size()), is(sameInstance(path)));
- assertThat(path.subpath(1, path.size()), hasSegments(pathFactory, "b",
"dna:c", "..", "d", ".", "dna:e",
"..", ".."));
- assertThat(path.subpath(2, path.size()), hasSegments(pathFactory,
"dna:c", "..", "d", ".", "dna:e",
"..", ".."));
- assertThat(path.subpath(3, path.size()), hasSegments(pathFactory, "..",
"d", ".", "dna:e", "..", ".."));
- assertThat(path.subpath(4, path.size()), hasSegments(pathFactory, "d",
".", "dna:e", "..", ".."));
- assertThat(path.subpath(5, path.size()), hasSegments(pathFactory, ".",
"dna:e", "..", ".."));
- assertThat(path.subpath(6, path.size()), hasSegments(pathFactory,
"dna:e", "..", ".."));
- assertThat(path.subpath(7, path.size()), hasSegments(pathFactory, "..",
".."));
- assertThat(path.subpath(8, path.size()), hasSegments(pathFactory,
".."));
-
- assertThat(path.subpath(0, 2), hasSegments(pathFactory, "dna:a",
"b"));
- assertThat(path.subpath(1, 2), hasSegments(pathFactory, "b"));
- assertThat(path.subpath(1, 5), hasSegments(pathFactory, "b",
"dna:c", "..", "d"));
- assertThat(path.subpath(2, 5), hasSegments(pathFactory, "dna:c",
"..", "d"));
- assertThat(path.subpath(3, 5), hasSegments(pathFactory, "..",
"d"));
- }
-
- @Test
- public void shouldFindRelativePaths() {
- path = pathFactory.create("/a/b/c/d");
- assertThat(path.relativeTo(pathFactory.create("/a/e/f")),
is(pathFactory.create("../../b/c/d")));
- assertThat(path.relativeTo(pathFactory.create("/e/f")),
is(pathFactory.create("../../a/b/c/d")));
-
- }
-
- @Test( expected = InvalidPathException.class )
- public void shouldNotAllowFindingRelativePathsFromRelativePaths() {
- path = pathFactory.create("a/b/c/d");
- path.relativeTo(pathFactory.create("/e/f"));
-
- }
-
- @Test( expected = InvalidPathException.class )
- public void shouldNotResolveRelativePathToAnotherRelativePath() {
- path = pathFactory.create("/a/b/c/d");
- path.relativeTo(pathFactory.create("e/f"));
-
- }
-
- @Test( expected = InvalidPathException.class )
- public void shouldNotResolveRelativePathUsingAnAbsolutePath() {
- path = pathFactory.create("/a/b/c/d");
- path.resolve(pathFactory.create("/e/f"));
- }
-
- @Test
- public void shouldResolveRelativePathToAbsolutePath() {
- path = pathFactory.create("/a/b/c/d");
- path2 = path.resolve(pathFactory.create("../../e/f"));
- assertThat(path2, is(pathFactory.create("/a/b/e/f")));
- assertThat(path2.isAbsolute(), is(true));
- assertThat(path2.isNormalized(), is(true));
- }
-
- @Test
- public void shouldOrderPathsCorrectly() {
- List<Path> paths = new ArrayList<Path>();
- paths.add(pathFactory.create("/a"));
- paths.add(pathFactory.create("/a/b"));
- paths.add(pathFactory.create("/a/b/alpha"));
- paths.add(pathFactory.create("/a/b/beta"));
- paths.add(pathFactory.create("/a/b/dna:mixinTypes"));
- paths.add(pathFactory.create("/a/b/dna:name"));
- paths.add(pathFactory.create("/a/b/dna:primaryType"));
- paths.add(pathFactory.create("/a/c[1]"));
- paths.add(pathFactory.create("/a/c[1]/alpha"));
- paths.add(pathFactory.create("/a/c[1]/beta"));
- paths.add(pathFactory.create("/a/c[1]/dna:mixinTypes"));
- paths.add(pathFactory.create("/a/c[1]/dna:name"));
- paths.add(pathFactory.create("/a/c[1]/dna:primaryType"));
- paths.add(pathFactory.create("/a/c[2]"));
- paths.add(pathFactory.create("/a/c[2]/alpha"));
- paths.add(pathFactory.create("/a/c[2]/beta"));
- paths.add(pathFactory.create("/a/c[2]/dna:mixinTypes"));
- paths.add(pathFactory.create("/a/c[2]/dna:name"));
- paths.add(pathFactory.create("/a/c[2]/dna:primaryType"));
-
- // Randomize the list of paths, so we have something to sort ...
- List<Path> randomizedPaths = new ArrayList<Path>(paths);
- Collections.shuffle(randomizedPaths);
- assertThat(randomizedPaths, is(not(paths)));
-
- // Sort ...
- Collections.sort(randomizedPaths);
- assertThat(randomizedPaths, is(paths));
- }
-
- @Test
- public void shouldGetNormalizedPathOfSelfShouldBeSame() {
- assertThat(pathFactory.create(".").getNormalizedPath(),
is(pathFactory.create(".")));
- assertThat(pathFactory.create("./").getNormalizedPath(),
is(pathFactory.create(".")));
- assertThat(pathFactory.create("./././").getNormalizedPath(),
is(pathFactory.create(".")));
- }
-
- @Test
- public void shouldGetNormalizedPathWithParentReferences() {
- assertThat(pathFactory.create("..").getNormalizedPath(),
is(pathFactory.create("..")));
- assertThat(pathFactory.create("../").getNormalizedPath(),
is(pathFactory.create("../")));
- assertThat(pathFactory.create("../../../../../..").getNormalizedPath(),
is(pathFactory.create("../../../../../..")));
- }
-
- @Test
- public void shouldGetRelativePathUsingSelf() {
- path = pathFactory.create("/a/b/c/d/e/f");
- assertThat(path.resolve(pathFactory.create(".")),
is(sameInstance(path)));
- assertThat(path.resolve(pathFactory.create("././.")),
is(sameInstance(path)));
- }
-
- @Test
- public void shouldResolveRelativePathToParent() {
- path = pathFactory.create("/a/b/c/d/e/f");
- assertThat(path.resolve(pathFactory.create("..")),
is(path.getParent()));
- assertThat(path.resolve(pathFactory.create("..")),
hasSegments(pathFactory, "a", "b", "c", "d",
"e"));
- }
-
- @Test
- public void shouldResolveRelativePaths() {
- path = pathFactory.create("/a/b/c/d/e/f");
- assertThat(path.resolve(pathFactory.create("../../../../../..")),
is(sameInstance(ROOT)));
- assertThat(path.resolve(pathFactory.create("../..")),
is(path.getParent().getParent()));
- assertThat(path.resolve(pathFactory.create("../..")),
hasSegments(pathFactory, "a", "b", "c", "d"));
- assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")),
is(path.getParent()));
- assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")),
hasSegments(pathFactory, "a", "b", "c", "d",
"e"));
- assertThat(path.resolve(pathFactory.create("../x")),
hasSegments(pathFactory, "a", "b", "c", "d",
"e", "x"));
- }
-
- public void shouldResolveNonAbsolutePaths() {
- path = pathFactory.create("a/b/c");
- assertThat(path, hasSegments(pathFactory, "a", "b",
"c"));
- }
-
- @Test
- public void shouldConvertPathToString() {
- TextEncoder encoder = new Jsr283Encoder();
- TextEncoder delimEncoder = new TextEncoder() {
- public String encode( String text ) {
- if ("/".equals(text)) return "\\/";
- if (":".equals(text)) return "\\:";
- if ("{".equals(text)) return "\\{";
- if ("}".equals(text)) return "\\}";
- return text;
- }
- };
- Path path = pathFactory.create("a/b/c");
- assertThat(path.getString(namespaceRegistry), is("a/b/c"));
- assertThat(path.getString(namespaceRegistry, encoder), is("a/b/c"));
- assertThat(path.getString(namespaceRegistry, encoder, delimEncoder),
is("a\\/b\\/c"));
-
- path = pathFactory.create("/a/b/c");
- assertThat(path.getString(namespaceRegistry), is("/a/b/c"));
- assertThat(path.getString(namespaceRegistry, encoder), is("/a/b/c"));
- assertThat(path.getString(namespaceRegistry, encoder, delimEncoder),
is("\\/a\\/b\\/c"));
-
- path = pathFactory.create("/dna:a/b/c");
- assertThat(path.getString(encoder), is("/{" +
encoder.encode(DnaLexicon.Namespace.URI) + "}a/{}b/{}c"));
- assertThat(path.getString(null, encoder, delimEncoder), is("\\/\\{" +
encoder.encode(DnaLexicon.Namespace.URI)
- +
"\\}a\\/\\{\\}b\\/\\{\\}c"));
- assertThat(path.getString(namespaceRegistry), is("/dna:a/b/c"));
- assertThat(path.getString(namespaceRegistry, encoder),
is("/dna:a/b/c"));
- assertThat(path.getString(namespaceRegistry, encoder, delimEncoder),
is("\\/dna\\:a\\/b\\/c"));
- }
-}
Added:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathTest.java
(rev 0)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/BasicPathTest.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -0,0 +1,882 @@
+/*
+ * 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.graph.properties.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.jboss.dna.graph.properties.basic.IsPathContaining.hasSegments;
+import static org.junit.Assert.assertThat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.jboss.dna.common.text.Jsr283Encoder;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.graph.DnaLexicon;
+import org.jboss.dna.graph.properties.InvalidPathException;
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.properties.ValueFormatException;
+import org.jboss.dna.graph.properties.basic.BasicName;
+import org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry;
+import org.jboss.dna.graph.properties.basic.BasicPath;
+import org.jboss.dna.graph.properties.basic.BasicPathSegment;
+import org.jboss.dna.graph.properties.basic.NameValueFactory;
+import org.jboss.dna.graph.properties.basic.PathValueFactory;
+import org.jboss.dna.graph.properties.basic.RootPath;
+import org.jboss.dna.graph.properties.basic.StringValueFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class BasicPathTest extends AbstractPathTest {
+
+ public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER;
+ public static final Path ROOT = RootPath.INSTANCE;
+
+ private BasicNamespaceRegistry namespaceRegistry;
+ private String validNamespaceUri;
+ private Path path2;
+ private Path.Segment[] validSegments;
+ private List<Path.Segment> validSegmentsList;
+ private Name[] validSegmentNames;
+ private String validNamespacePrefix;
+ private PathValueFactory pathFactory;
+
+ @Before
+ @Override
+ public void beforeEach() {
+ validNamespacePrefix = DnaLexicon.Namespace.PREFIX;
+ validNamespaceUri = DnaLexicon.Namespace.URI;
+ validSegmentNames = new Name[] {new BasicName(validNamespaceUri, "a"),
new BasicName(validNamespaceUri, "b"),
+ new BasicName(validNamespaceUri, "c")};
+ validSegments = new Path.Segment[] {new BasicPathSegment(validSegmentNames[0]),
+ new BasicPathSegment(validSegmentNames[1]), new
BasicPathSegment(validSegmentNames[1])};
+ validSegmentsList = new ArrayList<Path.Segment>();
+ for (Path.Segment segment : validSegments) {
+ validSegmentsList.add(segment);
+ }
+ super.path = new BasicPath(validSegmentsList, true);
+ namespaceRegistry = new BasicNamespaceRegistry();
+ namespaceRegistry.register(validNamespacePrefix, validNamespaceUri);
+ StringValueFactory stringValueFactory = new
StringValueFactory(Path.DEFAULT_DECODER, Path.DEFAULT_ENCODER);
+ NameValueFactory nameValueFactory = new NameValueFactory(namespaceRegistry,
Path.DEFAULT_DECODER, stringValueFactory);
+ pathFactory = new PathValueFactory(Path.DEFAULT_DECODER, stringValueFactory,
nameValueFactory);
+ }
+
+ @Test
+ public void shouldCreateAbsolutePathFromListOfValidSegments() {
+ path = new BasicPath(validSegmentsList, true);
+ assertThat(path.isAbsolute(), is(true));
+ assertThat(path.isNormalized(), is(true));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
+
+ @Test
+ public void shouldCreateRelativePathFromListOfValidSegments() {
+ path = new BasicPath(validSegmentsList, false);
+ assertThat(path.isAbsolute(), is(false));
+ assertThat(path.isNormalized(), is(true));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
+
+ @Test
+ public void shouldCreateAbsolutePathWithParentSegment() {
+ validSegmentsList.add(Path.PARENT_SEGMENT);
+ path = new BasicPath(validSegmentsList, true);
+ assertThat(path.isAbsolute(), is(true));
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
+
+ @Test
+ public void shouldCreateRelativePathWithParentSegment() {
+ validSegmentsList.add(Path.PARENT_SEGMENT);
+ path = new BasicPath(validSegmentsList, false);
+ assertThat(path.isAbsolute(), is(false));
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
+
+ @Test
+ public void shouldCreateAbsolutePathWithSelfSegment() {
+ validSegmentsList.add(Path.SELF_SEGMENT);
+ path = new BasicPath(validSegmentsList, true);
+ assertThat(path.isAbsolute(), is(true));
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
+
+ @Test
+ public void shouldCreateRelativePathWithSelfSegment() {
+ validSegmentsList.add(Path.SELF_SEGMENT);
+ path = new BasicPath(validSegmentsList, false);
+ assertThat(path.isAbsolute(), is(false));
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getSegmentsList(), is(validSegmentsList));
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
+
+ @Test
+ public void shouldCreatePathWithNoNamespacePrefixes() {
+ path = pathFactory.create("/a/b/c/");
+ assertThat(path.size(), is(3));
+ assertThat(path, hasSegments(pathFactory, "a", "b",
"c"));
+ }
+
+ @Test
+ public void shouldConstructRelativePath() {
+ assertThat(pathFactory.create("a/b/c").isAbsolute(), is(false));
+ assertThat(pathFactory.create("a/b/c").isNormalized(), is(true));
+ assertThat(pathFactory.create("a/b/c").size(), is(3));
+ assertThat(pathFactory.create("a/b/c").getString(namespaceRegistry),
is("a/b/c"));
+ }
+
+ @Test
+ public void shouldConstructRelativePathToSelf() {
+ assertThat(pathFactory.create(".").isAbsolute(), is(false));
+ assertThat(pathFactory.create(".").size(), is(1));
+ assertThat(pathFactory.create("."), hasSegments(pathFactory,
Path.SELF));
+
+ assertThat(pathFactory.create("./").isAbsolute(), is(false));
+ assertThat(pathFactory.create("./").size(), is(1));
+ assertThat(pathFactory.create("./"), hasSegments(pathFactory,
Path.SELF));
+ }
+
+ @Test
+ public void shouldConstructRelativePathToParent() {
+ assertThat(pathFactory.create("..").isAbsolute(), is(false));
+ assertThat(pathFactory.create("..").size(), is(1));
+ assertThat(pathFactory.create(".."), hasSegments(pathFactory,
Path.PARENT));
+
+ assertThat(pathFactory.create("../").isAbsolute(), is(false));
+ assertThat(pathFactory.create("../").size(), is(1));
+ assertThat(pathFactory.create("../"), hasSegments(pathFactory,
Path.PARENT));
+ }
+
+ @Test
+ public void shouldConstructRootPathFromStringWithSingleDelimiter() {
+ assertThat(pathFactory.create("/"), is(ROOT));
+ assertThat(pathFactory.create("/").isRoot(), is(true));
+ }
+
+ @Test( expected = ValueFormatException.class )
+ public void shouldNotConstructPathWithSuccessiveDelimiters() {
+ pathFactory.create("///a/b///c//d//");
+ }
+
+ @Test( expected = ValueFormatException.class )
+ public void shouldNotConstructPathWithOnlyDelimiters() {
+ pathFactory.create("///");
+ }
+
+ @Test
+ public void
shouldConstructPathFromStringAndShouldIgnoreLeadingAndTrailingWhitespace() {
+ assertThat(pathFactory.create(" \t / \t").toString(),
is("/"));
+ }
+
+ @Test
+ public void shouldConstructRelativePathIfSuppliedPathHasNoLeadingDelimiter() {
+ assertThat(pathFactory.create("a"), hasSegments(pathFactory,
"a"));
+ }
+
+ @Test
+ public void shouldHaveSizeThatReflectsNumberOfSegments() {
+ assertThat(path.size(), is(validSegmentsList.size()));
+ }
+
+ @Test
+ public void shouldIterateOverAllSegmentsReturnedByList() {
+ Iterator<Path.Segment> expectedIter = validSegmentsList.iterator();
+ for (Path.Segment segment : path) {
+ assertThat(segment, is(expectedIter.next()));
+ }
+
+ expectedIter = path.getSegmentsList().iterator();
+ for (Path.Segment segment : path) {
+ assertThat(segment, is(expectedIter.next()));
+ }
+ }
+
+ @Test
+ public void shouldReturnAncestorForNodeOtherThanRoot() {
+ assertThat(path.getParent(), is(pathFactory.create("/dna:a/dna:b")));
+ assertThat(path.getParent().getParent(),
is(pathFactory.create("/dna:a")));
+ assertThat(path.getParent().getParent().getParent(), is(ROOT));
+ }
+
+ @Test
+ public void shouldReturnNthDegreeAncestor() {
+ assertThat(path.getAncestor(1),
is(pathFactory.create("/dna:a/dna:b")));
+ assertThat(path.getAncestor(2), is(pathFactory.create("/dna:a")));
+ assertThat(path.getAncestor(3), is(ROOT));
+ }
+
+ @Test
+ public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodeAndRoot() {
+ assertThat(path.getCommonAncestor(ROOT), is(ROOT));
+ assertThat(ROOT.getCommonAncestor(path), is(ROOT));
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldReturnNullForLowestCommonAncestorWithNullPath() {
+ path.getCommonAncestor(null);
+ }
+
+ @Test
+ public void shouldFindLowestCommonAncestorBetweenTwoNonRootNodesOnCommonBranch() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path common = pathFactory.create("/a");
+ assertThat(path1.getCommonAncestor(path2), is(common));
+
+ path1 = pathFactory.create("/a/b/c");
+ path2 = pathFactory.create("/a/b/c/d");
+ common = path1;
+ assertThat(path1.getCommonAncestor(path2), is(common));
+
+ path1 = pathFactory.create("/a/b/c/x/y/");
+ path2 = pathFactory.create("/a/b/c/d/e/f/");
+ common = pathFactory.create("/a/b/c");
+ assertThat(path1.getCommonAncestor(path2), is(common));
+ }
+
+ @Test
+ public void shouldConsiderRootTheLowestCommonAncestorOfAnyNodesOnSeparateBrances() {
+ Path path1 = pathFactory.create("/x/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path common = ROOT;
+ assertThat(path1.getCommonAncestor(path2), is(common));
+ }
+
+ @Test
+ public void shouldConsiderNodeToBeAncestorOfEveryDecendantNode() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ Path common = pathFactory.create("/a");
+ assertThat(common.isAncestorOf(path1), is(true));
+ assertThat(common.isAncestorOf(path2), is(true));
+ assertThat(common.isAncestorOf(path3), is(false));
+
+ assertThat(path1.getParent().isAncestorOf(path1), is(true));
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.getAncestor(i).isAncestorOf(path1), is(true));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.getAncestor(i).isAncestorOf(path2), is(true));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.getAncestor(i).isAncestorOf(path3), is(true));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.getAncestor(i).isAncestorOf(path4), is(true));
+ }
+ }
+
+ @Test
+ public void shouldConsiderNodeToBeDecendantOfEveryAncestorNode() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ Path common = pathFactory.create("/a");
+ assertThat(path1.isDecendantOf(common), is(true));
+ assertThat(path2.isDecendantOf(common), is(true));
+ assertThat(path3.isDecendantOf(common), is(false));
+
+ assertThat(path1.getParent().isAncestorOf(path1), is(true));
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.isDecendantOf(path1.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.isDecendantOf(path2.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.isDecendantOf(path3.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.isDecendantOf(path4.getAncestor(i)), is(true));
+ }
+ }
+
+ @Override
+ @Test
+ public void shouldNotConsiderNodeToBeAncestorOfItself() {
+ super.shouldNotConsiderNodeToBeAncestorOfItself();
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ assertThat(path1.isAncestorOf(path1), is(false));
+ assertThat(path2.isAncestorOf(path2), is(false));
+ assertThat(path3.isAncestorOf(path3), is(false));
+ assertThat(ROOT.isAncestorOf(ROOT), is(false));
+ }
+
+ @Override
+ @Test
+ public void shouldNotConsiderNodeToBeDecendantOfItself() {
+ super.shouldNotConsiderNodeToBeDecendantOfItself();
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ assertThat(path1.isDecendantOf(path1), is(false));
+ assertThat(path2.isDecendantOf(path2), is(false));
+ assertThat(path3.isDecendantOf(path3), is(false));
+ assertThat(ROOT.isDecendantOf(ROOT), is(false));
+ }
+
+ @Test
+ public void shouldNotConsiderRootToBeDecendantOfAnyNode() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path common = pathFactory.create("/a");
+ assertThat(ROOT.isDecendantOf(path1), is(false));
+ assertThat(ROOT.isDecendantOf(path2), is(false));
+ assertThat(ROOT.isDecendantOf(path3), is(false));
+ assertThat(ROOT.isDecendantOf(common), is(false));
+ }
+
+ @Test
+ public void shouldConsiderRootToBeAncestorOfAnyNode() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path common = pathFactory.create("/a");
+ assertThat(ROOT.isAncestorOf(path1), is(true));
+ assertThat(ROOT.isAncestorOf(path2), is(true));
+ assertThat(ROOT.isAncestorOf(path3), is(true));
+ assertThat(ROOT.isAncestorOf(common), is(true));
+ }
+
+ @Test
+ public void shouldConsiderTwoNotRootSiblingNodesToHaveSameAncestor() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/y/c");
+ assertThat(path1.hasSameAncestor(path2), is(true));
+
+ path1 = pathFactory.create("/a/z");
+ path2 = pathFactory.create("/a/c");
+ assertThat(path1.hasSameAncestor(path2), is(true));
+
+ path1 = pathFactory.create("/z");
+ path2 = pathFactory.create("/c");
+ assertThat(path1.hasSameAncestor(path2), is(true));
+ }
+
+ @Test
+ public void shouldNotConsiderTwoNonSiblingNodesToHaveSameAncestor() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/x/c");
+ assertThat(path1.hasSameAncestor(path2), is(false));
+
+ path1 = pathFactory.create("/a/z");
+ path2 = pathFactory.create("/b/c");
+ assertThat(path1.hasSameAncestor(path2), is(false));
+
+ path1 = pathFactory.create("/z");
+ path2 = pathFactory.create("/a/c");
+ assertThat(path1.hasSameAncestor(path2), is(false));
+ }
+
+ @Test
+ public void shouldConsiderAncestorToBeAtOrAboveTheDecendant() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.getAncestor(i).isAtOrAbove(path1), is(true));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.getAncestor(i).isAtOrAbove(path2), is(true));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.getAncestor(i).isAtOrAbove(path3), is(true));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.getAncestor(i).isAtOrAbove(path4), is(true));
+ }
+ }
+
+ @Test
+ public void shouldConsiderDecendantToBeAtOrBelowTheAncestor() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.isAtOrBelow(path1.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.isAtOrBelow(path2.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.isAtOrBelow(path3.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.isAtOrBelow(path4.getAncestor(i)), is(true));
+ }
+ }
+
+ @Test
+ public void shouldNotConsiderAncestorToBeAtOrBelowTheDecendant() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.getAncestor(i).isAtOrBelow(path1), is(false));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.getAncestor(i).isAtOrBelow(path2), is(false));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.getAncestor(i).isAtOrBelow(path3), is(false));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.getAncestor(i).isAtOrBelow(path4), is(false));
+ }
+ }
+
+ @Test
+ public void shouldNotConsiderDecendantToBeAtOrAboveTheAncestor() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.isAtOrAbove(path1.getAncestor(i)), is(false));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.isAtOrAbove(path2.getAncestor(i)), is(false));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.isAtOrAbove(path3.getAncestor(i)), is(false));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.isAtOrAbove(path4.getAncestor(i)), is(false));
+ }
+ }
+
+ @Test
+ public void shouldReturnLastSegmentOfNonRootPath() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 =
pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x");
+ assertThat(path1.getLastSegment().getName().getLocalName(), is("z"));
+ assertThat(path2.getLastSegment().getName().getLocalName(), is("c"));
+ assertThat(path3.getLastSegment().getName().getLocalName(), is("c"));
+ assertThat(path4.getLastSegment().getName().getLocalName(), is("x"));
+ }
+
+ @Test
+ public void shouldNormalizePathWithSelfAndParentReferences() {
+ path = pathFactory.create("/a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a",
"b"));
+ assertThat(path.getNormalizedPath().isAbsolute(), is(true));
+ assertThat(path.getNormalizedPath().isNormalized(), is(true));
+
+ path = pathFactory.create("a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a",
"b"));
+ assertThat(path.getNormalizedPath().isAbsolute(), is(false));
+ assertThat(path.getNormalizedPath().isNormalized(), is(true));
+ }
+
+ @Test
+ public void shouldAlreadyBeNormalizedIfPathContainsNoParentOrSelfReferences() {
+ assertThat(pathFactory.create("/a/b/c/d/e").isNormalized(), is(true));
+ assertThat(pathFactory.create("a/b/c/d/e").isNormalized(), is(true));
+ assertThat(pathFactory.create("a").isNormalized(), is(true));
+ assertThat(pathFactory.create("/a").isNormalized(), is(true));
+ assertThat(ROOT.isNormalized(), is(true));
+ }
+
+ @Test
+ public void shouldNotBeNormalizedIfPathContainsParentOrSelfReferences() {
+ assertThat(pathFactory.create("/a/b/c/../d/./e/../..").isNormalized(),
is(false));
+ assertThat(pathFactory.create("a/b/c/../d/./e/../..").isNormalized(),
is(false));
+ assertThat(pathFactory.create("a/b/c/./d").isNormalized(), is(false));
+ assertThat(pathFactory.create("/a/b/c/../d").isNormalized(),
is(false));
+ assertThat(pathFactory.create(".").isNormalized(), is(false));
+ assertThat(pathFactory.create("/.").isNormalized(), is(false));
+ }
+
+ @Test( expected = InvalidPathException.class )
+ public void
shouldFailToReturnNormalizedPathIfPathContainsReferencesToParentsAboveRoot() {
+ path = pathFactory.create("/a/../../../..");
+ assertThat(path.isNormalized(), is(false));
+ path.getNormalizedPath();
+ }
+
+ @Test
+ public void
shouldReturnRootPathAsTheNormalizedPathForAnAbsolutePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved()
{
+ // "/a/../b/../c/.." => "/"
+ path = pathFactory.create("/a/../b/../c/../");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), is(ROOT));
+ }
+
+ @Test
+ public void
shouldReturnSelfPathAsTheNormalizedPathForARelativePathWithZeroSegmentsAfterParentAndSelfReferencesRemoved()
{
+ // "a/../b/../c/.." => "."
+ path = pathFactory.create("a/../b/../c/../");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath().size(), is(1));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "."));
+ }
+
+ @Test
+ public void
shouldNotHaveAnyParentOrSelfReferencesInTheNormalizedPathOfAnAbsolutePath() {
+ path = pathFactory.create("/a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a",
"b"));
+ assertThat(path.getNormalizedPath().isAbsolute(), is(true));
+ assertThat(path.getNormalizedPath().isNormalized(), is(true));
+ }
+
+ @Test
+ public void shouldNotHaveAnyParentReferencesInTheNormalizedPathOfARelativePath() {
+ path = pathFactory.create("a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.getNormalizedPath(), hasSegments(pathFactory, "a",
"b"));
+ assertThat(path.getNormalizedPath().isAbsolute(), is(false));
+ assertThat(path.getNormalizedPath().isNormalized(), is(true));
+ }
+
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotComputeCanonicalPathOfNodeThatIsNotAbsolute() {
+ pathFactory.create("a/b/c/../d/./e/../..").getCanonicalPath();
+ }
+
+ @Test
+ public void shouldReturnNormalizedPathForTheCanonicalPathOfAbsolutePath() {
+ path = pathFactory.create("/a/b/c/../d/./e/../..");
+ assertThat(path.isNormalized(), is(false));
+ assertThat(path.isAbsolute(), is(true));
+ assertThat(path.getCanonicalPath(), hasSegments(pathFactory, "a",
"b"));
+ assertThat(path.getCanonicalPath().isAbsolute(), is(true));
+ assertThat(path.getCanonicalPath().isNormalized(), is(true));
+ }
+
+ @Test
+ public void shouldReturnSameSegmentsInIteratorAndArrayAndList() {
+ testSegmentsByIteratorAndListAndArray("/a/b/c/../d/./e/../..",
"a", "b", "c", "..", "d", ".",
"e", "..", "..");
+ testSegmentsByIteratorAndListAndArray("/a/b/c", "a",
"b", "c");
+ testSegmentsByIteratorAndListAndArray("a/b/c/../d/./e/../..",
"a", "b", "c", "..", "d", ".",
"e", "..", "..");
+ testSegmentsByIteratorAndListAndArray("a/b/c", "a",
"b", "c");
+ testSegmentsByIteratorAndListAndArray("");
+ testSegmentsByIteratorAndListAndArray(ROOT.getString());
+ }
+
+ public void testSegmentsByIteratorAndListAndArray( String pathStr,
+ String... expectedSegmentStrings )
{
+ path = pathFactory.create(pathStr);
+ assertThat(expectedSegmentStrings.length, is(path.size()));
+ Path.Segment[] segmentArray = path.getSegmentsArray();
+ List<Path.Segment> segmentList = path.getSegmentsList();
+ assertThat(segmentArray.length, is(path.size()));
+ assertThat(segmentList.size(), is(path.size()));
+ Iterator<Path.Segment> iter = path.iterator();
+ Iterator<Path.Segment> listIter = segmentList.iterator();
+ for (int i = 0; i != path.size(); ++i) {
+ Path.Segment expected =
pathFactory.createSegment(expectedSegmentStrings[i]);
+ assertThat(path.getSegment(i), is(expected));
+ assertThat(segmentArray[i], is(expected));
+ assertThat(segmentList.get(i), is(expected));
+ assertThat(iter.next(), is(expected));
+ assertThat(listIter.next(), is(expected));
+ }
+ assertThat(iter.hasNext(), is(false));
+ assertThat(listIter.hasNext(), is(false));
+ }
+
+ @Test
+ public void shouldGetStringWithNamespaceUrisIfNoNamespaceRegistryIsProvided() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.getString(NO_OP_ENCODER),
+
is("/{http://www.jboss.org/dna}a/{}b/{http://www.jboss.org/dna}c/../...);
+ }
+
+ @Test
+ public void
shouldGetStringWithNamespacePrefixesForAllNamesIfNamespaceRegistryIsProvided() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER),
is("/dna:a/b/dna:c/../d/./dna:e/../.."));
+ namespaceRegistry.register("dna2", validNamespaceUri);
+ assertThat(path.getString(namespaceRegistry, NO_OP_ENCODER),
is("/dna2:a/b/dna2:c/../d/./dna2:e/../.."));
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailToReturnSubpathIfStartingIndexIsNegative() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(-1);
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void
shouldFailToReturnSubpathWithoutEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(path.size() + 1);
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void
shouldFailToReturnSubpathWithEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(path.size() + 1, path.size() + 2);
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldFailToReturnSubpathIfEndingIndexIsSmallerThanStartingIndex() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(2, 1);
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldFailToReturnSubpathIfEndingIndexIsEqualToOrLargerThanSize() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ path.subpath(2, path.size() + 1);
+ }
+
+ @Test
+ public void shouldReturnRootAsSubpathIfStartingIndexAndEndingIndexAreBothZero() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.subpath(0, 0), is(ROOT));
+ }
+
+ @Test
+ public void shouldReturnSubpathIfValidStartingIndexAndNoEndingIndexAreProvided() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a",
"b", "dna:c", "..", "d", ".",
"dna:e", "..", ".."));
+ assertThat(path.subpath(0), is(path));
+ assertThat(path.subpath(0), is(sameInstance(path)));
+ assertThat(path.subpath(1), hasSegments(pathFactory, "b",
"dna:c", "..", "d", ".", "dna:e",
"..", ".."));
+ assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c",
"..", "d", ".", "dna:e", "..",
".."));
+ assertThat(path.subpath(3), hasSegments(pathFactory, "..",
"d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(4), hasSegments(pathFactory, "d",
".", "dna:e", "..", ".."));
+ assertThat(path.subpath(5), hasSegments(pathFactory, ".",
"dna:e", "..", ".."));
+ assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e",
"..", ".."));
+ assertThat(path.subpath(7), hasSegments(pathFactory, "..",
".."));
+ assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
+
+ path = pathFactory.create("dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.subpath(0), hasSegments(pathFactory, "dna:a",
"b", "dna:c", "..", "d", ".",
"dna:e", "..", ".."));
+ assertThat(path.subpath(0), is(path));
+ assertThat(path.subpath(0), is(sameInstance(path)));
+ assertThat(path.subpath(1), hasSegments(pathFactory, "b",
"dna:c", "..", "d", ".", "dna:e",
"..", ".."));
+ assertThat(path.subpath(2), hasSegments(pathFactory, "dna:c",
"..", "d", ".", "dna:e", "..",
".."));
+ assertThat(path.subpath(3), hasSegments(pathFactory, "..",
"d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(4), hasSegments(pathFactory, "d",
".", "dna:e", "..", ".."));
+ assertThat(path.subpath(5), hasSegments(pathFactory, ".",
"dna:e", "..", ".."));
+ assertThat(path.subpath(6), hasSegments(pathFactory, "dna:e",
"..", ".."));
+ assertThat(path.subpath(7), hasSegments(pathFactory, "..",
".."));
+ assertThat(path.subpath(8), hasSegments(pathFactory, ".."));
+ }
+
+ @Test
+ public void shouldReturnSubpathIfValidStartingIndexAndEndingIndexAreProvided() {
+ path = pathFactory.create("/dna:a/b/dna:c/../d/./dna:e/../..");
+ assertThat(path.subpath(0, path.size()), hasSegments(pathFactory,
+ "dna:a",
+ "b",
+ "dna:c",
+ "..",
+ "d",
+ ".",
+ "dna:e",
+ "..",
+ ".."));
+ assertThat(path.subpath(0, path.size()), is(path));
+ assertThat(path.subpath(0, path.size()), is(sameInstance(path)));
+ assertThat(path.subpath(1, path.size()), hasSegments(pathFactory, "b",
"dna:c", "..", "d", ".", "dna:e",
"..", ".."));
+ assertThat(path.subpath(2, path.size()), hasSegments(pathFactory,
"dna:c", "..", "d", ".", "dna:e",
"..", ".."));
+ assertThat(path.subpath(3, path.size()), hasSegments(pathFactory, "..",
"d", ".", "dna:e", "..", ".."));
+ assertThat(path.subpath(4, path.size()), hasSegments(pathFactory, "d",
".", "dna:e", "..", ".."));
+ assertThat(path.subpath(5, path.size()), hasSegments(pathFactory, ".",
"dna:e", "..", ".."));
+ assertThat(path.subpath(6, path.size()), hasSegments(pathFactory,
"dna:e", "..", ".."));
+ assertThat(path.subpath(7, path.size()), hasSegments(pathFactory, "..",
".."));
+ assertThat(path.subpath(8, path.size()), hasSegments(pathFactory,
".."));
+
+ assertThat(path.subpath(0, 2), hasSegments(pathFactory, "dna:a",
"b"));
+ assertThat(path.subpath(1, 2), hasSegments(pathFactory, "b"));
+ assertThat(path.subpath(1, 5), hasSegments(pathFactory, "b",
"dna:c", "..", "d"));
+ assertThat(path.subpath(2, 5), hasSegments(pathFactory, "dna:c",
"..", "d"));
+ assertThat(path.subpath(3, 5), hasSegments(pathFactory, "..",
"d"));
+ }
+
+ @Test
+ public void shouldFindRelativePaths() {
+ path = pathFactory.create("/a/b/c/d");
+ assertThat(path.relativeTo(pathFactory.create("/a/e/f")),
is(pathFactory.create("../../b/c/d")));
+ assertThat(path.relativeTo(pathFactory.create("/e/f")),
is(pathFactory.create("../../a/b/c/d")));
+
+ }
+
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotAllowFindingRelativePathsFromRelativePaths() {
+ path = pathFactory.create("a/b/c/d");
+ path.relativeTo(pathFactory.create("/e/f"));
+
+ }
+
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotResolveRelativePathToAnotherRelativePath() {
+ path = pathFactory.create("/a/b/c/d");
+ path.relativeTo(pathFactory.create("e/f"));
+
+ }
+
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotResolveRelativePathUsingAnAbsolutePath() {
+ path = pathFactory.create("/a/b/c/d");
+ path.resolve(pathFactory.create("/e/f"));
+ }
+
+ @Test
+ public void shouldResolveRelativePathToAbsolutePath() {
+ path = pathFactory.create("/a/b/c/d");
+ path2 = path.resolve(pathFactory.create("../../e/f"));
+ assertThat(path2, is(pathFactory.create("/a/b/e/f")));
+ assertThat(path2.isAbsolute(), is(true));
+ assertThat(path2.isNormalized(), is(true));
+ }
+
+ @Test
+ public void shouldOrderPathsCorrectly() {
+ List<Path> paths = new ArrayList<Path>();
+ paths.add(pathFactory.create("/a"));
+ paths.add(pathFactory.create("/a/b"));
+ paths.add(pathFactory.create("/a/b/alpha"));
+ paths.add(pathFactory.create("/a/b/beta"));
+ paths.add(pathFactory.create("/a/b/dna:mixinTypes"));
+ paths.add(pathFactory.create("/a/b/dna:name"));
+ paths.add(pathFactory.create("/a/b/dna:primaryType"));
+ paths.add(pathFactory.create("/a/c[1]"));
+ paths.add(pathFactory.create("/a/c[1]/alpha"));
+ paths.add(pathFactory.create("/a/c[1]/beta"));
+ paths.add(pathFactory.create("/a/c[1]/dna:mixinTypes"));
+ paths.add(pathFactory.create("/a/c[1]/dna:name"));
+ paths.add(pathFactory.create("/a/c[1]/dna:primaryType"));
+ paths.add(pathFactory.create("/a/c[2]"));
+ paths.add(pathFactory.create("/a/c[2]/alpha"));
+ paths.add(pathFactory.create("/a/c[2]/beta"));
+ paths.add(pathFactory.create("/a/c[2]/dna:mixinTypes"));
+ paths.add(pathFactory.create("/a/c[2]/dna:name"));
+ paths.add(pathFactory.create("/a/c[2]/dna:primaryType"));
+
+ // Randomize the list of paths, so we have something to sort ...
+ List<Path> randomizedPaths = new ArrayList<Path>(paths);
+ Collections.shuffle(randomizedPaths);
+ assertThat(randomizedPaths, is(not(paths)));
+
+ // Sort ...
+ Collections.sort(randomizedPaths);
+ assertThat(randomizedPaths, is(paths));
+ }
+
+ @Test
+ public void shouldGetNormalizedPathOfSelfShouldBeSame() {
+ assertThat(pathFactory.create(".").getNormalizedPath(),
is(pathFactory.create(".")));
+ assertThat(pathFactory.create("./").getNormalizedPath(),
is(pathFactory.create(".")));
+ assertThat(pathFactory.create("./././").getNormalizedPath(),
is(pathFactory.create(".")));
+ }
+
+ @Test
+ public void shouldGetNormalizedPathWithParentReferences() {
+ assertThat(pathFactory.create("..").getNormalizedPath(),
is(pathFactory.create("..")));
+ assertThat(pathFactory.create("../").getNormalizedPath(),
is(pathFactory.create("../")));
+ assertThat(pathFactory.create("../../../../../..").getNormalizedPath(),
is(pathFactory.create("../../../../../..")));
+ }
+
+ @Test
+ public void shouldGetRelativePathUsingSelf() {
+ path = pathFactory.create("/a/b/c/d/e/f");
+ assertThat(path.resolve(pathFactory.create(".")),
is(sameInstance(path)));
+ assertThat(path.resolve(pathFactory.create("././.")),
is(sameInstance(path)));
+ }
+
+ @Test
+ public void shouldResolveRelativePathToParent() {
+ path = pathFactory.create("/a/b/c/d/e/f");
+ assertThat(path.resolve(pathFactory.create("..")),
is(path.getParent()));
+ assertThat(path.resolve(pathFactory.create("..")),
hasSegments(pathFactory, "a", "b", "c", "d",
"e"));
+ }
+
+ @Test
+ public void shouldResolveRelativePaths() {
+ path = pathFactory.create("/a/b/c/d/e/f");
+ assertThat(path.resolve(pathFactory.create("../../../../../..")),
is(ROOT));
+ assertThat(path.resolve(pathFactory.create("../..")),
is(path.getParent().getParent()));
+ assertThat(path.resolve(pathFactory.create("../..")),
hasSegments(pathFactory, "a", "b", "c", "d"));
+ assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")),
is(path.getParent()));
+ assertThat(path.resolve(pathFactory.create("../x/../y/../z/..")),
hasSegments(pathFactory, "a", "b", "c", "d",
"e"));
+ assertThat(path.resolve(pathFactory.create("../x")),
hasSegments(pathFactory, "a", "b", "c", "d",
"e", "x"));
+ }
+
+ public void shouldResolveNonAbsolutePaths() {
+ path = pathFactory.create("a/b/c");
+ assertThat(path, hasSegments(pathFactory, "a", "b",
"c"));
+ }
+
+ @Test
+ public void shouldConvertPathToString() {
+ TextEncoder encoder = new Jsr283Encoder();
+ TextEncoder delimEncoder = new TextEncoder() {
+ public String encode( String text ) {
+ if ("/".equals(text)) return "\\/";
+ if (":".equals(text)) return "\\:";
+ if ("{".equals(text)) return "\\{";
+ if ("}".equals(text)) return "\\}";
+ return text;
+ }
+ };
+ Path path = pathFactory.create("a/b/c");
+ assertThat(path.getString(namespaceRegistry), is("a/b/c"));
+ assertThat(path.getString(namespaceRegistry, encoder), is("a/b/c"));
+ assertThat(path.getString(namespaceRegistry, encoder, delimEncoder),
is("a\\/b\\/c"));
+
+ path = pathFactory.create("/a/b/c");
+ assertThat(path.getString(namespaceRegistry), is("/a/b/c"));
+ assertThat(path.getString(namespaceRegistry, encoder), is("/a/b/c"));
+ assertThat(path.getString(namespaceRegistry, encoder, delimEncoder),
is("\\/a\\/b\\/c"));
+
+ path = pathFactory.create("/dna:a/b/c");
+ assertThat(path.getString(encoder), is("/{" +
encoder.encode(DnaLexicon.Namespace.URI) + "}a/{}b/{}c"));
+ assertThat(path.getString(null, encoder, delimEncoder), is("\\/\\{" +
encoder.encode(DnaLexicon.Namespace.URI)
+ +
"\\}a\\/\\{\\}b\\/\\{\\}c"));
+ assertThat(path.getString(namespaceRegistry), is("/dna:a/b/c"));
+ assertThat(path.getString(namespaceRegistry, encoder),
is("/dna:a/b/c"));
+ assertThat(path.getString(namespaceRegistry, encoder, delimEncoder),
is("\\/dna\\:a\\/b\\/c"));
+ }
+}
Added:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/ChildPathTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/ChildPathTest.java
(rev 0)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/ChildPathTest.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -0,0 +1,352 @@
+/*
+ * 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.graph.properties.basic;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.stub;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import java.util.ArrayList;
+import java.util.List;
+import org.jboss.dna.graph.properties.Name;
+import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.properties.basic.BasicName;
+import org.jboss.dna.graph.properties.basic.BasicPath;
+import org.jboss.dna.graph.properties.basic.BasicPathSegment;
+import org.jboss.dna.graph.properties.basic.ChildPath;
+import org.jboss.dna.graph.properties.basic.RootPath;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class ChildPathTest extends AbstractPathTest {
+
+ protected Path parent;
+ protected Path root;
+ protected Path.Segment childSegment;
+
+ @Before
+ @Override
+ public void beforeEach() {
+ super.beforeEach();
+ // parent = mock(Path.class);
+ parent = path("/a/b/c");
+ childSegment = segment("d");
+ path = new ChildPath(parent, childSegment);
+ root = RootPath.INSTANCE;
+ }
+
+ protected Path path( String path ) {
+ path = path.trim();
+ if ("/".equals(path)) return RootPath.INSTANCE;
+ boolean absolute = path.startsWith("/");
+ path = path.replaceAll("^/+", "").replaceAll("/+$",
""); // remove leading and trailing slashes
+ String[] segmentStrings = path.split("/");
+ List<Path.Segment> segments = new
ArrayList<Path.Segment>(segmentStrings.length);
+ for (String segmentString : segmentStrings) {
+ Name name = new BasicName("", segmentString);
+ Path.Segment segment = new BasicPathSegment(name);
+ segments.add(segment);
+ }
+ return new BasicPath(segments, absolute);
+ }
+
+ protected Path.Segment segment( String segment ) {
+ Name name = new BasicName("", segment);
+ return new BasicPathSegment(name);
+ }
+
+ @Test
+ public void shouldReturnParentForAncestorOfDegreeOne() {
+ assertThat(path.getAncestor(1), is(sameInstance(parent)));
+ assertThat(path.getParent(), is(sameInstance(parent)));
+ }
+
+ @Test
+ public void shouldDelegateToParentForAncestorOfDegreeGreaterThanOne() {
+ parent = mock(Path.class);
+ stub(parent.getAncestor(anyInt())).toReturn(null);
+ path = new ChildPath(parent, segment("d"));
+ for (int i = 2; i != 10; ++i) {
+ path.getAncestor(i);
+ verify(parent).getAncestor(i - 1);
+ }
+ }
+
+ @Test
+ public void shouldConsiderChildPathToBeDecendantOfParent() {
+ assertThat(path.isDecendantOf(parent), is(true));
+ }
+
+ @Test
+ public void shouldConsiderChildPathToNotBeAncestorOfParent() {
+ assertThat(path.isAncestorOf(parent), is(false));
+ }
+
+ @Test
+ public void shouldConsiderParentNotBeDecendantOfChildPath() {
+ assertThat(parent.isDecendantOf(path), is(false));
+ }
+
+ @Test
+ public void shouldConsiderPathDecendantOfOtherPathIfParentIsAtOrBelowOtherPath() {
+ parent = mock(Path.class);
+ path = new ChildPath(parent, segment("d"));
+ Path other = mock(Path.class);
+ stub(parent.isAtOrBelow(other)).toReturn(true);
+ assertThat(path.isDecendantOf(other), is(true));
+ verify(parent).isAtOrBelow(other);
+
+ stub(parent.isAtOrBelow(other)).toReturn(false);
+ assertThat(path.isDecendantOf(other), is(false));
+ verify(parent, times(2)).isAtOrBelow(other);
+ }
+
+ @Test
+ public void shouldConsiderPathDecendantOfOtherParentPath() {
+ assertThat(path.isDecendantOf(parent), is(true));
+ }
+
+ @Test
+ public void shouldReturnChildSegmentFromGetLastSegment() {
+ assertThat(path.getLastSegment(), is(sameInstance(childSegment)));
+ }
+
+ @Test
+ public void shouldReturnChildSegmentFromGetSegmentWithIndexOfSizeMinusOne() {
+ assertThat(path.getSegment(path.size() - 1), is(sameInstance(childSegment)));
+ }
+
+ @Test
+ public void shouldDelegateGetSegmentToParentIfIndexNotEqualToSizeMinusOne() {
+ Path.Segment segment = mock(Path.Segment.class);
+ parent = mock(Path.class);
+ stub(parent.size()).toReturn(10);
+ path = new ChildPath(parent, segment("d"));
+ stub(parent.getSegment(anyInt())).toReturn(segment);
+ for (int i = 0; i < path.size() - 1; ++i) {
+ assertThat(path.getSegment(i), is(sameInstance(segment)));
+ }
+ verify(parent, times(parent.size())).getSegment(anyInt());
+ }
+
+ @Test
+ public void shouldReturnParentInstanceFromGetParent() {
+ assertThat(path.getParent(), is(sameInstance(parent)));
+ }
+
+ // @Test
+ // public void shouldReturnRootForLowestCommonAncestorWithAnyNodePath() {
+ // Path other = mock(Path.class);
+ // stub(other.isRoot()).toReturn(true);
+ // assertThat(root.getCommonAncestor(other).isRoot(), is(true));
+ //
+ // stub(other.isRoot()).toReturn(false);
+ // assertThat(root.getCommonAncestor(other).isRoot(), is(true));
+ // }
+ //
+ // @Test
+ // public void shouldConsiderRootToBeAncestorOfEveryNodeExceptRoot() {
+ // Path other = mock(Path.class);
+ // stub(other.size()).toReturn(1);
+ // assertThat(root.isAncestorOf(other), is(true));
+ // assertThat(root.isAncestorOf(root), is(false));
+ // }
+ //
+ // @Test
+ // public void shouldNotConsiderRootNodeToBeDecendantOfAnyNode() {
+ // Path other = mock(Path.class);
+ // assertThat(root.isDecendantOf(other), is(false));
+ // assertThat(root.isDecendantOf(root), is(false));
+ // }
+ //
+ // @Test
+ // public void shouldConsiderTwoRootNodesToHaveSameAncestor() {
+ // assertThat(root.hasSameAncestor(root), is(true));
+ // }
+ //
+ // @Test
+ // public void shouldBeNormalized() {
+ // assertThat(root.isNormalized(), is(true));
+ // }
+ //
+ // @Test
+ // public void shouldReturnSelfForGetNormalized() {
+ // assertThat(root.getNormalizedPath(), is(sameInstance(root)));
+ // }
+ //
+ // @Test
+ // public void shouldReturnSelfForGetCanonicalPath() {
+ // assertThat(root.getCanonicalPath(), is(sameInstance(root)));
+ // }
+ //
+ // @Test
+ // public void shouldReturnSizeOfZero() {
+ // assertThat(root.size(), is(0));
+ // }
+ //
+ // @Test
+ // public void shouldReturnEmptyIteratorOverSegments() {
+ // assertThat(root.iterator(), is(notNullValue()));
+ // assertThat(root.iterator().hasNext(), is(false));
+ // }
+ //
+ // @Test( expected = IndexOutOfBoundsException.class )
+ // public void shouldFailToReturnSegmentAtIndexZero() {
+ // root.getSegment(0);
+ // }
+ //
+ // @Test( expected = IndexOutOfBoundsException.class )
+ // public void shouldFailToReturnSegmentAtPositiveIndex() {
+ // root.getSegment(1);
+ // }
+ //
+ // @Test
+ // public void shouldReturnEmptySegmentsArray() {
+ // assertThat(root.getSegmentsArray(), is(notNullValue()));
+ // assertThat(root.getSegmentsArray().length, is(0));
+ // }
+ //
+ // @Test
+ // public void shouldReturnEmptySegmentsList() {
+ // assertThat(root.getSegmentsList(), is(notNullValue()));
+ // assertThat(root.getSegmentsList().isEmpty(), is(true));
+ // }
+ //
+ // @Test
+ // public void shouldAlwaysReturnPathWithSingleSlashForGetString() {
+ // NamespaceRegistry registry = mock(NamespaceRegistry.class);
+ // TextEncoder encoder = mock(TextEncoder.class);
+ // stub(encoder.encode("/")).toReturn("/");
+ // assertThat(root.getString(), is("/"));
+ // assertThat(root.getString(registry), is("/"));
+ // assertThat(root.getString(registry, encoder), is("/"));
+ // assertThat(root.getString(registry, encoder, encoder), is("/"));
+ // assertThat(root.getString(encoder), is("/"));
+ // }
+ //
+ // @Test
+ // public void
shouldAllowNullNamespaceRegistryWithNonNullTextEncodersSinceRegistryIsNotNeeded() {
+ // TextEncoder encoder = mock(TextEncoder.class);
+ // stub(encoder.encode("/")).toReturn("/");
+ // assertThat(root.getString((NamespaceRegistry)null, encoder, encoder),
is("/"));
+ // }
+ //
+ // @Test
+ // public void shouldAllowNullTextEncoder() {
+ // assertThat(root.getString((TextEncoder)null), is("/"));
+ // }
+ //
+ // @Test
+ // public void shouldNotAllowNullTextEncoderWithNonNullNamespaceRegistry() {
+ // NamespaceRegistry registry = mock(NamespaceRegistry.class);
+ // assertThat(root.getString(registry, (TextEncoder)null), is("/"));
+ // }
+ //
+ // @Test
+ // public void
shouldNotAllowNullTextEncoderForDelimiterWithNonNullNamespaceRegistry() {
+ // NamespaceRegistry registry = mock(NamespaceRegistry.class);
+ // TextEncoder encoder = mock(TextEncoder.class);
+ // assertThat(root.getString(registry, encoder, (TextEncoder)null),
is("/"));
+ // }
+ //
+ // @Test( expected = IndexOutOfBoundsException.class )
+ // public void shouldNotAllowSubpathStartingAtOne() {
+ // root.subpath(1);
+ // }
+ //
+ // @Test( expected = IndexOutOfBoundsException.class )
+ // public void shouldNotAllowSubpathStartingAtMoreThanOne() {
+ // root.subpath(2);
+ // }
+ //
+ // @Test( expected = IndexOutOfBoundsException.class )
+ // public void shouldNotAllowSubpathEndingAtMoreThanZero() {
+ // root.subpath(0, 1);
+ // }
+ //
+ // @Test
+ // public void
shouldReturnRelativePathConsistingOfSameNumberOfParentReferencesAsSizeOfSuppliedPath() {
+ // List<Path.Segment> segments = new ArrayList<Path.Segment>();
+ // segments.add(new BasicPathSegment(new BasicName("http://example.com",
"a")));
+ // Path other = new BasicPath(segments, true);
+ //
+ // assertThat(root.relativeTo(other).toString(), is(".."));
+ //
+ // segments.add(new BasicPathSegment(new BasicName("http://example.com",
"b")));
+ // other = new BasicPath(segments, true);
+ // assertThat(root.relativeTo(other).toString(), is("../.."));
+ //
+ // String expected = "..";
+ // segments.clear();
+ // for (int i = 1; i != 100; ++i) {
+ // segments.add(new BasicPathSegment(new BasicName("http://example.com",
"b" + i)));
+ // other = new BasicPath(segments, true);
+ // assertThat(root.relativeTo(other).toString(), is(expected));
+ // expected = expected + "/..";
+ // }
+ // }
+ //
+ // @Test
+ // public void shouldResolveAllRelativePathsToTheirAbsolutePath() {
+ // List<Path.Segment> segments = new ArrayList<Path.Segment>();
+ // segments.add(new BasicPathSegment(new BasicName("http://example.com",
"a")));
+ // Path other = mock(Path.class);
+ // stub(other.isAbsolute()).toReturn(false);
+ // stub(other.getSegmentsList()).toReturn(segments);
+ // Path resolved = root.resolve(other);
+ // assertThat(resolved.getSegmentsList(), is(segments));
+ // assertThat(resolved.isAbsolute(), is(true));
+ // }
+ //
+ // @Test( expected = InvalidPathException.class )
+ // public void shouldNotResolveRelativePathUsingAnAbsolutePath() {
+ // Path other = mock(Path.class);
+ // stub(other.isAbsolute()).toReturn(true);
+ // root.resolve(other);
+ // }
+ //
+ // @Test
+ // public void shouldAlwaysConsiderRootAsLessThanAnyPathOtherThanRoot() {
+ // Path other = mock(Path.class);
+ // stub(other.isRoot()).toReturn(false);
+ // assertThat(root.compareTo(other), is(-1));
+ // assertThat(root.equals(other), is(false));
+ // }
+ //
+ // @Test
+ // public void shouldAlwaysConsiderRootAsEqualToAnyOtherRoot() {
+ // Path other = mock(Path.class);
+ // stub(other.isRoot()).toReturn(true);
+ // assertThat(root.compareTo(other), is(0));
+ // assertThat(root.equals(other), is(true));
+ // assertThat(root.equals(root), is(true));
+ // }
+
+}
Added:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/RootPathTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/RootPathTest.java
(rev 0)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/properties/basic/RootPathTest.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -0,0 +1,254 @@
+/*
+ * 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.graph.properties.basic;
+
+import static org.hamcrest.core.Is.is;
+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.List;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.graph.properties.InvalidPathException;
+import org.jboss.dna.graph.properties.NamespaceRegistry;
+import org.jboss.dna.graph.properties.Path;
+import org.jboss.dna.graph.properties.basic.BasicName;
+import org.jboss.dna.graph.properties.basic.BasicPath;
+import org.jboss.dna.graph.properties.basic.BasicPathSegment;
+import org.jboss.dna.graph.properties.basic.RootPath;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ * @author John Verhaeg
+ */
+public class RootPathTest extends AbstractPathTest {
+
+ protected Path root;
+
+ @Before
+ @Override
+ public void beforeEach() {
+ super.beforeEach();
+ super.path = RootPath.INSTANCE;
+ root = path;
+ }
+
+ @Test
+ public void shouldReturnRootForLowestCommonAncestorWithAnyNodePath() {
+ Path other = mock(Path.class);
+ stub(other.isRoot()).toReturn(true);
+ assertThat(root.getCommonAncestor(other).isRoot(), is(true));
+
+ stub(other.isRoot()).toReturn(false);
+ assertThat(root.getCommonAncestor(other).isRoot(), is(true));
+ }
+
+ @Test
+ public void shouldConsiderRootToBeAncestorOfEveryNodeExceptRoot() {
+ Path other = mock(Path.class);
+ stub(other.size()).toReturn(1);
+ assertThat(root.isAncestorOf(other), is(true));
+ assertThat(root.isAncestorOf(root), is(false));
+ }
+
+ @Test
+ public void shouldNotConsiderRootNodeToBeDecendantOfAnyNode() {
+ Path other = mock(Path.class);
+ assertThat(root.isDecendantOf(other), is(false));
+ assertThat(root.isDecendantOf(root), is(false));
+ }
+
+ @Test
+ public void shouldConsiderTwoRootNodesToHaveSameAncestor() {
+ assertThat(root.hasSameAncestor(root), is(true));
+ }
+
+ @Test
+ public void shouldBeNormalized() {
+ assertThat(root.isNormalized(), is(true));
+ }
+
+ @Test
+ public void shouldReturnSelfForGetNormalized() {
+ assertThat(root.getNormalizedPath(), is(sameInstance(root)));
+ }
+
+ @Test
+ public void shouldReturnSelfForGetCanonicalPath() {
+ assertThat(root.getCanonicalPath(), is(sameInstance(root)));
+ }
+
+ @Test
+ public void shouldReturnSizeOfZero() {
+ assertThat(root.size(), is(0));
+ }
+
+ @Override
+ @Test( expected = IllegalStateException.class )
+ public void shouldReturnImmutableSegmentsIterator() {
+ root.iterator().remove();
+ }
+
+ @Test
+ public void shouldReturnEmptyIteratorOverSegments() {
+ assertThat(root.iterator(), is(notNullValue()));
+ assertThat(root.iterator().hasNext(), is(false));
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldFailToReturnSegmentAtIndexZero() {
+ root.getSegment(0);
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldFailToReturnSegmentAtPositiveIndex() {
+ root.getSegment(1);
+ }
+
+ @Test
+ public void shouldReturnEmptySegmentsArray() {
+ assertThat(root.getSegmentsArray(), is(notNullValue()));
+ assertThat(root.getSegmentsArray().length, is(0));
+ }
+
+ @Test
+ public void shouldReturnEmptySegmentsList() {
+ assertThat(root.getSegmentsList(), is(notNullValue()));
+ assertThat(root.getSegmentsList().isEmpty(), is(true));
+ }
+
+ @Test
+ public void shouldAlwaysReturnPathWithSingleSlashForGetString() {
+ NamespaceRegistry registry = mock(NamespaceRegistry.class);
+ TextEncoder encoder = mock(TextEncoder.class);
+ stub(encoder.encode("/")).toReturn("/");
+ assertThat(root.getString(), is("/"));
+ assertThat(root.getString(registry), is("/"));
+ assertThat(root.getString(registry, encoder), is("/"));
+ assertThat(root.getString(registry, encoder, encoder), is("/"));
+ assertThat(root.getString(encoder), is("/"));
+ }
+
+ @Test
+ public void
shouldAllowNullNamespaceRegistryWithNonNullTextEncodersSinceRegistryIsNotNeeded() {
+ TextEncoder encoder = mock(TextEncoder.class);
+ stub(encoder.encode("/")).toReturn("/");
+ assertThat(root.getString((NamespaceRegistry)null, encoder, encoder),
is("/"));
+ }
+
+ @Test
+ public void shouldAllowNullTextEncoder() {
+ assertThat(root.getString((TextEncoder)null), is("/"));
+ }
+
+ @Test
+ public void shouldNotAllowNullTextEncoderWithNonNullNamespaceRegistry() {
+ NamespaceRegistry registry = mock(NamespaceRegistry.class);
+ assertThat(root.getString(registry, (TextEncoder)null), is("/"));
+ }
+
+ @Test
+ public void shouldNotAllowNullTextEncoderForDelimiterWithNonNullNamespaceRegistry()
{
+ NamespaceRegistry registry = mock(NamespaceRegistry.class);
+ TextEncoder encoder = mock(TextEncoder.class);
+ assertThat(root.getString(registry, encoder, (TextEncoder)null),
is("/"));
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldNotAllowSubpathStartingAtOne() {
+ root.subpath(1);
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldNotAllowSubpathStartingAtMoreThanOne() {
+ root.subpath(2);
+ }
+
+ @Test( expected = IndexOutOfBoundsException.class )
+ public void shouldNotAllowSubpathEndingAtMoreThanZero() {
+ root.subpath(0, 1);
+ }
+
+ @Test
+ public void
shouldReturnRelativePathConsistingOfSameNumberOfParentReferencesAsSizeOfSuppliedPath() {
+ List<Path.Segment> segments = new ArrayList<Path.Segment>();
+ segments.add(new BasicPathSegment(new BasicName("http://example.com",
"a")));
+ Path other = new BasicPath(segments, true);
+
+ assertThat(root.relativeTo(other).toString(), is(".."));
+
+ segments.add(new BasicPathSegment(new BasicName("http://example.com",
"b")));
+ other = new BasicPath(segments, true);
+ assertThat(root.relativeTo(other).toString(), is("../.."));
+
+ String expected = "..";
+ segments.clear();
+ for (int i = 1; i != 100; ++i) {
+ segments.add(new BasicPathSegment(new
BasicName("http://example.com", "b" + i)));
+ other = new BasicPath(segments, true);
+ assertThat(root.relativeTo(other).toString(), is(expected));
+ expected = expected + "/..";
+ }
+ }
+
+ @Test
+ public void shouldResolveAllRelativePathsToTheirAbsolutePath() {
+ List<Path.Segment> segments = new ArrayList<Path.Segment>();
+ segments.add(new BasicPathSegment(new BasicName("http://example.com",
"a")));
+ Path other = mock(Path.class);
+ stub(other.isAbsolute()).toReturn(false);
+ stub(other.getSegmentsList()).toReturn(segments);
+ stub(other.getNormalizedPath()).toReturn(other);
+ Path resolved = root.resolve(other);
+ assertThat(resolved.getSegmentsList(), is(segments));
+ assertThat(resolved.isAbsolute(), is(true));
+ }
+
+ @Test( expected = InvalidPathException.class )
+ public void shouldNotResolveRelativePathUsingAnAbsolutePath() {
+ Path other = mock(Path.class);
+ stub(other.isAbsolute()).toReturn(true);
+ root.resolve(other);
+ }
+
+ @Test
+ public void shouldAlwaysConsiderRootAsLessThanAnyPathOtherThanRoot() {
+ Path other = mock(Path.class);
+ stub(other.isRoot()).toReturn(false);
+ assertThat(root.compareTo(other), is(-1));
+ assertThat(root.equals(other), is(false));
+ }
+
+ @Test
+ public void shouldAlwaysConsiderRootAsEqualToAnyOtherRoot() {
+ Path other = mock(Path.class);
+ stub(other.isRoot()).toReturn(true);
+ assertThat(root.compareTo(other), is(0));
+ assertThat(root.equals(other), is(true));
+ assertThat(root.equals(root), is(true));
+ }
+
+}
Modified:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/Projection.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/Projection.java 2008-12-08
16:20:36 UTC (rev 667)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/Projection.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -604,7 +604,7 @@
*/
protected boolean includes( Path pathInSource ) {
// Check whether the path is outside the source-specific path ...
- if (this.sourcePath.isAtOrAbove(pathInSource)) {
+ if (pathInSource != null &&
this.sourcePath.isAtOrAbove(pathInSource)) {
// The path is inside the source-specific region, so check the exceptions
...
List<Path> exceptions = getExceptionsToRule();
Modified:
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/MultiChildContributionTest.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/MultiChildContributionTest.java 2008-12-08
16:20:36 UTC (rev 667)
+++
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/MultiChildContributionTest.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -34,8 +34,8 @@
import org.jboss.dna.graph.properties.DateTime;
import org.jboss.dna.graph.properties.Name;
import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.basic.BasicPath;
import org.jboss.dna.graph.properties.basic.JodaDateTime;
+import org.jboss.dna.graph.properties.basic.RootPath;
import org.junit.Before;
import org.junit.Test;
@@ -61,7 +61,7 @@
@Before
public void beforeEach() throws Exception {
sourceName = "some source";
- pathInSource = BasicPath.ROOT;
+ pathInSource = RootPath.INSTANCE;
expiration = TOMORROW;
child1 = mock(Location.class);
child2 = mock(Location.class);
Modified:
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/MultiPropertyContributionTest.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/MultiPropertyContributionTest.java 2008-12-08
16:20:36 UTC (rev 667)
+++
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/MultiPropertyContributionTest.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -36,9 +36,9 @@
import org.jboss.dna.graph.properties.Path;
import org.jboss.dna.graph.properties.Property;
import org.jboss.dna.graph.properties.basic.BasicName;
-import org.jboss.dna.graph.properties.basic.BasicPath;
import org.jboss.dna.graph.properties.basic.BasicSingleValueProperty;
import org.jboss.dna.graph.properties.basic.JodaDateTime;
+import org.jboss.dna.graph.properties.basic.RootPath;
import org.junit.Before;
import org.junit.Test;
@@ -64,7 +64,7 @@
@Before
public void beforeEach() throws Exception {
sourceName = "some source";
- pathInSource = BasicPath.ROOT;
+ pathInSource = RootPath.INSTANCE;
expiration = TOMORROW;
String nsUri = "http://www.jboss.org/default";
property1 = new BasicSingleValueProperty(new BasicName(nsUri,
"property1"), "value1");
Modified:
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/NodeContributionTest.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/NodeContributionTest.java 2008-12-08
16:20:36 UTC (rev 667)
+++
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/NodeContributionTest.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -37,9 +37,9 @@
import org.jboss.dna.graph.properties.Path;
import org.jboss.dna.graph.properties.Property;
import org.jboss.dna.graph.properties.basic.BasicName;
-import org.jboss.dna.graph.properties.basic.BasicPath;
import org.jboss.dna.graph.properties.basic.BasicSingleValueProperty;
import org.jboss.dna.graph.properties.basic.JodaDateTime;
+import org.jboss.dna.graph.properties.basic.RootPath;
import org.junit.Before;
import org.junit.Test;
@@ -69,7 +69,7 @@
@Before
public void beforeEach() throws Exception {
sourceName = "some source";
- pathInSource = BasicPath.ROOT;
+ pathInSource = RootPath.INSTANCE;
expiration = TOMORROW;
String nsUri = "http://www.jboss.org/default";
property1 = new BasicSingleValueProperty(new BasicName(nsUri,
"property1"), "value1");
Modified:
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/OneChildContributionTest.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/OneChildContributionTest.java 2008-12-08
16:20:36 UTC (rev 667)
+++
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/OneChildContributionTest.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -31,8 +31,8 @@
import org.jboss.dna.graph.properties.DateTime;
import org.jboss.dna.graph.properties.Name;
import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.basic.BasicPath;
import org.jboss.dna.graph.properties.basic.JodaDateTime;
+import org.jboss.dna.graph.properties.basic.RootPath;
import org.junit.Before;
import org.junit.Test;
@@ -55,7 +55,7 @@
@Before
public void beforeEach() throws Exception {
sourceName = "some source";
- pathInSource = BasicPath.ROOT;
+ pathInSource = RootPath.INSTANCE;
expiration = TOMORROW;
child1 = mock(Location.class);
contribution = new OneChildContribution(sourceName, new Location(pathInSource),
expiration, child1);
Modified:
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/OnePropertyContributionTest.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/OnePropertyContributionTest.java 2008-12-08
16:20:36 UTC (rev 667)
+++
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/OnePropertyContributionTest.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -34,9 +34,9 @@
import org.jboss.dna.graph.properties.Path;
import org.jboss.dna.graph.properties.Property;
import org.jboss.dna.graph.properties.basic.BasicName;
-import org.jboss.dna.graph.properties.basic.BasicPath;
import org.jboss.dna.graph.properties.basic.BasicSingleValueProperty;
import org.jboss.dna.graph.properties.basic.JodaDateTime;
+import org.jboss.dna.graph.properties.basic.RootPath;
import org.junit.Before;
import org.junit.Test;
@@ -59,7 +59,7 @@
@Before
public void beforeEach() throws Exception {
sourceName = "some source";
- pathInSource = BasicPath.ROOT;
+ pathInSource = RootPath.INSTANCE;
expiration = TOMORROW;
String nsUri = "http://www.jboss.org/default";
property1 = new BasicSingleValueProperty(new BasicName(nsUri,
"property1"), "value1");
Modified:
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/ThreePropertyContributionTest.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/ThreePropertyContributionTest.java 2008-12-08
16:20:36 UTC (rev 667)
+++
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/ThreePropertyContributionTest.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -34,9 +34,9 @@
import org.jboss.dna.graph.properties.Path;
import org.jboss.dna.graph.properties.Property;
import org.jboss.dna.graph.properties.basic.BasicName;
-import org.jboss.dna.graph.properties.basic.BasicPath;
import org.jboss.dna.graph.properties.basic.BasicSingleValueProperty;
import org.jboss.dna.graph.properties.basic.JodaDateTime;
+import org.jboss.dna.graph.properties.basic.RootPath;
import org.junit.Before;
import org.junit.Test;
@@ -61,7 +61,7 @@
@Before
public void beforeEach() throws Exception {
sourceName = "some source";
- pathInSource = BasicPath.ROOT;
+ pathInSource = RootPath.INSTANCE;
expiration = TOMORROW;
String nsUri = "http://www.jboss.org/default";
property1 = new BasicSingleValueProperty(new BasicName(nsUri,
"property1"), "value1");
Modified:
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/TwoChildContributionTest.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/TwoChildContributionTest.java 2008-12-08
16:20:36 UTC (rev 667)
+++
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/TwoChildContributionTest.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -31,8 +31,8 @@
import org.jboss.dna.graph.properties.DateTime;
import org.jboss.dna.graph.properties.Name;
import org.jboss.dna.graph.properties.Path;
-import org.jboss.dna.graph.properties.basic.BasicPath;
import org.jboss.dna.graph.properties.basic.JodaDateTime;
+import org.jboss.dna.graph.properties.basic.RootPath;
import org.junit.Before;
import org.junit.Test;
@@ -56,7 +56,7 @@
@Before
public void beforeEach() throws Exception {
sourceName = "some source";
- pathInSource = BasicPath.ROOT;
+ pathInSource = RootPath.INSTANCE;
expiration = TOMORROW;
child1 = mock(Location.class);
child2 = mock(Location.class);
Modified:
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/TwoPropertyContributionTest.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/TwoPropertyContributionTest.java 2008-12-08
16:20:36 UTC (rev 667)
+++
trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/contribution/TwoPropertyContributionTest.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -34,9 +34,9 @@
import org.jboss.dna.graph.properties.Path;
import org.jboss.dna.graph.properties.Property;
import org.jboss.dna.graph.properties.basic.BasicName;
-import org.jboss.dna.graph.properties.basic.BasicPath;
import org.jboss.dna.graph.properties.basic.BasicSingleValueProperty;
import org.jboss.dna.graph.properties.basic.JodaDateTime;
+import org.jboss.dna.graph.properties.basic.RootPath;
import org.junit.Before;
import org.junit.Test;
@@ -60,7 +60,7 @@
@Before
public void beforeEach() throws Exception {
sourceName = "some source";
- pathInSource = BasicPath.ROOT;
+ pathInSource = RootPath.INSTANCE;
expiration = TOMORROW;
String nsUri = "http://www.jboss.org/default";
property1 = new BasicSingleValueProperty(new BasicName(nsUri,
"property1"), "value1");
Modified:
trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java
===================================================================
---
trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java 2008-12-08
16:20:36 UTC (rev 667)
+++
trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -41,7 +41,7 @@
import org.jboss.dna.graph.properties.Property;
import org.jboss.dna.graph.properties.PropertyFactory;
import org.jboss.dna.graph.properties.Path.Segment;
-import org.jboss.dna.graph.properties.basic.BasicPath;
+import org.jboss.dna.graph.properties.basic.RootPath;
import org.jboss.dna.graph.requests.CopyBranchRequest;
import org.jboss.dna.graph.requests.CreateNodeRequest;
import org.jboss.dna.graph.requests.DeleteBranchRequest;
@@ -165,7 +165,7 @@
}
++segmentNumber;
}
- return BasicPath.ROOT;
+ return RootPath.INSTANCE;
}
protected UUID generateUuid() {
Modified:
trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerTest.java
===================================================================
---
trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerTest.java 2008-12-08
16:20:36 UTC (rev 667)
+++
trunk/extensions/dna-sequencer-xml/src/test/java/org/jboss/dna/sequencer/xml/XmlSequencerTest.java 2008-12-08
16:53:45 UTC (rev 668)
@@ -102,9 +102,9 @@
assertThat(text.startsWith("Licensed to the Apache Software Foundation
(ASF)"), is(true));
assertThat(text.indexOf('\n') > 0, is(true));
assertThat(text.endsWith(" limitations under the License."),
is(true));
- verifyString("/", DTD_NAME, "Repository");
- verifyString("/", DTD_PUBLIC_ID, "-//The Apache Software
Foundation//DTD Jackrabbit 1.2//EN");
- verifyString("/", DTD_SYSTEM_ID,
"http://jackrabbit.apache.org/dtd/repository-1.2.dtd");
+ verifyString("", DTD_NAME, "Repository");
+ verifyString("", DTD_PUBLIC_ID, "-//The Apache Software
Foundation//DTD Jackrabbit 1.2//EN");
+ verifyString("", DTD_SYSTEM_ID,
"http://jackrabbit.apache.org/dtd/repository-1.2.dtd");
verifyName(COMMENT + "[2]", "jcr:primaryType", COMMENT);
verifyString(COMMENT + "[2]", COMMENT_CONTENT, "Example Repository
Configuration File");
verifyName("Repository[1]", "jcr:primaryType",
"nt:unstructured");