You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by md...@apache.org on 2013/02/14 20:02:23 UTC

svn commit: r1446301 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/plugins/identifier/ test/java/org/apache/jackrabbit/oak/plugins/identifier/

Author: mduerig
Date: Thu Feb 14 19:02:22 2013
New Revision: 1446301

URL: http://svn.apache.org/r1446301
Log:
OAK-101: implement identifier handling (byUUID, byIdentifier, etc)

Added:
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/identifier/
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManagerTest.java   (with props)
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java?rev=1446301&r1=1446300&r2=1446301&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java Thu Feb 14 19:02:22 2013
@@ -50,6 +50,7 @@ import org.apache.jackrabbit.oak.spi.que
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static org.apache.jackrabbit.oak.api.Type.STRING;
 
 /**
@@ -87,55 +88,77 @@ public class IdentifierManager {
         }
     }
 
+    /**
+     * Return the identifier of a tree.
+     *
+     * @param tree  a tree
+     * @return  identifier of {@code tree}
+     */
     @Nonnull
     public String getIdentifier(Tree tree) {
         PropertyState property = tree.getProperty(JcrConstants.JCR_UUID);
-        if (property == null) {
-            // TODO calculate the identifier from closest referenceable parent
-            // TODO and a relative path irrespective of the accessibility of the parent node(s)
+        if (property != null) {
+            return property.getValue(STRING);
+        } else if (tree.isRoot()) {
             return tree.getPath();
         } else {
-            return property.getValue(STRING);
+            return PathUtils.concat(getIdentifier(tree.getParent()), tree.getName());
         }
     }
 
     /**
      * The tree identified by the specified {@code identifier} or {@code null}.
      *
-     * @param identifier The identifier of the Node such as exposed by {@link javax.jcr.Node#getIdentifier()}
+     * @param identifier The identifier of the tree such as exposed by {@link #getIdentifier(Tree)}
      * @return The tree with the given {@code identifier} or {@code null} if no
-     *         such tree exists or isn't accessible to the content session.
+     *         such tree exists or if the tree is not accessible.
      */
     @CheckForNull
     public Tree getTree(String identifier) {
-        if (isValidUUID(identifier)) {
-            String path = resolveUUID(identifier);
-            return (path == null) ? null : root.getTree(path);
-        } else {
-            // TODO as stated in NodeDelegate#getIdentifier() a non-uuid ID should
-            // TODO consisting of closest referenceable parent and a relative path
-            // TODO irrespective of the accessibility of the parent node(s)
-            return root.getTree(identifier);
-        }
+        return getLocation(identifier).getTree();
     }
 
     /**
      * The path of the tree identified by the specified {@code identifier} or {@code null}.
      *
-     * @param identifier The identifier of the Tree such as exposed by {@link javax.jcr.Node#getIdentifier()}
-     * @return The tree with the given {@code identifier} or {@code null} if no
-     *         such tree exists or isn't accessible to the content session.
+     * @param identifier The identifier of the tree such as exposed by {@link #getIdentifier(Tree)}
+     * @return The path of the tree with the given {@code identifier} or {@code null} if no
+     *         such tree exists or if the tree is not accessible.
      */
     @CheckForNull
     public String getPath(String identifier) {
-        if (isValidUUID(identifier)) {
-            return resolveUUID(identifier);
+        TreeLocation location = getLocation(identifier);
+        return location.exists()
+            ? location.getPath()
+            : null;
+    }
+
+    /**
+     * The tree location of the tree identified by the specified {@code identifier}.
+     *
+     * @param identifier The identifier of the tree such as exposed by {@link #getIdentifier(Tree)}
+     * @return The tree location of the tree with the given {@code identifier}.
+     */
+    @Nonnull
+    public TreeLocation getLocation(String identifier) {
+        if (identifier.startsWith("/")) {
+            return root.getLocation(identifier);
         } else {
-            // TODO as stated in NodeDelegate#getIdentifier() a non-uuid ID should
-            // TODO consisting of closest referenceable parent and a relative path
-            // TODO irrespective of the accessibility of the parent node(s)
-            Tree tree = root.getTree(identifier);
-            return tree == null ? null : tree.getPath();
+            int k = identifier.indexOf('/');
+            String uuid = k == -1
+                ? identifier
+                : identifier.substring(0, k);
+
+            checkArgument(isValidUUID(uuid), "Not a valid identifier '" + identifier + '\'');
+
+            String basePath = resolveUUID(uuid);
+            if (basePath == null) {
+                return root.getLocation("/").getParent(); // a null location
+            } else if (k == -1) {
+                return root.getLocation(basePath);
+            } else {
+                return root.getLocation(PathUtils.concat(basePath, identifier.substring(k + 1)));
+            }
         }
     }
 

Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManagerTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManagerTest.java?rev=1446301&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManagerTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManagerTest.java Thu Feb 14 19:02:22 2013
@@ -0,0 +1,135 @@
+/*
+ * 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.plugins.identifier;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.oak.Oak;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.PropertyState;
+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.plugins.memory.PropertyStates;
+import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+public class IdentifierManagerTest {
+    private static final String UUID_Y = IdentifierManager.generateUUID();
+    private static final String UUID_Z1 = IdentifierManager.generateUUID();
+    public static final String ID_ROOT = "/";
+    public static final String ID_X1 = "/x/x1";
+    public static final String ID_Y1 = UUID_Y + "/y1";
+    public static final String ID_Z1 = UUID_Z1;
+    public static final String PATH_X1 = "/x/x1";
+    public static final String PATH_Y1 = "/y/y1";
+    public static final String PATH_Z1 = "/z/z1";
+    public static final String ID_INVALID = "invalid";
+    public static final String ID_NON_EXISTING = IdentifierManager.generateUUID();
+
+    private IdentifierManager identifierManager;
+    private Root root;
+
+    @Before
+    public void setUp() throws CommitFailedException {
+        root = new Oak()
+            .with(new InitialContent())
+            .createContentSession().getLatestRoot();
+
+        Tree tree = root.getTree("/");
+        Tree x = tree.addChild("x");
+        Tree y = tree.addChild("y");
+        y.setProperty(JcrConstants.JCR_UUID, UUID_Y);
+        Tree z = tree.addChild("z");
+        x.addChild("x1");
+        y.addChild("y1");
+        z.addChild("z1").setProperty(JcrConstants.JCR_UUID, UUID_Z1);
+        root.commit();
+
+        identifierManager = new IdentifierManager(root);
+    }
+
+    @Test
+    public void getIdentifierTest() {
+        Tree rootTree = root.getTree("/");
+        assertEquals(ID_ROOT, identifierManager.getIdentifier(rootTree));
+
+        Tree xx1 = root.getTree(PATH_X1);
+        assertEquals(ID_X1, identifierManager.getIdentifier(xx1));
+
+        Tree yy1 = root.getTree(PATH_Y1);
+        assertEquals(ID_Y1, identifierManager.getIdentifier(yy1));
+
+        Tree zz1 = root.getTree(PATH_Z1);
+        assertEquals(ID_Z1, identifierManager.getIdentifier(zz1));
+    }
+
+    @Test
+    public void getTreeTest() {
+        assertEquals("/", identifierManager.getTree(ID_ROOT).getPath());
+        assertEquals(PATH_X1, identifierManager.getTree(ID_X1).getPath());
+        assertEquals(PATH_Y1, identifierManager.getTree(ID_Y1).getPath());
+        assertEquals(PATH_Z1, identifierManager.getTree(ID_Z1).getPath());
+        assertNull(identifierManager.getTree(ID_NON_EXISTING));
+
+        try {
+            identifierManager.getTree(ID_INVALID);
+            fail("Expected IllegalArgumentException");
+        }
+        catch (IllegalArgumentException expected) { }
+    }
+
+    @Test
+    public void getPathTest() {
+        assertEquals("/", identifierManager.getPath(ID_ROOT));
+        assertEquals(PATH_X1, identifierManager.getPath(ID_X1));
+        assertEquals(PATH_Y1, identifierManager.getPath(ID_Y1));
+        assertEquals(PATH_Z1, identifierManager.getPath(ID_Z1));
+        assertNull(identifierManager.getPath(ID_NON_EXISTING));
+
+        try {
+            identifierManager.getPath(ID_INVALID);
+            fail("Expected IllegalArgumentException");
+        }
+        catch (IllegalArgumentException expected) { }
+    }
+
+    @Test
+    public void getPathFromPropertyTest() {
+        assertEquals("/y", identifierManager.getPath(createReferenceProperty(UUID_Y)));
+        assertEquals(PATH_Z1, identifierManager.getPath(createReferenceProperty(UUID_Z1)));
+        assertNull(identifierManager.getPath(createReferenceProperty(ID_NON_EXISTING)));
+        assertNull(identifierManager.getPath(createReferenceProperty(ID_INVALID)));
+
+        try {
+            identifierManager.getPath(PropertyStates.createProperty("any", "any"));
+            fail("Expected IllegalArgumentException");
+        }
+        catch (IllegalArgumentException expected) { }
+    }
+
+    private static PropertyState createReferenceProperty(String value) {
+        return PropertyStates.createProperty("ref", value, Type.REFERENCE);
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManagerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManagerTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL