[ONOS-7299] YANG Runtime and Serializer: LeafType handling in json serializer

Change-Id: Ic42f18a5446fcc4b8b7c4d17e8c5c947c97dc5ff
diff --git a/serializers/json/src/main/java/org/onosproject/yang/serializers/json/DataNodeJsonVisitor.java b/serializers/json/src/main/java/org/onosproject/yang/serializers/json/DataNodeJsonVisitor.java
index 054f3cf..4b3a863 100644
--- a/serializers/json/src/main/java/org/onosproject/yang/serializers/json/DataNodeJsonVisitor.java
+++ b/serializers/json/src/main/java/org/onosproject/yang/serializers/json/DataNodeJsonVisitor.java
@@ -70,9 +70,8 @@
                     valNamespace = getModuleNameFromNameSpace(
                             jsonSerializerContext, sLeafNode.valueNamespace());
                 }
-                jsonBuilder.addNodeWithValueTopHalf(nodeName,
-                                                    sLeafNode.asString(),
-                                                    valNamespace);
+                jsonBuilder.addNodeWithValueTopHalf(nodeName, sLeafNode.asString(),
+                                                    valNamespace, sLeafNode.leafType());
                 break;
             case MULTI_INSTANCE_LEAF_VALUE_NODE:
                 if (siblingType == FIRST_INSTANCE ||
@@ -84,8 +83,9 @@
                     valNamespace = getModuleNameFromNameSpace(
                             jsonSerializerContext, mLeafNode.valueNamespace());
                 }
-                jsonBuilder.addValueToLeafListNode(mLeafNode.asString(),
-                                                   valNamespace);
+                jsonBuilder.addValueToLeafListNode(
+                        mLeafNode.asString(), valNamespace,
+                        mLeafNode.leafType());
                 break;
             default:
                 break;
diff --git a/serializers/json/src/main/java/org/onosproject/yang/serializers/json/DefaultJsonBuilder.java b/serializers/json/src/main/java/org/onosproject/yang/serializers/json/DefaultJsonBuilder.java
index cff16cd..2c401f9 100644
--- a/serializers/json/src/main/java/org/onosproject/yang/serializers/json/DefaultJsonBuilder.java
+++ b/serializers/json/src/main/java/org/onosproject/yang/serializers/json/DefaultJsonBuilder.java
@@ -20,6 +20,7 @@
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.JsonNodeType;
 import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.yang.model.LeafType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -71,27 +72,51 @@
             default:
                 log.error("Unknown support type {} for this method.", nodeType);
         }
-
     }
 
     @Override
     public void addNodeWithValueTopHalf(String nodeName, String value,
-                                        String valNamespace) {
+                                        String valNamespace, LeafType type) {
         if (isNullOrEmpty(nodeName)) {
             return;
         }
         appendField(nodeName);
-        treeString.append(QUOTE);
         if (valNamespace != null) {
+            treeString.append(QUOTE);
             treeString.append(valNamespace);
             treeString.append(COLON);
         }
-        treeString.append(value);
-
-        treeString.append(QUOTE);
+        appendLeafValue(type, value, valNamespace);
         treeString.append(COMMA);
     }
 
+    /**
+     * Appends the value with quotes orr without quotes based on given
+     * leaf-type.
+     *
+     * @param type current leaf type
+     * @param v    value
+     * @param ns   namespace for value in case of identity ref
+     */
+    private void appendLeafValue(LeafType type, String v, String ns) {
+        switch (type) {
+            case INT8:
+            case INT16:
+            case UINT8:
+            case INT32:
+            case UINT16:
+            case UINT32:
+                treeString.append(v);
+                break;
+            default:
+                if (ns == null) {
+                    treeString.append(QUOTE);
+                }
+                treeString.append(v);
+                treeString.append(QUOTE);
+        }
+    }
+
     @Override
     public void addNodeWithSetTopHalf(String nodeName, Set<String> sets) {
         if (isNullOrEmpty(nodeName)) {
@@ -108,18 +133,16 @@
     }
 
     @Override
-    public void addValueToLeafListNode(String value, String valNamespace) {
-        if (isNullOrEmpty(value)) {
+    public void addValueToLeafListNode(String v, String ns, LeafType t) {
+        if (isNullOrEmpty(v)) {
             return;
         }
-
-        treeString.append(QUOTE);
-        treeString.append(value);
-        if (valNamespace != null) {
+        if (ns != null) {
+            treeString.append(QUOTE);
+            treeString.append(ns);
             treeString.append(COLON);
-            treeString.append(valNamespace);
         }
-        treeString.append(QUOTE);
+        appendLeafValue(t, v, ns);
         treeString.append(COMMA);
     }
 
diff --git a/serializers/json/src/main/java/org/onosproject/yang/serializers/json/JsonBuilder.java b/serializers/json/src/main/java/org/onosproject/yang/serializers/json/JsonBuilder.java
index 3405a39..689554d 100644
--- a/serializers/json/src/main/java/org/onosproject/yang/serializers/json/JsonBuilder.java
+++ b/serializers/json/src/main/java/org/onosproject/yang/serializers/json/JsonBuilder.java
@@ -18,6 +18,7 @@
 
 import com.fasterxml.jackson.databind.node.JsonNodeType;
 import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.yang.model.LeafType;
 
 import java.util.Set;
 
@@ -43,12 +44,13 @@
      * both single instance and multi instance node. Protocols aware of nature
      * of node will use it for single instance value node addition.
      *
-     * @param nodeName name of child to be added
-     * @param value    value of the child node
+     * @param nodeName     name of child to be added
+     * @param value        value of the child node
      * @param valNamespace value namespace
+     * @param type         leaf value type
      */
     void addNodeWithValueTopHalf(String nodeName, String value,
-                                 String valNamespace);
+                                 String valNamespace, LeafType type);
 
     /**
      * Adds a child with list of values to JSON data tree. This method is
@@ -63,10 +65,11 @@
     /**
      * Adds value to a leaf list node.
      *
-     * @param value value to be added
+     * @param value        value to be added
      * @param valNamespace value namespace
+     * @param type         leaf-list value type
      */
-    void addValueToLeafListNode(String value, String valNamespace);
+    void addValueToLeafListNode(String value, String valNamespace, LeafType type);
 
     /**
      * Adds the bottom half(a right brace/bracket) of a JSON
diff --git a/serializers/json/src/test/java/org/onosproject/yang/serializers/json/JsonSerializerTest.java b/serializers/json/src/test/java/org/onosproject/yang/serializers/json/JsonSerializerTest.java
index 6c96fec..2c43192 100644
--- a/serializers/json/src/test/java/org/onosproject/yang/serializers/json/JsonSerializerTest.java
+++ b/serializers/json/src/test/java/org/onosproject/yang/serializers/json/JsonSerializerTest.java
@@ -62,13 +62,21 @@
     private static YangSerializerContext context;
     private static YangSerializer jsonSerializer;
 
-    private static String outputIdTestJson = "{\"identity-test:con1\":{\"inte" +
-            "rface\":\"identity-types:physical\",\"interfaces\":{\"int-list" +
-            "\":[{\"iden\":\"identity-types-second:virtual\",\"available\":" +
-            "{\"ll\":[\"Loopback:identity-types\",\"Giga:identity-test\",\"" +
-            "Ethernet:identity-types-second\"]}},{\"iden\":\"optical\",\"av" +
-            "ailable\":{\"ll\":[\"Giga\"]}}]}}}";
+    private static String outputIdTestJson = "{\"identity-test:con1\":{" +
+            "\"interface\":\"identity-types:physical\",\"interfaces\":{" +
+            "\"int-list\":[{\"iden\":\"identity-types-second:virtual\"," +
+            "\"available\":{\"ll\":[\"identity-types:Loopback\"," +
+            "\"identity-test:Giga\",\"identity-types-second:Ethernet\"]}}," +
+            "{\"iden\":\"optical\",\"available\":{\"ll\":[\"Giga\"]}}]}}}";
 
+    private static String outputIdTestJson1 = "{\"jsonlist:c2\":{\"leaflist1" +
+            "\":[\"a\",\"b\",\"c\"],\"leaf1\":1,\"leaf2\":2,\"leaf3\":3," +
+            "\"leaf4\":4,\"leaf5\":5,\"leaf6\":6,\"leaf7\":\"7\",\"leaf8\"" +
+            ":\"8\",\"leaf9\":\"true\",\"leaf10\":\"-922337203685477580.8\"" +
+            ",\"ll1\":[1,10],\"ll2\":[2,20],\"ll3\":[3,30],\"ll4\":[4,40],\"" +
+            "ll5\":[5,50],\"ll6\":[6,60],\"ll7\":[\"7\",\"70\"],\"ll8\":[\"" +
+            "8\",\"80\"],\"ll9\":[\"true\",\"false\"],\"ll10\":[" +
+            "\"-922337203685477580.8\",\"-922337203685477480.8\"]}}";
     @Rule
     public ExpectedException thrown = ExpectedException.none();
 
@@ -109,6 +117,42 @@
     }
 
     @Test
+    public void jsonListTest() throws IOException {
+        String path = "src/test/resources/testinput1.json";
+        // decode
+        DefaultCompositeStream external =
+                new DefaultCompositeStream("jsonlist:top1", parseInput(path));
+        CompositeData compositeData = jsonSerializer.decode(external, context);
+        ResourceData resourceData = compositeData.resourceData();
+        ResourceId rid = resourceData.resourceId();
+        DataNode rootNode = resourceData.dataNodes().get(0);
+
+        // encode
+        RuntimeContext.Builder runtimeContextBuilder = DefaultRuntimeContext.builder();
+        runtimeContextBuilder.setDataFormat("JSON");
+        DefaultResourceData.Builder resourceDataBuilder = DefaultResourceData.builder();
+        resourceDataBuilder.addDataNode(rootNode);
+        resourceDataBuilder.resourceId(rid);
+
+        ResourceData resourceDataOutput = resourceDataBuilder.build();
+        DefaultCompositeData.Builder compositeDataBuilder = DefaultCompositeData.builder();
+        compositeDataBuilder.resourceData(resourceDataOutput);
+        CompositeData compositeData1 = compositeDataBuilder.build();
+        // CompositeData --- YangRuntimeService ---> CompositeStream.
+        CompositeStream compositeStreamOutPut = jsonSerializer.encode(compositeData1,
+                                                                      context);
+        InputStream inputStreamOutput = compositeStreamOutPut.resourceData();
+        ObjectNode rootNodeOutput;
+        ObjectMapper mapper = new ObjectMapper();
+        try {
+            rootNodeOutput = (ObjectNode) mapper.readTree(inputStreamOutput);
+            assertEquals(rootNodeOutput.toString(), outputIdTestJson1);
+        } catch (IOException e) {
+            throw e;
+        }
+    }
+
+    @Test
     public void identityValueNsTest() throws IOException {
         String path = "src/test/resources/id-test1.json";
         // decode
diff --git a/serializers/json/src/test/resources/json-test.yang b/serializers/json/src/test/resources/json-test.yang
index 46a1caf..53a4109 100644
--- a/serializers/json/src/test/resources/json-test.yang
+++ b/serializers/json/src/test/resources/json-test.yang
@@ -40,7 +40,89 @@
       leaf-list leaflist1 {
           type string;
       }
-    }
+      leaf leaf1 {
+         type int8;
+      }
 
+      leaf leaf2 {
+        type int16;
+      }
+
+      leaf leaf3 {
+        type int32;
+      }
+
+      leaf leaf4 {
+         type uint8;
+      }
+
+      leaf leaf5 {
+        type uint16;
+      }
+
+      leaf leaf6 {
+        type uint32;
+      }
+
+      leaf leaf7 {
+        type int64;
+      }
+
+      leaf leaf8 {
+        type uint64;
+      }
+
+      leaf leaf9 {
+        type boolean;
+      }
+
+      leaf leaf10 {
+       type decimal64 {
+           fraction-digits 1;
+       }
+      }
+
+      leaf-list ll1 {
+          type int8;
+      }
+
+      leaf-list ll2 {
+          type int16;
+      }
+
+      leaf-list ll3 {
+          type int32;
+      }
+
+      leaf-list ll4 {
+          type uint8;
+      }
+
+      leaf-list ll5 {
+          type uint16;
+      }
+
+      leaf-list ll6 {
+          type uint32;
+      }
+
+      leaf-list ll7 {
+          type int64;
+      }
+
+      leaf-list ll8 {
+          type uint64;
+      }
+
+      leaf-list ll9 {
+          type boolean;
+      }
+
+      leaf-list ll10 {
+        type decimal64 {
+            fraction-digits 1;
+        }
+      }
+    }
   }
 }
diff --git a/serializers/json/src/test/resources/testinput1.json b/serializers/json/src/test/resources/testinput1.json
new file mode 100644
index 0000000..74ac948
--- /dev/null
+++ b/serializers/json/src/test/resources/testinput1.json
@@ -0,0 +1,59 @@
+{
+  "jsonlist:c2": {
+    "leaflist1": [
+      "a",
+      "b",
+      "c"
+    ],
+    "leaf1": 1,
+    "leaf2": 2,
+    "leaf3": 3,
+    "leaf4": 4,
+    "leaf5": 5,
+    "leaf6": 6,
+    "leaf7": "7",
+    "leaf8": "8",
+    "leaf9": "true",
+    "leaf10": "-922337203685477580.8",
+    "ll1": [
+      1,
+      10
+    ],
+    "ll2": [
+      2,
+      20
+    ],
+    "ll3": [
+      3,
+      30
+    ],
+    "ll4": [
+      4,
+      40
+    ],
+    "ll5": [
+      5,
+      50
+    ],
+    "ll6": [
+      6,
+      60
+    ],
+    "ll7": [
+      7,
+      70
+    ],
+    "ll8": [
+      8,
+      80
+    ],
+    "ll9": [
+      "true",
+      "false"
+    ],
+    "ll10": [
+      "-922337203685477580.8",
+      "-922337203685477480.8"
+    ]
+  }
+}
\ No newline at end of file