/* * ModeShape (http://www.modeshape.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.modeshape.jcr.value.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.junit.Assert.assertThat; import static org.modeshape.jcr.value.basic.IsPathContaining.hasSegments; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.junit.Before; import org.junit.Test; import org.modeshape.common.text.Jsr283Encoder; import org.modeshape.common.text.TextEncoder; import org.modeshape.jcr.ModeShapeLexicon; import org.modeshape.jcr.value.InvalidPathException; import org.modeshape.jcr.value.Name; import org.modeshape.jcr.value.Path; import org.modeshape.jcr.value.ValueFormatException; /** * @author Randall Hauch * @author John Verhaeg */ public class BasicPathOldTest extends BaseValueFactoryTest { public static final TextEncoder NO_OP_ENCODER = Path.NO_OP_ENCODER; public static final Path ROOT = RootPath.INSTANCE; 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 @Override public void beforeEach() { super.beforeEach(); validNamespacePrefix = ModeShapeLexicon.Namespace.PREFIX; validNamespaceUri = ModeShapeLexicon.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); registry.register(validNamespacePrefix, validNamespaceUri); pathFactory = new PathValueFactory(Path.DEFAULT_DECODER, valueFactories); } @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(registry), 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("/mode:a/mode:b"))); assertThat(path.getParent().getParent(), is(pathFactory.create("/mode:a"))); assertThat(path.getParent().getParent().getParent(), is(ROOT)); } @Test public void shouldReturnNthDegreeAncestor() { assertThat(path.getAncestor(1), is(pathFactory.create("/mode:a/mode:b"))); assertThat(path.getAncestor(2), is(pathFactory.create("/mode: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.isDescendantOf(common), is(true)); assertThat(path2.isDescendantOf(common), is(true)); assertThat(path3.isDescendantOf(common), is(false)); assertThat(path1.getParent().isAncestorOf(path1), is(true)); for (int i = 1; i < path1.size(); ++i) { assertThat(path1.isDescendantOf(path1.getAncestor(i)), is(true)); } for (int i = 1; i < path2.size(); ++i) { assertThat(path2.isDescendantOf(path2.getAncestor(i)), is(true)); } for (int i = 1; i < path3.size(); ++i) { assertThat(path3.isDescendantOf(path3.getAncestor(i)), is(true)); } for (int i = 1; i < path4.size(); ++i) { assertThat(path4.isDescendantOf(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.isDescendantOf(path1), is(false)); assertThat(path2.isDescendantOf(path2), is(false)); assertThat(path3.isDescendantOf(path3), is(false)); assertThat(ROOT.isDescendantOf(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.isDescendantOf(path1), is(false)); assertThat(ROOT.isDescendantOf(path2), is(false)); assertThat(ROOT.isDescendantOf(path3), is(false)); assertThat(ROOT.isDescendantOf(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.isDescendantOf(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.isDescendantOf(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("/mode:a/b/mode:c/../d/./mode:e/../.."); assertThat(path.getString(NO_OP_ENCODER), is("/{http://www.modeshape.org/1.0}a/{}b/{http://www.modeshape.org/1.0}c/../{}d/./{http://www.modeshape.org/1.0}e/../..")); } @Test public void shouldGetStringWithNamespacePrefixesForAllNamesIfNamespaceRegistryIsProvided() { path = pathFactory.create("/mode:a/b/mode:c/../d/./mode:e/../.."); assertThat(path.getString(registry, NO_OP_ENCODER), is("/mode:a/b/mode:c/../d/./mode:e/../..")); registry.register("dna2", validNamespaceUri); assertThat(path.getString(registry, NO_OP_ENCODER), is("/dna2:a/b/dna2:c/../d/./dna2:e/../..")); } @Test( expected = IllegalArgumentException.class ) public void shouldFailToReturnSubpathIfStartingIndexIsNegative() { path = pathFactory.create("/mode:a/b/mode:c/../d/./mode:e/../.."); path.subpath(-1); } @Test( expected = IndexOutOfBoundsException.class ) public void shouldFailToReturnSubpathWithoutEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() { path = pathFactory.create("/mode:a/b/mode:c/../d/./mode:e/../.."); path.subpath(path.size() + 1); } @Test( expected = IndexOutOfBoundsException.class ) public void shouldFailToReturnSubpathWithEndingIndexIfStartingIndexIsEqualToOrLargerThanSize() { path = pathFactory.create("/mode:a/b/mode:c/../d/./mode:e/../.."); path.subpath(path.size() + 1, path.size() + 2); } @Test( expected = IndexOutOfBoundsException.class ) public void shouldFailToReturnSubpathIfEndingIndexIsSmallerThanStartingIndex() { path = pathFactory.create("/mode:a/b/mode:c/../d/./mode:e/../.."); path.subpath(2, 1); } @Test( expected = IndexOutOfBoundsException.class ) public void shouldFailToReturnSubpathIfEndingIndexIsEqualToOrLargerThanSize() { path = pathFactory.create("/mode:a/b/mode:c/../d/./mode:e/../.."); path.subpath(2, path.size() + 1); } @Test public void shouldReturnRootAsSubpathIfStartingIndexAndEndingIndexAreBothZero() { path = pathFactory.create("/mode:a/b/mode:c/../d/./mode:e/../.."); assertThat(path.subpath(0, 0), is(ROOT)); } @Test public void shouldReturnSubpathIfValidStartingIndexAndNoEndingIndexAreProvided() { path = pathFactory.create("/mode:a/b/mode:c/../d/./mode:e/../.."); assertThat(path.subpath(0), hasSegments(pathFactory, "mode:a", "b", "mode:c", "..", "d", ".", "mode:e", "..", "..")); assertThat(path.subpath(0), is(path)); assertThat(path.subpath(0), is(sameInstance(path))); assertThat(path.subpath(1), hasSegments(pathFactory, "b", "mode:c", "..", "d", ".", "mode:e", "..", "..")); assertThat(path.subpath(2), hasSegments(pathFactory, "mode:c", "..", "d", ".", "mode:e", "..", "..")); assertThat(path.subpath(3), hasSegments(pathFactory, "..", "d", ".", "mode:e", "..", "..")); assertThat(path.subpath(4), hasSegments(pathFactory, "d", ".", "mode:e", "..", "..")); assertThat(path.subpath(5), hasSegments(pathFactory, ".", "mode:e", "..", "..")); assertThat(path.subpath(6), hasSegments(pathFactory, "mode:e", "..", "..")); assertThat(path.subpath(7), hasSegments(pathFactory, "..", "..")); assertThat(path.subpath(8), hasSegments(pathFactory, "..")); path = pathFactory.create("mode:a/b/mode:c/../d/./mode:e/../.."); assertThat(path.subpath(0), hasSegments(pathFactory, "mode:a", "b", "mode:c", "..", "d", ".", "mode:e", "..", "..")); assertThat(path.subpath(0), is(path)); assertThat(path.subpath(0), is(sameInstance(path))); assertThat(path.subpath(1), hasSegments(pathFactory, "b", "mode:c", "..", "d", ".", "mode:e", "..", "..")); assertThat(path.subpath(2), hasSegments(pathFactory, "mode:c", "..", "d", ".", "mode:e", "..", "..")); assertThat(path.subpath(3), hasSegments(pathFactory, "..", "d", ".", "mode:e", "..", "..")); assertThat(path.subpath(4), hasSegments(pathFactory, "d", ".", "mode:e", "..", "..")); assertThat(path.subpath(5), hasSegments(pathFactory, ".", "mode:e", "..", "..")); assertThat(path.subpath(6), hasSegments(pathFactory, "mode:e", "..", "..")); assertThat(path.subpath(7), hasSegments(pathFactory, "..", "..")); assertThat(path.subpath(8), hasSegments(pathFactory, "..")); } @Test public void shouldReturnSubpathIfValidStartingIndexAndEndingIndexAreProvided() { path = pathFactory.create("/mode:a/b/mode:c/../d/./mode:e/../.."); assertThat(path.subpath(0, path.size()), hasSegments(pathFactory, "mode:a", "b", "mode:c", "..", "d", ".", "mode: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", "mode:c", "..", "d", ".", "mode:e", "..", "..")); assertThat(path.subpath(2, path.size()), hasSegments(pathFactory, "mode:c", "..", "d", ".", "mode:e", "..", "..")); assertThat(path.subpath(3, path.size()), hasSegments(pathFactory, "..", "d", ".", "mode:e", "..", "..")); assertThat(path.subpath(4, path.size()), hasSegments(pathFactory, "d", ".", "mode:e", "..", "..")); assertThat(path.subpath(5, path.size()), hasSegments(pathFactory, ".", "mode:e", "..", "..")); assertThat(path.subpath(6, path.size()), hasSegments(pathFactory, "mode:e", "..", "..")); assertThat(path.subpath(7, path.size()), hasSegments(pathFactory, "..", "..")); assertThat(path.subpath(8, path.size()), hasSegments(pathFactory, "..")); assertThat(path.subpath(0, 2), hasSegments(pathFactory, "mode:a", "b")); assertThat(path.subpath(1, 2), hasSegments(pathFactory, "b")); assertThat(path.subpath(1, 5), hasSegments(pathFactory, "b", "mode:c", "..", "d")); assertThat(path.subpath(2, 5), hasSegments(pathFactory, "mode: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/mode:mixinTypes")); paths.add(pathFactory.create("/a/b/mode:name")); paths.add(pathFactory.create("/a/b/mode: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]/mode:mixinTypes")); paths.add(pathFactory.create("/a/c[1]/mode:name")); paths.add(pathFactory.create("/a/c[1]/mode: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]/mode:mixinTypes")); paths.add(pathFactory.create("/a/c[2]/mode:name")); paths.add(pathFactory.create("/a/c[2]/mode: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() { @Override 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(registry), is("a/b/c")); assertThat(path.getString(registry, encoder), is("a/b/c")); assertThat(path.getString(registry, encoder, delimEncoder), is("a\\/b\\/c")); path = pathFactory.create("/a/b/c"); assertThat(path.getString(registry), is("/a/b/c")); assertThat(path.getString(registry, encoder), is("/a/b/c")); assertThat(path.getString(registry, encoder, delimEncoder), is("\\/a\\/b\\/c")); path = pathFactory.create("/mode:a/b/c"); assertThat(path.getString(encoder), is("/{" + encoder.encode(ModeShapeLexicon.Namespace.URI) + "}a/{}b/{}c")); assertThat(path.getString(null, encoder, delimEncoder), is("\\/mode:a\\/\\{\\}b\\/\\{\\}c")); assertThat(path.getString(registry), is("/mode:a/b/c")); assertThat(path.getString(registry, encoder), is("/mode:a/b/c")); assertThat(path.getString(registry, encoder, delimEncoder), is("\\/mode\\:a\\/b\\/c")); } }