Refactor gRPC northbound device service

Change-Id: I2f15074ab086f9a5e3294b49e09976f0dd77f51e
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/GrpcNbDeviceService.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/GrpcNbDeviceService.java
new file mode 100644
index 0000000..1e1bdc9
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/GrpcNbDeviceService.java
@@ -0,0 +1,356 @@
+/*
+ * 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.device;
+
+
+import com.google.common.annotations.Beta;
+import io.grpc.stub.StreamObserver;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.grpc.net.device.models.PortEnumsProto;
+import org.onosproject.grpc.net.device.models.PortStatisticsProtoOuterClass.PortStatisticsProto;
+import org.onosproject.grpc.nb.net.device.DeviceServiceGrpc.DeviceServiceImplBase;
+import org.onosproject.grpc.net.models.PortProtoOuterClass.PortProto;
+import org.onosproject.grpc.net.device.models.DeviceEnumsProto;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MastershipRole;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.grpc.nb.utils.GrpcNbDeviceServiceUtil;
+
+import static org.onosproject.grpc.nb.net.device.DeviceServiceNb.*;
+
+
+/**
+ * A server that provides access to the methods exposed by {@link DeviceService}.
+ * TODO this requires major refactoring, translation should be delegated to calls to
+ * TODO{@link GrpcNbDeviceServiceUtil}.
+ */
+@Beta
+@Component(immediate = true)
+public class GrpcNbDeviceService {
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DeviceService deviceService;
+
+    @Activate
+    public void activate() {
+        //TODO this should contact the registry service and register an instance
+        // of this service.
+    }
+
+    @Deactivate
+    public void deactivate() {
+    }
+
+    private class DeviceServiceNbServerInternal extends DeviceServiceImplBase {
+
+        public DeviceServiceNbServerInternal() {
+            super();
+        }
+
+
+        @Override
+        public void getDeviceCount(
+                getDeviceCountRequest request,
+                StreamObserver<DeviceServiceNb.getDeviceCountReply> responseObserver) {
+            responseObserver
+                    .onNext(getDeviceCountReply
+                            .newBuilder()
+                            .setDeviceCount(
+                                    deviceService.getDeviceCount())
+                            .build());
+            responseObserver.onCompleted();
+        }
+
+        //FIXME NOTE: this will be switched to a streaming version.
+        @Override
+        public void getDevices(getDevicesRequest request,
+                               StreamObserver<DeviceServiceNb.getDevicesReply> responseObserver) {
+            getDevicesReply.Builder replyBuilder = getDevicesReply.newBuilder();
+            deviceService.getDevices().forEach(d -> {
+                replyBuilder.addDevice(
+                        org.onosproject.grpc.net.models.DeviceProtoOuterClass.DeviceProto
+                                .newBuilder()
+                                .setDeviceId(d.id().toString())
+                                .setType(
+                                        DeviceEnumsProto.DeviceTypeProto
+                                                .valueOf(d.type().toString()))
+                                .setManufacturer(d.manufacturer())
+                                .setHwVersion(d.hwVersion())
+                                .setSwVersion(d.swVersion())
+                                .setSerialNumber(d.serialNumber())
+                                .setChassisId(d.chassisId().toString())
+                                .build());
+            });
+            responseObserver.onNext(replyBuilder.build());
+            responseObserver.onCompleted();
+        }
+
+        //FIXME NOTE: this will be switched to a streaming version.
+        @Override
+        public void getAvailableDevices(getAvailableDevicesRequest request,
+                                        StreamObserver
+                                                <DeviceServiceNb.getAvailableDevicesReply> responseObserver) {
+            getAvailableDevicesReply.Builder replyBuilder = getAvailableDevicesReply.newBuilder();
+            deviceService.getAvailableDevices().forEach(d -> {
+                replyBuilder.addDevice(
+                        org.onosproject.grpc.net.models.DeviceProtoOuterClass.DeviceProto
+                                .newBuilder()
+                                .setDeviceId(d.id().toString())
+                                .setType(DeviceEnumsProto.DeviceTypeProto.valueOf(
+                                        d.type().toString()))
+                                .setManufacturer(d.manufacturer())
+                                .setHwVersion(d.hwVersion())
+                                .setSwVersion(d.swVersion())
+                                .setSerialNumber(d.serialNumber())
+                                .setChassisId(d.chassisId().toString())
+                                .build());
+            });
+            responseObserver.onNext(replyBuilder.build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getDevice(getDeviceRequest request,
+                              io.grpc.stub.StreamObserver<DeviceServiceNb.getDeviceReply> responseObserver) {
+            org.onosproject.net.Device device = deviceService.getDevice(
+                    DeviceId.deviceId(request.getDeviceId()));
+            responseObserver.onNext(
+                    getDeviceReply.newBuilder().setDevice(
+                            org.onosproject.grpc.net.models.DeviceProtoOuterClass.DeviceProto
+                                    .newBuilder()
+                                    .setDeviceId(device.id().toString())
+                                    .setType(
+                                            //TODO check for better approach to mapping between enum varieties
+                                            DeviceEnumsProto.DeviceTypeProto.valueOf(device.type().toString()))
+                                    .setManufacturer(device.manufacturer())
+                                    .setHwVersion(device.hwVersion())
+                                    .setSwVersion(device.swVersion())
+                                    .setSerialNumber(device.serialNumber())
+                                    .setChassisId(device.chassisId().toString())
+                                    .build()).build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getRole(getRoleRequest request,
+                            StreamObserver<DeviceServiceNb.getRoleReply> responseObserver) {
+            DeviceId deviceId = DeviceId.deviceId(request.getDeviceId());
+            MastershipRole role = deviceService.getRole(deviceId);
+            DeviceEnumsProto.MastershipRoleProto mastershipRole =
+                    DeviceEnumsProto.MastershipRoleProto.valueOf(role.toString());
+            responseObserver.onNext(getRoleReply.newBuilder()
+                    .setRole(mastershipRole).build());
+            responseObserver.onCompleted();
+        }
+
+        //FIXME NOTE: this may be switched to a streaming version.
+        @Override
+        public void getPorts(getPortsRequest request, StreamObserver<getPortsReply> responseObserver) {
+            getPortsReply.Builder replyBuilder = getPortsReply.newBuilder();
+            deviceService.getPorts(
+                    DeviceId.deviceId(request.getDeviceId()))
+                    .forEach(port -> {
+                        PortProto.Builder portBuilder = PortProto
+                                .newBuilder()
+                                .setPortNumber(port.number().toString())
+                                .setIsEnabled(port.isEnabled())
+                                .setType(PortEnumsProto.PortTypeProto.valueOf(port.type().toString()))
+                                .setPortSpeed(port.portSpeed());
+                        port.annotations().keys().forEach(key -> portBuilder
+                                .putAnnotations(key, port.annotations().value(key)));
+
+                        replyBuilder.addPort(portBuilder.build());
+                    });
+            responseObserver.onNext(replyBuilder.build());
+            responseObserver.onCompleted();
+        }
+
+        //FIXME NOTE: this may be switched to a streaming version.
+        @Override
+        public void getPortStatistics(getPortStatisticsRequest request,
+                                      StreamObserver<getPortStatisticsReply> responseObserver) {
+            getPortStatisticsReply.Builder replyBuilder = getPortStatisticsReply.newBuilder();
+            deviceService.getPortStatistics(DeviceId.deviceId(request.getDeviceId()))
+                    .forEach(statistic -> {
+                        replyBuilder.addPortStatistics(
+                                PortStatisticsProto
+                                        .newBuilder()
+                                        .setPort(statistic.port())
+                                        .setPacketsReceived(statistic.packetsReceived())
+                                        .setPacketsSent(statistic.packetsSent())
+                                        .setBytesReceived(statistic.bytesReceived())
+                                        .setBytesSent(statistic.bytesSent())
+                                        .setPacketsRxDropped(statistic.packetsRxDropped())
+                                        .setPacketsTxDropped(statistic.packetsTxDropped())
+                                        .setPacketsRxErrors(statistic.packetsRxErrors())
+                                        .setPacketsTxErrors(statistic.packetsTxErrors())
+                                        .setDurationSec(statistic.durationSec())
+                                        .setDurationNano(statistic.durationNano())
+                                        .setIsZero(statistic.isZero())
+                                        .build());
+                    });
+            responseObserver.onNext(replyBuilder.build());
+            responseObserver.onCompleted();
+        }
+
+        //FIXME NOTE: this may be switched to a streaming version.
+        @Override
+        public void getPortDeltaStatistics(getPortDeltaStatisticsRequest request,
+                                           StreamObserver<getPortDeltaStatisticsReply> responseObserver) {
+            getPortDeltaStatisticsReply.Builder replyBuilder = getPortDeltaStatisticsReply.newBuilder();
+            deviceService.getPortDeltaStatistics(DeviceId.deviceId(request.getDeviceId()))
+                    .forEach(statistic -> {
+                        replyBuilder.addPortStatistics(
+                                PortStatisticsProto
+                                        .newBuilder()
+                                        .setPort(statistic.port())
+                                        .setPacketsReceived(statistic.packetsReceived())
+                                        .setPacketsSent(statistic.packetsSent())
+                                        .setBytesReceived(statistic.bytesReceived())
+                                        .setBytesSent(statistic.bytesSent())
+                                        .setPacketsRxDropped(statistic.packetsRxDropped())
+                                        .setPacketsTxDropped(statistic.packetsTxDropped())
+                                        .setPacketsRxErrors(statistic.packetsRxErrors())
+                                        .setPacketsTxErrors(statistic.packetsTxErrors())
+                                        .setDurationSec(statistic.durationSec())
+                                        .setDurationNano(statistic.durationNano())
+                                        .setIsZero(statistic.isZero())
+                                        .build());
+                    });
+            responseObserver.onNext(replyBuilder.build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getStatisticsForPort(getStatisticsForPortRequest request,
+                                         StreamObserver<getStatisticsForPortReply> responseObserver) {
+            org.onosproject.net.device.PortStatistics statistics = deviceService
+                    .getStatisticsForPort(DeviceId.deviceId(request.getDeviceId()),
+                            PortNumber.portNumber(request.getPortNumber()));
+            responseObserver.onNext(
+                    getStatisticsForPortReply
+                            .newBuilder()
+                            .setPortStatistics(
+                                    PortStatisticsProto
+                                            .newBuilder()
+                                            .setPort(statistics.port())
+                                            .setPacketsReceived(statistics.packetsReceived())
+                                            .setPacketsSent(statistics.packetsSent())
+                                            .setBytesReceived(statistics.bytesReceived())
+                                            .setBytesSent(statistics.bytesSent())
+                                            .setPacketsRxDropped(statistics.packetsRxDropped())
+                                            .setPacketsTxDropped(statistics.packetsTxDropped())
+                                            .setPacketsRxErrors(statistics.packetsRxErrors())
+                                            .setPacketsTxErrors(statistics.packetsTxErrors())
+                                            .setDurationSec(statistics.durationSec())
+                                            .setDurationNano(statistics.durationNano())
+                                            .setIsZero(statistics.isZero())
+                                            .build()).build());
+            responseObserver.onCompleted();
+
+        }
+
+        @Override
+        public void getDeltaStatisticsForPort(getDeltaStatisticsForPortRequest request,
+                                              StreamObserver<getDeltaStatisticsForPortReply> responseObserver) {
+            org.onosproject.net.device.PortStatistics statistics = deviceService
+                    .getDeltaStatisticsForPort(DeviceId.deviceId(request.getDeviceId()),
+                            PortNumber.portNumber(request.getPortNumber()));
+            responseObserver.onNext(
+                    getDeltaStatisticsForPortReply
+                            .newBuilder()
+                            .setPortStatistics(
+                                    PortStatisticsProto
+                                            .newBuilder()
+                                            .setPort(statistics.port())
+                                            .setPacketsReceived(statistics.packetsReceived())
+                                            .setPacketsSent(statistics.packetsSent())
+                                            .setBytesReceived(statistics.bytesReceived())
+                                            .setBytesSent(statistics.bytesSent())
+                                            .setPacketsRxDropped(statistics.packetsRxDropped())
+                                            .setPacketsTxDropped(statistics.packetsTxDropped())
+                                            .setPacketsRxErrors(statistics.packetsRxErrors())
+                                            .setPacketsTxErrors(statistics.packetsTxErrors())
+                                            .setDurationSec(statistics.durationSec())
+                                            .setDurationNano(statistics.durationNano())
+                                            .setIsZero(statistics.isZero())
+                                            .build()).build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getPort(getPortRequest request,
+                            StreamObserver<getPortReply> responseObserver) {
+            //FIXME getting deviceId here is dangerous because it is not guaranteed to be populated as port of a OneOf
+            org.onosproject.net.Port port = deviceService.getPort(
+                    new ConnectPoint(DeviceId.deviceId(
+                            request.getConnectPoint().getDeviceId()),
+                            PortNumber.portNumber(
+                                    request.getConnectPoint()
+                                            .getPortNumber())));
+            PortProto.Builder portBuilder =
+                    PortProto.newBuilder()
+                            .setPortNumber(port.number().toString())
+                            .setIsEnabled(port.isEnabled())
+                            .setType(
+                                    PortEnumsProto.PortTypeProto
+                                            .valueOf(port.type().toString()))
+                            .setPortSpeed(port.portSpeed());
+
+            port.annotations().keys().forEach(key -> portBuilder
+                    .putAnnotations(key, port.annotations().value(key)));
+
+            responseObserver.onNext(getPortReply
+                    .newBuilder()
+                    .setPort(portBuilder.build())
+                    .build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void isAvailable(isAvailableRequest request,
+                                StreamObserver<isAvailableReply> responseObserver) {
+            responseObserver.onNext(
+                    isAvailableReply
+                            .newBuilder()
+                            .setIsAvailable(
+                                    deviceService.isAvailable(
+                                            DeviceId.deviceId(
+                                                    request.getDeviceId())))
+                            .build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void localStatus(localStatusRequest request,
+                                StreamObserver<localStatusReply> responseObserver) {
+            responseObserver.onNext(
+                    localStatusReply
+                            .newBuilder()
+                            .setStatus(
+                                    deviceService.localStatus(
+                                            DeviceId.deviceId(request.getDeviceId())))
+                            .build());
+            responseObserver.onCompleted();
+        }
+    }
+}
\ No newline at end of file