Repository: curator
Updated Branches:
  refs/heads/CURATOR-397 0cafc9199 -> 5ebcfa32d


start of a mechanism to have variable/parameterized paths


Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/5ebcfa32
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/5ebcfa32
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/5ebcfa32

Branch: refs/heads/CURATOR-397
Commit: 5ebcfa32d7b00d5c2fc2eb4268a46fea2f98083d
Parents: 0cafc91
Author: randgalt <[email protected]>
Authored: Wed Apr 26 15:45:10 2017 -0500
Committer: randgalt <[email protected]>
Committed: Wed Apr 26 15:45:10 2017 -0500

----------------------------------------------------------------------
 .../x/async/modeled/CuratorModelSpec.java       | 10 +++
 .../apache/curator/x/async/modeled/ZPath.java   | 29 +++++++
 .../modeled/details/CuratorModelSpecImpl.java   |  8 +-
 .../x/async/modeled/details/ZPathImpl.java      | 88 ++++++++++++++------
 4 files changed, 108 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/5ebcfa32/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/CuratorModelSpec.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/CuratorModelSpec.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/CuratorModelSpec.java
index 0843e47..d491cfa 100644
--- 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/CuratorModelSpec.java
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/CuratorModelSpec.java
@@ -59,6 +59,16 @@ public interface CuratorModelSpec<T>
     CuratorModelSpec<T> at(String child);
 
     /**
+     * Return a new CuratorModel instance with all the same options but 
applying to the given parameters of this CuratorModel's
+     * path via {@link 
org.apache.curator.x.async.modeled.ZPath#resolved(Object...)}
+     *
+     * @param parameters list of replacements. Must have be the same length as 
the number of
+     *                   parameter nodes in the path
+     * @return new Modeled Curator instance
+     */
+    CuratorModelSpec<T> resolved(Object... parameters);
+
+    /**
      * Return the model's path
      *
      * @return path

http://git-wip-us.apache.org/repos/asf/curator/blob/5ebcfa32/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ZPath.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ZPath.java 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ZPath.java
index 0f1556b..ff84d26 100644
--- 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ZPath.java
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ZPath.java
@@ -19,6 +19,7 @@
 package org.apache.curator.x.async.modeled;
 
 import org.apache.curator.x.async.modeled.details.ZPathImpl;
+import java.util.regex.Pattern;
 
 /**
  * Abstracts a ZooKeeper ZNode path
@@ -66,6 +67,27 @@ public interface ZPath
     }
 
     /**
+     * Return the special node name that can be used for replacements at 
runtime
+     * via {@link #resolved(Object...)}
+     *
+     * @return name
+     */
+    static String parameterNodeName()
+    {
+        return ZPathImpl.parameter;
+    }
+
+    /**
+     * When creating paths, any node in the path can be set to {@link 
#parameterNodeName()}.
+     * At runtime, the ZPath can be "resolved" by replacing these nodes with 
values.
+     *
+     * @param parameters list of replacements. Must have be the same length as 
the number of
+     *                   parameter nodes in the path
+     * @return new resolved ZPath
+     */
+    ZPath resolved(Object... parameters);
+
+    /**
      * Return a ZPath that represents a child ZNode of this ZPath. e.g.
      * <code>ZPath.from("a", "b").at("c")</code> represents the path "/a/b/c"
      *
@@ -110,4 +132,11 @@ public interface ZPath
      * @return name
      */
     String nodeName();
+
+    /**
+     * Return a regex Pattern useful for using in {@link 
org.apache.curator.framework.schema.Schema}
+     *
+     * @return pattern for this path
+     */
+    Pattern toSchemaPathPattern();
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/5ebcfa32/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/CuratorModelSpecImpl.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/CuratorModelSpecImpl.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/CuratorModelSpecImpl.java
index 5522b15..863a9e3 100644
--- 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/CuratorModelSpecImpl.java
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/CuratorModelSpecImpl.java
@@ -69,6 +69,12 @@ public class CuratorModelSpecImpl<T> implements 
CuratorModelSpec<T>, SchemaValid
     }
 
     @Override
+    public CuratorModelSpec<T> resolved(Object... parameters)
+    {
+        return new CuratorModelSpecImpl<>(path.resolved(parameters), 
serializer, createMode, aclList, createOptions, deleteOptions);
+    }
+
+    @Override
     public ZPath path()
     {
         return path;
@@ -192,7 +198,7 @@ public class CuratorModelSpecImpl<T> implements 
CuratorModelSpec<T>, SchemaValid
 
     private Schema makeSchema()
     {
-        return Schema.builder(path.fullPath() + ZKPaths.PATH_SEPARATOR + ".*")
+        return Schema.builder(path.toSchemaPathPattern())
             .dataValidator(this)
             .ephemeral(createMode.isEphemeral() ? Schema.Allowance.MUST : 
Schema.Allowance.CANNOT)
             .canBeDeleted(true)

http://git-wip-us.apache.org/repos/asf/curator/blob/5ebcfa32/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/ZPathImpl.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/ZPathImpl.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/ZPathImpl.java
index 8c51e32..a4685af 100644
--- 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/ZPathImpl.java
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/ZPathImpl.java
@@ -18,8 +18,10 @@
  */
 package org.apache.curator.x.async.modeled.details;
 
+import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
 import org.apache.curator.utils.ZKPaths;
 import org.apache.curator.x.async.modeled.ZPath;
 import org.apache.zookeeper.common.PathUtils;
@@ -27,24 +29,25 @@ import java.util.Collections;
 import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Objects;
+import java.util.regex.Pattern;
 
 public class ZPathImpl implements ZPath
 {
-    public static final ZPath root = new 
ZPathImpl(Collections.singletonList(ZKPaths.PATH_SEPARATOR));
+    public static final ZPath root = new 
ZPathImpl(Collections.singletonList(ZKPaths.PATH_SEPARATOR), null);
 
-    private volatile String fullPathCache = null;
-    private volatile String parentPathCache = null;
+    public static final String parameter = "\u0000";    // 
PathUtils.validatePath() rejects this so it's useful for this purpose
 
     private final List<String> nodes;
+    private final boolean isResolved;
 
     public static ZPath parse(String fullPath)
     {
-        PathUtils.validatePath(fullPath);
         List<String> nodes = ImmutableList.<String>builder()
             .add(ZKPaths.PATH_SEPARATOR)
             
.addAll(Splitter.on(ZKPaths.PATH_SEPARATOR).omitEmptyStrings().splitToList(fullPath))
             .build();
-        return new ZPathImpl(nodes);
+        nodes.forEach(ZPathImpl::validate);
+        return new ZPathImpl(nodes, null);
     }
 
     @Override
@@ -57,7 +60,7 @@ public class ZPathImpl implements ZPath
     public ZPath parent()
     {
         checkRootAccess();
-        return new ZPathImpl(nodes.subList(0, nodes.size() - 1));
+        return new ZPathImpl(nodes.subList(0, nodes.size() - 1), null);
     }
 
     @Override
@@ -67,8 +70,15 @@ public class ZPathImpl implements ZPath
     }
 
     @Override
+    public Pattern toSchemaPathPattern()
+    {
+        return Pattern.compile(fullPath() + ZKPaths.PATH_SEPARATOR + ".*");
+    }
+
+    @Override
     public String fullPath()
     {
+        checkResolved();
         return buildFullPath(false);
     }
 
@@ -76,12 +86,14 @@ public class ZPathImpl implements ZPath
     public String parentPath()
     {
         checkRootAccess();
+        checkResolved();
         return buildFullPath(true);
     }
 
     @Override
     public String nodeName()
     {
+        checkResolved();
         return nodes.get(nodes.size() - 1);
     }
 
@@ -114,18 +126,39 @@ public class ZPathImpl implements ZPath
         return "ZPathImpl{" + "nodes=" + nodes + '}';
     }
 
-    private ZPathImpl(List<String> nodes)
+    @Override
+    public ZPath resolved(Object... parameters)
     {
-        this.nodes = Objects.requireNonNull(nodes, "nodes cannot be null");
+        List<String> nodeNames = Lists.newArrayList();
+        for ( int i = 0; i < nodes.size(); ++i )
+        {
+            String name = nodes.get(i);
+            if ( name.equals(parameter) )
+            {
+                if ( parameters.length >= i )
+                {
+                    throw new IllegalStateException(String.format("Parameter 
missing at index [%d] for [%s]", i, nodes.toString()));
+                }
+                nodeNames.add(parameters[i].toString());
+            }
+            else
+            {
+                nodeNames.add(name);
+            }
+        }
+        return new ZPathImpl(nodeNames, null);
     }
 
     private ZPathImpl(List<String> nodes, String child)
     {
-        PathUtils.validatePath(ZKPaths.PATH_SEPARATOR + child);
-        this.nodes = ImmutableList.<String>builder()
-            .addAll(nodes)
-            .add(child)
-            .build();
+        ImmutableList.Builder<String> builder = 
ImmutableList.<String>builder().addAll(nodes);
+        if ( child != null )
+        {
+            validate(child);
+            builder.add(child);
+        }
+        this.nodes = builder.build();
+        isResolved = !this.nodes.contains(parameter);
     }
 
     private void checkRootAccess()
@@ -136,14 +169,13 @@ public class ZPathImpl implements ZPath
         }
     }
 
-    private String buildFullPath(boolean parent)
+    private void checkResolved()
     {
-        String path = parent ? parentPathCache : fullPathCache;
-        if ( path != null )
-        {
-            return path;
-        }
+        Preconditions.checkState(isResolved, "This ZPath has not been 
resolved");
+    }
 
+    private String buildFullPath(boolean parent)
+    {
         boolean addSeparator = false;
         StringBuilder str = new StringBuilder();
         int size = parent ? (nodes.size() - 1) : nodes.size();
@@ -153,18 +185,22 @@ public class ZPathImpl implements ZPath
             {
                 str.append(ZKPaths.PATH_SEPARATOR);
             }
-            str.append(nodes.get(i));
+            String value = nodes.get(i);
+            str.append(value.equals(parameter) ? ".*" : value);
         }
-        path = str.toString();
+        return str.toString();
+    }
 
-        if ( parent )
+    private static void validate(String nodeName)
+    {
+        if ( parameter.equals(Objects.requireNonNull(nodeName, "nodeName 
cannot be null")) )
         {
-            parentPathCache = path;
+            return;
         }
-        else
+        if ( nodeName.equals(ZKPaths.PATH_SEPARATOR) )
         {
-            fullPathCache = path;
+            return;
         }
-        return path;
+        PathUtils.validatePath(ZKPaths.PATH_SEPARATOR + nodeName);
     }
 }

Reply via email to