[VOL-4055][ONOS-8138] Adding annotations to meter to allow passing of associated information

This patch allows for adding key value elements in the meter request and in the meter generated from it.
An example is:
Annotations annotations = DefaultAnnotations.builder().set("MeterForDeviceType", "olt").build();
DefaultMeterRequest.builder().withAnnotations(annotations)
Generates:
 DefaultMeter{device=of:00000a0a0a0a0a0b, cellId=2, appId=org.opencord.olt, unit=KB_PER_SEC, isBurst=true, state=ADDED, bands=[DefaultBand{rate=100000, burst-size=5000, type=DROP, drop-precedence=null}, DefaultBand{rate=100000, burst-size=5000, type=DROP, drop-precedence=null}, DefaultBand{rate=100000, burst-size=0, type=DROP, drop-precedence=null}], annotations={MeterForDeviceType=olt}}

Change-Id: Ifaded96ebeb7956bc60cdf311180c984c3ba954e
diff --git a/core/api/src/main/java/org/onosproject/net/meter/DefaultMeter.java b/core/api/src/main/java/org/onosproject/net/meter/DefaultMeter.java
index ad0256e..681846f 100644
--- a/core/api/src/main/java/org/onosproject/net/meter/DefaultMeter.java
+++ b/core/api/src/main/java/org/onosproject/net/meter/DefaultMeter.java
@@ -18,6 +18,8 @@
 import com.google.common.base.Objects;
 import com.google.common.collect.ImmutableSet;
 import org.onosproject.core.ApplicationId;
+import org.onosproject.net.AbstractAnnotated;
+import org.onosproject.net.Annotations;
 import org.onosproject.net.DeviceId;
 
 import java.util.Collection;
@@ -30,7 +32,7 @@
 /**
  * A default implementation of a meter.
  */
-public final class DefaultMeter implements Meter, MeterEntry  {
+public final class DefaultMeter extends AbstractAnnotated implements Meter, MeterEntry {
 
 
     private final MeterCellId cellId;
@@ -47,7 +49,9 @@
     private long bytes;
 
     private DefaultMeter(DeviceId deviceId, MeterCellId cellId, ApplicationId appId,
-                         Unit unit, boolean burst, Collection<Band> bands) {
+                         Unit unit, boolean burst, Collection<Band> bands,
+                         Annotations... annotations) {
+        super(annotations);
         this.deviceId = deviceId;
         this.cellId = cellId;
         this.appId = appId;
@@ -158,7 +162,9 @@
                 .add("unit", unit)
                 .add("isBurst", burst)
                 .add("state", state)
-                .add("bands", bands).toString();
+                .add("bands", bands)
+                .add("annotations", annotations())
+                .toString();
     }
 
     @Override
@@ -189,6 +195,7 @@
         private boolean burst = false;
         private Collection<Band> bands;
         private DeviceId deviceId;
+        private Annotations annotations;
 
         @Override
         public Meter.Builder forDevice(DeviceId deviceId) {
@@ -233,13 +240,20 @@
         }
 
         @Override
+        public Builder withAnnotations(Annotations anns) {
+            this.annotations = anns;
+            return this;
+        }
+
+        @Override
         public DefaultMeter build() {
             checkNotNull(deviceId, "Must specify a device");
             checkNotNull(bands, "Must have bands.");
             checkArgument(!bands.isEmpty(), "Must have at least one band.");
             checkNotNull(appId, "Must have an application id");
             checkArgument(cellId != null, "Must specify a cell id.");
-            return new DefaultMeter(deviceId, cellId, appId, unit, burst, bands);
+            return new DefaultMeter(deviceId, cellId, appId, unit, burst, bands,
+                                    annotations);
         }
 
 
diff --git a/core/api/src/main/java/org/onosproject/net/meter/DefaultMeterRequest.java b/core/api/src/main/java/org/onosproject/net/meter/DefaultMeterRequest.java
index d246534..e6e2d1b 100644
--- a/core/api/src/main/java/org/onosproject/net/meter/DefaultMeterRequest.java
+++ b/core/api/src/main/java/org/onosproject/net/meter/DefaultMeterRequest.java
@@ -17,6 +17,8 @@
 
 import com.google.common.collect.ImmutableSet;
 import org.onosproject.core.ApplicationId;
+import org.onosproject.net.AbstractAnnotated;
+import org.onosproject.net.Annotations;
 import org.onosproject.net.DeviceId;
 
 import java.util.Collection;
@@ -29,7 +31,7 @@
 /**
  * A default implementation of a meter.
  */
-public final class DefaultMeterRequest implements MeterRequest {
+public final class DefaultMeterRequest extends AbstractAnnotated implements MeterRequest {
 
 
 
@@ -44,7 +46,8 @@
     private DefaultMeterRequest(DeviceId deviceId, ApplicationId appId,
                                 Meter.Unit unit, boolean burst,
                                 Collection<Band> bands, MeterContext context,
-                                Type op) {
+                                Type op, Annotations... annotations) {
+        super(annotations);
         this.deviceId = deviceId;
         this.appId = appId;
         this.unit = unit;
@@ -98,7 +101,9 @@
                 .add("appId", appId.name())
                 .add("unit", unit)
                 .add("isBurst", burst)
-                .add("bands", bands).toString();
+                .add("bands", bands)
+                .add("annotations", annotations())
+                .toString();
     }
 
     public static final class Builder implements MeterRequest.Builder {
@@ -110,6 +115,7 @@
         private DeviceId deviceId;
         private MeterContext context;
         private Optional<MeterId> desiredId = Optional.empty();
+        private Annotations annotations;
 
 
         @Override
@@ -149,17 +155,23 @@
         }
 
         @Override
+        public MeterRequest.Builder withAnnotations(Annotations annotations) {
+            this.annotations = annotations;
+            return this;
+        }
+
+        @Override
         public MeterRequest add() {
             validate();
             return new DefaultMeterRequest(deviceId, appId, unit, burst, bands,
-                                           context, Type.ADD);
+                                           context, Type.ADD, annotations);
         }
 
         @Override
         public MeterRequest remove() {
             validate();
             return new DefaultMeterRequest(deviceId, appId, unit, burst, bands,
-                                           context, Type.REMOVE);
+                                           context, Type.REMOVE, annotations);
         }
 
         private void validate() {
diff --git a/core/api/src/main/java/org/onosproject/net/meter/Meter.java b/core/api/src/main/java/org/onosproject/net/meter/Meter.java
index 3d7544e..63b6db3 100644
--- a/core/api/src/main/java/org/onosproject/net/meter/Meter.java
+++ b/core/api/src/main/java/org/onosproject/net/meter/Meter.java
@@ -16,6 +16,8 @@
 package org.onosproject.net.meter;
 
 import org.onosproject.core.ApplicationId;
+import org.onosproject.net.Annotated;
+import org.onosproject.net.Annotations;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.pi.service.PiTranslatable;
 
@@ -24,7 +26,7 @@
 /**
  * Represents a generalized meter cell configuration to be deployed on a device.
  */
-public interface Meter extends PiTranslatable {
+public interface Meter extends PiTranslatable, Annotated {
 
     enum Unit {
         /**
@@ -190,6 +192,14 @@
         Builder withBands(Collection<Band> bands);
 
         /**
+         * Sets the annotations.
+         *
+         * @param annotations annotations
+         * @return builder object
+         */
+        Builder withAnnotations(Annotations annotations);
+
+        /**
          * Builds the meter based on the specified parameters.
          *
          * @return a meter
diff --git a/core/api/src/main/java/org/onosproject/net/meter/MeterRequest.java b/core/api/src/main/java/org/onosproject/net/meter/MeterRequest.java
index 9060b95..a2be1ce 100644
--- a/core/api/src/main/java/org/onosproject/net/meter/MeterRequest.java
+++ b/core/api/src/main/java/org/onosproject/net/meter/MeterRequest.java
@@ -16,6 +16,8 @@
 package org.onosproject.net.meter;
 
 import org.onosproject.core.ApplicationId;
+import org.onosproject.net.Annotated;
+import org.onosproject.net.Annotations;
 import org.onosproject.net.DeviceId;
 
 import java.util.Collection;
@@ -24,7 +26,7 @@
 /**
  * Represents a generalized meter request to be deployed on a device.
  */
-public interface MeterRequest {
+public interface MeterRequest extends Annotated {
 
     enum Type {
         ADD,
@@ -129,6 +131,14 @@
         Builder withContext(MeterContext context);
 
         /**
+         * Sets the annotations.
+         *
+         * @param annotations annotations
+         * @return builder object
+         */
+        Builder withAnnotations(Annotations annotations);
+
+        /**
          * Requests the addition of a meter.
          *
          * @return a meter request
diff --git a/core/api/src/test/java/org/onosproject/net/meter/MeterOperationTest.java b/core/api/src/test/java/org/onosproject/net/meter/MeterOperationTest.java
index 0716d7d..c43c5c7 100644
--- a/core/api/src/test/java/org/onosproject/net/meter/MeterOperationTest.java
+++ b/core/api/src/test/java/org/onosproject/net/meter/MeterOperationTest.java
@@ -18,6 +18,7 @@
 import com.google.common.testing.EqualsTester;
 import org.junit.Test;
 import org.onosproject.core.ApplicationId;
+import org.onosproject.net.AbstractAnnotated;
 import org.onosproject.net.DeviceId;
 
 import java.util.Collection;
@@ -67,7 +68,7 @@
         assertThat(op.meter(), is(m1));
     }
 
-    private static final class TestMeter implements Meter {
+    private static final class TestMeter extends AbstractAnnotated implements Meter {
 
         @Override
         public DeviceId deviceId() {
diff --git a/core/net/src/main/java/org/onosproject/net/meter/impl/MeterManager.java b/core/net/src/main/java/org/onosproject/net/meter/impl/MeterManager.java
index a06a037..39ef3d9 100644
--- a/core/net/src/main/java/org/onosproject/net/meter/impl/MeterManager.java
+++ b/core/net/src/main/java/org/onosproject/net/meter/impl/MeterManager.java
@@ -262,6 +262,9 @@
         if (request.isBurst()) {
             mBuilder.burst();
         }
+        if (request.annotations() != null && !request.annotations().keys().isEmpty()) {
+            mBuilder.withAnnotations(request.annotations());
+        }
         DefaultMeter m = (DefaultMeter) mBuilder.build();
         // Meter installation logic (happy ending case)
         // PENDING -> stats -> ADDED -> future completes
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/MetersResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/MetersResourceTest.java
index 65b932d..d7db030 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/MetersResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/MetersResourceTest.java
@@ -34,6 +34,7 @@
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
 import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.net.AbstractAnnotated;
 import org.onosproject.net.DefaultDevice;
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
@@ -104,7 +105,7 @@
     /**
      * Mock class for a meter.
      */
-    private static class MockMeter implements Meter {
+    private static class MockMeter extends AbstractAnnotated implements Meter {
 
         final DeviceId deviceId;
         final ApplicationId appId;