Adding additional resources for instantiating async consistent treemaps.

Change-Id: I7bfc602ac22eda1844fea2a7b3e3133f83157bf3
diff --git a/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnStorageServiceAdapter.java b/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnStorageServiceAdapter.java
index 8421bb2..a04ef98 100644
--- a/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnStorageServiceAdapter.java
+++ b/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnStorageServiceAdapter.java
@@ -16,6 +16,7 @@
 package org.onosproject.vtnrsc.util;
 
 import org.onosproject.store.service.Topic;
+import org.onosproject.store.service.ConsistentTreeMapBuilder;
 import org.onosproject.store.service.WorkQueue;
 import org.onosproject.store.service.EventuallyConsistentMapBuilder;
 import org.onosproject.store.service.ConsistentMapBuilder;
@@ -42,6 +43,11 @@
     }
 
     @Override
+    public <V> ConsistentTreeMapBuilder<V> consistentTreeMapBuilder() {
+        return null;
+    }
+
+    @Override
     public <E> DistributedSetBuilder<E> setBuilder() {
         return null;
     }
diff --git a/core/api/src/main/java/org/onosproject/store/primitives/DefaultConsistentTreeMap.java b/core/api/src/main/java/org/onosproject/store/primitives/DefaultConsistentTreeMap.java
index 782a1ec..a38da9e 100644
--- a/core/api/src/main/java/org/onosproject/store/primitives/DefaultConsistentTreeMap.java
+++ b/core/api/src/main/java/org/onosproject/store/primitives/DefaultConsistentTreeMap.java
@@ -45,7 +45,6 @@
 public class DefaultConsistentTreeMap<V>
         extends Synchronous<AsyncConsistentTreeMap<V>>
         implements ConsistentTreeMap<V> {
-    private static final int MAX_DELAY_BETWEEN_RETRY_MILLIS = 50;
     private final AsyncConsistentTreeMap<V> treeMap;
     private final long operationTimeoutMillis;
     private Map<String, V> javaMap;
diff --git a/core/api/src/main/java/org/onosproject/store/primitives/DistributedPrimitiveCreator.java b/core/api/src/main/java/org/onosproject/store/primitives/DistributedPrimitiveCreator.java
index 5080b82..a8827a7 100644
--- a/core/api/src/main/java/org/onosproject/store/primitives/DistributedPrimitiveCreator.java
+++ b/core/api/src/main/java/org/onosproject/store/primitives/DistributedPrimitiveCreator.java
@@ -20,6 +20,7 @@
 import org.onosproject.store.service.AsyncAtomicCounter;
 import org.onosproject.store.service.AsyncAtomicValue;
 import org.onosproject.store.service.AsyncConsistentMap;
+import org.onosproject.store.service.AsyncConsistentTreeMap;
 import org.onosproject.store.service.AsyncDistributedSet;
 import org.onosproject.store.service.AsyncLeaderElector;
 import org.onosproject.store.service.WorkQueue;
@@ -42,6 +43,16 @@
     <K, V> AsyncConsistentMap<K, V> newAsyncConsistentMap(String name, Serializer serializer);
 
     /**
+     * Creates a new {@code AsyncConsistentTreeMap}.
+     *
+     * @param name tree name
+     * @param serializer serializer to use for serializing/deserializing map entries
+     * @param <V> value type
+     * @return distributedTreeMap
+     */
+    <V> AsyncConsistentTreeMap<V> newAsyncConsistentTreeMap(String name, Serializer serializer);
+
+    /**
      * Creates a new {@code AsyncAtomicCounter}.
      *
      * @param name counter name
diff --git a/core/api/src/main/java/org/onosproject/store/service/ConsistentTreeMapBuilder.java b/core/api/src/main/java/org/onosproject/store/service/ConsistentTreeMapBuilder.java
new file mode 100644
index 0000000..bb343da
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/store/service/ConsistentTreeMapBuilder.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.store.service;
+
+import org.onosproject.store.primitives.DistributedPrimitiveBuilder;
+
+/**
+ * Builder for {@link ConsistentTreeMap}.
+ */
+public abstract class ConsistentTreeMapBuilder<V>
+        extends DistributedPrimitiveBuilder<ConsistentTreeMapBuilder<V>, ConsistentTreeMap<V>> {
+
+    private boolean purgeOnUninstall = false;
+
+    public ConsistentTreeMapBuilder() {
+        super(DistributedPrimitive.Type.CONSISTENT_TREEMAP);
+    }
+
+    /**
+     * Clears map contents when the owning application is uninstalled.
+     *
+     * @return this builder
+     */
+    public ConsistentTreeMapBuilder<V> withPurgeOnUninstall() {
+        purgeOnUninstall = true;
+        return this;
+    }
+
+    /**
+     * Return if map entries need to be cleared when owning application is uninstalled.
+     *
+     * @return true if items are to be cleared on uninstall
+     */
+    public boolean purgeOnUninstall() {
+        return purgeOnUninstall;
+    }
+
+    /**
+     * Builds the distributed tree map based on the configuration options supplied
+     * to this builder.
+     *
+     * @return new distributed tree map
+     * @throw java.lang.RuntimeException if a mandatory parameter is missing
+     */
+    public abstract AsyncConsistentTreeMap<V> buildTreeMap();
+
+}
diff --git a/core/api/src/main/java/org/onosproject/store/service/DistributedPrimitive.java b/core/api/src/main/java/org/onosproject/store/service/DistributedPrimitive.java
index b19a04b..8a2c7ba 100644
--- a/core/api/src/main/java/org/onosproject/store/service/DistributedPrimitive.java
+++ b/core/api/src/main/java/org/onosproject/store/service/DistributedPrimitive.java
@@ -52,6 +52,11 @@
         SET,
 
         /**
+         * Tree map.
+         */
+        CONSISTENT_TREEMAP,
+
+        /**
          * atomic counter.
          */
         COUNTER,
diff --git a/core/api/src/main/java/org/onosproject/store/service/StorageService.java b/core/api/src/main/java/org/onosproject/store/service/StorageService.java
index e646e38..4edb438 100644
--- a/core/api/src/main/java/org/onosproject/store/service/StorageService.java
+++ b/core/api/src/main/java/org/onosproject/store/service/StorageService.java
@@ -44,6 +44,14 @@
     <K, V> ConsistentMapBuilder<K, V> consistentMapBuilder();
 
     /**
+     * Creates a new {@code AsyncConsistentTreeMapBuilder}.
+     *
+     * @param <V> value type
+     * @return builder for a async consistent tree map
+     */
+    <V> ConsistentTreeMapBuilder<V> consistentTreeMapBuilder();
+
+    /**
      * Creates a new DistributedSetBuilder.
      *
      * @param <E> set element type
diff --git a/core/api/src/test/java/org/onosproject/store/service/StorageServiceAdapter.java b/core/api/src/test/java/org/onosproject/store/service/StorageServiceAdapter.java
index 0cd1b60..e75c59e 100644
--- a/core/api/src/test/java/org/onosproject/store/service/StorageServiceAdapter.java
+++ b/core/api/src/test/java/org/onosproject/store/service/StorageServiceAdapter.java
@@ -63,4 +63,8 @@
     public <T> Topic<T> getTopic(String name, Serializer serializer) {
         return null;
     }
+
+    public <V> ConsistentTreeMapBuilder<V> consistentTreeMapBuilder() {
+        return null;
+    }
 }
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/CatalystSerializers.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/CatalystSerializers.java
index f07f838..74d7f0b 100644
--- a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/CatalystSerializers.java
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/CatalystSerializers.java
@@ -31,6 +31,7 @@
 import org.onosproject.store.primitives.TransactionId;
 import org.onosproject.store.primitives.resources.impl.AtomixConsistentMapCommands;
 import org.onosproject.store.primitives.resources.impl.AtomixConsistentMapFactory;
+import org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapCommands;
 import org.onosproject.store.primitives.resources.impl.AtomixLeaderElectorCommands;
 import org.onosproject.store.primitives.resources.impl.AtomixLeaderElectorFactory;
 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueueCommands;
@@ -96,6 +97,7 @@
         serializer.resolve(new AtomixLeaderElectorCommands.TypeResolver());
         serializer.resolve(new AtomixWorkQueueCommands.TypeResolver());
         serializer.resolve(new ResourceManagerTypeResolver());
+        serializer.resolve(new AtomixConsistentTreeMapCommands.TypeResolver());
 
         serializer.registerClassLoader(AtomixConsistentMapFactory.class)
                   .registerClassLoader(AtomixLeaderElectorFactory.class)
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/DefaultConsistentTreeMapBuilder.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/DefaultConsistentTreeMapBuilder.java
new file mode 100644
index 0000000..2aa906a
--- /dev/null
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/DefaultConsistentTreeMapBuilder.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.store.primitives.impl;
+
+import org.onosproject.store.primitives.DistributedPrimitiveCreator;
+import org.onosproject.store.service.AsyncConsistentTreeMap;
+import org.onosproject.store.service.ConsistentTreeMap;
+import org.onosproject.store.service.ConsistentTreeMapBuilder;
+
+/**
+ * Default {@link org.onosproject.store.service.AsyncConsistentTreeMap} builder.
+ *
+ * @param <V> type for map value
+ */
+public class DefaultConsistentTreeMapBuilder<V> extends ConsistentTreeMapBuilder<V> {
+
+    private final DistributedPrimitiveCreator primitiveCreator;
+
+    public DefaultConsistentTreeMapBuilder(DistributedPrimitiveCreator primitiveCreator) {
+        this.primitiveCreator = primitiveCreator;
+    }
+
+    @Override
+    public AsyncConsistentTreeMap<V> buildTreeMap() {
+        return primitiveCreator.newAsyncConsistentTreeMap(name(), serializer());
+    }
+
+    @Override
+    public ConsistentTreeMap<V> build() {
+        return buildTreeMap().asTreeMap();
+    }
+
+}
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/DelegatingAsyncConsistentTreeMap.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/DelegatingAsyncConsistentTreeMap.java
new file mode 100644
index 0000000..31d5f8e
--- /dev/null
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/DelegatingAsyncConsistentTreeMap.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.store.primitives.impl;
+
+import org.onosproject.store.primitives.TransactionId;
+import org.onosproject.store.service.AsyncConsistentTreeMap;
+import org.onosproject.store.service.MapEventListener;
+import org.onosproject.store.service.MapTransaction;
+import org.onosproject.store.service.Versioned;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.NavigableMap;
+import java.util.NavigableSet;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.function.BiFunction;
+import java.util.function.Predicate;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A {@link AsyncConsistentTreeMap} that delegates control to another instance
+ * of {@link AsyncConsistentTreeMap}.
+ */
+public class DelegatingAsyncConsistentTreeMap<V>
+        implements AsyncConsistentTreeMap<V> {
+
+    private final AsyncConsistentTreeMap<V> delegateMap;
+
+    DelegatingAsyncConsistentTreeMap(AsyncConsistentTreeMap<V> delegateMap) {
+        this.delegateMap = checkNotNull(delegateMap,
+                                        "delegate map cannot be null");
+    }
+
+    @Override
+    public CompletableFuture<String> firstKey() {
+        return delegateMap.firstKey();
+    }
+
+    @Override
+    public CompletableFuture<String> lastKey() {
+        return delegateMap.lastKey();
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V>>> ceilingEntry(String key) {
+        return delegateMap.ceilingEntry(key);
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V>>> floorEntry(String key) {
+        return delegateMap.floorEntry(key);
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V>>> higherEntry(String key) {
+        return delegateMap.higherEntry(key);
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V>>> lowerEntry(String key) {
+        return delegateMap.lowerEntry(key);
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V>>> firstEntry() {
+        return delegateMap.firstEntry();
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V>>> lastEntry() {
+        return delegateMap.lastEntry();
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V>>> pollFirstEntry() {
+        return delegateMap.pollFirstEntry();
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V>>> pollLastEntry() {
+        return delegateMap.pollLastEntry();
+    }
+
+    @Override
+    public CompletableFuture<String> lowerKey(String key) {
+        return delegateMap.lowerKey(key);
+    }
+
+    @Override
+    public CompletableFuture<String> floorKey(String key) {
+        return delegateMap.floorKey(key);
+    }
+
+    @Override
+    public CompletableFuture<String> ceilingKey(String key) {
+        return delegateMap.ceilingKey(key);
+    }
+
+    @Override
+    public CompletableFuture<String> higherKey(String key) {
+        return delegateMap.higherKey(key);
+    }
+
+    @Override
+    public CompletableFuture<NavigableSet<String>> navigableKeySet() {
+        return delegateMap.navigableKeySet();
+    }
+
+    @Override
+    public CompletableFuture<NavigableMap<String, V>> subMap(
+            String upperKey,
+            String lowerKey,
+            boolean inclusiveUpper,
+            boolean inclusiveLower) {
+        return delegateMap.subMap(upperKey, lowerKey,
+                                  inclusiveUpper, inclusiveLower);
+    }
+
+    @Override
+    public String name() {
+        return delegateMap.name();
+    }
+
+    @Override
+    public CompletableFuture<Integer> size() {
+        return delegateMap.size();
+    }
+
+    @Override
+    public CompletableFuture<Boolean> containsKey(String key) {
+        return delegateMap.containsKey(key);
+    }
+
+    @Override
+    public CompletableFuture<Boolean> containsValue(V value) {
+        return delegateMap.containsValue(value);
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> get(String key) {
+        return delegateMap.get(key);
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> computeIf(
+            String key,
+            Predicate<? super V> condition,
+            BiFunction<? super String, ? super V,
+                    ? extends V> remappingFunction) {
+        return delegateMap.computeIf(key, condition, remappingFunction);
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> put(String key, V value) {
+        return delegateMap.put(key, value);
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> putAndGet(String key, V value) {
+        return delegateMap.putAndGet(key, value);
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> remove(String key) {
+        return delegateMap.remove(key);
+    }
+
+    @Override
+    public CompletableFuture<Void> clear() {
+        return delegateMap.clear();
+    }
+
+    @Override
+    public CompletableFuture<Set<String>> keySet() {
+        return delegateMap.keySet();
+    }
+
+    @Override
+    public CompletableFuture<Collection<Versioned<V>>> values() {
+        return delegateMap.values();
+    }
+
+    @Override
+    public CompletableFuture<Set<Map.Entry<String, Versioned<V>>>> entrySet() {
+        return delegateMap.entrySet();
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> putIfAbsent(String key, V value) {
+        return delegateMap.putIfAbsent(key, value);
+    }
+
+    @Override
+    public CompletableFuture<Boolean> remove(String key, V value) {
+        return delegateMap.remove(key, value);
+    }
+
+    @Override
+    public CompletableFuture<Boolean> remove(String key, long version) {
+        return delegateMap.remove(key, version);
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> replace(String key, V value) {
+        return delegateMap.replace(key, value);
+    }
+
+    @Override
+    public CompletableFuture<Boolean> replace(String key, V oldValue,
+                                              V newValue) {
+        return delegateMap.replace(key, oldValue, newValue);
+    }
+
+    @Override
+    public CompletableFuture<Boolean> replace(String key, long oldVersion,
+                                              V newValue) {
+        return delegateMap.replace(key, oldVersion, newValue);
+    }
+
+    @Override
+    public CompletableFuture<Void> addListener(
+            MapEventListener<String, V> listener, Executor executor) {
+        return delegateMap.addListener(listener, executor);
+    }
+
+    @Override
+    public CompletableFuture<Void> removeListener(
+            MapEventListener<String, V> listener) {
+        return delegateMap.removeListener(listener);
+    }
+
+    @Override
+    public CompletableFuture<Boolean> prepare(
+            MapTransaction<String, V> transaction) {
+        return delegateMap.prepare(transaction);
+    }
+
+    @Override
+    public CompletableFuture<Void> commit(TransactionId transactionId) {
+        return delegateMap.commit(transactionId);
+    }
+
+    @Override
+    public CompletableFuture<Void> rollback(TransactionId transactionId) {
+        return delegateMap.rollback(transactionId);
+    }
+
+    @Override
+    public CompletableFuture<Boolean> prepareAndCommit(
+            MapTransaction<String, V> transaction) {
+        return delegateMap.prepareAndCommit(transaction);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other instanceof DelegatingAsyncConsistentTreeMap) {
+            DelegatingAsyncConsistentTreeMap<V> that =
+                    (DelegatingAsyncConsistentTreeMap) other;
+            return this.delegateMap.equals(that.delegateMap);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(delegateMap);
+    }
+
+}
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/DistributedPrimitives.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/DistributedPrimitives.java
index bf1aa0e..83af62d 100644
--- a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/DistributedPrimitives.java
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/DistributedPrimitives.java
@@ -18,6 +18,7 @@
 import java.util.function.Function;
 
 import org.onosproject.store.service.AsyncConsistentMap;
+import org.onosproject.store.service.AsyncConsistentTreeMap;
 import org.onosproject.store.service.AsyncDistributedSet;
 
 /**
@@ -100,4 +101,24 @@
                 valueEncoder,
                 valueDecoder);
     }
+
+    /**
+     * Creates an instance of {@code DistributedTreeMap} that transforms operations inputs and applies them
+     * to corresponding operation in a different typed map and returns the output after reverse transforming it.
+     *
+     * @param map backing map
+     * @param valueEncoder transformer for value type of returned map to value type of input map
+     * @param valueDecoder transformer for value type of input map to value type of returned map
+     * @param <V1> returned map value type
+     * @param <V2> input map key type
+     * @return new map
+     */
+    public static <V1, V2> AsyncConsistentTreeMap<V1> newTranscodingTreeMap(
+            AsyncConsistentTreeMap<V2> map,
+            Function<V1, V2> valueEncoder,
+            Function<V2, V1> valueDecoder) {
+        return new TranscodingAsyncConsistentTreeMap<>(map,
+                                                       valueEncoder,
+                                                       valueDecoder);
+    }
 }
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/FederatedDistributedPrimitiveCreator.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/FederatedDistributedPrimitiveCreator.java
index 4dc2bc4..efb32d7 100644
--- a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/FederatedDistributedPrimitiveCreator.java
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/FederatedDistributedPrimitiveCreator.java
@@ -27,6 +27,7 @@
 import org.onosproject.store.service.AsyncAtomicCounter;
 import org.onosproject.store.service.AsyncAtomicValue;
 import org.onosproject.store.service.AsyncConsistentMap;
+import org.onosproject.store.service.AsyncConsistentTreeMap;
 import org.onosproject.store.service.AsyncDistributedSet;
 import org.onosproject.store.service.AsyncLeaderElector;
 import org.onosproject.store.service.Serializer;
@@ -68,6 +69,12 @@
     }
 
     @Override
+    public <V> AsyncConsistentTreeMap<V> newAsyncConsistentTreeMap(String name,
+                                                                   Serializer serializer) {
+        return getCreator(name).newAsyncConsistentTreeMap(name, serializer);
+    }
+
+    @Override
     public <E> AsyncDistributedSet<E> newAsyncDistributedSet(String name, Serializer serializer) {
         return DistributedPrimitives.newSetFromMap(newAsyncConsistentMap(name, serializer));
     }
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StorageManager.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StorageManager.java
index 7658793..25eb3a5 100644
--- a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StorageManager.java
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StorageManager.java
@@ -47,6 +47,7 @@
 import org.onosproject.store.service.AtomicValueBuilder;
 import org.onosproject.store.service.ConsistentMap;
 import org.onosproject.store.service.ConsistentMapBuilder;
+import org.onosproject.store.service.ConsistentTreeMapBuilder;
 import org.onosproject.store.service.DistributedSetBuilder;
 import org.onosproject.store.service.EventuallyConsistentMapBuilder;
 import org.onosproject.store.service.LeaderElectorBuilder;
@@ -131,6 +132,12 @@
     }
 
     @Override
+    public <V> ConsistentTreeMapBuilder<V> consistentTreeMapBuilder() {
+        return new DefaultConsistentTreeMapBuilder<V>(
+                federatedPrimitiveCreator);
+    }
+
+    @Override
     public <E> DistributedSetBuilder<E> setBuilder() {
         checkPermission(STORAGE_WRITE);
         return new DefaultDistributedSetBuilder<>(() -> this.<E, Boolean>consistentMapBuilder());
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartitionClient.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartitionClient.java
index 205656e..1b59752 100644
--- a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartitionClient.java
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartitionClient.java
@@ -39,6 +39,7 @@
 import org.onlab.util.HexString;
 import org.onosproject.store.primitives.DistributedPrimitiveCreator;
 import org.onosproject.store.primitives.resources.impl.AtomixConsistentMap;
+import org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMap;
 import org.onosproject.store.primitives.resources.impl.AtomixCounter;
 import org.onosproject.store.primitives.resources.impl.AtomixLeaderElector;
 import org.onosproject.store.primitives.resources.impl.AtomixWorkQueue;
@@ -46,6 +47,7 @@
 import org.onosproject.store.service.AsyncAtomicCounter;
 import org.onosproject.store.service.AsyncAtomicValue;
 import org.onosproject.store.service.AsyncConsistentMap;
+import org.onosproject.store.service.AsyncConsistentTreeMap;
 import org.onosproject.store.service.AsyncDistributedSet;
 import org.onosproject.store.service.AsyncLeaderElector;
 import org.onosproject.store.service.DistributedPrimitive.Status;
@@ -143,6 +145,30 @@
     }
 
     @Override
+    public <V> AsyncConsistentTreeMap<V> newAsyncConsistentTreeMap(String name, Serializer serializer) {
+        AtomixConsistentTreeMap atomixConsistentTreeMap =
+                client.getResource(name, AtomixConsistentTreeMap.class).join();
+        Consumer<State> statusListener = state -> {
+            atomixConsistentTreeMap.statusChangeListeners()
+                    .forEach(listener -> listener.accept(mapper.apply(state)));
+        };
+            resourceClient.client().onStateChange(statusListener);
+        AsyncConsistentTreeMap<byte[]> rawMap =
+                new DelegatingAsyncConsistentTreeMap<byte[]>(atomixConsistentTreeMap) {
+                    @Override
+                    public String name() {
+                        return name();
+                    }
+                };
+        AsyncConsistentTreeMap<V> transcodedMap =
+                DistributedPrimitives.<V, byte[]>newTranscodingTreeMap(
+                rawMap,
+                value -> value == null ? null : serializer.encode(value),
+                bytes -> serializer.decode(bytes));
+        return transcodedMap;
+    }
+
+    @Override
     public <E> AsyncDistributedSet<E> newAsyncDistributedSet(String name, Serializer serializer) {
         return DistributedPrimitives.newSetFromMap(this.<E, Boolean>newAsyncConsistentMap(name, serializer));
     }
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/TranscodingAsyncConsistentTreeMap.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/TranscodingAsyncConsistentTreeMap.java
new file mode 100644
index 0000000..71ff975
--- /dev/null
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/TranscodingAsyncConsistentTreeMap.java
@@ -0,0 +1,386 @@
+/*
+ * Copyright 2016 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.store.primitives.impl;
+
+import com.google.common.collect.Maps;
+import org.onlab.util.Tools;
+import org.onosproject.store.primitives.TransactionId;
+import org.onosproject.store.service.AsyncConsistentTreeMap;
+import org.onosproject.store.service.MapEvent;
+import org.onosproject.store.service.MapEventListener;
+import org.onosproject.store.service.MapTransaction;
+import org.onosproject.store.service.Versioned;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.NavigableMap;
+import java.util.NavigableSet;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+/**
+ * Created by admin on 8/3/16.
+ */
+public class TranscodingAsyncConsistentTreeMap<V1, V2>
+        implements AsyncConsistentTreeMap<V1> {
+    private final AsyncConsistentTreeMap<V2> backingMap;
+    private final Function<V2, V1> valueDecoder;
+    private final Function<V1, V2> valueEncoder;
+    private final Function<Versioned<V2>, Versioned<V1>>
+            versionedValueTransform;
+    private final Map<MapEventListener<String, V1>,
+            TranscodingAsyncConsistentTreeMap.InternalBackingMapEventListener>
+            listeners = Maps.newIdentityHashMap();
+
+    public TranscodingAsyncConsistentTreeMap(
+            AsyncConsistentTreeMap<V2> backingMap,
+            Function<V1, V2> valueEncoder,
+            Function<V2, V1> valueDecoder) {
+        this.backingMap = backingMap;
+        this.valueEncoder = v -> v == null ? null : valueEncoder.apply(v);
+        this.valueDecoder = v -> v == null ? null : valueDecoder.apply(v);
+        this.versionedValueTransform = v -> v == null ? null :
+                v.map(valueDecoder);
+    }
+    @Override
+    public CompletableFuture<String> firstKey() {
+        return backingMap.firstKey();
+    }
+
+    @Override
+    public CompletableFuture<String> lastKey() {
+        return backingMap.lastKey();
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V1>>>
+    ceilingEntry(String key) {
+        return backingMap.ceilingEntry(key)
+                .thenApply(
+                        entry ->
+                                Maps.immutableEntry(
+                                        entry.getKey(),
+                                        entry.getValue().map(valueDecoder)));
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V1>>>
+    floorEntry(String key) {
+        return backingMap.floorEntry(key)
+                .thenApply(
+                        entry ->
+                                Maps.immutableEntry(
+                                        entry.getKey(),
+                                        entry.getValue().map(valueDecoder)));
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V1>>>
+    higherEntry(String key) {
+        return backingMap
+                .higherEntry(key)
+                .thenApply(entry ->
+                               Maps.immutableEntry(
+                                       entry.getKey(),
+                                       entry.getValue().map(valueDecoder)));
+}
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V1>>>
+    lowerEntry(String key) {
+        return backingMap.lowerEntry(key).thenApply(
+                entry ->
+                    Maps.immutableEntry(
+                            entry.getKey(),
+                            entry.getValue().map(valueDecoder)));
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V1>>>
+    firstEntry() {
+        return backingMap.firstEntry()
+                .thenApply(entry ->
+                                   Maps.immutableEntry(
+                                       entry.getKey(),
+                                       entry.getValue().map(valueDecoder)));
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V1>>>
+    lastEntry() {
+        return backingMap.lastEntry()
+                .thenApply(
+                        entry -> Maps.immutableEntry(
+                                entry.getKey(),
+                                entry.getValue().map(valueDecoder)));
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V1>>>
+    pollFirstEntry() {
+        return backingMap.pollFirstEntry()
+                .thenApply(
+                        entry -> Maps.immutableEntry(
+                                entry.getKey(),
+                                entry.getValue().map(valueDecoder)));
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V1>>>
+    pollLastEntry() {
+        return backingMap.pollLastEntry()
+                .thenApply(entry -> Maps.immutableEntry(
+                        entry.getKey(),
+                        entry.getValue().map(valueDecoder)));
+    }
+
+    @Override
+    public CompletableFuture<String> lowerKey(String key) {
+        return backingMap.lowerKey(key);
+    }
+
+    @Override
+    public CompletableFuture<String> floorKey(String key) {
+        return backingMap.floorKey(key);
+    }
+
+    @Override
+    public CompletableFuture<String> ceilingKey(String key) {
+        return backingMap.ceilingKey(key);
+    }
+
+    @Override
+    public CompletableFuture<String> higherKey(String key) {
+        return backingMap.higherKey(key);
+    }
+
+    @Override
+    public CompletableFuture<NavigableSet<String>> navigableKeySet() {
+        return backingMap.navigableKeySet();
+    }
+
+    @Override
+    public CompletableFuture<NavigableMap<String, V1>> subMap(
+            String upperKey,
+            String lowerKey,
+            boolean inclusiveUpper,
+            boolean inclusiveLower) {
+        throw new UnsupportedOperationException("This operation is not yet" +
+                                                        "supported.");
+    }
+
+    @Override
+    public String name() {
+        return backingMap.name();
+    }
+
+    @Override
+    public CompletableFuture<Integer> size() {
+        return backingMap.size();
+    }
+
+    @Override
+    public CompletableFuture<Boolean> containsKey(String key) {
+        return backingMap.containsKey(key);
+    }
+
+    @Override
+    public CompletableFuture<Boolean> containsValue(V1 value) {
+        return backingMap.containsValue(valueEncoder.apply(value));
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V1>> get(String key) {
+        return backingMap.get(key).thenApply(value -> value.map(valueDecoder));
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V1>> computeIf(
+            String key, Predicate<? super V1> condition,
+            BiFunction<? super String, ? super V1, ? extends V1>
+                    remappingFunction) {
+        try {
+            return backingMap
+                    .computeIf(
+                            key,
+                            v -> condition.test(valueDecoder.apply(v)),
+                            (k, v) -> valueEncoder
+                                    .apply(
+                                            remappingFunction.apply(
+                                                    key,
+                                                    valueDecoder.apply(v))))
+                    .thenApply(versionedValueTransform);
+        } catch (Exception e) {
+            return Tools.exceptionalFuture(e);
+        }
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V1>> put(String key, V1 value) {
+        return backingMap.put(key, valueEncoder.apply(value))
+                .thenApply(v -> v.map(valueDecoder));
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V1>> putAndGet(String key, V1 value) {
+        return backingMap.putAndGet(key, valueEncoder.apply(value))
+                .thenApply(v -> v.map(valueDecoder));
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V1>> remove(String key) {
+        return backingMap.remove(key).thenApply(v -> v.map(valueDecoder));
+    }
+
+    @Override
+    public CompletableFuture<Void> clear() {
+        return backingMap.clear();
+    }
+
+    @Override
+    public CompletableFuture<Set<String>> keySet() {
+        return backingMap.keySet();
+    }
+
+    @Override
+    public CompletableFuture<Collection<Versioned<V1>>> values() {
+        return backingMap.values().thenApply(valueSet -> valueSet.stream()
+                .map(v -> v.map(valueDecoder)).collect(Collectors.toSet()));
+    }
+
+    @Override
+    public CompletableFuture<Set<Map.Entry<String, Versioned<V1>>>>
+    entrySet() {
+        return backingMap.entrySet()
+                .thenApply(
+                    entries -> entries
+                        .stream()
+                        .map(entry ->
+                             Maps.immutableEntry(entry.getKey(),
+                                                 entry.getValue()
+                                                     .map(valueDecoder)))
+                            .collect(Collectors.toSet()));
+        }
+
+    @Override
+    public CompletableFuture<Versioned<V1>> putIfAbsent(String key, V1 value) {
+        return backingMap.putIfAbsent(key, valueEncoder.apply(value))
+                .thenApply(v -> v.map(valueDecoder));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> remove(String key, V1 value) {
+        return backingMap.remove(key, valueEncoder.apply(value));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> remove(String key, long version) {
+        return backingMap.remove(key, version);
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V1>> replace(String key, V1 value) {
+        return backingMap.replace(key, valueEncoder.apply(value))
+                .thenApply(v -> v.map(valueDecoder));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> replace(String key, V1 oldValue,
+                                              V1 newValue) {
+        return backingMap.replace(key, valueEncoder.apply(oldValue),
+                                  valueEncoder.apply(newValue));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> replace(String key, long oldVersion,
+                                              V1 newValue) {
+        return backingMap.replace(key, oldVersion,
+                                  valueEncoder.apply(newValue));
+    }
+
+    @Override
+    public CompletableFuture<Void> addListener(
+            MapEventListener<String, V1> listener,
+            Executor executor) {
+        InternalBackingMapEventListener backingMapEventListener =
+                listeners.computeIfAbsent(
+                        listener,
+                        k -> new InternalBackingMapEventListener(listener));
+        return backingMap.addListener(backingMapEventListener, executor);
+    }
+
+    @Override
+    public CompletableFuture<Void> removeListener(
+            MapEventListener<String, V1> listener) {
+        InternalBackingMapEventListener backingMapEventListener =
+                listeners.remove(listener);
+        if (backingMapEventListener == null) {
+            return CompletableFuture.completedFuture(null);
+        } else {
+            return backingMap.removeListener(backingMapEventListener);
+        }
+    }
+
+    @Override
+    public CompletableFuture<Boolean> prepare(
+            MapTransaction<String, V1> transaction) {
+        throw new UnsupportedOperationException("This operation is not yet " +
+                                                        "supported.");
+    }
+
+    @Override
+    public CompletableFuture<Void> commit(TransactionId transactionId) {
+        throw new UnsupportedOperationException("This operation is not yet " +
+                                                        "supported.");    }
+
+    @Override
+    public CompletableFuture<Void> rollback(TransactionId transactionId) {
+        throw new UnsupportedOperationException("This operation is not yet " +
+                                                        "supported.");    }
+
+    @Override
+    public CompletableFuture<Boolean> prepareAndCommit(
+            MapTransaction<String, V1> transaction) {
+        throw new UnsupportedOperationException("This operation is not yet " +
+                                                        "supported.");    }
+    private class InternalBackingMapEventListener
+            implements MapEventListener<String, V2> {
+
+        private final MapEventListener<String, V1> listener;
+
+        InternalBackingMapEventListener(
+                MapEventListener<String, V1> listener) {
+            this.listener = listener;
+        }
+
+        @Override
+        public void event(MapEvent<String, V2> event) {
+            listener.event(new MapEvent<String, V1>(
+                    event.name(),
+                    event.key(),
+                    event.newValue() != null ?
+                            event.newValue().map(valueDecoder) : null,
+                    event.oldValue() != null ?
+                            event.oldValue().map(valueDecoder) : null));
+        }
+    }
+}