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 ju...@apache.org on 2013/11/02 03:08:36 UTC

svn commit: r1538131 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath: GlobalNameMapper.java LocalNameMapper.java NamePathMapperImpl.java

Author: jukka
Date: Sat Nov  2 02:08:35 2013
New Revision: 1538131

URL: http://svn.apache.org/r1538131
Log:
OAK-1015: Optimise path parsing

Imprve the heuristics used to avoid full path parsing for "simple" paths
Also unify the getJcrName() checks against hidden and expanded names

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/GlobalNameMapper.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/LocalNameMapper.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/NamePathMapperImpl.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/GlobalNameMapper.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/GlobalNameMapper.java?rev=1538131&r1=1538130&r2=1538131&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/GlobalNameMapper.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/GlobalNameMapper.java Sat Nov  2 02:08:35 2013
@@ -41,6 +41,19 @@ import static org.apache.jackrabbit.oak.
  */
 public class GlobalNameMapper implements NameMapper {
 
+    protected static boolean isHiddenName(String name) {
+        return name.startsWith(":");
+    }
+
+    protected static boolean isExpandedName(String name) {
+        if (name.startsWith("{")) {
+            int brace = name.indexOf('}', 1);
+            return brace != -1 && name.substring(1, brace).indexOf(':') != -1;
+        } else {
+            return false;
+        }
+    }
+
     protected final Tree tree;
 
     public GlobalNameMapper(Tree tree) {
@@ -51,8 +64,8 @@ public class GlobalNameMapper implements
     public String getJcrName(@Nonnull String oakName) {
         // Sanity checks, can be turned to assertions if needed for performance
         checkNotNull(oakName);
-        checkArgument(!oakName.startsWith(":")); // hidden name
-        checkArgument(!oakName.startsWith("{")); // expanded name
+        checkArgument(!isHiddenName(oakName), oakName);
+        checkArgument(!isExpandedName(oakName), oakName);
 
         return oakName;
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/LocalNameMapper.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/LocalNameMapper.java?rev=1538131&r1=1538130&r2=1538131&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/LocalNameMapper.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/LocalNameMapper.java Sat Nov  2 02:08:35 2013
@@ -35,15 +35,6 @@ public abstract class LocalNameMapper ex
         super(tree);
     }
 
-    private static boolean isExpandedName(String name) {
-        if (name.startsWith("{")) {
-            int brace = name.indexOf('}', 1);
-            return brace != -1 && name.substring(1, brace).indexOf(':') != -1;
-        } else {
-            return false;
-        }
-    }
-
     @Override @CheckForNull
     public String getJcrName(String oakName) {
         checkNotNull(oakName);

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/NamePathMapperImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/NamePathMapperImpl.java?rev=1538131&r1=1538130&r2=1538131&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/NamePathMapperImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/NamePathMapperImpl.java Sat Nov  2 02:08:35 2013
@@ -140,9 +140,8 @@ public class NamePathMapperImpl implemen
     }
 
     private String getOakPath(final String jcrPath, final boolean keepIndex) {
-        if ("/".equals(jcrPath)) {
-            // avoid the need to special case the root path later on
-            return "/";
+        if (!needsFullMapping(jcrPath)) {
+            return jcrPath;
         }
 
         int length = jcrPath.length();
@@ -160,23 +159,6 @@ public class NamePathMapperImpl implemen
             return this.idManager.getPath(jcrPath.substring(1, length - 1));
         }
 
-        // Shortcut iff the JCR path does not start with a dot, does not contain any of
-        // {}[]/ and if it contains a colon the session does not have local re-mappings.
-        boolean hasLocalMappings = hasSessionLocalMappings();
-        boolean shortcut = length > 0 && jcrPath.charAt(0) != '.';
-        for (int i = 0; shortcut && i < length; i++) {
-            char c = jcrPath.charAt(i);
-            if (c == '{' || c == '}' || c == '[' || c == ']' || c == '/') {
-                shortcut = false;
-            } else if (c == ':') {
-                shortcut = !hasLocalMappings;
-            }
-        }
-
-        if (shortcut) {
-            return jcrPath;
-        }
-
         final StringBuilder parseErrors = new StringBuilder();
 
         PathListener listener = new PathListener() {
@@ -233,6 +215,68 @@ public class NamePathMapperImpl implemen
         return oakPath.toString();
     }
 
+    /**
+     * Checks if the given path needs to be fully parsed to apply namespace
+     * mappings or to validate its syntax. If the given path is "simple", i.e.
+     * it doesn't contain any complex constructs, and there are no local
+     * namespace remappings, it's possible to skip the full path parsing
+     * and simply use the JCR path string as-is as an Oak path.
+     *
+     * @param path JCR path
+     * @return {@code true} if the path needs to be fully parsed,
+     *         {@code false} if not
+     */
+    private boolean needsFullMapping(String path) {
+        int length = path.length();
+        if (length == 0) {
+            return true;
+        }
+
+        int slash = -1; // index of the last slash in the path
+        int colon = -1; // index of the last colon in the path
+
+        switch (path.charAt(0)) {
+        case '{': // possibly an expanded name
+        case '[': // starts with an identifier
+        case '.': // possibly "." or ".."
+        case ':': // colon as the first character
+            return true;
+        case '/':
+            if (length == 1) {
+                return false; // the root path
+            }
+            slash = 0;
+            break;
+        }
+
+        for (int i = 1; i < length; i++) {
+            switch (path.charAt(i)) {
+            case '{': // possibly an expanded name
+            case '[': // possibly an index
+                return true;
+            case '.':
+                if (i == slash + 1) {
+                    return true; // possibly "." or ".."
+                }
+                break;
+            case ':':
+                if (i == slash + 1 || i == colon + i || i + 1 == length) {
+                    return true; // colon following slash/colon or as last char
+                }
+                colon = i;
+                break;
+            case '/':
+                if (i == slash + 1 || i == colon + i || i + 1 == length) {
+                    return true; // colon following slash/colon or as last char
+                }
+                slash = i;
+                break;
+            }
+        }
+
+        return colon != -1 && hasSessionLocalMappings();
+    }
+
     //------------------------------------------------------------< PathListener >---
 
     private abstract static class PathListener implements Listener {