You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2010/09/10 15:21:10 UTC

svn commit: r995787 - in /jackrabbit/trunk: jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/ jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/ jackrabbit-spi-commons/src/main/java/org/apache/jac...

Author: jukka
Date: Fri Sep 10 13:21:10 2010
New Revision: 995787

URL: http://svn.apache.org/viewvc?rev=995787&view=rev
Log:
JCR-2744: Avoid element arrays in PathImpl

Use new path construction mechanisms in PathBuilder and PathFactoryImpl

Modified:
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/PathFactoryLogger.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/AbstractPath.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/MatchResult.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/Matcher.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathBuilder.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/RelativePath.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/xpath/XPathQueryBuilder.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/PathTest.java
    jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Path.java
    jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/PathFactory.java

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/PathFactoryLogger.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/PathFactoryLogger.java?rev=995787&r1=995786&r2=995787&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/PathFactoryLogger.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/PathFactoryLogger.java Fri Sep 10 13:21:10 2010
@@ -89,6 +89,13 @@ public class PathFactoryLogger extends A
             }}, "create(Name, int)", new Object[]{name, new Integer(index)});
     }
 
+    public Path create(final Element element) {
+        return (Path) execute(new SafeCallable() {
+            public Object call() {
+                return pathFactory.create(element);
+            }}, "create(Element)", new Object[]{element});
+    }
+
     public Path create(final Element[] elements) {
         return (Path) execute(new SafeCallable() {
             public Object call() {

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/AbstractPath.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/AbstractPath.java?rev=995787&r1=995786&r2=995787&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/AbstractPath.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/AbstractPath.java Fri Sep 10 13:21:10 2010
@@ -28,31 +28,37 @@ abstract class AbstractPath implements P
     /** Serial version UID */
     private static final long serialVersionUID = 3018771833963770499L;
 
-    protected Path createPath(Path parent, Element element)
-            throws RepositoryException {
-        if (element.denotesCurrent()) {
-            return new CurrentPath(parent);
+    public final Path resolve(Element element) {
+        if (element.denotesName()) {
+            return new NamePath(this, element);
         } else if (element.denotesParent()) {
-            return new ParentPath(parent);
-        } else if (element.denotesName()) {
-            return new NamePath(parent, element);
+            if (isAbsolute() && getDepth() == 0) {
+                throw new IllegalArgumentException(
+                        "An absolute paths with negative depth is not allowed");
+            }
+            return new ParentPath(this);
+        } else if (element.denotesCurrent()) {
+            return new CurrentPath(this);
+        } else if (element.denotesRoot()) {
+            return RootPath.INSTANCE;
+        } else if (element.denotesIdentifier()) {
+            return new IdentifierPath(element);
         } else {
-            throw new RepositoryException("Unknown path element: " + element);
+            throw new IllegalArgumentException(
+                    "Unknown path element type: " + element);
         }
     }
 
-    public final Path resolve(Path relative) throws RepositoryException {
+    public final Path resolve(Path relative) {
         if (relative.isAbsolute()) {
             return relative;
         } else {
-            Element element = relative.getNameElement();
+            Path path = this;
             int n = relative.getLength();
             if (n > 1) {
-                Path parent = relative.subPath(0, n - 1);
-                return createPath(resolve(parent), element);
-            } else {
-                return createPath(this, element);
+                path = resolve(relative.subPath(0, n - 1));
             }
+            return path.resolve(relative.getNameElement());
         }
     }
 
@@ -103,7 +109,7 @@ abstract class AbstractPath implements P
                 }
 
                 while (bi < b.length) {
-                    path = createPath(path, b[bi++]);
+                    path = path.resolve(b[bi++]);
                 }
 
                 if (path != null) {

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/MatchResult.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/MatchResult.java?rev=995787&r1=995786&r2=995787&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/MatchResult.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/MatchResult.java Fri Sep 10 13:21:10 2010
@@ -16,8 +16,6 @@
  */
 package org.apache.jackrabbit.spi.commons.name;
 
-import javax.jcr.RepositoryException;
-
 import org.apache.jackrabbit.spi.Path;
 
 /**
@@ -54,15 +52,8 @@ public class MatchResult {
     public Path getRemainder() {
         if (matchPos + matchLength >= pathLength) {
             return null;
-        }
-        else {
-            try {
-                return path.subPath(matchPos + matchLength, pathLength);
-            }
-            catch (RepositoryException e) {
-                throw (IllegalStateException) new IllegalStateException("Path not normalized")
-                        .initCause(e);
-            }
+        } else {
+            return path.subPath(matchPos + matchLength, pathLength);
         }
     }
 
@@ -75,17 +66,9 @@ public class MatchResult {
     public Path getMatch() {
         if (matchLength == 0) {
             return null;
+        } else {
+            return path.subPath(matchPos, matchPos + matchLength);
         }
-        else {
-            try {
-                return path.subPath(matchPos, matchPos + matchLength);
-            }
-            catch (RepositoryException e) {
-                throw (IllegalStateException) new IllegalStateException("Path not normalized")
-                        .initCause(e);
-            }
-        }
-
     }
 
     /**

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/Matcher.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/Matcher.java?rev=995787&r1=995786&r2=995787&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/Matcher.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/Matcher.java Fri Sep 10 13:21:10 2010
@@ -16,8 +16,6 @@
  */
 package org.apache.jackrabbit.spi.commons.name;
 
-import javax.jcr.RepositoryException;
-
 import org.apache.jackrabbit.spi.Path;
 
 /**
@@ -79,20 +77,14 @@ public final class Matcher {
             throw new IllegalArgumentException("Index out of bounds");
         }
 
-        try {
-            for (int k = pos; k < length; k++) {
-                Path path = input.subPath(k, length);
-                MatchResult result = pattern.match(path);
-                if (result.isMatch()) {
-                    return new MatchResult(input, k, result.getMatchLength());
-                }
+        for (int k = pos; k < length; k++) {
+            Path path = input.subPath(k, length);
+            MatchResult result = pattern.match(path);
+            if (result.isMatch()) {
+                return new MatchResult(input, k, result.getMatchLength());
             }
-            return null;
-        }
-        catch (RepositoryException e) {
-            throw (IllegalArgumentException) new IllegalArgumentException("Path not normalizable")
-                    .initCause(e);
         }
+        return null;
     }
 
 }

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathBuilder.java?rev=995787&r1=995786&r2=995787&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathBuilder.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathBuilder.java Fri Sep 10 13:21:10 2010
@@ -16,16 +16,14 @@
  */
 package org.apache.jackrabbit.spi.commons.name;
 
-import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.PathFactory;
 import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
 
-import java.util.LinkedList;
-
 /**
  * Helper class used to build a path from pre-parsed path elements.
- * <p/>
+ * <p>
  * Note that this class does neither validate the format of the path elements nor
  * does it validate the format of the entire path.
  * This class should therefore only be used in situations, where the elements
@@ -41,9 +39,9 @@ public final class PathBuilder {
     private final PathFactory factory;
 
     /**
-     * the list of path elements of the constructed path
+     * The current path
      */
-    private final LinkedList<Path.Element> queue;
+    private Path path = null;
 
     /**
      * Creates a new PathBuilder to create a Path using the
@@ -61,8 +59,7 @@ public final class PathBuilder {
      * @param factory The PathFactory used to create the elements and the final path.
      */
     public PathBuilder(PathFactory factory) {
-        this.factory = (factory != null) ? factory : PathFactoryImpl.getInstance();
-        queue = new LinkedList<Path.Element>();
+        this.factory = factory;
     }
 
     /**
@@ -73,7 +70,7 @@ public final class PathBuilder {
      */
     public PathBuilder(Path.Element[] elements) {
         this();
-        addAll(elements);
+        path = factory.create(elements);
     }
 
     /**
@@ -84,14 +81,18 @@ public final class PathBuilder {
      */
     public PathBuilder(Path parent) {
         this();
-        addAll(parent.getElements());
+        path = parent;
     }
 
     /**
      * Adds the {@link org.apache.jackrabbit.spi.PathFactory#getRootElement()}.
      */
     public void addRoot() {
-        addFirst(factory.getRootElement());
+        if (path != null) {
+            path = RootPath.INSTANCE.resolve(path);
+        } else {
+            path = RootPath.INSTANCE;
+        }
     }
 
     /**
@@ -101,7 +102,11 @@ public final class PathBuilder {
      */
     public void addAll(Path.Element[] elements) {
         for (Path.Element element : elements) {
-            addLast(element);
+            if (path != null) {
+                path = path.resolve(element);
+            } else {
+                path = factory.create(element);
+            }
         }
     }
 
@@ -111,7 +116,12 @@ public final class PathBuilder {
      * @param elem
      */
     public void addFirst(Path.Element elem) {
-        queue.addFirst(elem);
+        Path first = factory.create(elem);
+        if (path != null) {
+            path = first.resolve(path);
+        } else {
+            path = first;
+        }
     }
 
     /**
@@ -139,7 +149,11 @@ public final class PathBuilder {
      * @param elem
      */
     public void addLast(Path.Element elem) {
-        queue.addLast(elem);
+        if (path != null) {
+            path = path.resolve(elem);
+        } else {
+            path = factory.create(elem);
+        }
     }
 
     /**
@@ -148,7 +162,7 @@ public final class PathBuilder {
      * @param name
      */
     public void addLast(Name name) {
-        addLast(factory.createElement(name));
+        addLast(name, Path.INDEX_UNDEFINED);
     }
 
     /**
@@ -158,7 +172,7 @@ public final class PathBuilder {
      * @param index
      */
     public void addLast(Name name, int index) {
-        addLast(factory.createElement(name, index));
+        path = new NamePath(path, NameElement.create(name, index));
     }
 
     /**
@@ -168,10 +182,10 @@ public final class PathBuilder {
      * @throws MalformedPathException if the internal path element queue is empty.
      */
     public Path getPath() throws MalformedPathException {
-        if (queue.size() == 0) {
+        if (path != null) {
+            return path;
+        } else {
             throw new MalformedPathException("empty path");
         }
-        Path.Element[] elements = queue.toArray(new Path.Element[queue.size()]);
-        return factory.create(elements);
     }
 }
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java?rev=995787&r1=995786&r2=995787&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java Fri Sep 10 13:21:10 2010
@@ -16,15 +16,14 @@
  */
 package org.apache.jackrabbit.spi.commons.name;
 
-import org.apache.jackrabbit.spi.Path;
-import org.apache.jackrabbit.spi.Name;
-import org.apache.jackrabbit.spi.PathFactory;
-import org.apache.jackrabbit.spi.NameFactory;
+import java.util.ArrayList;
 
 import javax.jcr.RepositoryException;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Arrays;
+
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.NameFactory;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.PathFactory;
 
 /**
  * <code>PathFactoryImpl</code>...
@@ -41,11 +40,6 @@ public class PathFactoryImpl implements 
     private final static Name PARENT_NAME = NAME_FACTORY.create(Name.NS_DEFAULT_URI, PARENT_LITERAL);
     private final static Name ROOT_NAME = NAME_FACTORY.create(Name.NS_DEFAULT_URI, "");
 
-    /**
-     * the root path
-     */
-    private static final Path ROOT = RootPath.INSTANCE;
-
     private PathFactoryImpl() {}
 
     public static PathFactory getInstance() {
@@ -60,22 +54,13 @@ public class PathFactoryImpl implements 
         if (relPath.isAbsolute()) {
             throw new IllegalArgumentException(
                     "relPath is not a relative path: " + relPath);
-        }
-        List<Path.Element> l = new ArrayList<Path.Element>();
-        l.addAll(Arrays.asList(parent.getElements()));
-        l.addAll(Arrays.asList(relPath.getElements()));
-
-        Builder pb;
-        try {
-            pb = new Builder(l);
-        } catch (IllegalArgumentException iae) {
-             throw new RepositoryException(iae.getMessage());
-        }
-        Path path = pb.getPath();
-        if (normalize) {
-            return path.getNormalizedPath();
         } else {
-            return path;
+            Path path = parent.resolve(relPath);
+            if (normalize) {
+                return path.getNormalizedPath();
+            } else {
+                return path;
+            }
         }
     }
 
@@ -83,39 +68,18 @@ public class PathFactoryImpl implements 
      * @see PathFactory#create(Path, Name, boolean)
      */
     public Path create(Path parent, Name name, boolean normalize) throws RepositoryException {
-        List<Path.Element> elements = new ArrayList<Path.Element>();
-        elements.addAll(Arrays.asList(parent.getElements()));
-        elements.add(createElement(name));
-
-        Builder pb;
-        try {
-            pb = new Builder(elements);
-        } catch (IllegalArgumentException iae) {
-             throw new RepositoryException(iae.getMessage());
-        }
-        Path path = pb.getPath();
-        if (normalize) {
-            return path.getNormalizedPath();
-        } else {
-            return path;
-        }
+        return create(parent, name, Path.INDEX_UNDEFINED, normalize);
     }
 
     /**
      * @see PathFactory#create(Path, Name, int, boolean)
      */
     public Path create(Path parent, Name name, int index, boolean normalize) throws IllegalArgumentException, RepositoryException {
-        List<Path.Element> elements = new ArrayList<Path.Element>();
-        elements.addAll(Arrays.asList(parent.getElements()));
-        elements.add(createElement(name, index));
-
-        Builder pb;
-        try {
-            pb = new Builder(elements);
-        } catch (IllegalArgumentException iae) {
-             throw new RepositoryException(iae.getMessage());
+        if (ROOT_NAME.equals(name)) {
+            throw new IllegalArgumentException();
         }
-        Path path = pb.getPath();
+        NameElement element = NameElement.create(name, index);
+        Path path = new NamePath(parent, element).getNormalizedPath();
         if (normalize) {
             return path.getNormalizedPath();
         } else {
@@ -127,8 +91,7 @@ public class PathFactoryImpl implements 
      * @see PathFactory#create(Name)
      */
     public Path create(Name name) throws IllegalArgumentException {
-        Path.Element elem = createElement(name);
-        return new Builder(new Path.Element[]{elem}).getPath();
+        return create(name, Path.INDEX_UNDEFINED);
     }
 
     /**
@@ -138,16 +101,74 @@ public class PathFactoryImpl implements 
         if (index < Path.INDEX_UNDEFINED) {
             throw new IllegalArgumentException(
                     "Index must not be negative: " + name + "[" + index + "]");
+        } else if (CURRENT_NAME.equals(name)) {
+            if (index == Path.INDEX_UNDEFINED) {
+                return new CurrentPath(null);
+            } else {
+                throw new IllegalArgumentException();
+            }
+        } else if (PARENT_NAME.equals(name)) {
+            if (index == Path.INDEX_UNDEFINED) {
+                return new ParentPath(null);
+            } else {
+                throw new IllegalArgumentException();
+            }
+        } else if (ROOT_NAME.equals(name)) {
+            if (index == Path.INDEX_UNDEFINED) {
+                return RootPath.INSTANCE;
+            } else {
+                throw new IllegalArgumentException();
+            }
+        } else {
+            return new NamePath(null, NameElement.create(name, index));
+        }
+    }
+
+    public Path create(Path.Element element) {
+        if (element.denotesCurrent()) {
+            return new CurrentPath(null);
+        } else if (element.denotesIdentifier()) {
+            return new IdentifierPath(element);
+        } else if (element.denotesName()) {
+            return new NamePath(null, element);
+        } else if (element.denotesParent()) {
+            return new ParentPath(null);
+        } else if (element.denotesRoot()) {
+            return RootPath.INSTANCE;
+        } else {
+            throw new IllegalArgumentException(
+                    "Unknown path element type: " + element);
         }
-        Path.Element elem = createElement(name, index);
-        return new Builder(new Path.Element[]{elem}).getPath();
     }
 
     /**
      * @see PathFactory#create(org.apache.jackrabbit.spi.Path.Element[])
      */
     public Path create(Path.Element[] elements) throws IllegalArgumentException {
-        return new Builder(elements).getPath();
+        Path path = null;
+        for (Path.Element element : elements) {
+            if (element.denotesCurrent()) {
+                path = new CurrentPath(path);
+            } else if (element.denotesIdentifier()) {
+                if (path != null) {
+                    throw new IllegalArgumentException();
+                }
+                path = new IdentifierPath(element);
+            } else if (element.denotesName()) {
+                path = new NamePath(path, element);
+            } else if (element.denotesParent()) {
+                if (path != null && path.isAbsolute() && path.getDepth() == 0) {
+                    throw new IllegalArgumentException();
+                }
+                path = new ParentPath(path);
+            } else if (element.denotesRoot()) {
+                if (path != null) {
+                    throw new IllegalArgumentException();
+                }
+                path = RootPath.INSTANCE;
+            }
+        }
+        return path;
     }
 
     /**
@@ -173,7 +194,7 @@ public class PathFactoryImpl implements 
             }
             list.add(elem);
         }
-        return new Builder(list).getPath();
+        return create(list.toArray(new Path.Element[list.size()]));
     }
 
     /**
@@ -284,90 +305,7 @@ public class PathFactoryImpl implements 
      * @see PathFactory#getRootPath()
      */
     public Path getRootPath() {
-        return ROOT;
-    }
-
-    /**
-     * Builder internal class
-     */
-    private static final class Builder {
-
-        /**
-         * the lpath elements of the constructed path
-         */
-        private final Path.Element[] elements;
-
-        /**
-         * Creates a new Builder and initialized it with the given path
-         * elements.
-         *
-         * @param elemList
-         * @throws IllegalArgumentException if the given elements array is null
-         * or has a zero length or would otherwise constitute an invalid path
-         */
-        private Builder(List<Path.Element> elemList) throws IllegalArgumentException {
-            this(elemList.toArray(new Path.Element[elemList.size()]));
-        }
-
-        /**
-         * Creates a new Builder and initialized it with the given path
-         * elements.
-         *
-         * @param elements
-         * @throws IllegalArgumentException if the given elements array is null
-         * or has a zero length or would otherwise constitute an invalid path
-         */
-        private Builder(Path.Element[] elements) throws IllegalArgumentException {
-            if (elements == null || elements.length == 0) {
-                throw new IllegalArgumentException("Cannot build path from null or 0 elements.");
-            }
-
-            this.elements = elements;
-            if (elements.length > 1) {
-                boolean absolute = elements[0].denotesRoot();
-                int depth = 0;
-                for (int i = 0; i < elements.length; i++) {
-                    Path.Element elem = elements[i];
-                    if (elem.denotesName()) {
-                        depth++;
-                    } else if (elem.denotesRoot()) {
-                        if (i > 0) {
-                            throw new IllegalArgumentException("Invalid path: The root element may only occur at the beginning.");
-                        }
-                    } else if (elem.denotesIdentifier()) {
-                        throw new IllegalArgumentException("Invalid path: The identifier element may only occur at the beginning of a single element path.");
-                    } else  if (elem.denotesParent()) {
-                        depth--;
-                        if (absolute && depth < 0) {
-                            throw new IllegalArgumentException("Invalid path: Too many parent elements.");
-                        }
-                    }
-                }
-            }
-        }
-
-        /**
-         * Assembles the built path and returns a new {@link Path}.
-         *
-         * @return a new {@link Path}
-         */
-        private Path getPath() {
-            Path path = null;
-            for (Path.Element element : elements) {
-                if (element.denotesCurrent()) {
-                    path = new CurrentPath(path);
-                } else if (element.denotesIdentifier()) {
-                    path = new IdentifierPath(element);
-                } else if (element.denotesName()) {
-                    path = new NamePath(path, element);
-                } else if (element.denotesParent()) {
-                    path = new ParentPath(path);
-                } else if (element.denotesRoot()) {
-                    path = RootPath.INSTANCE;
-                }
-            }
-            return path;
-        }
+        return RootPath.INSTANCE;
     }
 
 }

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/RelativePath.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/RelativePath.java?rev=995787&r1=995786&r2=995787&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/RelativePath.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/RelativePath.java Fri Sep 10 13:21:10 2010
@@ -93,22 +93,29 @@ abstract class RelativePath extends Abst
         return length;
     }
 
-    public final Path subPath(int from, int to) throws RepositoryException {
+    public final Path subPath(int from, int to) {
         if (from < 0 || length < to || to <= from) {
             throw new IllegalArgumentException(
                     this + ".subPath(" + from + ", " + to + ")");
-        } else if (!isNormalized()) {
-            throw new RepositoryException(
-                    "Path " + this + " is not normalized");
         } else if (from == 0 && to == length) {
-            // this is only case where parent can be null
+            // this is only case where parent can be null (from = 0, to = 1)
             return this;
         } else if (to < length) {
             return parent.subPath(from, to);
-        } else if (from < to - 1) {
-            return createPath(parent.subPath(from, to - 1), getNameElement());
         } else {
-            return createPath(null, getNameElement());
+            Element element = getNameElement();
+            if (from < to - 1) {
+                return parent.subPath(from, to - 1).resolve(element);
+            } else if (element.denotesName()) {
+                return new NamePath(null, element);
+            } else if (element.denotesParent()) {
+                return new ParentPath(null);
+            } else if (element.denotesCurrent()) {
+                return new CurrentPath(null);
+            } else {
+                throw new IllegalStateException(
+                        "Unknown path element type: " + element);
+            }
         }
     }
 

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/xpath/XPathQueryBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/xpath/XPathQueryBuilder.java?rev=995787&r1=995786&r2=995787&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/xpath/XPathQueryBuilder.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/xpath/XPathQueryBuilder.java Fri Sep 10 13:21:10 2010
@@ -1131,14 +1131,15 @@ public class XPathQueryBuilder implement
                 // cut off left parenthesis at end
                 propName = propName.substring(0, propName.length() - 1);
             }
-            PathBuilder builder = new PathBuilder();
-            Name name = decode(resolver.getQName(propName));
-            Path relPath = getRelativePath();
-            if (relPath != null) {
-                builder.addAll(relPath.getElements());
+            Path.Element element = PathFactoryImpl.getInstance().createElement(
+                    decode(resolver.getQName(propName)));
+            Path path = getRelativePath();
+            if (path != null) {
+                path = path.resolve(element);
+            } else {
+                path = PathFactoryImpl.getInstance().create(element);
             }
-            builder.addLast(name);
-            spec = new OrderQueryNode.OrderSpec(builder.getPath(), true);
+            spec = new OrderQueryNode.OrderSpec(path, true);
             queryNode.addOrderSpec(spec);
         } catch (NameException e) {
             exceptions.add(new InvalidQueryException("Illegal name: " + child.getValue()));

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/PathTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/PathTest.java?rev=995787&r1=995786&r2=995787&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/PathTest.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/PathTest.java Fri Sep 10 13:21:10 2010
@@ -566,22 +566,6 @@ public class PathTest extends TestCase {
         }
     }
 
-    public void testSubPathNotNormalized() throws RepositoryException {
-        Path root = factory.getRootPath();
-        JcrPath[] tests = JcrPath.getTests();
-        for (int i = 0; i < tests.length; i++) {
-            if (tests[i].isValid() && !tests[i].isNormalized()) {
-                Path p = resolver.getQPath(tests[i].path);
-                try {
-                    p.subPath(0, p.getLength());
-                    fail("Path.subPath on a non-normalized path to must throw RepositoryException");
-                } catch (RepositoryException e) {
-                    // ok
-                }
-            }
-        }
-    }
-
     //--------------------------------------------------------------------------
     private static class JcrPathAndAncestor {
 

Modified: jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Path.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Path.java?rev=995787&r1=995786&r2=995787&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Path.java (original)
+++ jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Path.java Fri Sep 10 13:21:10 2010
@@ -201,6 +201,27 @@ public interface Path extends Serializab
     public Path getCanonicalPath() throws RepositoryException;
 
     /**
+     * Resolves the given path element against this path. If the given
+     * element is absolute (i.e. the root or an identifier element), then
+     * a path containing just that element is returned. Otherwise the
+     * returned path consists of this path followed by the given element.
+     *
+     * @param element path element
+     * @return resolved path
+     */
+    Path resolve(Element element);
+
+    /**
+     * Resolves the given path against this path. If the given path is
+     * absolute, then it is returned as-is. Otherwise the path is resolved
+     * relative to this path and the resulting resolved path is returned.
+     *
+     * @param relative the path to be resolved
+     * @return resolved path
+     */
+    Path resolve(Path relative);
+
+    /**
      * Computes the relative path from <code>this</code> absolute path to
      * <code>other</code>.
      *
@@ -335,11 +356,10 @@ public interface Path extends Serializab
 
     /**
      * Returns a new <code>Path</code> consisting of those Path.Element objects
-     * between the given <tt><code>from</code>, inclusive, and the given <code>to</code>,
+     * between the given <code>from</code>, inclusive, and the given <code>to</code>,
      * exclusive. An <code>IllegalArgumentException</code> is thrown if <code>from</code>
      * is greater or equal than <code>to</code> or if any of both params is
-     * out of the possible range. A <code>RepositoryException</code> is thrown
-     * if this <code>Path</code> is not normalized.
+     * out of the possible range.
      *
      * @param from index of the element to start with and low endpoint
      * (inclusive) within the list of elements to use for the sub-path.
@@ -351,9 +371,8 @@ public interface Path extends Serializab
      * @throws IllegalArgumentException if <code>from</code>
      * is greater or equal than <code>to</code> or if any of both params is
      * out of the possible range.
-     * @throws RepositoryException If this Path is not normalized.
      */
-    public Path subPath(int from, int to) throws IllegalArgumentException, RepositoryException;
+    public Path subPath(int from, int to) throws IllegalArgumentException;
 
     /**
      * Returns the elements of this path.

Modified: jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/PathFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/PathFactory.java?rev=995787&r1=995786&r2=995787&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/PathFactory.java (original)
+++ jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/PathFactory.java Fri Sep 10 13:21:10 2010
@@ -40,7 +40,7 @@ public interface PathFactory {
     public Path create(Path parent, Path relPath, boolean normalize) throws IllegalArgumentException, RepositoryException;
 
     /**
-     * Creates a new <code>Path</code> out of the given <code>parent<code> path
+     * Creates a new <code>Path</code> out of the given <code>parent</code> path
      * and the give name. If <code>normalize</code> is <code>true</code>,
      * the returned path will be normalized (or canonicalized, if the parent
      * path is absolute). Use {@link PathFactory#create(Path, Name, int, boolean)}
@@ -95,6 +95,15 @@ public interface PathFactory {
     public Path create(Name name, int index) throws IllegalArgumentException;
 
     /**
+     * Creates a path from the given element.
+     *
+     * @param element path element
+     * @return the created path
+     * @throws IllegalArgumentException if the given element is <code>null</code>
+     */
+    Path create(Path.Element element) throws IllegalArgumentException;
+
+    /**
      * Create a new <code>Path</code> from the given elements.
      *
      * @param elements