Index: oak-core/src/main/java/org/apache/jackrabbit/oak/api/TreeLocation.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/api/TreeLocation.java (revision 56a769a) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/api/TreeLocation.java (revision 7d2aa033467f7292c7df973fd201f9c6fd50880b) @@ -45,13 +45,12 @@ TreeLocation getParent(); /** - * Navigate to a child through a relative path. A relative path consists of a - * possibly empty lists of names separated by forward slashes. - * @param relPath relative path to the child + * Navigate to a child of the given {@code name}. + * @param name name of the child * @return a {@code TreeLocation} for a child with the given {@code name}. */ @Nonnull - TreeLocation getChild(String relPath); + TreeLocation getChild(String name); /** * Determine whether the underlying {@link org.apache.jackrabbit.oak.api.Tree} or Index: oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractNodeLocation.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractNodeLocation.java (revision 56a769a) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractNodeLocation.java (revision 7d2aa033467f7292c7df973fd201f9c6fd50880b) @@ -17,13 +17,11 @@ package org.apache.jackrabbit.oak.core; import static com.google.common.base.Objects.toStringHelper; -import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.api.Tree; import org.apache.jackrabbit.oak.api.TreeLocation; -import org.apache.jackrabbit.oak.commons.PathUtils; /** * AbstractNodeLocation... TODO @@ -58,28 +56,17 @@ } @Override - public TreeLocation getChild(String relPath) { - checkArgument(!PathUtils.isAbsolute(relPath), "Not a relative path: " + relPath); - if (relPath.isEmpty()) { - return this; - } - - String parent = PathUtils.getParentPath(relPath); - if (parent.isEmpty()) { - T child = getChildTree(relPath); + public TreeLocation getChild(String name) { + T child = getChildTree(name); - if (child != null) { - return createNodeLocation(child); - } + if (child != null) { + return createNodeLocation(child); + } - PropertyState prop = getPropertyState(relPath); + PropertyState prop = getPropertyState(name); - if (prop != null) { + if (prop != null) { - return createPropertyLocation(this, relPath); + return createPropertyLocation(this, name); - } + } - return new NullLocation(this, relPath); - } - else { - return getChild(parent).getChild(PathUtils.getName(relPath)); - } + return new NullLocation(this, name); } @Override \ No newline at end of file Index: oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractTreeLocation.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractTreeLocation.java (revision 56a769a) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractTreeLocation.java (revision 7d2aa033467f7292c7df973fd201f9c6fd50880b) @@ -21,22 +21,12 @@ import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.api.Tree; import org.apache.jackrabbit.oak.api.TreeLocation; -import org.apache.jackrabbit.oak.commons.PathUtils; -import static com.google.common.base.Preconditions.checkArgument; - abstract class AbstractTreeLocation implements TreeLocation { @Override - public TreeLocation getChild(String relPath) { - checkArgument(!PathUtils.isAbsolute(relPath), "Not a relative path: " + relPath); - - TreeLocation child = this; - for (String e : PathUtils.elements(relPath)) { - child = new NullLocation(child, e); - } - - return child; + public TreeLocation getChild(String name) { + return new NullLocation(this, name); } /** Index: oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java (revision 56a769a) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java (revision 7d2aa033467f7292c7df973fd201f9c6fd50880b) @@ -18,6 +18,9 @@ */ package org.apache.jackrabbit.oak.core; +import static com.google.common.base.Preconditions.checkArgument; +import static org.apache.jackrabbit.oak.commons.PathUtils.elements; + import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -29,8 +32,6 @@ import org.apache.jackrabbit.oak.commons.PathUtils; import org.apache.jackrabbit.oak.spi.state.NodeState; -import static com.google.common.base.Preconditions.checkArgument; - /** * Simple implementation of the Root interface that only supports simple read * operations (excluding query) based on the {@code NodeState} (or {@code ImmutableTree}) @@ -82,7 +83,11 @@ @Override public TreeLocation getLocation(String path) { checkArgument(PathUtils.isAbsolute(path)); - return rootTree.getLocation().getChild(path.substring(1)); + TreeLocation child = rootTree.getLocation(); + for (String name : elements(path)) { + child = child.getChild(name); + } + return child; } @Override Index: oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java (revision 56a769a) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java (revision 7d2aa033467f7292c7df973fd201f9c6fd50880b) @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static org.apache.jackrabbit.oak.commons.PathUtils.elements; import static org.apache.jackrabbit.oak.commons.PathUtils.getName; import static org.apache.jackrabbit.oak.commons.PathUtils.getParentPath; @@ -226,9 +227,13 @@ @Override public TreeLocation getLocation(String path) { + checkArgument(PathUtils.isAbsolute(path)); checkLive(); - checkArgument(PathUtils.isAbsolute(path), "Not an absolute path: " + path); - return rootTree.getLocation().getChild(path.substring(1)); + TreeLocation child = rootTree.getLocation(); + for (String name : elements(path)) { + child = child.getChild(name); + } + return child; } @Override Index: oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java (revision 56a769a) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java (revision 7d2aa033467f7292c7df973fd201f9c6fd50880b) @@ -470,7 +470,7 @@ */ @CheckForNull TreeImpl getTree(String path) { - checkArgument(path.startsWith("/")); + checkArgument(PathUtils.isAbsolute(path)); TreeImpl child = this; for (String name : elements(path)) { child = child.internalGetChild(name); Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java (revision 56a769a) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java (revision 7d2aa033467f7292c7df973fd201f9c6fd50880b) @@ -52,6 +52,7 @@ import org.apache.jackrabbit.oak.api.Root; import org.apache.jackrabbit.oak.api.Tree; import org.apache.jackrabbit.oak.api.Type; +import org.apache.jackrabbit.oak.commons.PathUtils; import org.apache.jackrabbit.oak.core.ReadOnlyTree; import org.apache.jackrabbit.oak.namepath.NameMapper; import org.apache.jackrabbit.oak.namepath.NamePathMapper; @@ -145,17 +146,19 @@ */ @Nonnull public static ReadOnlyNodeTypeManager getInstance(NodeState root) { - Tree tree = new ReadOnlyTree(root).getLocation() - .getChild(NODE_TYPES_PATH.substring(1)).getTree(); + NodeState typesNode = root; + for (String name : PathUtils.elements(NODE_TYPES_PATH)) { + typesNode = typesNode.getChildNode(name); + if (typesNode == null) { + typesNode = EMPTY_NODE; + } + } - final Tree types = tree == null - ? new ReadOnlyTree(EMPTY_NODE) // No node types in content, use an empty node - : tree; - + final Tree typesTree = new ReadOnlyTree(typesNode); return new ReadOnlyNodeTypeManager() { @Override protected Tree getTypes() { - return types; + return typesTree; } }; } Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadOnlyVersionManager.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadOnlyVersionManager.java (revision 56a769a) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadOnlyVersionManager.java (revision 7d2aa033467f7292c7df973fd201f9c6fd50880b) @@ -18,6 +18,9 @@ */ package org.apache.jackrabbit.oak.plugins.version; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import javax.jcr.RepositoryException; @@ -31,10 +34,8 @@ import org.apache.jackrabbit.oak.commons.PathUtils; import org.apache.jackrabbit.oak.core.IdentifierManager; import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager; +import org.apache.jackrabbit.oak.util.TreeUtil; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - /** * {@code ReadOnlyVersionManager} provides implementations for read-only * version operations modeled after the ones available in {@link javax.jcr.version.VersionManager}. @@ -101,7 +102,7 @@ RepositoryException { checkVersionable(versionable); String uuid = versionable.getProperty(VersionConstants.JCR_UUID).getValue(Type.STRING); - return getVersionStorageLocation().getChild(getVersionHistoryPath(uuid)).getTree(); + return TreeUtil.getTree(getVersionStorageLocation(), getVersionHistoryPath(uuid)); } /** Index: oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java (revision 56a769a) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java (revision 7d2aa033467f7292c7df973fd201f9c6fd50880b) @@ -54,6 +54,7 @@ import org.apache.jackrabbit.oak.spi.query.PropertyValues; import org.apache.jackrabbit.oak.spi.query.QueryIndex; import org.apache.jackrabbit.oak.spi.state.NodeState; +import org.apache.jackrabbit.oak.util.TreeUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -620,10 +621,7 @@ } public Tree getTree(String path) { - return rootTree - .getLocation() - .getChild(PathUtils.isAbsolute(path) ? path.substring(1) : path) - .getTree(); + return TreeUtil.getTree(rootTree, PathUtils.isAbsolute(path) ? path.substring(1) : path); } /** Index: oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizablePropertiesImpl.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizablePropertiesImpl.java (revision 56a769a) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizablePropertiesImpl.java (revision 7d2aa033467f7292c7df973fd201f9c6fd50880b) @@ -36,8 +36,8 @@ import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager; import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl; import org.apache.jackrabbit.oak.spi.security.user.UserConstants; -import org.apache.jackrabbit.oak.util.LocationUtil; import org.apache.jackrabbit.oak.util.NodeUtil; +import org.apache.jackrabbit.oak.util.TreeUtil; import org.apache.jackrabbit.util.Text; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -169,7 +169,7 @@ checkRelativePath(relPath); Tree node = getTree(); - TreeLocation propertyLocation = node.getLocation().getChild(relPath); + TreeLocation propertyLocation = TreeUtil.getTreeLocation(node, relPath); if (propertyLocation.getProperty() != null) { if (isAuthorizableProperty(node, propertyLocation, true)) { return propertyLocation.remove(); @@ -296,7 +296,7 @@ @Nonnull private static TreeLocation getLocation(Tree tree, String relativePath) { - return LocationUtil.getTreeLocation(tree.getLocation(), relativePath); + return TreeUtil.getTreeLocation(tree, relativePath); } private static void checkRelativePath(String relativePath) throws RepositoryException { Index: oak-core/src/main/java/org/apache/jackrabbit/oak/util/LocationUtil.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/util/LocationUtil.java (revision 56a769a) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/util/LocationUtil.java (revision 56a769a) @@ -1,51 +0,0 @@ -/* - * 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.oak.util; - -import javax.annotation.Nonnull; - -import org.apache.jackrabbit.oak.api.TreeLocation; -import org.apache.jackrabbit.oak.commons.PathUtils; -import org.apache.jackrabbit.util.Text; - -/** - * LocationUtil... FIXME: workaround for OAK-426 - */ -public final class LocationUtil { - - private LocationUtil() { - } - - @Nonnull - public static TreeLocation getTreeLocation(TreeLocation parentLocation, String relativePath) { - TreeLocation targetLocation = parentLocation; - String[] segments = Text.explode(relativePath, '/', false); - for (int i = 0; i < segments.length && targetLocation.exists(); i++) { - String segment = segments[i]; - if (PathUtils.denotesCurrent(segment)) { - continue; - } else if (PathUtils.denotesParent(segment)) { - targetLocation = targetLocation.getParent(); - } else { - targetLocation = targetLocation.getChild(segment); - } - } - return targetLocation; - } -} Index: oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java (revision 56a769a) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/util/NodeUtil.java (revision 7d2aa033467f7292c7df973fd201f9c6fd50880b) @@ -16,10 +16,19 @@ */ package org.apache.jackrabbit.oak.util; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.apache.jackrabbit.oak.api.Type.DATE; +import static org.apache.jackrabbit.oak.api.Type.LONG; +import static org.apache.jackrabbit.oak.api.Type.NAME; +import static org.apache.jackrabbit.oak.api.Type.NAMES; +import static org.apache.jackrabbit.oak.api.Type.STRING; +import static org.apache.jackrabbit.oak.api.Type.STRINGS; + import java.util.Arrays; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.List; + import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -42,14 +51,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static com.google.common.base.Preconditions.checkNotNull; -import static org.apache.jackrabbit.oak.api.Type.DATE; -import static org.apache.jackrabbit.oak.api.Type.LONG; -import static org.apache.jackrabbit.oak.api.Type.NAME; -import static org.apache.jackrabbit.oak.api.Type.NAMES; -import static org.apache.jackrabbit.oak.api.Type.STRING; -import static org.apache.jackrabbit.oak.api.Type.STRINGS; - /** * Utility class for accessing and writing typed content of a tree. */ @@ -139,7 +140,7 @@ if (relativePath.indexOf('/') == -1) { return getOrAddChild(relativePath, primaryTypeName); } else { - TreeLocation location = LocationUtil.getTreeLocation(tree.getLocation(), relativePath); + TreeLocation location = TreeUtil.getTreeLocation(tree, relativePath); if (location.getTree() == null) { NodeUtil target = this; for (String segment : Text.explode(relativePath, '/')) { Index: oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java (revision 56a769a) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java (revision 7d2aa033467f7292c7df973fd201f9c6fd50880b) @@ -16,17 +16,21 @@ */ package org.apache.jackrabbit.oak.util; +import static org.apache.jackrabbit.oak.api.Type.BOOLEAN; +import static org.apache.jackrabbit.oak.api.Type.STRINGS; + import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; import com.google.common.collect.Iterables; import org.apache.jackrabbit.JcrConstants; import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.api.Tree; +import org.apache.jackrabbit.oak.api.TreeLocation; import org.apache.jackrabbit.oak.api.Type; +import org.apache.jackrabbit.oak.commons.PathUtils; +import org.apache.jackrabbit.util.Text; -import static org.apache.jackrabbit.oak.api.Type.BOOLEAN; -import static org.apache.jackrabbit.oak.api.Type.STRINGS; - /** * Utility providing common operations for the {@code Tree} that are not provided * by the API. @@ -76,5 +80,71 @@ public static boolean getBoolean(Tree tree, String propertyName) { PropertyState property = tree.getProperty(propertyName); return property != null && !property.isArray() && property.getValue(BOOLEAN); + } + + /** + * Return the tree location located at the passed {@code path} from the + * {@code start} location. + * Parent (..) and current (.) elements in the path are + * interpreted as the parent of the current location and the current + * location, respectively. Empty elements are ignored. + * + * @param start start location + * @param path path from the start location + * @return tree location located at {@code path} from {@code start} + */ + @Nonnull + public static TreeLocation getTreeLocation(TreeLocation start, String path) { + TreeLocation loc = start; + for (String element : Text.explode(path, '/', false)) { + if (PathUtils.denotesParent(element)) { + loc = loc.getParent(); + } else if (!PathUtils.denotesCurrent(element)) { + loc = loc.getChild(element); + } // else . -> skip to next element + } + return loc; + } + + /** + * Return the tree location located at the passed {@code path} from the + * location of the {@code start} tree. + * Equivalent to {@code getTreeLocation(start.getLocation(), path)}. + * + * @param start start tree + * @param path path from the start tree + * @return tree location located at {@code path} from {@code start} + */ + @Nonnull + public static TreeLocation getTreeLocation(Tree start, String path) { + return getTreeLocation(start.getLocation(), path); + } + + /** + * Return the tree located at the passed {@code path} from the {@code start} + * location or {@code null} if no such tree exists or is accessible. + * Equivalent to {@code getTreeLocation(start, path).getTree()}. + * + * @param start start location + * @param path path from the start location + * @return tree located at {@code path} from {@code start} or {@code null} + */ + @CheckForNull + public static Tree getTree(TreeLocation start, String path) { + return getTreeLocation(start, path).getTree(); + } + + /** + * Return the tree located at the passed {@code path} from the location of + * the {@code start} tree or {@code null} if no such tree exists or is accessible. + * Equivalent to {@code getTreeLocation(start.getLocation(), path).getTree()}. + * + * @param start start tree + * @param path path from the start tree + * @return tree located at {@code path} from {@code start} or {@code null} + */ + @CheckForNull + public static Tree getTree(Tree start, String path) { + return getTreeLocation(start.getLocation(), path).getTree(); } } \ No newline at end of file Index: oak-core/src/test/java/org/apache/jackrabbit/oak/core/TreeLocationTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/test/java/org/apache/jackrabbit/oak/core/TreeLocationTest.java (revision 56a769a) +++ oak-core/src/test/java/org/apache/jackrabbit/oak/core/TreeLocationTest.java (revision 7d2aa033467f7292c7df973fd201f9c6fd50880b) @@ -18,6 +18,11 @@ */ package org.apache.jackrabbit.oak.core; +import static org.apache.jackrabbit.oak.core.NullLocation.NULL; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + import org.apache.jackrabbit.oak.Oak; import org.apache.jackrabbit.oak.api.CommitFailedException; import org.apache.jackrabbit.oak.api.ContentSession; @@ -29,11 +34,6 @@ import org.junit.Before; import org.junit.Test; -import static org.apache.jackrabbit.oak.core.NullLocation.NULL; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - public class TreeLocationTest { private Root root; @@ -64,7 +64,7 @@ @Test public void testNullLocation() { - TreeLocation xyz = NULL.getChild("x/y/z"); + TreeLocation xyz = NULL.getChild("x").getChild("y").getChild("z"); Assert.assertEquals("x/y/z", xyz.getPath()); assertEquals("x/y", xyz.getParent().getPath()); assertEquals("x", xyz.getParent().getParent().getPath()); @@ -82,7 +82,7 @@ TreeLocation x = root.getLocation("/x"); assertNotNull(x.getTree()); - TreeLocation xyz = x.getChild("y/z"); + TreeLocation xyz = x.getChild("y").getChild("z"); assertEquals("/x/y/z", xyz.getPath()); assertNull(xyz.getTree()); @@ -98,7 +98,7 @@ TreeLocation a = root.getLocation("/a"); assertNotNull(a.getProperty()); - TreeLocation abc = a.getChild("b/c"); + TreeLocation abc = a.getChild("b").getChild("c"); assertEquals("/a/b/c", abc.getPath()); assertNull(abc.getProperty()); Index: oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java (revision 56a769a) +++ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java (revision 7d2aa033467f7292c7df973fd201f9c6fd50880b) @@ -1482,7 +1482,7 @@ private Property internalRemoveProperty(final String jcrName) throws RepositoryException { - final String oakName = getOakPathOrThrow(checkNotNull(jcrName)); + final String oakName = getOakName(checkNotNull(jcrName)); return perform(new ItemWriteOperation() { @Override protected Property perform() throws RepositoryException { Index: oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java (revision 56a769a) +++ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java (revision 7d2aa033467f7292c7df973fd201f9c6fd50880b) @@ -33,6 +33,7 @@ import org.apache.jackrabbit.oak.api.Tree; import org.apache.jackrabbit.oak.api.TreeLocation; import org.apache.jackrabbit.oak.commons.PathUtils; +import org.apache.jackrabbit.oak.util.TreeUtil; /** * {@code NodeDelegate} serve as internal representations of {@code Node}s. @@ -246,15 +247,7 @@ throw new RepositoryException("Not a relative path: " + relPath); } - TreeLocation loc = getLocation(); - for (String element : PathUtils.elements(relPath)) { - if (PathUtils.denotesParent(element)) { - loc = loc.getParent(); - } else if (!PathUtils.denotesCurrent(element)) { - loc = loc.getChild(element); - } // else . -> skip to next element - } - return loc; + return TreeUtil.getTreeLocation(getLocation(), relPath); } private Iterator nodeDelegateIterator(