Implemented a Builder pattern for EventuallyConsistentMaps.

EventuallyConsistentMap has been moved to the API package so is now available outside the stores.

ONOS-1357

Change-Id: I1c892eb3dbefa72cb3f3eb3ccc74e9a02c7e2ac9
diff --git a/core/api/src/main/java/org/onosproject/store/service/ClockService.java b/core/api/src/main/java/org/onosproject/store/service/ClockService.java
new file mode 100644
index 0000000..a0de0a9
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/store/service/ClockService.java
@@ -0,0 +1,35 @@
+/*
+ * 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.service;
+
+import org.onosproject.store.Timestamp;
+
+/**
+ * Clock service that can generate timestamps based off of two input objects.
+ * Implementations are free to only take one or none of the objects into account
+ * when generating timestamps.
+ */
+public interface ClockService<T, U> {
+
+    /**
+     * Gets a new timestamp for the given objects.
+     *
+     * @param object1 First object to use when generating timestamps
+     * @param object2 Second object to use when generating timestamps
+     * @return the new timestamp
+     */
+    public Timestamp getTimestamp(T object1, U object2);
+}
diff --git a/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMap.java b/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMap.java
new file mode 100644
index 0000000..58a81cc
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMap.java
@@ -0,0 +1,197 @@
+/*
+ * 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.service;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A distributed, eventually consistent map.
+ * <p>
+ * This map does not offer read after writes consistency. Operations are
+ * serialized via the timestamps issued by the clock service. If two updates
+ * are in conflict, the update with the more recent timestamp will endure.
+ * </p><p>
+ * The interface is mostly similar to {@link java.util.Map} with some minor
+ * semantic changes and the addition of a listener framework (because the map
+ * can be mutated by clients on other instances, not only through the local Java
+ * API).
+ * </p><p>
+ * Clients are expected to register an
+ * {@link EventuallyConsistentMapListener} if they
+ * are interested in receiving notifications of update to the map.
+ * </p><p>
+ * Null values are not allowed in this map.
+ * </p>
+ */
+public interface EventuallyConsistentMap<K, V> {
+
+    /**
+     * Returns the number of key-value mappings in this map.
+     *
+     * @return number of key-value mappings
+     */
+    public int size();
+
+    /**
+     * Returns true if this map is empty.
+     *
+     * @return true if this map is empty, otherwise false
+     */
+    public boolean isEmpty();
+
+    /**
+     * Returns true if the map contains a mapping for the specified key.
+     *
+     * @param key the key to check if this map contains
+     * @return true if this map has a mapping for the key, otherwise false
+     */
+    public boolean containsKey(K key);
+
+    /**
+     * Returns true if the map contains a mapping from any key to the specified
+     * value.
+     *
+     * @param value the value to check if this map has a mapping for
+     * @return true if this map has a mapping to this value, otherwise false
+     */
+    public boolean containsValue(V value);
+
+    /**
+     * Returns the value mapped to the specified key.
+     *
+     * @param key the key to look up in this map
+     * @return the value mapped to the key, or null if no mapping is found
+     */
+    public V get(K key);
+
+    /**
+     * Associates the specified value to the specified key in this map.
+     * <p>
+     * Note: this differs from the specification of {@link java.util.Map}
+     * because it does not return the previous value associated with the key.
+     * Clients are expected to register an
+     * {@link EventuallyConsistentMapListener} if
+     * they are interested in receiving notification of updates to the map.
+     * </p><p>
+     * Null values are not allowed in the map.
+     * </p>
+     *
+     * @param key the key to add a mapping for in this map
+     * @param value the value to associate with the key in this map
+     */
+    public void put(K key, V value);
+
+    /**
+     * Removes the mapping associated with the specified key from the map.
+     * <p>
+     * Note: this differs from the specification of {@link java.util.Map}
+     * because it does not return the previous value associated with the key.
+     * Clients are expected to register an
+     * {@link EventuallyConsistentMapListener} if
+     * they are interested in receiving notification of updates to the map.
+     * </p>
+     *
+     * @param key the key to remove the mapping for
+     */
+    public void remove(K key);
+
+    /**
+     * Removes the given key-value mapping from the map, if it exists.
+     * <p>
+     * This actually means remove any values up to and including the timestamp
+     * given by {@link org.onosproject.store.service.ClockService#getTimestamp(Object, Object)}.
+     * Any mappings that produce an earlier timestamp than this given key-value
+     * pair will be removed, and any mappings that produce a later timestamp
+     * will supersede this remove.
+     * </p><p>
+     * Note: this differs from the specification of {@link java.util.Map}
+     * because it does not return a boolean indication whether a value was removed.
+     * Clients are expected to register an
+     * {@link EventuallyConsistentMapListener} if
+     * they are interested in receiving notification of updates to the map.
+     * </p>
+     *
+     * @param key the key to remove the mapping for
+     * @param value the value mapped to the key
+     */
+    public void remove(K key, V value);
+
+    /**
+     * Adds mappings for all key-value pairs in the specified map to this map.
+     * <p>
+     * This will be more efficient in communication than calling individual put
+     * operations.
+     * </p>
+     *
+     * @param m a map of values to add to this map
+     */
+    public void putAll(Map<? extends K, ? extends V> m);
+
+    /**
+     * Removes all mappings from this map.
+     */
+    public void clear();
+
+    /**
+     * Returns a set of the keys in this map. Changes to the set are not
+     * reflected back to the map.
+     *
+     * @return set of keys in the map
+     */
+    public Set<K> keySet();
+
+    /**
+     * Returns a collections of values in this map. Changes to the collection
+     * are not reflected back to the map.
+     *
+     * @return collection of values in the map
+     */
+    public Collection<V> values();
+
+    /**
+     * Returns a set of mappings contained in this map. Changes to the set are
+     * not reflected back to the map.
+     *
+     * @return set of key-value mappings in this map
+     */
+    public Set<Map.Entry<K, V>> entrySet();
+
+    /**
+     * Adds the specified listener to the map which will be notified whenever
+     * the mappings in the map are changed.
+     *
+     * @param listener listener to register for events
+     */
+    public void addListener(EventuallyConsistentMapListener<K, V> listener);
+
+    /**
+     * Removes the specified listener from the map such that it will no longer
+     * receive change notifications.
+     *
+     * @param listener listener to deregister for events
+     */
+    public void removeListener(EventuallyConsistentMapListener<K, V> listener);
+
+    /**
+     * Shuts down the map and breaks communication between different instances.
+     * This allows the map objects to be cleaned up and garbage collected.
+     * Calls to any methods on the map subsequent to calling destroy() will
+     * throw a {@link java.lang.RuntimeException}.
+     */
+    public void destroy();
+}
diff --git a/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapBuilder.java b/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapBuilder.java
new file mode 100644
index 0000000..779c329
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapBuilder.java
@@ -0,0 +1,176 @@
+/*
+ * 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.service;
+
+import org.onlab.util.KryoNamespace;
+import org.onosproject.cluster.NodeId;
+
+import java.util.Collection;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.function.BiFunction;
+
+/**
+ * Builder for eventually consistent maps.
+ *
+ * @param <K> type for map keys
+ * @param <V> type for map values
+ */
+public interface EventuallyConsistentMapBuilder<K, V> {
+
+    /**
+     * Sets the name of the map.
+     * <p>
+     * Each map is identified by a string map name. EventuallyConsistentMapImpl
+     * objects in different JVMs that use the same map name will form a
+     * distributed map across JVMs (provided the cluster service is aware of
+     * both nodes).
+     * </p>
+     * <p>
+     * Note: This is a mandatory parameter.
+     * </p>
+     *
+     * @param name name of the map
+     * @return this EventuallyConsistentMapBuilder
+     */
+    public EventuallyConsistentMapBuilder<K, V> withName(String name);
+
+    /**
+     * Sets a serializer builder that can be used to create a serializer that
+     * can serialize both the keys and values put into the map. The serializer
+     * builder should be pre-populated with any classes that will be put into
+     * the map.
+     * <p>
+     * Note: This is a mandatory parameter.
+     * </p>
+     *
+     * @param serializerBuilder serializer builder
+     * @return this EventuallyConsistentMapBuilder
+     */
+    public EventuallyConsistentMapBuilder<K, V> withSerializer(
+            KryoNamespace.Builder serializerBuilder);
+
+    /**
+     * Sets the clock service to use for generating timestamps for map updates.
+     * <p>
+     * The client must provide an {@link org.onosproject.store.service.ClockService}
+     * which can generate timestamps for a given key. The clock service is free
+     * to generate timestamps however it wishes, however these timestamps will
+     * be used to serialize updates to the map so they must be strict enough
+     * to ensure updates are properly ordered for the use case (i.e. in some
+     * cases wallclock time will suffice, whereas in other cases logical time
+     * will be necessary).
+     * </p>
+     * <p>
+     * Note: This is a mandatory parameter.
+     * </p>
+     *
+     * @param clockService clock service
+     * @return this EventuallyConsistentMapBuilder
+     */
+    public EventuallyConsistentMapBuilder<K, V> withClockService(
+            ClockService<K, V> clockService);
+
+    /**
+     * Sets the executor to use for processing events coming in from peers.
+     *
+     * @param executor event executor
+     * @return this EventuallyConsistentMapBuilder
+     */
+    public EventuallyConsistentMapBuilder<K, V> withEventExecutor(
+            ExecutorService executor);
+
+    /**
+     * Sets the executor to use for sending events to peers.
+     *
+     * @param executor event executor
+     * @return this EventuallyConsistentMapBuilder
+     */
+    public EventuallyConsistentMapBuilder<K, V> withCommunicationExecutor(
+            ExecutorService executor);
+
+    /**
+     * Sets the executor to use for background anti-entropy tasks.
+     *
+     * @param executor event executor
+     * @return this EventuallyConsistentMapBuilder
+     */
+    public EventuallyConsistentMapBuilder<K, V> withBackgroundExecutor(
+            ScheduledExecutorService executor);
+
+    /**
+     * Sets a function that can determine which peers to replicate updates to.
+     * <p>
+     * The default function replicates to all nodes.
+     * </p>
+     *
+     * @param peerUpdateFunction function that takes a K, V input and returns
+     *                           a collection of NodeIds to replicate the event
+     *                           to
+     * @return this EventuallyConsistentMapBuilder
+     */
+    public EventuallyConsistentMapBuilder<K, V> withPeerUpdateFunction(
+            BiFunction<K, V, Collection<NodeId>> peerUpdateFunction);
+
+    /**
+     * Prevents this map from writing tombstones of items that have been
+     * removed. This may result in zombie items reappearing after they have
+     * been removed.
+     * <p>
+     * The default behavior is tombstones are enabled.
+     * </p>
+     *
+     * @return this EventuallyConsistentMapBuilder
+     */
+    public EventuallyConsistentMapBuilder<K, V> withTombstonesDisabled();
+
+    /**
+     * Configures how often to run the anti-entropy background task.
+     * <p>
+     * The default anti-entropy period is 5 seconds.
+     * </p>
+     *
+     * @param period anti-entropy period
+     * @param unit time unit for the period
+     * @return this EventuallyConsistentMapBuilder
+     */
+    public EventuallyConsistentMapBuilder<K, V> withAntiEntropyPeriod(
+            long period, TimeUnit unit);
+
+    /**
+     * Configure anti-entropy to converge faster at the cost of doing more work
+     * for each anti-entropy cycle. Suited to maps with low update rate where
+     * convergence time is more important than throughput.
+     * <p>
+     * The default behavior is to do less anti-entropy work at the cost of
+     * slower convergence.
+     * </p>
+     *
+     * @return this EventuallyConsistentMapBuilder
+     */
+    public EventuallyConsistentMapBuilder<K, V> withFasterConvergence();
+
+    /**
+     * Builds an eventually consistent map based on the configuration options
+     * supplied to this builder.
+     *
+     * @return new eventually consistent map
+     * @throws java.lang.RuntimeException if a mandatory parameter is missing
+     */
+    public EventuallyConsistentMap<K, V> build();
+}
diff --git a/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapEvent.java b/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapEvent.java
new file mode 100644
index 0000000..8f63325
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapEvent.java
@@ -0,0 +1,101 @@
+/*
+ * 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.service;
+
+import com.google.common.base.MoreObjects;
+
+import java.util.Objects;
+
+/**
+ * Event object signalling that the map was modified.
+ */
+public class EventuallyConsistentMapEvent<K, V> {
+
+    public enum Type {
+        PUT,
+        REMOVE
+    }
+
+    private final Type type;
+    private final K key;
+    private final V value;
+
+    /**
+     * Creates a new event object.
+     *
+     * @param type the type of the event
+     * @param key the key the event concerns
+     * @param value the value related to the key, or null for remove events
+     */
+    public EventuallyConsistentMapEvent(Type type, K key, V value) {
+        this.type = type;
+        this.key = key;
+        this.value = value;
+    }
+
+    /**
+     * Returns the type of the event.
+     *
+     * @return the type of the event
+     */
+    public Type type() {
+        return type;
+    }
+
+    /**
+     * Returns the key this event concerns.
+     *
+     * @return the key
+     */
+    public K key() {
+        return key;
+    }
+
+    /**
+     * Returns the value associated with this event.
+     *
+     * @return the value, or null if the event was REMOVE
+     */
+    public V value() {
+        return value;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof EventuallyConsistentMapEvent)) {
+            return false;
+        }
+
+        EventuallyConsistentMapEvent that = (EventuallyConsistentMapEvent) o;
+        return Objects.equals(this.type, that.type) &&
+                Objects.equals(this.key, that.key) &&
+                Objects.equals(this.value, that.value);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type, key, value);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("type", type)
+                .add("key", key)
+                .add("value", value)
+                .toString();
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapListener.java b/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapListener.java
new file mode 100644
index 0000000..686255e
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/store/service/EventuallyConsistentMapListener.java
@@ -0,0 +1,30 @@
+/*
+ * 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.service;
+
+/**
+ * Listener interested in receiving modification events for an
+ * EventuallyConsistentMap.
+ */
+public interface EventuallyConsistentMapListener<K, V> {
+
+    /**
+     * Reacts to the specified event.
+     *
+     * @param event the event
+     */
+    public void event(EventuallyConsistentMapEvent<K, V> event);
+}
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 7e447cc..a59e376 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
@@ -30,6 +30,7 @@
 
     /**
      * Creates a ConsistentMap.
+     *
      * @param name map name
      * @param serializer serializer to use for serializing keys and values
      * @return consistent map.
@@ -40,6 +41,7 @@
 
     /**
      * Creates a AsyncConsistentMap.
+     *
      * @param name map name
      * @param serializer serializer to use for serializing keys and values
      * @return async consistent map
@@ -50,7 +52,18 @@
 
     /**
      * Creates a new transaction context.
+     *
      * @return transaction context
      */
     TransactionContext createTransactionContext();
-}
\ No newline at end of file
+
+    /**
+     * Creates a new EventuallyConsistentMapBuilder.
+     *
+     * @param <K> key type
+     * @param <V> value type
+     * @return builder for an eventually consistent map
+     */
+    <K, V> EventuallyConsistentMapBuilder<K, V> eventuallyConsistentMapBuilder();
+
+}