Repository: curator
Updated Branches:
  refs/heads/CURATOR-397 3184b8f1d -> 3a3e6dd2d (forced update)


Created/abstracted CuratorModelSpec so that models can be specified 
independently of a CuratorFramework instance, etc. i.e. they can all be created 
at startup. The CuratorModelSpec also can generate a Schema object


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

Branch: refs/heads/CURATOR-397
Commit: 3a3e6dd2d90fd2cf70507f247d1dcc1e59204721
Parents: 63225ba
Author: randgalt <randg...@apache.org>
Authored: Tue Apr 25 13:30:11 2017 -0500
Committer: randgalt <randg...@apache.org>
Committed: Tue Apr 25 13:30:39 2017 -0500

----------------------------------------------------------------------
 .../java/modeled/ModeledCuratorExamples.java    |   6 +-
 .../x/async/modeled/CuratorModelSpec.java       | 110 ++++++++++
 .../async/modeled/CuratorModelSpecBuilder.java  | 104 ++++++++++
 .../x/async/modeled/ModelSerializer.java        |   1 +
 .../async/modeled/ModeledCuratorFramework.java  |  32 +--
 .../modeled/ModeledCuratorFrameworkBuilder.java |  74 +------
 .../x/async/modeled/caching/Caching.java        |  18 ++
 .../x/async/modeled/caching/CachingOption.java  |  18 ++
 .../x/async/modeled/details/CachingImpl.java    |  18 ++
 .../modeled/details/CuratorModelSpecImpl.java   | 203 +++++++++++++++++++
 .../details/ModeledCuratorFrameworkImpl.java    |  81 +++-----
 .../modeled/TestModeledCuratorFramework.java    |  15 +-
 .../TestCachedModeledCuratorFramework.java      |   3 +-
 .../x/async/modeled/models/TestSimpleModel.java |  18 ++
 .../modeled/recipes/TestModeledCaches.java      |   3 +-
 15 files changed, 549 insertions(+), 155 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/curator/blob/3a3e6dd2/curator-examples/src/main/java/modeled/ModeledCuratorExamples.java
----------------------------------------------------------------------
diff --git a/curator-examples/src/main/java/modeled/ModeledCuratorExamples.java 
b/curator-examples/src/main/java/modeled/ModeledCuratorExamples.java
index 81eead8..6fc530f 100644
--- a/curator-examples/src/main/java/modeled/ModeledCuratorExamples.java
+++ b/curator-examples/src/main/java/modeled/ModeledCuratorExamples.java
@@ -19,6 +19,7 @@
 package modeled;
 
 import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.x.async.modeled.CuratorModelSpec;
 import org.apache.curator.x.async.modeled.JacksonModelSerializer;
 import org.apache.curator.x.async.modeled.ModeledCuratorFramework;
 import org.apache.curator.x.async.modeled.ZPath;
@@ -30,10 +31,13 @@ public class ModeledCuratorExamples
     {
         JacksonModelSerializer<PersonModel> serializer = 
JacksonModelSerializer.build(PersonModel.class);
 
+        // build a model specification - you can pre-build all the model 
specifications for your app at startup
+        CuratorModelSpec<PersonModel> modelSpec = 
CuratorModelSpec.builder(ZPath.parse("/example/path"), serializer).build();
+
         // wrap a CuratorFramework instance so that it can be used "modeled".
         // do this once and re-use the returned ModeledCuratorFramework 
instance.
         // ModeledCuratorFramework instances are tied to a given path
-        return ModeledCuratorFramework.wrap(client, 
ZPath.parse("/example/path"), serializer);
+        return ModeledCuratorFramework.wrap(client, modelSpec);
     }
 
     public static void createOrUpdate(ModeledCuratorFramework<PersonModel> 
modeled, PersonModel model)

http://git-wip-us.apache.org/repos/asf/curator/blob/3a3e6dd2/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
new file mode 100644
index 0000000..0843e47
--- /dev/null
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/CuratorModelSpec.java
@@ -0,0 +1,110 @@
+/**
+ * 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 com.google.common.collect.ImmutableSet;
+import org.apache.curator.framework.schema.Schema;
+import org.apache.curator.x.async.api.CreateOption;
+import org.apache.curator.x.async.api.DeleteOption;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.data.ACL;
+import java.util.List;
+import java.util.Set;
+
+public interface CuratorModelSpec<T>
+{
+    Set<CreateOption> defaultCreateOptions = 
ImmutableSet.of(CreateOption.createParentsAsContainers, 
CreateOption.setDataIfExists);
+    Set<DeleteOption> defaultDeleteOptions = 
ImmutableSet.of(DeleteOption.guaranteed);
+
+    /**
+     * Start a new CuratorModelBuilder for the given path and serializer. The 
returned CuratorModelBuilder
+     * uses {@link #defaultCreateOptions} and {@link #defaultDeleteOptions}, 
but you can change these
+     * with builder methods.
+     *
+     * @param path path to model
+     * @param serializer the model's serializer
+     * @return builder
+     */
+    static <T> CuratorModelSpecBuilder<T> builder(ZPath path, 
ModelSerializer<T> serializer)
+    {
+        return new CuratorModelSpecBuilder<>(path, serializer)
+            .withCreateOptions(defaultCreateOptions)
+            .withDeleteOptions(defaultDeleteOptions);
+    }
+
+    /**
+     * Return a new CuratorModel instance with all the same options but 
applying to the given child node of this CuratorModel's
+     * path. E.g. if this CuratorModel instance applies to "/a/b", calling 
<code>modeled.at("c")</code> returns an instance that applies to
+     * "/a/b/c".
+     *
+     * @param child child node.
+     * @return new Modeled Curator instance
+     */
+    CuratorModelSpec<T> at(String child);
+
+    /**
+     * Return the model's path
+     *
+     * @return path
+     */
+    ZPath path();
+
+    /**
+     * Return the model's serializer
+     *
+     * @return serializer
+     */
+    ModelSerializer<T> serializer();
+
+    /**
+     * Return the model's create mode
+     *
+     * @return create mode
+     */
+    CreateMode createMode();
+
+    /**
+     * Return the model's ACL list
+     *
+     * @return ACL list
+     */
+    List<ACL> aclList();
+
+    /**
+     * Return the model's create options
+     *
+     * @return create options
+     */
+    Set<CreateOption> createOptions();
+
+    /**
+     * Return the model's delete options
+     *
+     * @return delete options
+     */
+    Set<DeleteOption> deleteOptions();
+
+    /**
+     * Return a Curator schema that validates ZNodes at this model's
+     * path using this model's values
+     *
+     * @return schema
+     */
+    Schema schema();
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/3a3e6dd2/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/CuratorModelSpecBuilder.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/CuratorModelSpecBuilder.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/CuratorModelSpecBuilder.java
new file mode 100644
index 0000000..1d91784
--- /dev/null
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/CuratorModelSpecBuilder.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;
+
+import com.google.common.collect.ImmutableSet;
+import org.apache.curator.x.async.api.CreateOption;
+import org.apache.curator.x.async.api.DeleteOption;
+import org.apache.curator.x.async.modeled.details.CuratorModelSpecImpl;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.data.ACL;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+public class CuratorModelSpecBuilder<T>
+{
+    private final ZPath path;
+    private final ModelSerializer<T> serializer;
+    private CreateMode createMode = CreateMode.PERSISTENT;
+    private List<ACL> aclList = Collections.emptyList();
+    private Set<CreateOption> createOptions = Collections.emptySet();
+    private Set<DeleteOption> deleteOptions = Collections.emptySet();
+
+    /**
+     * Build a new CuratorModel instance
+     *
+     * @return new CuratorModel instance
+     */
+    public CuratorModelSpec<T> build()
+    {
+        return new CuratorModelSpecImpl<>(path, serializer, createMode, 
aclList, createOptions, deleteOptions);
+    }
+
+    /**
+     * Use the given createMode for create operations on the Modeled Curator's 
ZNode
+     *
+     * @param createMode create mode
+     * @return this for chaining
+     */
+    public CuratorModelSpecBuilder<T> withCreateMode(CreateMode createMode)
+    {
+        this.createMode = createMode;
+        return this;
+    }
+
+    /**
+     * Use the given aclList for create operations on the Modeled Curator's 
ZNode
+     *
+     * @param aclList ACLs
+     * @return this for chaining
+     */
+    public CuratorModelSpecBuilder<T> withAclList(List<ACL> aclList)
+    {
+        this.aclList = aclList;
+        return this;
+    }
+
+    /**
+     * Use the given create options on the Modeled Curator's ZNode
+     *
+     * @param createOptions options
+     * @return this for chaining
+     */
+    public CuratorModelSpecBuilder<T> withCreateOptions(Set<CreateOption> 
createOptions)
+    {
+        this.createOptions = (createOptions != null) ? 
ImmutableSet.copyOf(createOptions) : null;
+        return this;
+    }
+
+    /**
+     * Use the given delete options on the Modeled Curator's ZNode
+     *
+     * @param deleteOptions options
+     * @return this for chaining
+     */
+    public CuratorModelSpecBuilder<T> withDeleteOptions(Set<DeleteOption> 
deleteOptions)
+    {
+        this.deleteOptions = (deleteOptions != null) ? 
ImmutableSet.copyOf(deleteOptions) : null;
+        return this;
+    }
+
+    CuratorModelSpecBuilder(ZPath path, ModelSerializer<T> serializer)
+    {
+        this.path = Objects.requireNonNull(path, "path cannot be null");
+        this.serializer = Objects.requireNonNull(serializer, "serializer 
cannot be null");
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/3a3e6dd2/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModelSerializer.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModelSerializer.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModelSerializer.java
index 9828c26..428096e 100644
--- 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModelSerializer.java
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModelSerializer.java
@@ -37,6 +37,7 @@ public interface ModelSerializer<T>
      *
      * @param bytes serialized bytes
      * @return model
+     * @throws RuntimeException if <code>bytes</code> is invalid or there was 
an error deserializing
      */
     T deserialize(byte[] bytes);
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/3a3e6dd2/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledCuratorFramework.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledCuratorFramework.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledCuratorFramework.java
index 1accb72..5008b86 100644
--- 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledCuratorFramework.java
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledCuratorFramework.java
@@ -18,54 +18,40 @@
  */
 package org.apache.curator.x.async.modeled;
 
-import com.google.common.collect.ImmutableSet;
 import org.apache.curator.framework.CuratorFramework;
 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.curator.x.async.modeled.caching.Caching;
 import org.apache.zookeeper.data.Stat;
 import java.util.List;
-import java.util.Set;
 
 public interface ModeledCuratorFramework<T>
 {
-    Set<CreateOption> defaultCreateOptions = 
ImmutableSet.of(CreateOption.createParentsAsContainers, 
CreateOption.setDataIfExists);
-    Set<DeleteOption> defaultDeleteOptions = 
ImmutableSet.of(DeleteOption.guaranteed);
-
     /**
-     * Return a new ModeledCuratorFramework for the given path and serializer. 
The returned ModeledCuratorFramework
-     * is set to not watch ZNodes and uses {@link #defaultCreateOptions} and 
{@link #defaultDeleteOptions}.
+     * Return a new ModeledCuratorFramework for the given model
      *
      * @param client Curator client
-     * @param path path to model
-     * @param serializer the model's serializer
+     * @param model the model
      * @return new Modeled Curator instance
      */
-    static <T> ModeledCuratorFramework<T> wrap(CuratorFramework client, ZPath 
path, ModelSerializer<T> serializer)
+    static <T> ModeledCuratorFramework<T> wrap(CuratorFramework client, 
CuratorModelSpec<T> model)
     {
-        return builder(client, path, serializer).build();
+        return builder(client, model).build();
     }
 
     /**
-     * Start a new ModeledCuratorFrameworkBuilder for the given path and 
serializer. The returned ModeledCuratorFrameworkBuilder
-     * is set to not watch ZNodes and uses {@link #defaultCreateOptions} and 
{@link #defaultDeleteOptions}, but you can change these
-     * with builder methods.
+     * Start a new ModeledCuratorFrameworkBuilder for the given model
      *
      * @param client Curator client
-     * @param path path to model
-     * @param serializer the model's serializer
+     * @param model the model
      * @return builder
      */
-    static <T> ModeledCuratorFrameworkBuilder<T> builder(CuratorFramework 
client, ZPath path, ModelSerializer<T> serializer)
+    static <T> ModeledCuratorFrameworkBuilder<T> builder(CuratorFramework 
client, CuratorModelSpec<T> model)
     {
-        return new ModeledCuratorFrameworkBuilder<>(client, path, serializer)
-            .withCreateOptions(defaultCreateOptions)
-            .withDeleteOptions(defaultDeleteOptions);
+        return new ModeledCuratorFrameworkBuilder<>(client, model);
     }
 
     /**
-     * Returns the client that was originally passed to {@link 
#wrap(org.apache.curator.framework.CuratorFramework, ZPath, ModelSerializer)} or
+     * Returns the client that was originally passed to {@link 
#wrap(org.apache.curator.framework.CuratorFramework, CuratorModelSpec)} or
      * the builder.
      *
      * @return original client

http://git-wip-us.apache.org/repos/asf/curator/blob/3a3e6dd2/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledCuratorFrameworkBuilder.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledCuratorFrameworkBuilder.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledCuratorFrameworkBuilder.java
index 46f9cc3..1ed4b8d 100644
--- 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledCuratorFrameworkBuilder.java
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/ModeledCuratorFrameworkBuilder.java
@@ -18,20 +18,14 @@
  */
 package org.apache.curator.x.async.modeled;
 
-import com.google.common.collect.ImmutableSet;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.api.CuratorEvent;
 import org.apache.curator.framework.api.UnhandledErrorListener;
 import org.apache.curator.x.async.WatchMode;
-import org.apache.curator.x.async.api.CreateOption;
-import org.apache.curator.x.async.api.DeleteOption;
 import org.apache.curator.x.async.modeled.caching.CachingOption;
 import org.apache.curator.x.async.modeled.details.ModeledCuratorFrameworkImpl;
-import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.WatchedEvent;
-import org.apache.zookeeper.data.ACL;
 import java.util.Collections;
-import java.util.List;
 import java.util.Objects;
 import java.util.Set;
 import java.util.function.UnaryOperator;
@@ -39,16 +33,11 @@ import java.util.function.UnaryOperator;
 public class ModeledCuratorFrameworkBuilder<T>
 {
     private final CuratorFramework client;
-    private final ZPath path;
-    private final ModelSerializer<T> serializer;
+    private final CuratorModelSpec<T> model;
     private WatchMode watchMode;
     private UnaryOperator<WatchedEvent> watcherFilter;
     private UnhandledErrorListener unhandledErrorListener;
     private UnaryOperator<CuratorEvent> resultFilter;
-    private CreateMode createMode = CreateMode.PERSISTENT;
-    private List<ACL> aclList = Collections.emptyList();
-    private Set<CreateOption> createOptions = Collections.emptySet();
-    private Set<DeleteOption> deleteOptions = Collections.emptySet();
     private Set<CachingOption> cachingOptions = Collections.emptySet();
     private boolean cached = false;
 
@@ -59,19 +48,13 @@ public class ModeledCuratorFrameworkBuilder<T>
      */
     public ModeledCuratorFramework<T> build()
     {
-        String fullPath = this.path.fullPath();
         return ModeledCuratorFrameworkImpl.build(
             client,
-            fullPath,
-            serializer,
+            model,
             watchMode,
             watcherFilter,
             unhandledErrorListener,
             resultFilter,
-            createMode,
-            aclList,
-            createOptions,
-            deleteOptions,
             cachingOptions,
             cached
         );
@@ -142,54 +125,6 @@ public class ModeledCuratorFrameworkBuilder<T>
         return this;
     }
 
-    /**
-     * Use the given createMode for create operations on the Modeled Curator's 
ZNode
-     *
-     * @param createMode create mode
-     * @return this for chaining
-     */
-    public ModeledCuratorFrameworkBuilder<T> withCreateMode(CreateMode 
createMode)
-    {
-        this.createMode = createMode;
-        return this;
-    }
-
-    /**
-     * Use the given aclList for create operations on the Modeled Curator's 
ZNode
-     *
-     * @param aclList ACLs
-     * @return this for chaining
-     */
-    public ModeledCuratorFrameworkBuilder<T> withAclList(List<ACL> aclList)
-    {
-        this.aclList = aclList;
-        return this;
-    }
-
-    /**
-     * Use the given create options on the Modeled Curator's ZNode
-     *
-     * @param createOptions options
-     * @return this for chaining
-     */
-    public ModeledCuratorFrameworkBuilder<T> 
withCreateOptions(Set<CreateOption> createOptions)
-    {
-        this.createOptions = (createOptions != null) ? 
ImmutableSet.copyOf(createOptions) : null;
-        return this;
-    }
-
-    /**
-     * Use the given delete options on the Modeled Curator's ZNode
-     *
-     * @param deleteOptions options
-     * @return this for chaining
-     */
-    public ModeledCuratorFrameworkBuilder<T> 
withDeleteOptions(Set<DeleteOption> deleteOptions)
-    {
-        this.deleteOptions = (deleteOptions != null) ? 
ImmutableSet.copyOf(deleteOptions) : null;
-        return this;
-    }
-
     public ModeledCuratorFrameworkBuilder<T> cached()
     {
         this.cachingOptions = Collections.emptySet();
@@ -204,10 +139,9 @@ public class ModeledCuratorFrameworkBuilder<T>
         return this;
     }
 
-    ModeledCuratorFrameworkBuilder(CuratorFramework client, ZPath path, 
ModelSerializer<T> serializer)
+    ModeledCuratorFrameworkBuilder(CuratorFramework client, 
CuratorModelSpec<T> model)
     {
         this.client = Objects.requireNonNull(client, "client cannot be null");
-        this.path = Objects.requireNonNull(path, "path cannot be null");
-        this.serializer = Objects.requireNonNull(serializer, "serializer 
cannot be null");
+        this.model = Objects.requireNonNull(model, "model cannot be null");
     }
 }

http://git-wip-us.apache.org/repos/asf/curator/blob/3a3e6dd2/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/caching/Caching.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/caching/Caching.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/caching/Caching.java
index 87637ca..6bd460e 100644
--- 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/caching/Caching.java
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/caching/Caching.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.caching;
 
 import org.apache.curator.framework.listen.Listenable;

http://git-wip-us.apache.org/repos/asf/curator/blob/3a3e6dd2/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/caching/CachingOption.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/caching/CachingOption.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/caching/CachingOption.java
index 9b9ec08..6611301 100644
--- 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/caching/CachingOption.java
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/caching/CachingOption.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.caching;
 
 public enum CachingOption

http://git-wip-us.apache.org/repos/asf/curator/blob/3a3e6dd2/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/CachingImpl.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/CachingImpl.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/CachingImpl.java
index 9730d05..a77972b 100644
--- 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/CachingImpl.java
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/CachingImpl.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 org.apache.curator.framework.CuratorFramework;

http://git-wip-us.apache.org/repos/asf/curator/blob/3a3e6dd2/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
new file mode 100644
index 0000000..5522b15
--- /dev/null
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/CuratorModelSpecImpl.java
@@ -0,0 +1,203 @@
+/**
+ * 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.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.apache.curator.framework.schema.Schema;
+import org.apache.curator.framework.schema.SchemaValidator;
+import org.apache.curator.framework.schema.SchemaViolation;
+import org.apache.curator.utils.ZKPaths;
+import org.apache.curator.x.async.api.CreateOption;
+import org.apache.curator.x.async.api.DeleteOption;
+import org.apache.curator.x.async.modeled.CuratorModelSpec;
+import org.apache.curator.x.async.modeled.ModelSerializer;
+import org.apache.curator.x.async.modeled.ZPath;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.data.ACL;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+public class CuratorModelSpecImpl<T> implements CuratorModelSpec<T>, 
SchemaValidator
+{
+    private final ZPath path;
+    private final ModelSerializer<T> serializer;
+    private final CreateMode createMode;
+    private final List<ACL> aclList;
+    private final Set<CreateOption> createOptions;
+    private final Set<DeleteOption> deleteOptions;
+    private final Schema schema;
+
+    public CuratorModelSpecImpl(ZPath path, ModelSerializer<T> serializer, 
CreateMode createMode, List<ACL> aclList, Set<CreateOption> createOptions, 
Set<DeleteOption> deleteOptions)
+    {
+        this(path, serializer, createMode, aclList, createOptions, 
deleteOptions, null);
+    }
+
+    private CuratorModelSpecImpl(ZPath path, ModelSerializer<T> serializer, 
CreateMode createMode, List<ACL> aclList, Set<CreateOption> createOptions, 
Set<DeleteOption> deleteOptions, Schema schema)
+    {
+        this.path = Objects.requireNonNull(path, "path cannot be null");
+        this.serializer = Objects.requireNonNull(serializer, "serializer 
cannot be null");
+        this.createMode = Objects.requireNonNull(createMode, "createMode 
cannot be null");
+        this.aclList = ImmutableList.copyOf(Objects.requireNonNull(aclList, 
"aclList cannot be null"));
+        this.createOptions = 
ImmutableSet.copyOf(Objects.requireNonNull(createOptions, "createOptions cannot 
be null"));
+        this.deleteOptions = 
ImmutableSet.copyOf(Objects.requireNonNull(deleteOptions, "deleteOptions cannot 
be null"));
+
+        this.schema = (schema != null) ? schema : makeSchema(); // must be 
last in statement in ctor
+    }
+
+    @Override
+    public CuratorModelSpec<T> at(String child)
+    {
+        return new CuratorModelSpecImpl<>(path.at(child), serializer, 
createMode, aclList, createOptions, deleteOptions);
+    }
+
+    @Override
+    public ZPath path()
+    {
+        return path;
+    }
+
+    @Override
+    public ModelSerializer<T> serializer()
+    {
+        return serializer;
+    }
+
+    @Override
+    public CreateMode createMode()
+    {
+        return createMode;
+    }
+
+    @Override
+    public List<ACL> aclList()
+    {
+        return aclList;
+    }
+
+    @Override
+    public Set<CreateOption> createOptions()
+    {
+        return createOptions;
+    }
+
+    @Override
+    public Set<DeleteOption> deleteOptions()
+    {
+        return deleteOptions;
+    }
+
+    @Override
+    public Schema schema()
+    {
+        return schema;
+    }
+
+    @Override
+    public boolean equals(Object o)
+    {
+        if ( this == o )
+        {
+            return true;
+        }
+        if ( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        CuratorModelSpecImpl<?> that = (CuratorModelSpecImpl<?>)o;
+
+        if ( !path.equals(that.path) )
+        {
+            return false;
+        }
+        if ( !serializer.equals(that.serializer) )
+        {
+            return false;
+        }
+        if ( createMode != that.createMode )
+        {
+            return false;
+        }
+        if ( !aclList.equals(that.aclList) )
+        {
+            return false;
+        }
+        if ( !createOptions.equals(that.createOptions) )
+        {
+            return false;
+        }
+        //noinspection SimplifiableIfStatement
+        if ( !deleteOptions.equals(that.deleteOptions) )
+        {
+            return false;
+        }
+        return schema.equals(that.schema);
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int result = path.hashCode();
+        result = 31 * result + serializer.hashCode();
+        result = 31 * result + createMode.hashCode();
+        result = 31 * result + aclList.hashCode();
+        result = 31 * result + createOptions.hashCode();
+        result = 31 * result + deleteOptions.hashCode();
+        result = 31 * result + schema.hashCode();
+        return result;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "CuratorModelImpl{" + "path=" + path + ", serializer=" + 
serializer + ", createMode=" + createMode + ", aclList=" + aclList + ", 
createOptions=" + createOptions + ", deleteOptions=" + deleteOptions + ", 
schema=" + schema + '}';
+    }
+
+    @Override
+    public boolean isValid(Schema schema, String path, byte[] data, List<ACL> 
acl)
+    {
+        if ( !acl.equals(aclList) )
+        {
+            throw new SchemaViolation(schema, new 
SchemaViolation.ViolatorData(path, data, acl), "ACLs do not match model ACLs");
+        }
+
+        try
+        {
+            serializer.deserialize(data);
+        }
+        catch ( RuntimeException e )
+        {
+            throw new SchemaViolation(schema, new 
SchemaViolation.ViolatorData(path, data, acl), "Data cannot be deserialized 
into a model");
+        }
+        return true;
+    }
+
+    private Schema makeSchema()
+    {
+        return Schema.builder(path.fullPath() + ZKPaths.PATH_SEPARATOR + ".*")
+            .dataValidator(this)
+            .ephemeral(createMode.isEphemeral() ? Schema.Allowance.MUST : 
Schema.Allowance.CANNOT)
+            .canBeDeleted(true)
+            .sequential(createMode.isSequential() ? Schema.Allowance.MUST : 
Schema.Allowance.CANNOT)
+            .watched(Schema.Allowance.CAN)
+            .build();
+    }
+}

http://git-wip-us.apache.org/repos/asf/curator/blob/3a3e6dd2/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/ModeledCuratorFrameworkImpl.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/ModeledCuratorFrameworkImpl.java
 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/ModeledCuratorFrameworkImpl.java
index a6fc968..1926cf0 100644
--- 
a/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/ModeledCuratorFrameworkImpl.java
+++ 
b/curator-x-async/src/main/java/org/apache/curator/x/async/modeled/details/ModeledCuratorFrameworkImpl.java
@@ -30,15 +30,13 @@ import 
org.apache.curator.x.async.api.AsyncCuratorFrameworkDsl;
 import org.apache.curator.x.async.api.AsyncPathAndBytesable;
 import org.apache.curator.x.async.api.AsyncPathable;
 import org.apache.curator.x.async.api.CreateOption;
-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.CuratorModelSpec;
 import org.apache.curator.x.async.modeled.ModeledCuratorFramework;
 import org.apache.curator.x.async.modeled.ZPath;
 import org.apache.curator.x.async.modeled.caching.Caching;
 import org.apache.curator.x.async.modeled.caching.CachingOption;
 import org.apache.curator.x.async.modeled.recipes.ModeledCachedNode;
-import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.data.ACL;
 import org.apache.zookeeper.data.Stat;
@@ -54,73 +52,52 @@ public class ModeledCuratorFrameworkImpl<T> implements 
ModeledCuratorFramework<T
 {
     private final AsyncCuratorFramework client;
     private final WatchableAsyncCuratorFramework watchableClient;
-    private final ZPath path;
-    private final ModelSerializer<T> serializer;
+    private final CuratorModelSpec<T> model;
     private final WatchMode watchMode;
     private final UnaryOperator<WatchedEvent> watcherFilter;
     private final UnhandledErrorListener unhandledErrorListener;
     private final UnaryOperator<CuratorEvent> resultFilter;
-    private final CreateMode createMode;
-    private final List<ACL> aclList;
-    private final Set<CreateOption> createOptions;
-    private final Set<DeleteOption> deleteOptions;
     private final AsyncCuratorFrameworkDsl dslClient;
     private final CachingImpl<T> caching;
 
-    public static <T> ModeledCuratorFrameworkImpl<T> build(CuratorFramework 
client, String path, ModelSerializer<T> serializer, WatchMode watchMode, 
UnaryOperator<WatchedEvent> watcherFilter, UnhandledErrorListener 
unhandledErrorListener, UnaryOperator<CuratorEvent> resultFilter, CreateMode 
createMode, List<ACL> aclList, Set<CreateOption> createOptions, 
Set<DeleteOption> deleteOptions, Set<CachingOption> cachingOptions, boolean 
cached)
+    public static <T> ModeledCuratorFrameworkImpl<T> build(CuratorFramework 
client, CuratorModelSpec<T> model, WatchMode watchMode, 
UnaryOperator<WatchedEvent> watcherFilter, UnhandledErrorListener 
unhandledErrorListener, UnaryOperator<CuratorEvent> resultFilter, 
Set<CachingOption> cachingOptions, boolean cached)
     {
         boolean localIsWatched = (watchMode != null);
 
         Objects.requireNonNull(client, "client cannot be null");
-        Objects.requireNonNull(path, "path cannot be null");
-        Objects.requireNonNull(serializer, "serializer cannot be null");
-        Objects.requireNonNull(createOptions, "createOptions cannot be null");
-        Objects.requireNonNull(createMode, "createMode cannot be null");
-        Objects.requireNonNull(aclList, "aclList cannot be null");
+        Objects.requireNonNull(model, "model cannot be null");
 
         watchMode = (watchMode != null) ? watchMode : 
WatchMode.stateChangeAndSuccess;
 
-        ZPath zPath = ZPath.parse(path);
-
         AsyncCuratorFramework asyncClient = AsyncCuratorFramework.wrap(client);
         AsyncCuratorFrameworkDsl dslClient = asyncClient.with(watchMode, 
unhandledErrorListener, resultFilter, watcherFilter);
         WatchableAsyncCuratorFramework watchableClient = localIsWatched ? 
dslClient.watched() : dslClient;
 
-        CachingImpl<T> caching = cached ? new CachingImpl<>(client, 
serializer, zPath, cachingOptions, createOptions) : null;
+        CachingImpl<T> caching = cached ? new CachingImpl<>(client, 
model.serializer(), model.path(), cachingOptions, model.createOptions()) : null;
 
         return new ModeledCuratorFrameworkImpl<>(
             asyncClient,
             dslClient,
             watchableClient,
-            zPath,
-            serializer,
+            model,
             watchMode,
             watcherFilter,
             unhandledErrorListener,
             resultFilter,
-            createMode,
-            aclList,
-            createOptions,
-            deleteOptions,
             caching
         );
     }
 
-    private ModeledCuratorFrameworkImpl(AsyncCuratorFramework client, 
AsyncCuratorFrameworkDsl dslClient, WatchableAsyncCuratorFramework 
watchableClient, ZPath path, ModelSerializer<T> serializer, WatchMode 
watchMode, UnaryOperator<WatchedEvent> watcherFilter, UnhandledErrorListener 
unhandledErrorListener, UnaryOperator<CuratorEvent> resultFilter, CreateMode 
createMode, List<ACL> aclList, Set<CreateOption> createOptions, 
Set<DeleteOption> deleteOptions, CachingImpl<T> caching)
+    private ModeledCuratorFrameworkImpl(AsyncCuratorFramework client, 
AsyncCuratorFrameworkDsl dslClient, WatchableAsyncCuratorFramework 
watchableClient, CuratorModelSpec<T> model, WatchMode watchMode, 
UnaryOperator<WatchedEvent> watcherFilter, UnhandledErrorListener 
unhandledErrorListener, UnaryOperator<CuratorEvent> resultFilter, 
CachingImpl<T> caching)
     {
         this.client = client;
         this.dslClient = dslClient;
         this.watchableClient = watchableClient;
-        this.path = path;
-        this.serializer = serializer;
+        this.model = model;
         this.watchMode = watchMode;
         this.watcherFilter = watcherFilter;
         this.unhandledErrorListener = unhandledErrorListener;
         this.resultFilter = resultFilter;
-        this.createMode = createMode;
-        this.aclList = aclList;
-        this.createOptions = createOptions;
-        this.deleteOptions = deleteOptions;
         this.caching = caching;
     }
 
@@ -138,17 +115,17 @@ public class ModeledCuratorFrameworkImpl<T> implements 
ModeledCuratorFramework<T
     }
 
     @Override
-    public AsyncStage<String> create(T model)
+    public AsyncStage<String> create(T item)
     {
-        return create(model, null);
+        return create(item, null);
     }
 
     @Override
-    public AsyncStage<String> create(T model, Stat storingStatIn)
+    public AsyncStage<String> create(T item, Stat storingStatIn)
     {
         long dirtyZxid = getDirtyZxid();
-        byte[] bytes = serializer.serialize(model);
-        AsyncStage<String> asyncStage = 
dslClient.create().withOptions(createOptions, createMode, fixAclList(aclList), 
storingStatIn).forPath(path.fullPath(), bytes);
+        byte[] bytes = model.serializer().serialize(item);
+        AsyncStage<String> asyncStage = 
dslClient.create().withOptions(model.createOptions(), model.createMode(), 
fixAclList(model.aclList()), storingStatIn).forPath(model.path().fullPath(), 
bytes);
         ModelStage<String> modelStage = new ModelStage<>(asyncStage.event());
         markDirtyCompleter(dirtyZxid, asyncStage, modelStage);
         return modelStage;
@@ -197,7 +174,7 @@ public class ModeledCuratorFrameworkImpl<T> implements 
ModeledCuratorFramework<T
         {
             next = (storingStatIn != null) ? 
watchableClient.getData().storingStatIn(storingStatIn) : 
watchableClient.getData();
         }
-        AsyncStage<byte[]> asyncStage = next.forPath(path.fullPath());
+        AsyncStage<byte[]> asyncStage = next.forPath(model.path().fullPath());
         ModelStage<T> modelStage = new ModelStage<>(asyncStage.event());
         asyncStage.whenComplete((value, e) -> {
             if ( e != null )
@@ -208,7 +185,7 @@ public class ModeledCuratorFrameworkImpl<T> implements 
ModeledCuratorFramework<T
             {
                 try
                 {
-                    modelStage.complete(serializer.deserialize(value));
+                    modelStage.complete(model.serializer().deserialize(value));
                 }
                 catch ( Exception deserializeException )
                 {
@@ -220,18 +197,18 @@ public class ModeledCuratorFrameworkImpl<T> implements 
ModeledCuratorFramework<T
     }
 
     @Override
-    public AsyncStage<Stat> update(T model)
+    public AsyncStage<Stat> update(T item)
     {
-        return update(model, -1);
+        return update(item, -1);
     }
 
     @Override
-    public AsyncStage<Stat> update(T model, int version)
+    public AsyncStage<Stat> update(T item, int version)
     {
         long dirtyZxid = getDirtyZxid();
-        byte[] bytes = serializer.serialize(model);
+        byte[] bytes = model.serializer().serialize(item);
         AsyncPathAndBytesable<AsyncStage<Stat>> next = isCompressed() ? 
dslClient.setData().compressedWithVersion(version) : dslClient.setData();
-        AsyncStage<Stat> asyncStage = next.forPath(path.fullPath(), bytes);
+        AsyncStage<Stat> asyncStage = next.forPath(model.path().fullPath(), 
bytes);
         ModelStage<Stat> modelStage = new ModelStage<>(asyncStage.event());
         markDirtyCompleter(dirtyZxid, asyncStage, modelStage);
         return modelStage;
@@ -250,7 +227,7 @@ public class ModeledCuratorFrameworkImpl<T> implements 
ModeledCuratorFramework<T
             }
             return result;
         }
-        return watchableClient.checkExists().forPath(path.fullPath());
+        return watchableClient.checkExists().forPath(model.path().fullPath());
     }
 
     @Override
@@ -263,7 +240,7 @@ public class ModeledCuratorFrameworkImpl<T> implements 
ModeledCuratorFramework<T
     public AsyncStage<Void> delete(int version)
     {
         long dirtyZxid = getDirtyZxid();
-        AsyncStage<Void> asyncStage = 
dslClient.delete().withVersion(-1).forPath(path.fullPath());
+        AsyncStage<Void> asyncStage = 
dslClient.delete().withVersion(-1).forPath(model.path().fullPath());
         ModelStage<Void> modelStage = new ModelStage<>(asyncStage.event());
         markDirtyCompleter(dirtyZxid, asyncStage, modelStage);
         return modelStage;
@@ -272,7 +249,7 @@ public class ModeledCuratorFrameworkImpl<T> implements 
ModeledCuratorFramework<T
     @Override
     public AsyncStage<List<ZPath>> getChildren()
     {
-        AsyncStage<List<String>> asyncStage = 
watchableClient.getChildren().forPath(path.fullPath());
+        AsyncStage<List<String>> asyncStage = 
watchableClient.getChildren().forPath(model.path().fullPath());
         ModelStage<List<ZPath>> modelStage = new 
ModelStage<>(asyncStage.event());
         asyncStage.whenComplete((children, e) -> {
             if ( e != null )
@@ -281,7 +258,7 @@ public class ModeledCuratorFrameworkImpl<T> implements 
ModeledCuratorFramework<T
             }
             else
             {
-                
modelStage.complete(children.stream().map(path::at).collect(Collectors.toList()));
+                modelStage.complete(children.stream().map(child -> 
model.path().at(child)).collect(Collectors.toList()));
             }
         });
         return modelStage;
@@ -290,21 +267,17 @@ public class ModeledCuratorFrameworkImpl<T> implements 
ModeledCuratorFramework<T
     @Override
     public ModeledCuratorFramework<T> at(String child)
     {
-        ZPath childPath = path.at(child);
+        CuratorModelSpec<T> childModel = model.at(child);
         CachingImpl<T> newCaching = (caching != null) ? caching.at(child) : 
null;
         return new ModeledCuratorFrameworkImpl<>(
             client,
             dslClient,
             watchableClient,
-            childPath, serializer,
+            childModel,
             watchMode,
             watcherFilter,
             unhandledErrorListener,
             resultFilter,
-            createMode,
-            aclList,
-            createOptions,
-            deleteOptions,
             newCaching
         );
     }
@@ -334,7 +307,7 @@ public class ModeledCuratorFrameworkImpl<T> implements 
ModeledCuratorFramework<T
 
     private boolean isCompressed()
     {
-        return createOptions.contains(CreateOption.compress);
+        return model.createOptions().contains(CreateOption.compress);
     }
 
     private ModeledCachedNode<T> getCached()

http://git-wip-us.apache.org/repos/asf/curator/blob/3a3e6dd2/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/TestModeledCuratorFramework.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/TestModeledCuratorFramework.java
 
b/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/TestModeledCuratorFramework.java
index ac4c607..da63d37 100644
--- 
a/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/TestModeledCuratorFramework.java
+++ 
b/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/TestModeledCuratorFramework.java
@@ -41,6 +41,8 @@ public class TestModeledCuratorFramework extends 
CompletableBaseClassForTests
     private CuratorFramework rawClient;
     private JacksonModelSerializer<TestModel> serializer;
     private JacksonModelSerializer<TestNewerModel> newSerializer;
+    private CuratorModelSpec<TestModel> modelSpec;
+    private CuratorModelSpec<TestNewerModel> newModelSpec;
 
     @BeforeMethod
     @Override
@@ -53,6 +55,9 @@ public class TestModeledCuratorFramework extends 
CompletableBaseClassForTests
 
         serializer = new JacksonModelSerializer<>(TestModel.class);
         newSerializer = new JacksonModelSerializer<>(TestNewerModel.class);
+
+        modelSpec = CuratorModelSpec.builder(path, serializer).build();
+        newModelSpec = CuratorModelSpec.builder(path, newSerializer).build();
     }
 
     @AfterMethod
@@ -68,7 +73,7 @@ public class TestModeledCuratorFramework extends 
CompletableBaseClassForTests
     {
         TestModel rawModel = new TestModel("John", "Galt", "1 Galt's Gulch", 
42, BigInteger.valueOf(1));
         TestModel rawModel2 = new TestModel("Wayne", "Rooney", "Old Trafford", 
10, BigInteger.valueOf(1));
-        ModeledCuratorFramework<TestModel> client = 
ModeledCuratorFramework.wrap(rawClient, path, serializer);
+        ModeledCuratorFramework<TestModel> client = 
ModeledCuratorFramework.wrap(rawClient, modelSpec);
         AsyncStage<String> stage = client.create(rawModel);
         Assert.assertNull(stage.event());
         complete(stage, (s, e) -> Assert.assertNotNull(s));
@@ -83,10 +88,10 @@ public class TestModeledCuratorFramework extends 
CompletableBaseClassForTests
     public void testBackwardCompatibility()
     {
         TestNewerModel rawNewModel = new TestNewerModel("John", "Galt", "1 
Galt's Gulch", 42, BigInteger.valueOf(1), 100);
-        ModeledCuratorFramework<TestNewerModel> clientForNew = 
ModeledCuratorFramework.wrap(rawClient, path, newSerializer);
+        ModeledCuratorFramework<TestNewerModel> clientForNew = 
ModeledCuratorFramework.wrap(rawClient, newModelSpec);
         complete(clientForNew.create(rawNewModel), (s, e) -> 
Assert.assertNotNull(s));
 
-        ModeledCuratorFramework<TestModel> clientForOld = 
ModeledCuratorFramework.wrap(rawClient, path, serializer);
+        ModeledCuratorFramework<TestModel> clientForOld = 
ModeledCuratorFramework.wrap(rawClient, modelSpec);
         complete(clientForOld.read(), (model, e) -> 
Assert.assertTrue(rawNewModel.equalsOld(model)));
     }
 
@@ -94,7 +99,7 @@ public class TestModeledCuratorFramework extends 
CompletableBaseClassForTests
     public void testWatched() throws InterruptedException
     {
         CountDownLatch latch = new CountDownLatch(1);
-        ModeledCuratorFramework<TestModel> client = 
ModeledCuratorFramework.builder(rawClient, path, serializer).watched().build();
+        ModeledCuratorFramework<TestModel> client = 
ModeledCuratorFramework.builder(rawClient, modelSpec).watched().build();
         client.checkExists().event().whenComplete((event, ex) -> 
latch.countDown());
         timing.sleepABit();
         Assert.assertEquals(latch.getCount(), 1);
@@ -106,7 +111,7 @@ public class TestModeledCuratorFramework extends 
CompletableBaseClassForTests
     public void testGetChildren()
     {
         TestModel model = new TestModel("John", "Galt", "1 Galt's Gulch", 42, 
BigInteger.valueOf(1));
-        ModeledCuratorFramework<TestModel> client = 
ModeledCuratorFramework.builder(rawClient, path, serializer).build();
+        ModeledCuratorFramework<TestModel> client = 
ModeledCuratorFramework.builder(rawClient, modelSpec).build();
         complete(client.at("one").create(model));
         complete(client.at("two").create(model));
         complete(client.at("three").create(model));

http://git-wip-us.apache.org/repos/asf/curator/blob/3a3e6dd2/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/details/TestCachedModeledCuratorFramework.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/details/TestCachedModeledCuratorFramework.java
 
b/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/details/TestCachedModeledCuratorFramework.java
index 160ec7d..06d6834 100644
--- 
a/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/details/TestCachedModeledCuratorFramework.java
+++ 
b/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/details/TestCachedModeledCuratorFramework.java
@@ -24,6 +24,7 @@ import org.apache.curator.framework.CuratorFrameworkFactory;
 import org.apache.curator.retry.RetryOneTime;
 import org.apache.curator.utils.CloseableUtils;
 import org.apache.curator.x.async.CompletableBaseClassForTests;
+import org.apache.curator.x.async.modeled.CuratorModelSpec;
 import org.apache.curator.x.async.modeled.JacksonModelSerializer;
 import org.apache.curator.x.async.modeled.ModelSerializer;
 import org.apache.curator.x.async.modeled.ModeledCuratorFramework;
@@ -52,7 +53,7 @@ public class TestCachedModeledCuratorFramework extends 
CompletableBaseClassForTe
         rawClient.start();
 
         ModelSerializer<TestSimpleModel> serializer = new 
JacksonModelSerializer<>(TestSimpleModel.class);
-        client = ModeledCuratorFramework.builder(rawClient, path, 
serializer).cached().build();
+        client = ModeledCuratorFramework.builder(rawClient, 
CuratorModelSpec.builder(path, serializer).build()).cached().build();
     }
 
     @AfterMethod

http://git-wip-us.apache.org/repos/asf/curator/blob/3a3e6dd2/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/models/TestSimpleModel.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/models/TestSimpleModel.java
 
b/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/models/TestSimpleModel.java
index def50c5..f998da2 100644
--- 
a/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/models/TestSimpleModel.java
+++ 
b/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/models/TestSimpleModel.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.models;
 
 import java.util.Objects;

http://git-wip-us.apache.org/repos/asf/curator/blob/3a3e6dd2/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/recipes/TestModeledCaches.java
----------------------------------------------------------------------
diff --git 
a/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/recipes/TestModeledCaches.java
 
b/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/recipes/TestModeledCaches.java
index 6b168a4..aacc4a9 100644
--- 
a/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/recipes/TestModeledCaches.java
+++ 
b/curator-x-async/src/test/java/org/apache/curator/x/async/modeled/recipes/TestModeledCaches.java
@@ -26,6 +26,7 @@ import org.apache.curator.framework.recipes.cache.TreeCache;
 import org.apache.curator.retry.RetryOneTime;
 import org.apache.curator.utils.CloseableUtils;
 import org.apache.curator.x.async.CompletableBaseClassForTests;
+import org.apache.curator.x.async.modeled.CuratorModelSpec;
 import org.apache.curator.x.async.modeled.JacksonModelSerializer;
 import org.apache.curator.x.async.modeled.ModeledCuratorFramework;
 import org.apache.curator.x.async.modeled.ZPath;
@@ -59,7 +60,7 @@ public class TestModeledCaches extends 
CompletableBaseClassForTests
         serializer = JacksonModelSerializer.build(TestModel.class);
 
         path = ZPath.parse("/test/path");
-        modeled = ModeledCuratorFramework.wrap(client, path, serializer);
+        modeled = ModeledCuratorFramework.wrap(client, 
CuratorModelSpec.builder(path, serializer).build());
     }
 
     @AfterMethod

Reply via email to