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 11:25:19 UTC

svn commit: r995712 - in /jackrabbit/trunk: jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/ jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/ jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/

Author: jukka
Date: Fri Sep 10 09:25:18 2010
New Revision: 995712

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

Add new Path iplementation classes.

Change Path.getDepth() to return 0 for an identifier, as that's better in line with the way the depth of a relative path is handled.

Added:
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/AbstractPath.java   (with props)
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/CurrentPath.java   (with props)
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/IdentifierPath.java   (with props)
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/NamePath.java   (with props)
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/ParentPath.java   (with props)
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/RelativePath.java   (with props)
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/RootPath.java   (with props)
Modified:
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/PathFactoryTest.java
    jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Path.java

Added: 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=995712&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/AbstractPath.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/AbstractPath.java Fri Sep 10 09:25:18 2010
@@ -0,0 +1,199 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.jackrabbit.spi.commons.name;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.spi.Path;
+
+/**
+ * Abstract base class for paths.
+ */
+abstract class AbstractPath implements Path {
+
+    /** 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);
+        } else if (element.denotesParent()) {
+            return new ParentPath(parent);
+        } else if (element.denotesName()) {
+            return new NamePath(parent, element);
+        } else {
+            throw new RepositoryException("Unknown path element: " + element);
+        }
+    }
+
+    public final Path resolve(Path relative) throws RepositoryException {
+        if (relative.isAbsolute()) {
+            return relative;
+        } else {
+            Element element = relative.getNameElement();
+            int n = relative.getLength();
+            if (n > 1) {
+                Path parent = relative.subPath(0, n - 1);
+                return createPath(resolve(parent), element);
+            } else {
+                return createPath(this, element);
+            }
+        }
+    }
+
+    /**
+     * Computes the relative path from this path to the given other path.
+     * Both paths must be absolute.
+     *
+     * @param other other path
+     * @return relative path
+     * @throws RepositoryException if the relative path can not be computed
+     */
+    public final Path computeRelativePath(Path other)
+            throws RepositoryException {
+        if (other != null && isAbsolute() && other.isAbsolute()) {
+            Element[] a = getElements();
+            Element[] b = other.getElements();
+
+            // The first elements (root or identifier) must be equal
+            if (a.length > 0 && b.length > 0 && a[0].equals(b[0])) {
+                int ai = 1;
+                int bi = 1;
+
+                while (ai < a.length && bi < b.length) {
+                    if (a[ai].equals(b[bi])) {
+                        ai++;
+                        bi++;
+                    } else if (a[ai].denotesCurrent()) {
+                        ai++;
+                    } else if (b[bi].denotesCurrent()) {
+                        bi++;
+                    } else {
+                        break;
+                    }
+                }
+
+                Path path = null;
+
+                while (ai < a.length) {
+                    if (a[ai].denotesName()) {
+                        path = new ParentPath(path);
+                        ai++;
+                    } else if (a[ai].denotesCurrent()) {
+                        ai++;
+                    } else {
+                        throw new RepositoryException(
+                                "Unexpected path element: " + a[ai]);
+                    }
+                }
+
+                while (bi < b.length) {
+                    path = createPath(path, b[bi++]);
+                }
+
+                if (path != null) {
+                    return path;
+                } else {
+                    return new CurrentPath(null);
+                }
+            }
+        }
+        throw new RepositoryException(
+                "No relative path from " + this  + " to " + other);
+    }
+
+    /**
+     * Determines if this path is equivalent to the given other path by
+     * comparing the normalized paths for equality.
+     *
+     * @param other other path
+     * @return <code>true</code> if this path is equivalent to the other path,
+     *         <code>false</code> otherwise
+     * @throws IllegalArgumentException if the other path is <code>null</code>
+     * @throws RepositoryException if an error occurs
+     */
+    public final boolean isEquivalentTo(Path other)
+            throws IllegalArgumentException, RepositoryException {
+        if (other != null) {
+            return getNormalizedPath().equals(other.getNormalizedPath());
+        } else {
+            throw new IllegalArgumentException(
+                    this + ".isEquivalentTo(" + other + ")");
+        }
+    }
+
+    /**
+     * Determines if this path is a ancestor of the given other path
+     * by comparing the depths of the paths and checking if the corresponding
+     * ancestor of the given other path is equivalent to this path.
+     *
+     * @param other other path
+     * @return <code>true</code> if this path is an ancestor of the other path,
+     *         <code>false</code> otherwise
+     * @throws IllegalArgumentException if the other path is <code>null</code>,
+     *                                  or relative when this path is absolute,
+     *                                  or vice versa
+     * @throws RepositoryException if an error occurs
+     */
+    public final boolean isAncestorOf(Path other)
+            throws IllegalArgumentException, RepositoryException {
+        if (other != null && isAbsolute() == other.isAbsolute()) {
+            int d = other.getDepth() - getDepth();
+            return d > 0 && isEquivalentTo(other.getAncestor(d));
+        } else {
+            throw new IllegalArgumentException(
+                    this + ".isAncestorOf(" + other + ")");
+        }
+    }
+
+    /**
+     * Determines if this path is a descendant of the given other path
+     * by comparing the depths of the paths and checking if the corresponding
+     * ancestor of this path is equivalent to the given other path.
+     *
+     * @param other other path
+     * @return <code>true</code> if this path is a descendant of the other path,
+     *         <code>false</code> otherwise
+     * @throws IllegalArgumentException if the other path is <code>null</code>,
+     *                                  or relative when this path is absolute,
+     *                                  or vice versa
+     * @throws RepositoryException if an error occurs
+     */
+    public final boolean isDescendantOf(Path other)
+            throws IllegalArgumentException, RepositoryException {
+        if (other != null && isAbsolute() == other.isAbsolute()) {
+            int d = getDepth() - other.getDepth();
+            return d > 0 && getAncestor(d).isEquivalentTo(other);
+        } else {
+            throw new IllegalArgumentException(
+                    this + ".isDescendantOf(" + other + ")");
+        }
+    }
+
+    //--------------------------------------------------------------< Object >
+
+    /**
+     * Returns the string representation of this path.
+     *
+     * @return path string
+     */
+    public final String toString() {
+        return getString();
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/AbstractPath.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/CurrentPath.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/CurrentPath.java?rev=995712&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/CurrentPath.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/CurrentPath.java Fri Sep 10 09:25:18 2010
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.jackrabbit.spi.commons.name;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.spi.Path;
+
+/**
+ * A relative path whose last element is the current path element, i.e. ".".
+ *
+ * @see CurrentElement
+ */
+final class CurrentPath extends RelativePath {
+
+    /** Serial version UID */
+    private static final long serialVersionUID = 1729196441091297231L;
+
+    public CurrentPath(Path parent) {
+        super(parent);
+    }
+
+    protected int getDepthModifier() {
+        return 0;
+    }
+
+    protected Path getParent() throws RepositoryException {
+        if (parent != null) {
+            return parent.getAncestor(1);
+        } else {
+            return new ParentPath(null);
+        }
+    }
+
+    /**
+     * Returns <code>false</code> as a path with a "." element is
+     * never canonical.
+     *
+     * @return <code>false</code>
+     */
+    public boolean isCanonical() {
+        return false;
+    }
+
+    public boolean isNormalized() {
+        return parent == null;
+    }
+
+    public Path getNormalizedPath() throws RepositoryException {
+        if (parent != null) {
+            return parent.getNormalizedPath();
+        } else {
+            return this;
+        }
+    }
+
+    public Path getCanonicalPath() throws RepositoryException {
+        if (parent != null) {
+            return parent.getCanonicalPath();
+        } else {
+            throw new RepositoryException(
+                    "There is no canonical representation of .");
+        }
+    }
+
+    public Element getNameElement() {
+        return CurrentElement.INSTANCE;
+    }
+
+    public String getString() {
+        if (parent != null) {
+            return parent.getString() + Path.DELIMITER + ".";
+        } else {
+            return ".";
+        }
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/CurrentPath.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/IdentifierPath.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/IdentifierPath.java?rev=995712&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/IdentifierPath.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/IdentifierPath.java Fri Sep 10 09:25:18 2010
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.jackrabbit.spi.commons.name;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.spi.Path;
+
+final class IdentifierPath extends AbstractPath {
+
+    /** Serial version UID */
+    private static final long serialVersionUID = 1602959709588338642L;
+
+    private final IdentifierElement element;
+
+    public IdentifierPath(IdentifierElement element) {
+        this.element = element;
+    }
+
+    /**
+     * Returns <code>false</code> as this is an identifier-based path.
+     *
+     * @return <code>false</code>
+     */
+    public boolean denotesRoot() {
+        return false;
+    }
+
+    /**
+     * Returns <code>true</code> as this is an identifier-based path.
+     *
+     * @return <code>true</code>
+     */
+    public boolean denotesIdentifier() {
+        return true;
+    }
+
+    /**
+     * Returns <code>true</code> as an identifier-based path with no other
+     * elements is absolute.
+     *
+     * @return <code>true</code>
+     */
+    public boolean isAbsolute() {
+        return true;
+    }
+
+    /**
+     * Returns <code>true</code> as an identifier-based path with no other
+     * elements is canonical.
+     *
+     * @return <code>true</code>
+     */
+    public boolean isCanonical() {
+        return true;
+    }
+
+    /**
+     * Returns <code>false</code> as an identifier-based path is never
+     * normalized.
+     *
+     * @return <code>false</code>
+     */
+    public boolean isNormalized() {
+        return false;
+    }
+
+    public Path getNormalizedPath() throws RepositoryException {
+        throw new RepositoryException(
+                "Cannot normalize the identifier-based path " + this);
+    }
+
+    public Path getCanonicalPath() {
+        return this;
+    }
+
+    public Path getAncestor(int degree)
+            throws IllegalArgumentException, RepositoryException {
+        if (degree < 0) {
+            throw new IllegalArgumentException(
+                    this + ".getAncestor(" + degree + ")");
+        } else {
+            Path ancestor = this;
+            while (degree-- > 0) {
+                ancestor = new ParentPath(ancestor);
+            }
+            return ancestor;
+        }
+    }
+
+    public int getAncestorCount() {
+        return 0;
+    }
+
+    public int getLength() {
+        return 1;
+    }
+
+    public int getDepth() {
+        return 0;
+    }
+
+    public Path subPath(int from, int to) throws IllegalArgumentException {
+        if (from == 0 && to == 1) {
+            return this;
+        } else {
+            throw new IllegalArgumentException(
+                    this + ".subPath(" + from + ", " + to + ")");
+        }
+    }
+
+    public Element[] getElements() {
+        return new Element[] { element };
+    }
+
+    public Element getNameElement() {
+        return element;
+    }
+
+    public String getString() {
+        return element.getString();
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/IdentifierPath.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/NamePath.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/NamePath.java?rev=995712&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/NamePath.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/NamePath.java Fri Sep 10 09:25:18 2010
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.jackrabbit.spi.commons.name;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.spi.Path;
+
+final class NamePath extends RelativePath {
+
+    /** Serial version UID */
+    private static final long serialVersionUID = -2887665244213430950L;
+
+    private final Element element;
+
+    public NamePath(Path parent, Element element) {
+        super(parent);
+        assert element.denotesName();
+        this.element = element;
+    }
+
+    protected int getDepthModifier() {
+        return 1;
+    }
+
+    protected Path getParent() throws RepositoryException {
+        if (parent != null) {
+            return parent;
+        } else {
+            return new CurrentPath(null);
+        }
+    }
+
+    public boolean isCanonical() {
+        return parent != null && parent.isCanonical();
+    }
+
+    public boolean isNormalized() {
+        return parent == null || parent.isNormalized();
+    }
+
+    public Path getNormalizedPath() throws RepositoryException {
+        if (isNormalized()) {
+            return this;
+        } else {
+            // parent is guaranteed to be !null
+            return new NamePath(parent.getNormalizedPath(), element);
+        }
+    }
+
+    public Path getCanonicalPath() throws RepositoryException {
+        if (isCanonical()) {
+            return this;
+        } else if (parent != null) {
+            return new NamePath(parent.getCanonicalPath(), element);
+        } else {
+            throw new RepositoryException(
+                    "There is no canonical representation of " + this);
+        }
+    }
+
+    public Element getNameElement() {
+        return element;
+    }
+
+    public String getString() {
+        if (parent != null) {
+            return parent.getString() + "/" + element.getString();
+        } else {
+            return element.getString();
+        }
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/NamePath.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/ParentPath.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/ParentPath.java?rev=995712&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/ParentPath.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/ParentPath.java Fri Sep 10 09:25:18 2010
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.jackrabbit.spi.commons.name;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.spi.Path;
+
+/**
+ * A relative path whose last element is the parent path element, i.e. "..".
+ *
+ * @see ParentElement
+ */
+final class ParentPath extends RelativePath {
+
+    /** Serial version UID */
+    private static final long serialVersionUID = -688611157827116290L;
+
+    public ParentPath(Path parent) {
+        super(parent);
+    }
+
+    protected int getDepthModifier() {
+        return -1;
+    }
+
+    protected Path getParent() throws RepositoryException {
+        if (isNormalized()) {
+            return new ParentPath(this);
+        } else {
+            return parent.getAncestor(2);
+        }
+    }
+
+    /**
+     * Returns <code>false</code> as a path with a ".." element is
+     * never canonical.
+     *
+     * @return <code>false</code>
+     */
+    public boolean isCanonical() {
+        return false;
+    }
+
+    public boolean isNormalized() {
+        return parent == null
+            || (parent.isNormalized()
+                    && parent.getNameElement().denotesParent());
+    }
+
+    public Path getNormalizedPath() throws RepositoryException {
+        if (isNormalized()) {
+            return this;
+        } else {
+            return parent.getNormalizedPath().getAncestor(1);
+        }
+    }
+
+    public Path getCanonicalPath() throws RepositoryException {
+        if (parent != null) {
+            return parent.getCanonicalPath().getAncestor(1);
+        } else {
+            throw new RepositoryException(
+                    "There is no canonical representation of ..");
+        }
+    }
+
+    public Element getNameElement() {
+        return ParentElement.INSTANCE;
+    }
+
+    public String getString() {
+        if (parent != null) {
+            return parent.getString() + Path.DELIMITER + "..";
+        } else {
+            return "..";
+        }
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/ParentPath.java
------------------------------------------------------------------------------
    svn:eol-style = native

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=995712&r1=995711&r2=995712&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 09:25:18 2010
@@ -509,12 +509,7 @@ public class PathFactoryImpl implements 
          * @see Path#getAncestorCount()
          */
         public int getAncestorCount() {
-            try {
-                return (isAbsolute() && !denotesIdentifier()) ? getDepth() : -1;
-            } catch (RepositoryException e) {
-                // never gets here.
-                return -1;
-            }
+            return (isAbsolute() && !denotesIdentifier()) ? getDepth() : -1;
         }
 
         /**
@@ -527,17 +522,13 @@ public class PathFactoryImpl implements 
         /**
          * @see Path#getDepth()
          */
-        public int getDepth() throws RepositoryException {
-            if (denotesIdentifier()) {
-                throw new RepositoryException(
-                        "Cannot determine depth of an identifier based path: " + this);
-            }
+        public int getDepth() {
             int depth = ROOT_DEPTH;
             for (Element element : elements) {
                 if (element.denotesParent()) {
                     depth--;
                 } else if (element.denotesName()) {
-                    // don't count root/current element.
+                    // don't count root/identifier/current element.
                     depth++;
                 }
             }
@@ -587,6 +578,11 @@ public class PathFactoryImpl implements 
                         "Cannot compare a relative path with an absolute path: "
                         + this + " vs. " + other);
             }
+            // make sure both paths are either identifier-based or not
+            if (denotesIdentifier() != other.denotesIdentifier()) {
+                throw new RepositoryException(
+                        "Cannot compare paths: " + this + " vs. " + other);
+            }
 
             int delta = other.getDepth() - getDepth();
             if (delta <= 0)

Added: 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=995712&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/RelativePath.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/RelativePath.java Fri Sep 10 09:25:18 2010
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.jackrabbit.spi.commons.name;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.spi.Path;
+
+abstract class RelativePath extends AbstractPath {
+
+    /** Serial version UID */
+    private static final long serialVersionUID = 5707676677044863127L;
+
+    protected final Path parent;
+
+    private final boolean absolute;
+
+    private final int depth;
+
+    private final int length;
+
+    protected RelativePath(Path parent) {
+        this.parent = parent;
+        if (parent != null) {
+            this.absolute = parent.isAbsolute();
+            this.depth = parent.getDepth() + getDepthModifier();
+            this.length = parent.getLength() + 1;
+        } else {
+            this.absolute = false;
+            this.depth = getDepthModifier();
+            this.length = 1;
+        }
+    }
+
+    protected abstract int getDepthModifier();
+
+    protected abstract Path getParent() throws RepositoryException;
+
+    public final boolean denotesRoot() {
+        return false;
+    }
+
+    public final boolean denotesIdentifier() {
+        return false;
+    }
+
+    public final boolean isAbsolute() {
+        return absolute;
+    }
+
+    public final Path getAncestor(int degree) throws RepositoryException {
+        if (degree < 0) {
+            throw new IllegalArgumentException(
+                    "Invalid ancestor degree " + degree);
+        } else if (degree == 0) {
+            return this;
+        } else {
+            return getParent().getAncestor(degree - 1);
+        }
+    }
+
+    public final int getAncestorCount() {
+        if (absolute) {
+            return depth;
+        } else {
+            return -1;
+        }
+    }
+
+    public final int getDepth() {
+        return depth;
+    }
+
+    public final int getLength() {
+        return length;
+    }
+
+    public final Path subPath(int from, int to) throws RepositoryException {
+        if (from < 0 || length < to || to <= from) {
+            throw new IllegalArgumentException(
+                    this + ".subPath(" + from + ", " + to + ")");
+        } else if (from == 0 && to == length) {
+            // this is only case where parent can be null
+            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());
+        }
+    }
+
+    public final Element[] getElements() {
+        Element[] elements = new Element[length];
+        if (parent != null) {
+            System.arraycopy(parent.getElements(), 0, elements, 0, length - 1);
+        }
+        elements[length - 1] = getNameElement();
+        return elements;
+    }
+
+    //--------------------------------------------------------------< Object >
+
+    public final boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        } else if (that instanceof RelativePath) {
+            RelativePath path = (RelativePath) that;
+            if (!getNameElement().equals(path.getNameElement())) {
+                return false;
+            } else if (parent != null) {
+                return parent.equals(path.parent);
+            } else {
+                return path.parent == null;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    public final int hashCode() {
+        int h = 17;
+        if (parent != null) {
+            h = h * 37 + parent.hashCode();
+        }
+        h = h * 37 + getNameElement().hashCode();
+        return h;
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/RelativePath.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/RootPath.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/RootPath.java?rev=995712&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/RootPath.java (added)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/RootPath.java Fri Sep 10 09:25:18 2010
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.jackrabbit.spi.commons.name;
+
+import javax.jcr.PathNotFoundException;
+
+import org.apache.jackrabbit.spi.Path;
+
+final class RootPath extends AbstractPath {
+
+    /** Singleton instance */
+    public static final RootPath INSTANCE = new RootPath();
+
+    /** Serial version UID */
+    private static final long serialVersionUID = 8621451607549214925L;
+
+    /** Hidden constructor */
+    private RootPath() {
+    }
+
+    /**
+     * Returns <code>true</code> as this is the root path.
+     *
+     * @return <code>true</code>
+     */
+    public boolean denotesRoot() {
+        return true;
+    }
+
+    /**
+     * Returns <code>false</code> as this is the root path.
+     *
+     * @return <code>false</code>
+     */
+    public boolean denotesIdentifier() {
+        return false;
+    }
+
+    /**
+     * Returns <code>true</code> as this is the root path.
+     *
+     * @return <code>true</code>
+     */
+    public boolean isAbsolute() {
+        return true;
+    }
+
+    /**
+     * Returns <code>true</code> as this is the root path.
+     *
+     * @return <code>true</code>
+     */
+    public boolean isCanonical() {
+        return true;
+    }
+
+    /**
+     * Returns <code>true</code> as this is the root path.
+     *
+     * @return <code>true</code>
+     */
+    public boolean isNormalized() {
+        return true;
+    }
+
+    /**
+     * Returns this path as this is the root path.
+     *
+     * @return root path
+     */
+    public Path getNormalizedPath() {
+        return this;
+    }
+
+    /**
+     * Returns this path as this is the root path.
+     *
+     * @return root path
+     */
+    public Path getCanonicalPath() {
+        return this;
+    }
+
+    public Path getAncestor(int degree)
+            throws IllegalArgumentException, PathNotFoundException {
+        if (degree < 0) {
+            throw new IllegalArgumentException(
+                    "/.getAncestor(" + degree + ")");
+        } else if (degree > 0) {
+            throw new PathNotFoundException(
+                    "/.getAncestor(" + degree + ")");
+        } else {
+            return this;
+        }
+    }
+
+    /**
+     * Returns zero as this is the root path.
+     *
+     * @return zero
+     */
+    public int getAncestorCount() {
+        return 0;
+    }
+
+    /**
+     * Returns one as this is the root path.
+     *
+     * @return one
+     */
+    public int getLength() {
+        return 1;
+    }
+
+    /**
+     * Returns zero as this is the root path.
+     *
+     * @return zero
+     */
+    public int getDepth() {
+        return 0;
+    }
+
+    public Path subPath(int from, int to) throws IllegalArgumentException {
+        if (from == 0 && to == 1) {
+            return this;
+        } else {
+            throw new IllegalArgumentException(
+                    "/.subPath(" + from + ", " + to + ")");
+        }
+    }
+
+    public Element[] getElements() {
+        return new Element[] { RootElement.INSTANCE };
+    }
+
+    public Element getNameElement() {
+        return RootElement.INSTANCE;
+    }
+
+    public String getString() {
+        return "/";
+    }
+
+    //--------------------------------------------------------< Serializable >
+
+    /** Returns the singleton instance of this class */
+    public Object readResolve() {
+        return INSTANCE;
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/RootPath.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/PathFactoryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/PathFactoryTest.java?rev=995712&r1=995711&r2=995712&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/PathFactoryTest.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/PathFactoryTest.java Fri Sep 10 09:25:18 2010
@@ -230,12 +230,8 @@ public class PathFactoryTest extends Tes
 
         assertEquals(1, p.getElements().length);
 
-        try {
-            p.getDepth();
-            fail();
-        } catch (RepositoryException e) {
-            //expected
-        }
+        assertEquals(0, p.getDepth());
+
         try {
             p.getNormalizedPath();
             fail();

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=995712&r1=995711&r2=995712&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 09:25:18 2010
@@ -277,18 +277,17 @@ public interface Path extends Serializab
      * Returns the depth of this path. The depth reflects the absolute or
      * relative hierarchy level this path is representing, depending on whether
      * this path is an absolute or a relative path. The depth also takes '.'
-     * and '..' elements into account. The depth of the root path and the
-     * current path must be 0.
+     * and '..' elements into account. The depth of the root path, an
+     * identifier and the current path must be 0.
      * <p/>
      * Note that the returned value might be negative if this path is not
      * canonical, e.g. the depth of "../../a" is -1.
      *
      * @return the depth this path
-     * @throws RepositoryException If the depths cannot be determined.
      * @see #getLength()
      * @see #getAncestorCount()
      */
-    public int getDepth() throws RepositoryException;
+    public int getDepth();
 
     /**
      * Determines if the the <code>other</code> path would be equal to <code>this</code>