implemented annotation merging on SimpleDeviceStore.

- Added annotation support to PortsDescriptions

Change-Id: I157e4fb93b8f387b405722b8d004501d993decda
diff --git a/core/api/src/main/java/org/onlab/onos/net/DefaultAnnotations.java b/core/api/src/main/java/org/onlab/onos/net/DefaultAnnotations.java
index 001518e..0c0f375 100644
--- a/core/api/src/main/java/org/onlab/onos/net/DefaultAnnotations.java
+++ b/core/api/src/main/java/org/onlab/onos/net/DefaultAnnotations.java
@@ -1,5 +1,6 @@
 package org.onlab.onos.net;
 
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
@@ -71,9 +72,33 @@
         return new DefaultAnnotations(merged);
     }
 
+    /**
+     * Convert Annotations to DefaultAnnotations if needed and merges.
+     *
+     * @see #merge(DefaultAnnotations, SparseAnnotations)
+     *
+     * @param annotations       base annotations
+     * @param sparseAnnotations additional sparse annotations
+     * @return combined annotations or the original base annotations if there
+     * are not additional annotations
+     */
+    public static DefaultAnnotations merge(Annotations annotations,
+                                    SparseAnnotations sparseAnnotations) {
+        if (annotations instanceof DefaultAnnotations) {
+            return merge((DefaultAnnotations) annotations, sparseAnnotations);
+        }
+
+        DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
+        for (String key : annotations.keys()) {
+            builder.set(key, annotations.value(key));
+        }
+        return merge(builder.build(), sparseAnnotations);
+    }
+
     @Override
     public Set<String> keys() {
-        return map.keySet();
+        // TODO: unmodifiable to be removed after switching to ImmutableMap;
+        return Collections.unmodifiableSet(map.keySet());
     }
 
     @Override
diff --git a/core/api/src/main/java/org/onlab/onos/net/device/DefaultDeviceDescription.java b/core/api/src/main/java/org/onlab/onos/net/device/DefaultDeviceDescription.java
index fd04e5c..788d23a 100644
--- a/core/api/src/main/java/org/onlab/onos/net/device/DefaultDeviceDescription.java
+++ b/core/api/src/main/java/org/onlab/onos/net/device/DefaultDeviceDescription.java
@@ -45,6 +45,18 @@
         this.serialNumber = serialNumber;
     }
 
+    /**
+     * Creates a device description using the supplied information.
+     * @param base DeviceDescription to basic information
+     * @param annotations Annotations to use.
+     */
+    public DefaultDeviceDescription(DeviceDescription base,
+                                    SparseAnnotations... annotations) {
+        this(base.deviceURI(), base.type(), base.manufacturer(),
+             base.hwVersion(), base.swVersion(), base.serialNumber(),
+             annotations);
+    }
+
     @Override
     public URI deviceURI() {
         return uri;
diff --git a/core/api/src/main/java/org/onlab/onos/net/device/DefaultPortDescription.java b/core/api/src/main/java/org/onlab/onos/net/device/DefaultPortDescription.java
index 1d52ac9..eb75ede 100644
--- a/core/api/src/main/java/org/onlab/onos/net/device/DefaultPortDescription.java
+++ b/core/api/src/main/java/org/onlab/onos/net/device/DefaultPortDescription.java
@@ -1,20 +1,43 @@
 package org.onlab.onos.net.device;
 
+import org.onlab.onos.net.AbstractDescription;
 import org.onlab.onos.net.PortNumber;
+import org.onlab.onos.net.SparseAnnotations;
 
 /**
  * Default implementation of immutable port description.
  */
-public class DefaultPortDescription implements PortDescription {
+public class DefaultPortDescription extends AbstractDescription
+        implements PortDescription {
 
     private final PortNumber number;
     private final boolean isEnabled;
 
-    public DefaultPortDescription(PortNumber number, boolean isEnabled) {
+    /**
+     * Creates a port description using the supplied information.
+     *
+     * @param number       port number
+     * @param isEnabled    port enabled state
+     * @param annotations  optional key/value annotations map
+     */
+    public DefaultPortDescription(PortNumber number, boolean isEnabled,
+                SparseAnnotations... annotations) {
+        super(annotations);
         this.number = number;
         this.isEnabled = isEnabled;
     }
 
+    /**
+     * Creates a port description using the supplied information.
+     *
+     * @param base         PortDescription to get basic information from
+     * @param annotations  optional key/value annotations map
+     */
+    public DefaultPortDescription(PortDescription base,
+            SparseAnnotations annotations) {
+        this(base.portNumber(), base.isEnabled(), annotations);
+    }
+
     @Override
     public PortNumber portNumber() {
         return number;
diff --git a/core/api/src/main/java/org/onlab/onos/net/device/PortDescription.java b/core/api/src/main/java/org/onlab/onos/net/device/PortDescription.java
index f0dc8ee..f01b49c 100644
--- a/core/api/src/main/java/org/onlab/onos/net/device/PortDescription.java
+++ b/core/api/src/main/java/org/onlab/onos/net/device/PortDescription.java
@@ -1,11 +1,12 @@
 package org.onlab.onos.net.device;
 
+import org.onlab.onos.net.Description;
 import org.onlab.onos.net.PortNumber;
 
 /**
  * Information about a port.
  */
-public interface PortDescription {
+public interface PortDescription extends Description {
 
     // TODO: possibly relocate this to a common ground so that this can also used by host tracking if required