Repository: curator
Updated Branches:
  refs/heads/CURATOR-397 0f0db1c38 -> 4efc38f3d


wip on wrapping caches


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

Branch: refs/heads/CURATOR-397
Commit: 4efc38f3d16d111c3a96c4eb28212b2cc8a08188
Parents: 0f0db1c
Author: randgalt <randg...@apache.org>
Authored: Sat Apr 8 21:36:07 2017 -0500
Committer: randgalt <randg...@apache.org>
Committed: Sat Apr 8 21:36:07 2017 -0500

----------------------------------------------------------------------
 .../recipes/cache/PathChildrenCache.java        |   2 +-
 curator-x-async/pom.xml                         |   6 +
 .../x/async/modeled/JacksonModelSerializer.java |   2 +-
 .../modeled/ModeledAsyncCuratorFramework.java   |   7 +-
 .../curator/x/async/modeled/ModeledDetails.java |  46 ++++
 .../apache/curator/x/async/modeled/ZPath.java   |  18 ++
 .../ModeledAsyncCuratorFrameworkImpl.java       |  28 ++-
 .../x/async/modeled/details/ZPathImpl.java      |  18 ++
 .../details/recipes/ModeledNodeCacheImpl.java   | 117 ++++++++++
 .../recipes/ModeledPathChildrenCacheImpl.java   | 233 +++++++++++++++++++
 .../modeled/recipes/ModeledCachedNode.java      | 104 +++++++++
 .../async/modeled/recipes/ModeledNodeCache.java |  47 ++++
 .../recipes/ModeledPathChildrenCache.java       |  82 +++++++
 .../recipes/ModeledPathChildrenCacheEvent.java  |  28 +++
 .../ModeledPathChildrenCacheListener.java       |  24 ++
 .../curator/x/async/modeled/TestZPath.java      |  18 ++
 16 files changed, 775 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/4efc38f3/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/PathChildrenCache.java
----------------------------------------------------------------------
diff --git 
a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/PathChildrenCache.java
 
b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/PathChildrenCache.java
index d11ced6..c5449f2 100644
--- 
a/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/PathChildrenCache.java
+++ 
b/curator-recipes/src/main/java/org/apache/curator/framework/recipes/cache/PathChildrenCache.java
@@ -133,7 +133,7 @@ public class PathChildrenCache implements Closeable
             handleStateChange(newState);
         }
     };
-    private static final ThreadFactory defaultThreadFactory = 
ThreadUtils.newThreadFactory("PathChildrenCache");
+    public static final ThreadFactory defaultThreadFactory = 
ThreadUtils.newThreadFactory("PathChildrenCache");
 
     /**
      * @param client the client

http://git-wip-us.apache.org/repos/asf/curator/blob/4efc38f3/curator-x-async/pom.xml
----------------------------------------------------------------------
diff --git a/curator-x-async/pom.xml b/curator-x-async/pom.xml
index fa73942..4d645db 100644
--- a/curator-x-async/pom.xml
+++ b/curator-x-async/pom.xml
@@ -20,6 +20,12 @@
         </dependency>
 
         <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-recipes</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-databind</artifactId>
             <scope>provided</scope>

http://git-wip-us.apache.org/repos/asf/curator/blob/4efc38f3/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/JacksonModelSerializer.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/JacksonModelSerializer.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/JacksonModelSerializer.java
index 90b120a..429fea7 100644
--- 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/JacksonModelSerializer.java
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/JacksonModelSerializer.java
@@ -32,7 +32,7 @@ import java.util.Arrays;
  * Model serializer that uses Jackson for JSON serialization. 
<strong>IMPORTANT: </strong>
  * the jackson dependency is specified as <code>provided</code> in the 
curator-x-async Maven POM
  * file to avoid adding a new dependency to Curator. Therefore, if you wish to 
use the
- * JacksonModelSerializer you must manually add the dependency to your build 
system.
+ * JacksonModelSerializer you must manually add the dependency to your build 
syste
  */
 public class JacksonModelSerializer<T> implements ModelSerializer<T>
 {

http://git-wip-us.apache.org/repos/asf/curator/blob/4efc38f3/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledAsyncCuratorFramework.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledAsyncCuratorFramework.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledAsyncCuratorFramework.java
index 17c6c8e..d13de24 100644
--- 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledAsyncCuratorFramework.java
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledAsyncCuratorFramework.java
@@ -24,11 +24,12 @@ import org.apache.curator.x.async.AsyncStage;
 import org.apache.curator.x.async.api.CreateOption;
 import org.apache.curator.x.async.api.DeleteOption;
 import org.apache.zookeeper.data.Stat;
+import java.util.Set;
 
 public interface ModeledAsyncCuratorFramework<T>
 {
-    ImmutableSet<CreateOption> defaultCreateOptions = 
ImmutableSet.of(CreateOption.createParentsAsContainers, 
CreateOption.setDataIfExists);
-    ImmutableSet<DeleteOption> defaultDeleteOptions = 
ImmutableSet.of(DeleteOption.guaranteed);
+    Set<CreateOption> defaultCreateOptions = 
ImmutableSet.of(CreateOption.createParentsAsContainers, 
CreateOption.setDataIfExists);
+    Set<DeleteOption> defaultDeleteOptions = 
ImmutableSet.of(DeleteOption.guaranteed);
 
     /**
      * Return a new ModeledAsyncCuratorFramework for the given path and 
serializer. The returned ModeledAsyncCuratorFramework
@@ -69,6 +70,8 @@ public interface ModeledAsyncCuratorFramework<T>
      */
     CuratorFramework unwrap();
 
+    ModeledDetails<T> getDetails();
+
     /**
      * Return a new Modeled Curator instance with all the same options but 
applying to the given child node of this Modeled Curator's
      * path. E.g. if this Modeled Curator instance applies to "/a/b", calling 
<code>modeled.at("c")</code> returns an instance that applies to

http://git-wip-us.apache.org/repos/asf/curator/blob/4efc38f3/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledDetails.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledDetails.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledDetails.java
new file mode 100644
index 0000000..65afc94
--- /dev/null
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledDetails.java
@@ -0,0 +1,46 @@
+/**
+ * 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.curator.x.async.modeled;
+
+import org.apache.curator.x.async.api.CreateOption;
+import java.util.Set;
+
+public interface ModeledDetails<T>
+{
+    /**
+     * Return the create options set for this instance
+     *
+     * @return options
+     */
+    Set<CreateOption> getCreateOptions();
+
+    /**
+     * Return the serializer for this instance
+     *
+     * @return serializer
+     */
+    ModelSerializer<T> getSerializer();
+
+    /**
+     * Return the path for this instance
+     *
+     * @return path
+     */
+    ZPath getPath();
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4efc38f3/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 05d012a..3e0dc2d 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
@@ -1,3 +1,21 @@
+/**
+ * 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.curator.x.async.modeled;
 
 import org.apache.curator.x.async.modeled.details.ZPathImpl;

http://git-wip-us.apache.org/repos/asf/curator/blob/4efc38f3/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/ModeledAsyncCuratorFrameworkImpl.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/ModeledAsyncCuratorFrameworkImpl.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/ModeledAsyncCuratorFrameworkImpl.java
index 40a3be8..1754f03 100644
--- 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/ModeledAsyncCuratorFrameworkImpl.java
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/ModeledAsyncCuratorFrameworkImpl.java
@@ -34,6 +34,8 @@ import org.apache.curator.x.async.api.DeleteOption;
 import org.apache.curator.x.async.api.WatchableAsyncCuratorFramework;
 import org.apache.curator.x.async.modeled.ModelSerializer;
 import org.apache.curator.x.async.modeled.ModeledAsyncCuratorFramework;
+import org.apache.curator.x.async.modeled.ModeledDetails;
+import org.apache.curator.x.async.modeled.ZPath;
 import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.data.ACL;
@@ -45,7 +47,7 @@ import java.util.Set;
 import java.util.concurrent.CompletionStage;
 import java.util.function.UnaryOperator;
 
-public class ModeledAsyncCuratorFrameworkImpl<T> implements 
ModeledAsyncCuratorFramework<T>
+public class ModeledAsyncCuratorFrameworkImpl<T> implements 
ModeledAsyncCuratorFramework<T>, ModeledDetails<T>
 {
     private final AsyncCuratorFramework client;
     private final WatchableAsyncCuratorFramework watchableClient;
@@ -82,6 +84,30 @@ public class ModeledAsyncCuratorFrameworkImpl<T> implements 
ModeledAsyncCuratorF
     }
 
     @Override
+    public ModeledDetails<T> getDetails()
+    {
+        return this;
+    }
+
+    @Override
+    public Set<CreateOption> getCreateOptions()
+    {
+        return createOptions;
+    }
+
+    @Override
+    public ModelSerializer<T> getSerializer()
+    {
+        return serializer;
+    }
+
+    @Override
+    public ZPath getPath()
+    {
+        return ZPath.parse(path);
+    }
+
+    @Override
     public CuratorFramework unwrap()
     {
         return client.unwrap();

http://git-wip-us.apache.org/repos/asf/curator/blob/4efc38f3/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 06a15ad..35cae3c 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
@@ -1,3 +1,21 @@
+/**
+ * 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.curator.x.async.modeled.details;
 
 import com.google.common.base.Splitter;

http://git-wip-us.apache.org/repos/asf/curator/blob/4efc38f3/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/recipes/ModeledNodeCacheImpl.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/recipes/ModeledNodeCacheImpl.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/recipes/ModeledNodeCacheImpl.java
new file mode 100644
index 0000000..f704f77
--- /dev/null
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/recipes/ModeledNodeCacheImpl.java
@@ -0,0 +1,117 @@
+/**
+ * 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.curator.x.async.modeled.details.recipes;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.listen.Listenable;
+import org.apache.curator.framework.recipes.cache.ChildData;
+import org.apache.curator.framework.recipes.cache.NodeCache;
+import org.apache.curator.framework.recipes.cache.NodeCacheListener;
+import org.apache.curator.utils.CloseableUtils;
+import org.apache.curator.x.async.api.CreateOption;
+import org.apache.curator.x.async.modeled.ModeledDetails;
+import org.apache.curator.x.async.modeled.recipes.ModeledCachedNode;
+import org.apache.curator.x.async.modeled.recipes.ModeledNodeCache;
+import org.apache.zookeeper.data.Stat;
+import java.util.Objects;
+import java.util.Optional;
+
+public class ModeledNodeCacheImpl<T> implements ModeledNodeCache<T>
+{
+    private final NodeCache cache;
+    private final ModeledDetails<T> modeled;
+
+    public ModeledNodeCacheImpl(CuratorFramework client, ModeledDetails<T> 
modeled)
+    {
+        this.modeled = Objects.requireNonNull(modeled, "modeled cannot be 
null");
+        cache = new NodeCache(client, modeled.getPath().fullPath(), 
modeled.getCreateOptions().contains(CreateOption.compress));
+    }
+
+    @Override
+    public void start()
+    {
+        try
+        {
+            cache.start();
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException("Could not start", e);
+        }
+    }
+
+    @Override
+    public void start(boolean buildInitial)
+    {
+        try
+        {
+            cache.start(buildInitial);
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException("Could not start", e);
+        }
+    }
+
+    @Override
+    public void rebuild()
+    {
+        try
+        {
+            cache.rebuild();
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException("Could not rebuild", e);
+        }
+    }
+
+    @Override
+    public Listenable<NodeCacheListener> getListenable()
+    {
+        return cache.getListenable();
+    }
+
+    @Override
+    public Optional<ModeledCachedNode<T>> getCurrentData()
+    {
+        ChildData currentData = cache.getCurrentData();
+        if ( currentData == null )
+        {
+            return Optional.empty();
+        }
+        byte[] data = currentData.getData();
+        Stat stat = currentData.getStat();
+        if ( stat == null )
+        {
+            stat = new Stat();
+        }
+        if ( (data == null) || (data.length == 0) )
+        {
+            return Optional.of(new ModeledCachedNode<T>(modeled.getPath(), 
null, stat));
+        }
+        return Optional.of(new ModeledCachedNode<>(modeled.getPath(), 
modeled.getSerializer().deserialize(data), stat));
+    }
+
+    @Override
+    public void close()
+    {
+        CloseableUtils.closeQuietly(cache);
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4efc38f3/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/recipes/ModeledPathChildrenCacheImpl.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/recipes/ModeledPathChildrenCacheImpl.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/recipes/ModeledPathChildrenCacheImpl.java
new file mode 100644
index 0000000..5a5bdda
--- /dev/null
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/recipes/ModeledPathChildrenCacheImpl.java
@@ -0,0 +1,233 @@
+/**
+ * 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.curator.x.async.modeled.details.recipes;
+
+import com.google.common.util.concurrent.MoreExecutors;
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.listen.Listenable;
+import org.apache.curator.framework.recipes.cache.ChildData;
+import org.apache.curator.framework.recipes.cache.PathChildrenCache;
+import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
+import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
+import org.apache.curator.utils.CloseableExecutorService;
+import org.apache.curator.utils.CloseableUtils;
+import org.apache.curator.x.async.api.CreateOption;
+import org.apache.curator.x.async.modeled.ModeledDetails;
+import org.apache.curator.x.async.modeled.ZPath;
+import org.apache.curator.x.async.modeled.recipes.ModeledCachedNode;
+import org.apache.curator.x.async.modeled.recipes.ModeledPathChildrenCache;
+import 
org.apache.curator.x.async.modeled.recipes.ModeledPathChildrenCacheEvent;
+import 
org.apache.curator.x.async.modeled.recipes.ModeledPathChildrenCacheListener;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.stream.Collectors;
+
+public class ModeledPathChildrenCacheImpl<T> implements 
ModeledPathChildrenCache<T>
+{
+    private final ModeledDetails<T> modeled;
+    private final PathChildrenCache cache;
+    private final Map<ModeledPathChildrenCacheListener, 
PathChildrenCacheListener> listenerMap = new ConcurrentHashMap<>();
+
+    public ModeledPathChildrenCacheImpl(CuratorFramework client, 
ModeledDetails<T> modeled, boolean cacheData, ThreadFactory threadFactory, 
ExecutorService executorService, CloseableExecutorService 
closeableExecutorService)
+    {
+        this.modeled = modeled;
+        PathChildrenCache localCache;
+        if ( threadFactory != null )
+        {
+            localCache = new PathChildrenCache(client, 
modeled.getPath().fullPath(), cacheData, 
modeled.getCreateOptions().contains(CreateOption.compress), threadFactory);
+        }
+        else if ( executorService != null )
+        {
+            localCache = new PathChildrenCache(client, 
modeled.getPath().fullPath(), cacheData, 
modeled.getCreateOptions().contains(CreateOption.compress), executorService);
+        }
+        else if ( closeableExecutorService != null )
+        {
+            localCache = new PathChildrenCache(client, 
modeled.getPath().fullPath(), cacheData, 
modeled.getCreateOptions().contains(CreateOption.compress), 
closeableExecutorService);
+        }
+        else
+        {
+            localCache = new PathChildrenCache(client, 
modeled.getPath().fullPath(), cacheData, 
modeled.getCreateOptions().contains(CreateOption.compress), 
PathChildrenCache.defaultThreadFactory);
+        }
+        cache = localCache;
+    }
+
+    @Override
+    public void start()
+    {
+        try
+        {
+            cache.start();
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException("can't start cache", e);
+        }
+    }
+
+    @Override
+    public void start(PathChildrenCache.StartMode mode)
+    {
+        try
+        {
+            cache.start(mode);
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException("can't start cache", e);
+        }
+    }
+
+    @Override
+    public void rebuild()
+    {
+        try
+        {
+            cache.rebuild();
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException("can't rebuild cache", e);
+        }
+    }
+
+    @Override
+    public void rebuildNode(String fullPath)
+    {
+        try
+        {
+            cache.rebuildNode(fullPath);
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException("can't rebuild cache at " + fullPath, 
e);
+        }
+    }
+
+    @Override
+    public Listenable<ModeledPathChildrenCacheListener> getListenable()
+    {
+        return new Listenable<ModeledPathChildrenCacheListener>()
+        {
+            @Override
+            public void addListener(ModeledPathChildrenCacheListener listener)
+            {
+                addListener(listener, MoreExecutors.sameThreadExecutor());
+            }
+
+            @Override
+            public void addListener(ModeledPathChildrenCacheListener listener, 
Executor executor)
+            {
+                PathChildrenCacheListener pathChildrenCacheListener = (client, 
event) -> {
+                    ModeledPathChildrenCacheEvent modeledEvent = new 
ModeledPathChildrenCacheEvent()
+                    {
+                        @Override
+                        public PathChildrenCacheEvent.Type getType()
+                        {
+                            return event.getType();
+                        }
+
+                        @Override
+                        public ModeledCachedNode getNode()
+                        {
+                            return from(event.getData());
+                        }
+                    };
+                    listener.event(modeledEvent);
+                };
+                listenerMap.put(listener, pathChildrenCacheListener);
+                cache.getListenable().addListener(pathChildrenCacheListener);
+            }
+
+            @Override
+            public void removeListener(ModeledPathChildrenCacheListener 
listener)
+            {
+                PathChildrenCacheListener pathChildrenCacheListener = 
listenerMap.remove(listener);
+                if ( pathChildrenCacheListener != null )
+                {
+                    
cache.getListenable().removeListener(pathChildrenCacheListener);
+                }
+            }
+        };
+    }
+
+    @Override
+    public List<ModeledCachedNode> getCurrentData()
+    {
+        return cache.getCurrentData().stream()
+            .map(this::from)
+            .collect(Collectors.toList());
+    }
+
+    private ModeledCachedNode<T> from(ChildData data)
+    {
+        if ( data == null )
+        {
+            return null;
+        }
+        T model = (data.getData() != null) ? 
modeled.getSerializer().deserialize(data.getData()) : null;
+        return new ModeledCachedNode<>(ZPath.parse(data.getPath()), model, 
data.getStat());
+    }
+
+    @Override
+    public ModeledCachedNode getCurrentData(String fullPath)
+    {
+        return from(cache.getCurrentData(fullPath));
+    }
+
+    @Override
+    public void clearDataBytes(String fullPath)
+    {
+        cache.clearDataBytes(fullPath);
+    }
+
+    @Override
+    public boolean clearDataBytes(String fullPath, int ifVersion)
+    {
+        return cache.clearDataBytes(fullPath, ifVersion);
+    }
+
+    @Override
+    public void clearAndRefresh()
+    {
+        try
+        {
+            cache.clearAndRefresh();
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException("could not clear and refresh", e);
+        }
+    }
+
+    @Override
+    public void clear()
+    {
+        cache.clear();
+    }
+
+    @Override
+    public void close()
+    {
+        CloseableUtils.closeQuietly(cache);
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4efc38f3/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledCachedNode.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledCachedNode.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledCachedNode.java
new file mode 100644
index 0000000..8982396
--- /dev/null
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledCachedNode.java
@@ -0,0 +1,104 @@
+/**
+ * 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.curator.x.async.modeled.recipes;
+
+import org.apache.curator.x.async.modeled.ZPath;
+import org.apache.zookeeper.data.Stat;
+import java.util.Objects;
+import java.util.Optional;
+
+public class ModeledCachedNode<T>
+{
+    private final ZPath path;
+    private final Stat stat;
+    private final Optional<T> data;
+
+    public ModeledCachedNode(ZPath path)
+    {
+        this(path, null, new Stat());
+    }
+
+    public ModeledCachedNode(ZPath path, T data)
+    {
+        this(path, data, new Stat());
+    }
+
+    public ModeledCachedNode(ZPath path, T data, Stat stat)
+    {
+        this.path = Objects.requireNonNull(path, "path cannot be null");
+        this.data = Optional.ofNullable(data);
+        this.stat = Objects.requireNonNull(stat, "stat cannot be null");
+    }
+
+    public ZPath getPath()
+    {
+        return path;
+    }
+
+    public Stat getStat()
+    {
+        return stat;
+    }
+
+    public Optional<T> getData()
+    {
+        return data;
+    }
+
+    @Override
+    public boolean equals(Object o)
+    {
+        if ( this == o )
+        {
+            return true;
+        }
+        if ( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        ModeledCachedNode<?> that = (ModeledCachedNode<?>)o;
+
+        if ( !path.equals(that.path) )
+        {
+            return false;
+        }
+        //noinspection SimplifiableIfStatement
+        if ( !stat.equals(that.stat) )
+        {
+            return false;
+        }
+        return data.equals(that.data);
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int result = path.hashCode();
+        result = 31 * result + stat.hashCode();
+        result = 31 * result + data.hashCode();
+        return result;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "ModeledCachedNode{" + "stat=" + stat + ", data=" + data + '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4efc38f3/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledNodeCache.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledNodeCache.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledNodeCache.java
new file mode 100644
index 0000000..6da08c7
--- /dev/null
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledNodeCache.java
@@ -0,0 +1,47 @@
+/**
+ * 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.curator.x.async.modeled.recipes;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.listen.Listenable;
+import org.apache.curator.framework.recipes.cache.NodeCacheListener;
+import org.apache.curator.x.async.modeled.ModeledDetails;
+import org.apache.curator.x.async.modeled.details.recipes.ModeledNodeCacheImpl;
+import java.io.Closeable;
+import java.util.Optional;
+
+public interface ModeledNodeCache<T> extends Closeable
+{
+    static <T> ModeledNodeCache build(CuratorFramework client, 
ModeledDetails<T> modeled)
+    {
+        return new ModeledNodeCacheImpl<>(client, modeled);
+    }
+
+    void start();
+
+    void start(boolean buildInitial);
+
+    void rebuild();
+
+    Listenable<NodeCacheListener> getListenable();
+
+    Optional<ModeledCachedNode<T>> getCurrentData();
+
+    void close();
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4efc38f3/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledPathChildrenCache.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledPathChildrenCache.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledPathChildrenCache.java
new file mode 100644
index 0000000..06fa345
--- /dev/null
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledPathChildrenCache.java
@@ -0,0 +1,82 @@
+/**
+ * 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.curator.x.async.modeled.recipes;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.listen.Listenable;
+import org.apache.curator.framework.recipes.cache.PathChildrenCache;
+import org.apache.curator.utils.CloseableExecutorService;
+import org.apache.curator.x.async.modeled.ModeledDetails;
+import 
org.apache.curator.x.async.modeled.details.recipes.ModeledPathChildrenCacheImpl;
+import java.io.Closeable;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadFactory;
+
+public interface ModeledPathChildrenCache<T> extends Closeable
+{
+    static <T> ModeledPathChildrenCache<T> build(CuratorFramework client, 
ModeledDetails<T> modeled)
+    {
+        return new ModeledPathChildrenCacheImpl<>(client, modeled, true, null, 
null, null);
+    }
+
+    static <T> ModeledPathChildrenCache<T> build(CuratorFramework client, 
ModeledDetails<T> modeled, boolean cacheData)
+    {
+        return new ModeledPathChildrenCacheImpl<>(client, modeled, cacheData, 
null, null, null);
+    }
+
+    static <T> ModeledPathChildrenCache<T> build(CuratorFramework client, 
ModeledDetails<T> modeled, boolean cacheData, ThreadFactory threadFactory)
+    {
+        return new ModeledPathChildrenCacheImpl<>(client, modeled, cacheData, 
threadFactory, null, null);
+    }
+
+    static <T> ModeledPathChildrenCache<T> build(CuratorFramework client, 
ModeledDetails<T> modeled, boolean cacheData, ExecutorService executorService)
+    {
+        return new ModeledPathChildrenCacheImpl<>(client, modeled, cacheData, 
null, executorService, null);
+    }
+
+    static <T> ModeledPathChildrenCache<T> build(CuratorFramework client, 
ModeledDetails<T> modeled, boolean cacheData, CloseableExecutorService 
executorService)
+    {
+        return new ModeledPathChildrenCacheImpl<>(client, modeled, cacheData, 
null, null, executorService);
+    }
+
+    void start();
+
+    void start(PathChildrenCache.StartMode mode);
+
+    void rebuild();
+
+    void rebuildNode(String fullPath);
+
+    Listenable<ModeledPathChildrenCacheListener> getListenable();
+
+    List<ModeledCachedNode> getCurrentData();
+
+    ModeledCachedNode getCurrentData(String fullPath);
+
+    void clearDataBytes(String fullPath);
+
+    boolean clearDataBytes(String fullPath, int ifVersion);
+
+    void clearAndRefresh();
+
+    void clear();
+
+    void close();
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4efc38f3/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledPathChildrenCacheEvent.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledPathChildrenCacheEvent.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledPathChildrenCacheEvent.java
new file mode 100644
index 0000000..d2a9d71
--- /dev/null
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledPathChildrenCacheEvent.java
@@ -0,0 +1,28 @@
+/**
+ * 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.curator.x.async.modeled.recipes;
+
+import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
+
+public interface ModeledPathChildrenCacheEvent<T>
+{
+    PathChildrenCacheEvent.Type getType();
+
+    ModeledCachedNode<T> getNode();
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4efc38f3/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledPathChildrenCacheListener.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledPathChildrenCacheListener.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledPathChildrenCacheListener.java
new file mode 100644
index 0000000..9379961
--- /dev/null
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/recipes/ModeledPathChildrenCacheListener.java
@@ -0,0 +1,24 @@
+/**
+ * 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.curator.x.async.modeled.recipes;
+
+public interface ModeledPathChildrenCacheListener
+{
+    void event(ModeledPathChildrenCacheEvent event);
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/4efc38f3/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 9e7a718..f3c3dff 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
@@ -1,3 +1,21 @@
+/**
+ * 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.curator.x.async.modeled;
 
 import org.apache.curator.utils.ZKPaths;

Reply via email to