ONOS-5976 Added CodecContext service to UiMessageHandler to allow
handlers to use JsonCodecs.

Modified the DeviceView to utilize the JSON Codec context capability
for demonstration purposes.   Functionality should be identical.

Change-Id: Ic6d25b4be6fc634dfa88277f17f93287af4c331c
diff --git a/core/api/src/main/java/org/onosproject/ui/RequestHandler.java b/core/api/src/main/java/org/onosproject/ui/RequestHandler.java
index 04d2a56..d18f633 100644
--- a/core/api/src/main/java/org/onosproject/ui/RequestHandler.java
+++ b/core/api/src/main/java/org/onosproject/ui/RequestHandler.java
@@ -86,7 +86,6 @@
      * @param payload   message payload
      */
     protected void sendMessage(String eventType, ObjectNode payload) {
-        // TODO: remove sid
         parent.connection().sendMessage(eventType, payload);
     }
 
diff --git a/core/api/src/main/java/org/onosproject/ui/UiMessageHandler.java b/core/api/src/main/java/org/onosproject/ui/UiMessageHandler.java
index 609c28b..c38d741 100644
--- a/core/api/src/main/java/org/onosproject/ui/UiMessageHandler.java
+++ b/core/api/src/main/java/org/onosproject/ui/UiMessageHandler.java
@@ -19,6 +19,9 @@
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.onlab.osgi.ServiceDirectory;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.CodecService;
+import org.onosproject.codec.JsonCodec;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -51,6 +54,11 @@
  * the <em>event-type</em> is determined, and the message dispatched to the
  * corresponding <em>RequestHandler</em>'s
  * {@link RequestHandler#process process} method.
+ * <p>
+ * For convenience the implementation includes methods to obtain JSON
+ * generating objects (mapper, objectNode, arrayNode) as well as a
+ * JsonCodecContext for preparing and digesting messages to the UI
+ * client.
  */
 public abstract class UiMessageHandler {
 
@@ -62,6 +70,7 @@
     private UiConnection connection;
     private ServiceDirectory directory;
 
+    private MessageCodecContext codecContext;
 
     /**
      * Subclasses must create and return the collection of request handlers
@@ -202,4 +211,40 @@
             connection.sendMessage(data);
         }
     }
+
+    /**
+     * Obtain a CodecContext to be used in encoding and decoding objects
+     * that have a registered JsonCodec for their class.  This method
+     * instantiates a private inner class which is returned on
+     * subsequent calls.
+     *
+     * @return a CodecContext.
+     */
+    protected CodecContext getJsonCodecContext() {
+        if (codecContext != null) {
+            return codecContext;
+        }
+        codecContext = new MessageCodecContext();
+        return codecContext;
+    }
+
+    private class MessageCodecContext implements CodecContext {
+
+        CodecService cs = get(CodecService.class);
+
+        @Override
+        public ObjectMapper mapper() {
+            return mapper;
+        }
+
+        @Override
+        public <T> JsonCodec<T> codec(Class<T> entityClass) {
+            return cs.getCodec(entityClass);
+        }
+
+        @Override
+        public <T> T getService(Class<T> serviceClass) {
+            return get(serviceClass);
+        }
+    }
 }
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/DeviceViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/DeviceViewMessageHandler.java
index a04f616..fc62d37 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/DeviceViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/DeviceViewMessageHandler.java
@@ -57,6 +57,7 @@
     private static final String DEV_DATA_REQ = "deviceDataRequest";
     private static final String DEV_DATA_RESP = "deviceDataResponse";
     private static final String DEVICES = "devices";
+    private static final String DEVICE = "device";
 
     private static final String DEV_DETAILS_REQ = "deviceDetailsRequest";
     private static final String DEV_DETAILS_RESP = "deviceDetailsResponse";
@@ -217,6 +218,10 @@
 
             ObjectNode rootNode = objectNode();
             rootNode.set(DETAILS, data);
+
+            // use the codec context to get a JSON of the device. See ONOS-5976.
+            rootNode.set(DEVICE, getJsonCodecContext().encode(device, Device.class));
+
             sendMessage(DEV_DETAILS_RESP, rootNode);
         }
 
diff --git a/web/gui/src/main/webapp/app/view/device/device.js b/web/gui/src/main/webapp/app/view/device/device.js
index ec8d8b5..303e425 100644
--- a/web/gui/src/main/webapp/app/view/device/device.js
+++ b/web/gui/src/main/webapp/app/view/device/device.js
@@ -32,7 +32,8 @@
         bottom,
         iconDiv,
         wSize,
-        editingName = false;
+        editingName = false,
+        device;
 
     // constants
     var topPdg = 28,
@@ -173,10 +174,21 @@
         is.loadEmbeddedIcon(iconDiv, details._iconid_type, 40);
         top.select('h2').html(details.name);
 
-        propOrder.forEach(function (prop, i) {
-            // properties are split into two tables
-            addProp(i < propSplit ? leftTbl : rightTbl, i, details[prop]);
-        });
+        // === demonstrate use of JsonCodec object see ONOS-5976
+        addProp(leftTbl,  0, device.id);
+        addProp(leftTbl,  1, device.type);
+        addProp(leftTbl,  2, details['masterid']);
+        addProp(leftTbl,  3, details['chassid']);
+        addProp(rightTbl, 4, device.mfr);
+        addProp(rightTbl, 5, device.hw);
+        addProp(rightTbl, 6, device.sw);
+        addProp(rightTbl, 7, details['protocol']);
+        addProp(rightTbl, 8, device.serial);
+
+        // propOrder.forEach(function (prop, i) {
+        //     // properties are split into two tables
+        //     addProp(i < propSplit ? leftTbl : rightTbl, i, details[prop]);
+        // });
     }
 
     function addPortRow(tbody, port) {
@@ -234,6 +246,7 @@
 
     function respDetailsCb(data) {
         $scope.panelData = data.details;
+        device = data.device;
         $scope.$apply();
     }