State machine implementations for various distributed primitives based on latest Copycat APIs

Change-Id: I622cc196aa1cdf072a5a0b100a5ffaaf71b07900
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/resources/impl/MapEntryUpdateResult.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/resources/impl/MapEntryUpdateResult.java
new file mode 100644
index 0000000..7858595
--- /dev/null
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/resources/impl/MapEntryUpdateResult.java
@@ -0,0 +1,157 @@
+
+/*
+ * Copyright 2015 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.resources.impl;
+
+import java.util.function.Function;
+
+import org.onosproject.store.service.MapEvent;
+import org.onosproject.store.service.Versioned;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Result of a map entry update operation.
+ * <p>
+ * Both old and new values are accessible along with a flag that indicates if the
+ * the value was updated. If flag is false, oldValue and newValue both
+ * point to the same unmodified value.
+ * @param <V> result type
+ */
+public class MapEntryUpdateResult<K, V> {
+
+    public enum Status {
+
+        /**
+         * Indicates a successful update.
+         */
+        OK,
+
+        /**
+         * Indicates a noop i.e. existing and new value are both null.
+         */
+        NOOP,
+
+        /**
+         * Indicates a failed update due to a write lock.
+         */
+        WRITE_LOCK,
+
+        /**
+         * Indicates a failed update due to a precondition check failure.
+         */
+        PRECONDITION_FAILED
+    }
+
+    private final String mapName;
+    private Status status;
+    private final K key;
+    private final Versioned<V> oldValue;
+    private final Versioned<V> newValue;
+
+    public MapEntryUpdateResult(Status status, String mapName, K key, Versioned<V> oldValue, Versioned<V> newValue) {
+        this.status = status;
+        this.mapName = mapName;
+        this.key = key;
+        this.oldValue = oldValue;
+        this.newValue = newValue;
+    }
+
+    /**
+     * Returns {@code true} if the update was successful.
+     * @return {@code true} if yes, {@code false} otherwise
+     */
+    public boolean updated() {
+        return status == Status.OK;
+    }
+
+    /**
+     * Returns the map name.
+     * @return map name
+     */
+    public String mapName() {
+        return mapName;
+    }
+
+    /**
+     * Returns the update status.
+     * @return update status
+     */
+    public Status status() {
+        return status;
+    }
+
+    /**
+     * Returns the map key.
+     * @return key
+     */
+    public K key() {
+        return key;
+    }
+
+    /**
+     * Returns the old value.
+     * @return the previous value associated with key if updated was successful, otherwise current value
+     */
+    public Versioned<V> oldValue() {
+        return oldValue;
+    }
+
+    /**
+     * Returns the new value after update.
+     * @return if updated was unsuccessful, this is same as old value
+     */
+    public Versioned<V> newValue() {
+        return newValue;
+    }
+
+    /**
+     * Maps to another instance with different key and value types.
+     * @param keyTransform transformer to use for transcoding keys
+     * @param valueMapper mapper to use for transcoding values
+     * @return new instance
+     */
+    public <K1, V1> MapEntryUpdateResult<K1, V1> map(Function<K, K1> keyTransform, Function<V, V1> valueMapper) {
+        return new MapEntryUpdateResult<>(status,
+                mapName,
+                keyTransform.apply(key),
+                oldValue == null ? null : oldValue.map(valueMapper),
+                newValue == null ? null : newValue.map(valueMapper));
+    }
+
+    /**
+     * Return the map event that will be generated as a result of this update.
+     * @return map event. if update was unsuccessful, this returns {@code null}
+     */
+    public MapEvent<K, V> toMapEvent() {
+        if (!updated()) {
+            return null;
+        } else {
+            return new MapEvent<>(mapName(), key(), newValue, oldValue);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(MapEntryUpdateResult.class)
+                .add("mapName", mapName)
+                .add("status", status)
+                .add("key", key)
+                .add("oldValue", oldValue)
+                .add("newValue", newValue)
+                .toString();
+    }
+}