added a resolving version that takes suppliers for parameters

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

Branch: refs/heads/CURATOR-397
Commit: 52b334c30d82227ad7da3559976fa932fbbc5763
Parents: 22fdb29
Author: randgalt <[email protected]>
Authored: Wed Apr 26 16:53:17 2017 -0500
Committer: randgalt <[email protected]>
Committed: Wed Apr 26 16:53:17 2017 -0500

----------------------------------------------------------------------
 .../apache/curator/x/async/modeled/ZPath.java   | 50 ++++++++++--
 .../x/async/modeled/details/ZPathImpl.java      | 86 ++++++++++++++------
 .../curator/x/async/modeled/TestZPath.java      | 13 +++
 3 files changed, 115 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/52b334c3/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 ff84d26..f68679d 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,9 @@
 package org.apache.curator.x.async.modeled;
 
 import org.apache.curator.x.async.modeled.details.ZPathImpl;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Supplier;
 import java.util.regex.Pattern;
 
 /**
@@ -58,12 +61,19 @@ public interface ZPath
      */
     static ZPath from(String... names)
     {
-        ZPath path = root();
-        for ( String n : names )
-        {
-            path = path.at(n);
-        }
-        return path;
+        return ZPathImpl.from(names);
+    }
+
+    /**
+     * Convert individual path names into a ZPath
+     *
+     * @param names path names
+     * @return ZPath
+     * @throws IllegalArgumentException if any of the names is invalid
+     */
+    static ZPath from(List<String> names)
+    {
+        return ZPathImpl.from(names);
     }
 
     /**
@@ -85,7 +95,33 @@ public interface ZPath
      *                   parameter nodes in the path
      * @return new resolved ZPath
      */
-    ZPath resolved(Object... parameters);
+    default ZPath resolved(Object... parameters)
+    {
+        return resolved(Arrays.asList(parameters));
+    }
+
+    /**
+     * 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(List<Object> parameters);
+
+    /**
+     * An "auto" resolving version of this ZPath. i.e. if any of the path 
names is
+     * the {@link #parameterNodeName()} the ZPath must be resolved. This method
+     * creates a new ZPath that auto resolves by using the given parameter 
suppliers
+     * whenever needed.
+     *
+     * @param parameterSuppliers parameter suppliers
+     * @return new auto resolving ZNode
+     * @see #resolved(Object...)
+     * @see #parameterNodeName()
+     */
+    ZPath resolving(List<Supplier<Object>> parameterSuppliers);
 
     /**
      * Return a ZPath that represents a child ZNode of this ZPath. e.g.

http://git-wip-us.apache.org/repos/asf/curator/blob/52b334c3/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 be03963..e728537 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
@@ -21,24 +21,28 @@ 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;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Objects;
+import java.util.function.Supplier;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 public class ZPathImpl implements ZPath
 {
-    public static final ZPath root = new 
ZPathImpl(Collections.singletonList(ZKPaths.PATH_SEPARATOR), null);
+    public static final ZPath root = new 
ZPathImpl(Collections.singletonList(ZKPaths.PATH_SEPARATOR), null, 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;
+    private final List<Supplier<Object>> parameterSuppliers;
 
     public static ZPath parse(String fullPath)
     {
@@ -47,20 +51,36 @@ public class ZPathImpl implements ZPath
             
.addAll(Splitter.on(ZKPaths.PATH_SEPARATOR).omitEmptyStrings().splitToList(fullPath))
             .build();
         nodes.forEach(ZPathImpl::validate);
-        return new ZPathImpl(nodes, null);
+        return new ZPathImpl(nodes, null, null);
+    }
+
+    public static ZPath from(String[] names)
+    {
+        return from(Arrays.asList(names));
+    }
+
+    public static ZPath from(List<String> names)
+    {
+        names = Objects.requireNonNull(names, "names cannot be null");
+        names.forEach(ZPathImpl::validate);
+        List<String> nodes = ImmutableList.<String>builder()
+            .add(ZKPaths.PATH_SEPARATOR)
+            .addAll(names)
+            .build();
+        return new ZPathImpl(nodes, null, null);
     }
 
     @Override
     public ZPath at(String child)
     {
-        return new ZPathImpl(nodes, child);
+        return new ZPathImpl(nodes, child, parameterSuppliers);
     }
 
     @Override
     public ZPath parent()
     {
         checkRootAccess();
-        return new ZPathImpl(nodes.subList(0, nodes.size() - 1), null);
+        return new ZPathImpl(nodes.subList(0, nodes.size() - 1), null, 
parameterSuppliers);
     }
 
     @Override
@@ -93,7 +113,6 @@ public class ZPathImpl implements ZPath
     @Override
     public String nodeName()
     {
-        checkResolved();
         return nodes.get(nodes.size() - 1);
     }
 
@@ -127,31 +146,35 @@ public class ZPathImpl implements ZPath
     }
 
     @Override
-    public ZPath resolved(Object... parameters)
+    public ZPath resolved(List<Object> parameters)
     {
-        List<String> nodeNames = Lists.newArrayList();
-        int parameterIndex = 0;
-        for ( int i = 0; i < nodes.size(); ++i )
-        {
-            String name = nodes.get(i);
-            if ( name.equals(parameter) )
-            {
-                if ( parameterIndex >= parameters.length )
+        Iterator<Object> iterator = parameters.iterator();
+        List<String> nodeNames = nodes.stream()
+            .map(name -> {
+                if ( name.equals(parameter) )
                 {
-                    throw new IllegalStateException(String.format("Parameter 
missing at index [%d] for [%s]", parameterIndex, nodes.toString()));
+                    if ( !iterator.hasNext() )
+                    {
+                        throw new 
IllegalStateException(String.format("Parameter missing for [%s]", 
nodes.toString()));
+                    }
+                    return iterator.next().toString();
                 }
-                nodeNames.add(parameters[parameterIndex++].toString());
-            }
-            else
-            {
-                nodeNames.add(name);
-            }
-        }
-        return new ZPathImpl(nodeNames, null);
+                return name;
+            })
+            .collect(Collectors.toList());
+        return new ZPathImpl(nodeNames, null, parameterSuppliers);
     }
 
-    private ZPathImpl(List<String> nodes, String child)
+    @Override
+    public ZPath resolving(List<Supplier<Object>> parameterSuppliers)
     {
+        parameterSuppliers = Objects.requireNonNull(parameterSuppliers, 
"parameterSuppliers cannot be null");
+        return new ZPathImpl(nodes, null, parameterSuppliers);
+    }
+
+    private ZPathImpl(List<String> nodes, String child, List<Supplier<Object>> 
parameterSuppliers)
+    {
+        this.parameterSuppliers = parameterSuppliers;
         ImmutableList.Builder<String> builder = 
ImmutableList.<String>builder().addAll(nodes);
         if ( child != null )
         {
@@ -159,7 +182,7 @@ public class ZPathImpl implements ZPath
             builder.add(child);
         }
         this.nodes = builder.build();
-        isResolved = !this.nodes.contains(parameter);
+        isResolved = (parameterSuppliers != null) || 
!this.nodes.contains(parameter);
     }
 
     private void checkRootAccess()
@@ -180,6 +203,7 @@ public class ZPathImpl implements ZPath
         boolean addSeparator = false;
         StringBuilder str = new StringBuilder();
         int size = parent ? (nodes.size() - 1) : nodes.size();
+        int parameterIndex = 0;
         for ( int i = 0; i < size; ++i )
         {
             if ( i > 1 )
@@ -187,7 +211,15 @@ public class ZPathImpl implements ZPath
                 str.append(ZKPaths.PATH_SEPARATOR);
             }
             String value = nodes.get(i);
-            str.append(value.equals(parameter) ? ".*" : value);
+            if ( value.equals(parameter) )
+            {
+                if ( (parameterSuppliers == null) || 
(parameterSuppliers.size() <= parameterIndex) )
+                {
+                    throw new IllegalStateException(String.format("Parameter 
supplier missing at index [%d] for [%s]", parameterIndex, nodes.toString()));
+                }
+                value = 
parameterSuppliers.get(parameterIndex++).get().toString();
+            }
+            str.append(value);
         }
         return str.toString();
     }

http://git-wip-us.apache.org/repos/asf/curator/blob/52b334c3/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/TestZPath.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/TestZPath.java
 
b/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/TestZPath.java
index 2ca38ca..8397ef5 100644
--- 
a/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/TestZPath.java
+++ 
b/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/TestZPath.java
@@ -22,6 +22,8 @@ import org.apache.curator.utils.ZKPaths;
 import org.apache.curator.x.async.modeled.details.ZPathImpl;
 import org.testng.Assert;
 import org.testng.annotations.Test;
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicInteger;
 
 public class TestZPath
 {
@@ -68,4 +70,15 @@ public class TestZPath
         ZPath path = ZPath.from("one", ZPath.parameterNodeName(), "two", 
ZPath.parameterNodeName());
         Assert.assertEquals(path.resolved("a", "b"), ZPath.from("one", "a", 
"two", "b"));
     }
+
+    @Test
+    public void testResolving()
+    {
+        ZPath path = ZPath.from("one", ZPath.parameterNodeName(), "two", 
ZPath.parameterNodeName());
+        AtomicInteger count = new AtomicInteger(0);
+        ZPath resolving = path.resolving(Arrays.asList(() -> "x" + 
count.get(), () -> "y" + count.get()));
+        Assert.assertEquals(resolving.fullPath(), "/one/x0/two/y0");
+        count.incrementAndGet();
+        Assert.assertEquals(resolving.fullPath(), "/one/x1/two/y1");
+    }
 }

Reply via email to