[ONOS-7547] Implement support for backwards/forward compatibility of ConsistentMap values on read

Change-Id: Ifffb6a883ec4ee6aa5587da58a51c1e90694e5ea
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 d116988..78c41e8 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
@@ -15,6 +15,7 @@
  */
 package org.onosproject.store.primitives.impl;
 
+import org.onosproject.core.Version;
 import org.onosproject.store.service.AsyncAtomicCounterMap;
 import org.onosproject.store.service.AsyncConsistentMap;
 import org.onosproject.store.service.AsyncConsistentMultimap;
@@ -22,6 +23,7 @@
 import org.onosproject.store.service.AsyncDistributedSet;
 import org.onosproject.store.service.AsyncDocumentTree;
 
+import java.util.function.BiFunction;
 import java.util.function.Function;
 
 /**
@@ -91,6 +93,30 @@
     }
 
     /**
+     * Creates an instance of {@code AsyncConsistentMap} that converts values from other versions.
+     *
+     * @param map backing map
+     * @param compatibilityFunction the compatibility function
+     * @param version local node version
+     * @param <K> map key type
+     * @param <V> map value type
+     * @return compatible map
+     */
+    public static <K, V> AsyncConsistentMap<K, V> newCompatibleMap(
+        AsyncConsistentMap<K, CompatibleValue<V>> map,
+        BiFunction<V, Version, V> compatibilityFunction,
+        Version version) {
+        Function<V, CompatibleValue<V>> encoder = value -> new CompatibleValue<>(value, version);
+        Function<CompatibleValue<V>, V> decoder = value -> {
+            if (!value.version().equals(version)) {
+                return compatibilityFunction.apply(value.value(), value.version());
+            }
+            return value.value();
+        };
+        return new TranscodingAsyncConsistentMap<>(map, k -> k, k -> k, encoder, decoder);
+    }
+
+    /**
      * Creates an instance of {@code AsyncAtomicCounterMap} that transforms key types.
      *
      * @param map backing map