ONOS-6717 Meter Protobuf model

Change-Id: I0cba2811957ce9cab370c229fbdfa61712635d69
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/meter/GrpcNbMeterService.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/meter/GrpcNbMeterService.java
new file mode 100644
index 0000000..64ced8a
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/meter/GrpcNbMeterService.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.grpc.nb.net.meter;
+
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.net.meter.MeterService;
+import org.onosproject.grpc.nb.utils.GrpcNbMeterServiceUtil;
+
+import org.onosproject.grpc.nb.net.meter.MeterServiceGrpc.MeterServiceImplBase;
+import org.onosproject.grpc.nb.net.meter.MeterServiceNbProto.submitRequest;
+import org.onosproject.grpc.nb.net.meter.MeterServiceNbProto.submitReply;
+import org.onosproject.grpc.nb.net.meter.MeterServiceNbProto.withdrawRequest;
+import org.onosproject.grpc.nb.net.meter.MeterServiceNbProto.withdrawReply;
+import org.onosproject.grpc.nb.net.meter.MeterServiceNbProto.getMeterRequest;
+import org.onosproject.grpc.nb.net.meter.MeterServiceNbProto.getMeterReply;
+import org.onosproject.grpc.nb.net.meter.MeterServiceNbProto.getAllMetersRequest;
+import org.onosproject.grpc.nb.net.meter.MeterServiceNbProto.getAllMetersReply;
+import org.onosproject.grpc.nb.net.meter.MeterServiceNbProto.getMetersRequest;
+import org.onosproject.grpc.nb.net.meter.MeterServiceNbProto.getMetersReply;
+
+import io.grpc.stub.StreamObserver;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Deactivate;
+import com.google.common.annotations.Beta;
+import org.apache.felix.scr.annotations.Component;
+
+import org.onosproject.net.meter.Meter;
+import org.onosproject.net.meter.MeterId;
+import org.onosproject.net.DeviceId;
+
+/**
+ * A server that provides access to the methods exposed by {@link MeterService}.
+ * TODO this requires major refactoring, translation should be delegated to calls to
+ * TODO{@link GrpcNbMeterServiceUtil}.
+ */
+@Beta
+@Component(immediate = true)
+public class GrpcNbMeterService {
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected MeterService meterService;
+
+    @Activate
+    public void activate() {
+        //TODO this should contact the registry service and register an instance
+        // of this service.
+    }
+
+    @Deactivate
+    public void deactivate() {
+    }
+
+    private class MeterServiceNbServerInternal extends MeterServiceImplBase {
+
+        public MeterServiceNbServerInternal() {
+            super();
+        }
+
+        @Override
+        public void submit(submitRequest request,
+                           StreamObserver<submitReply> responseObserver) {
+            submitReply.Builder replyBuilder = submitReply.newBuilder();
+            Meter meter = meterService.submit(GrpcNbMeterServiceUtil.translate(request.getMeter()));
+            responseObserver.onNext(replyBuilder.setSubmitMeter(GrpcNbMeterServiceUtil.translate(meter)).build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void withdraw(withdrawRequest request,
+                             StreamObserver<withdrawReply> responseObserver) {
+            withdrawReply.Builder replyBuilder = withdrawReply.newBuilder();
+            meterService.withdraw(GrpcNbMeterServiceUtil.translate(request.getMeter()),
+                    MeterId.meterId(request.getMeterId()));
+            responseObserver.onNext(replyBuilder.build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getMeter(getMeterRequest request,
+                             StreamObserver<getMeterReply> responseObserver) {
+            getMeterReply.Builder replyBuilder = getMeterReply.newBuilder();
+            Meter meter = meterService.getMeter(DeviceId.deviceId(request.getDeviceId()),
+                    MeterId.meterId(request.getMeterId()));
+            responseObserver.onNext(replyBuilder.setMeter(GrpcNbMeterServiceUtil.translate(meter)).build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getAllMeters(getAllMetersRequest request,
+                                 StreamObserver<getAllMetersReply> responseObserver) {
+            getAllMetersReply.Builder replyBuilder = getAllMetersReply.newBuilder();
+            meterService.getAllMeters().forEach(d -> {
+                replyBuilder.addMeters(GrpcNbMeterServiceUtil.translate(d));
+            });
+            responseObserver.onNext(replyBuilder.build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getMeters(getMetersRequest request,
+                              StreamObserver<getMetersReply> responseObserver) {
+            getMetersReply.Builder replyBuilder = getMetersReply.newBuilder();
+            meterService.getMeters(DeviceId.deviceId(request.getDeviceId())).forEach(d -> {
+                replyBuilder.addMeters(GrpcNbMeterServiceUtil.translate(d));
+            });
+            responseObserver.onNext(replyBuilder.build());
+            responseObserver.onCompleted();
+        }
+    }
+}
+
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/meter/package-info.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/meter/package-info.java
new file mode 100644
index 0000000..3b63c95
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/meter/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.
+ */
+/**
+ * gRPC server implementations for northbound services.
+ */
+package org.onosproject.grpc.nb.net.meter;
\ No newline at end of file
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/utils/GrpcNbMeterServiceUtil.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/utils/GrpcNbMeterServiceUtil.java
new file mode 100644
index 0000000..43c4908
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/utils/GrpcNbMeterServiceUtil.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.grpc.nb.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.onosproject.net.meter.Band;
+import org.onosproject.net.meter.MeterRequest;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.meter.DefaultBand;
+import org.onosproject.net.meter.DefaultMeterRequest;
+import org.onosproject.net.meter.Meter;
+import org.onosproject.net.meter.MeterState;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.grpc.core.models.ApplicationIdProtoOuterClass.ApplicationIdProto;
+import org.onosproject.grpc.net.meter.models.BandProtoOuterClass.BandProto;
+import org.onosproject.grpc.net.meter.models.MeterEnumsProto.MeterRequestTypeProto;
+import org.onosproject.grpc.net.meter.models.MeterRequestProtoOuterClass.MeterRequestProto;
+import org.onosproject.grpc.net.meter.models.MeterEnumsProto.MeterUnitProto;
+import org.onosproject.grpc.net.meter.models.BandEnumsProto.BandTypeProto;
+import org.onosproject.grpc.net.meter.models.MeterEnumsProto.MeterStateProto;
+import org.onosproject.grpc.net.meter.models.MeterProtoOuterClass.MeterProto;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.stream.Collectors;
+import com.google.common.annotations.Beta;
+
+/**
+ * gRPC message conversion related utilities for meter service.
+ */
+@Beta
+public final class GrpcNbMeterServiceUtil {
+    private static final Logger log = LoggerFactory.getLogger(GrpcNbMeterServiceUtil.class);
+
+    /**
+     * Translates gRPC ApplicationId to {@link ApplicationId}.
+     *
+     * @param gAppId gRPC message
+     * @return {@link ApplicationId}
+     */
+    public static ApplicationId translate(ApplicationIdProto gAppId) {
+        int id = gAppId.getId();
+        String name = gAppId.getName();
+        ApplicationId appId = new DefaultApplicationId(id, name);
+        return appId;
+    }
+
+    /**
+     * Translates gRPC Band to {@link Band}.
+     *
+     * @param gBand gRPC message
+     * @return {@link Band}
+     */
+    public static Band translate(BandProto gBand) {
+        Band.Type type = translate(gBand.getType());
+        long rate = gBand.getRate();
+        long burstSize = gBand.getBurst();
+        short prec = (short) gBand.getDropPrecedence();
+        Band band = new DefaultBand(type, rate, burstSize, prec);
+        return band;
+    }
+
+    /**
+     * Translates gRPC List Bands to Collection Band.
+     *
+     * @param listBands gRPC message
+     * @return Collection Band
+     */
+    public static Collection<Band> translate(java.util.List<BandProto>  listBands) {
+        Collection<Band> bands = new ArrayList<>();
+        listBands.forEach(d -> {
+            bands.add(translate(d));
+        });
+        return bands;
+    }
+
+    /**
+     * Translates gRPC MeterRequestType to {@link MeterRequest.Type}.
+     *
+     * @param type gRPC message
+     * @return {@link MeterRequest.Type}
+     */
+    public static MeterRequest.Type translate(MeterRequestTypeProto type) {
+        switch (type) {
+            case ADD:
+                return MeterRequest.Type.ADD;
+            case MODIFY:
+                return MeterRequest.Type.MODIFY;
+            case REMOVE:
+                return MeterRequest.Type.REMOVE;
+            case UNRECOGNIZED:
+                log.warn("Unrecognized MeterRequest type gRPC message: {}", type);
+                return null;
+            default:
+                log.warn("Unrecognized MeterRequest type gRPC message: {}", type);
+                return null;
+        }
+    }
+
+    /**
+     * Translates gRPC MeterRequest to {@link MeterRequest}.
+     *
+     * @param meterRequest gRPC message
+     * @return {@link MeterRequest}
+     */
+    public static MeterRequest translate(MeterRequestProto meterRequest) {
+
+        DeviceId deviceid = DeviceId.deviceId(meterRequest.getDeviceId());
+        ApplicationId appId = translate(meterRequest.getApplicationId());
+        Meter.Unit unit = translate(meterRequest.getUnit());
+        boolean burst = meterRequest.getIsBurst();
+        Collection<Band> bands = translate(meterRequest.getBandsList());
+        MeterRequest.Type type = translate(meterRequest.getType());
+        if (type == MeterRequest.Type.ADD) {
+            return DefaultMeterRequest.builder()
+                    .forDevice(deviceid)
+                    .fromApp(appId)
+                    .withUnit(unit)
+                    .withBands(bands)
+                    .add();
+        } else {
+            return DefaultMeterRequest.builder()
+                    .forDevice(deviceid)
+                    .fromApp(appId)
+                    .withUnit(unit)
+                    .withBands(bands)
+                    .remove();
+        }
+    }
+
+    /**
+     * Translates {@link ApplicationId} to gRPC ApplicationId message.
+     *
+     * @param appId {@link ApplicationId}
+     * @return gRPC ApplicationId message
+     */
+    public static ApplicationIdProto translate(ApplicationId appId) {
+        return ApplicationIdProto.newBuilder()
+                .setId(appId.id())
+                .setName(appId.name())
+                .build();
+    }
+
+    /**
+     * Translates gRPC enum MeterUnit to ONOS enum.
+     *
+     * @param unit meterUnit in gRPC enum
+     * @return equivalent in ONOS enum
+     */
+    public static Meter.Unit translate(MeterUnitProto unit) {
+        switch (unit) {
+            case PKTS_PER_SEC:
+                return Meter.Unit.PKTS_PER_SEC;
+            case KB_PER_SEC:
+                return Meter.Unit.KB_PER_SEC;
+            case UNRECOGNIZED:
+                log.warn("Unrecognized MeterUnit gRPC message: {}", unit);
+                return null;
+            default:
+                log.warn("Unrecognized MeterUnit gRPC message: {}", unit);
+                return null;
+        }
+    }
+
+    /**
+     * Translates ONOS enum Meter.Unit Type to gRPC enum.
+     *
+     * @param unit Meter.Unit in ONOS enum
+     * @return equivalent in gRPC enum
+     */
+    public static MeterUnitProto translate(Meter.Unit unit) {
+        switch (unit) {
+            case PKTS_PER_SEC:
+                return org.onosproject.grpc.net.meter.models.MeterEnumsProto.MeterUnitProto.PKTS_PER_SEC;
+            case KB_PER_SEC:
+                return org.onosproject.grpc.net.meter.models.MeterEnumsProto.MeterUnitProto.KB_PER_SEC;
+            default:
+                log.warn("Unrecognized MeterUnit ONOS message: {}", unit);
+                return org.onosproject.grpc.net.meter.models.MeterEnumsProto.MeterUnitProto.UNRECOGNIZED;
+        }
+    }
+
+    /**
+     * Translates gRPC enum Band Type to ONOS enum.
+     *
+     * @param bandType BandType in gRPC enum
+     * @return equivalent in ONOS enum
+     */
+    public static Band.Type translate(BandTypeProto bandType) {
+        switch (bandType) {
+            case DROP:
+                return Band.Type.DROP;
+            case REMARK:
+                return Band.Type.REMARK;
+            case EXPERIMENTAL:
+                return Band.Type.EXPERIMENTAL;
+            case UNRECOGNIZED:
+                log.warn("Unrecognized BandType gRPC message: {}", bandType);
+                return null;
+            default:
+                log.warn("Unrecognized BandType gRPC message: {}", bandType);
+                return null;
+        }
+    }
+
+    /**
+     * Translates ONOS enum Band Type to gRPC enum.
+     *
+     * @param bandType BandType in ONOS enum
+     * @return equivalent in gRPC enum
+     */
+    public static BandTypeProto translate(Band.Type bandType) {
+        switch (bandType) {
+            case DROP:
+                return org.onosproject.grpc.net.meter.models.BandEnumsProto.BandTypeProto.DROP;
+            case REMARK:
+                return org.onosproject.grpc.net.meter.models.BandEnumsProto.BandTypeProto.REMARK;
+            case EXPERIMENTAL:
+                return org.onosproject.grpc.net.meter.models.BandEnumsProto.BandTypeProto.EXPERIMENTAL;
+            default:
+                log.warn("Unrecognized BandType ONOS message: {}", bandType);
+                return null;
+        }
+    }
+
+    /**
+     * Translates ONOS enum MeterState Type to gRPC enum.
+     *
+     * @param meterState MeterState in ONOS enum
+     * @return equivalent in gRPC enum
+     */
+    public static MeterStateProto translate(MeterState meterState) {
+        switch (meterState) {
+            case PENDING_ADD:
+                return org.onosproject.grpc.net.meter.models.MeterEnumsProto.MeterStateProto.PENDING_ADD;
+            case ADDED:
+                return org.onosproject.grpc.net.meter.models.MeterEnumsProto.MeterStateProto.ADDED;
+            case PENDING_REMOVE:
+                return org.onosproject.grpc.net.meter.models.MeterEnumsProto.MeterStateProto.PENDING_REMOVE;
+            case REMOVED:
+                return org.onosproject.grpc.net.meter.models.MeterEnumsProto.MeterStateProto.REMOVED;
+            default:
+                log.warn("Unrecognized MeterState ONOS message: {}", meterState);
+                return org.onosproject.grpc.net.meter.models.MeterEnumsProto.MeterStateProto.UNRECOGNIZED;
+        }
+    }
+
+    /**
+     * Translates {@link Meter} to gRPC MeterCore message.
+     *
+     * @param meter {@link Meter}
+     * @return gRPC MeterCore message
+     */
+    public static MeterProto translate(Meter meter) {
+        return MeterProto.newBuilder()
+                .setDeviceId(meter.deviceId().toString())
+                .setApplicationId(translate(meter.appId()))
+                .setUnit(translate(meter.unit()))
+                .setIsBurst(meter.isBurst())
+                .addAllBands(meter.bands().stream()
+                        .map(b -> BandProto.newBuilder()
+                                .setRate(b.rate())
+                                .setBurst(b.burst())
+                                .setDropPrecedence(b.dropPrecedence())
+                                .setType(translate(b.type()))
+                                .setPackets(b.packets())
+                                .setBytes(b.bytes())
+                                .build())
+                        .collect(Collectors.toList()))
+                .setState(translate(meter.state()))
+                .setLife(meter.life())
+                .setReferenceCount(meter.referenceCount())
+                .setPacketsSeen(meter.packetsSeen())
+                .setBytesSeen(meter.bytesSeen())
+                .build();
+    }
+
+    // Utility class not intended for instantiation.
+    private GrpcNbMeterServiceUtil() {
+    }
+}
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/utils/package-info.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/utils/package-info.java
new file mode 100644
index 0000000..341744c
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/utils/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+/**
+ * A package contains a set of utilities that are used to convert gRPC model
+ * object to ONOS data model object.
+ */
+package org.onosproject.grpc.nb.utils;
\ No newline at end of file