[ONOS-5397]fixbug:NBI Error for complicate list inside container

1.if a array's children are all not container node,
 it's a leaf-list in yang, should treat differently;
2.for a array, the field name should push into a stack,
 and then pop when exit the array
3. add namespace info for yangnode
4. process the exception of null array node

Change-Id: Ia7b0c25ab1ccea393b97a0fcf59187663348de3b
diff --git a/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/api/NormalizedYangNode.java b/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/api/NormalizedYangNode.java
new file mode 100755
index 0000000..31a1423
--- /dev/null
+++ b/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/api/NormalizedYangNode.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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.protocol.restconf.server.utils.parser.api;
+
+/**
+ * Abstraction of an entity which represents a simple YANG node. This entity
+ * is usually described by a path segment in URI, or a field name in a JSON
+ * node.
+ */
+public class NormalizedYangNode {
+    private final String namespace;
+    private final String name;
+
+    /**
+     * Creates an instance of normalized YANG node using the supplied information.
+     *
+     * @param namespace namespace of a YANG node
+     * @param name      name of a YANG node
+     */
+    public NormalizedYangNode(String namespace, String name) {
+        this.namespace = namespace;
+        this.name = name;
+    }
+
+    /**
+     * Returns the namespace info of a YANG node.
+     *
+     * @return namespace info
+     */
+    public String getNamespace() {
+        return namespace;
+    }
+
+    /**
+     * Returns the name of a YANG node.
+     *
+     * @return name
+     */
+    public String getName() {
+        return name;
+    }
+}
diff --git a/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/JsonToYdtListener.java b/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/JsonToYdtListener.java
old mode 100644
new mode 100755
index 4a130f7..7c59e11
--- a/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/JsonToYdtListener.java
+++ b/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/JsonToYdtListener.java
@@ -21,6 +21,7 @@
 import com.fasterxml.jackson.databind.node.JsonNodeType;
 import org.onosproject.protocol.restconf.server.utils.exceptions.JsonParseException;
 import org.onosproject.protocol.restconf.server.utils.parser.api.JsonListener;
+import org.onosproject.protocol.restconf.server.utils.parser.api.NormalizedYangNode;
 import org.onosproject.yms.ydt.YdtBuilder;
 import org.onosproject.yms.ydt.YdtContext;
 import org.slf4j.Logger;
@@ -28,9 +29,11 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.Stack;
 
 import static com.fasterxml.jackson.databind.node.JsonNodeType.ARRAY;
 import static com.google.common.base.Strings.isNullOrEmpty;
+import static org.onosproject.protocol.restconf.server.utils.parser.json.ParserUtils.buildNormalizedNode;
 import static org.onosproject.yms.ydt.YdtType.MULTI_INSTANCE_NODE;
 import static org.onosproject.yms.ydt.YdtType.SINGLE_INSTANCE_NODE;
 import static org.slf4j.LoggerFactory.getLogger;
@@ -49,8 +52,10 @@
     private Logger log = getLogger(getClass());
 
     private YdtBuilder ydtBuilder;
-    private String defaultMultiInsNodeName;
+    private NormalizedYangNode defaultMultiInsNode;
+    private Stack<NormalizedYangNode> nameStack = new Stack<>();
     private YdtContext rpcModule;
+    private boolean isListArray = false;
 
     /**
      * Creates a listener for the process of a Json Object, the listener will
@@ -65,27 +70,29 @@
     @Override
     public void enterJsonNode(String fieldName, JsonNode node) {
         if (isNullOrEmpty(fieldName)) {
-            if (!isNullOrEmpty(defaultMultiInsNodeName)) {
-                ydtBuilder.addChild(defaultMultiInsNodeName, null,
+            if (defaultMultiInsNode != null) {
+                ydtBuilder.addChild(defaultMultiInsNode.getName(),
+                                    defaultMultiInsNode.getNamespace(),
                                     MULTI_INSTANCE_NODE);
             }
             return;
         }
+        NormalizedYangNode normalizedNode = buildNormalizedNode(fieldName);
         JsonNodeType nodeType = node.getNodeType();
         switch (nodeType) {
             case OBJECT:
-                processObjectNode(fieldName);
+                processObjectNode(normalizedNode);
                 break;
 
             case ARRAY:
-                processArrayNode(fieldName, node);
+                processArrayNode(normalizedNode, node);
                 break;
 
             //TODO for now, just process the following three node type
             case STRING:
             case NUMBER:
             case BOOLEAN:
-                ydtBuilder.addLeaf(fieldName, null, node.asText());
+                processLeafNode(normalizedNode, node.asText());
                 break;
 
             case BINARY:
@@ -103,41 +110,40 @@
 
     @Override
     public void exitJsonNode(JsonNode jsonNode) {
-        if (jsonNode.getNodeType() == ARRAY) {
+        if (jsonNode.getNodeType() == ARRAY && nameStack.empty()) {
             return;
         }
+
+        if (jsonNode.getNodeType() == ARRAY && !isListArray) {
+            nameStack.pop();
+            if (nameStack.empty()) {
+                return;
+            }
+            defaultMultiInsNode = nameStack.get(nameStack.size() - 1);
+            return;
+        }
+        if (isListArray) {
+            isListArray = false;
+        }
+
         ydtBuilder.traverseToParent();
-        YdtContext curNode = ydtBuilder.getCurNode();
-        //if the current node is the RPC node, then should go to the father
-        //for we have enter the RPC node and Input node at the same time
-        //and the input is the only child of RPC node.
+    }
 
-        if (curNode == null) {
+    private void processObjectNode(NormalizedYangNode node) {
+        ydtBuilder.addChild(node.getName(), node.getNamespace(),
+                            SINGLE_INSTANCE_NODE);
+    }
+
+    private void processLeafNode(NormalizedYangNode node, String value) {
+        ydtBuilder.addLeaf(node.getName(), node.getNamespace(), value);
+    }
+
+    private void processArrayNode(NormalizedYangNode normalizedNode,
+                                  JsonNode node) {
+        ArrayNode arrayNode = (ArrayNode) node;
+        if (arrayNode.size() == 0) {
             return;
         }
-        String name = curNode.getName();
-        if (rpcModule != null && name.equals(rpcModule.getName())) {
-            ydtBuilder.traverseToParent();
-        }
-    }
-
-    private void processObjectNode(String fieldName) {
-        String[] segments = fieldName.split(COLON);
-        Boolean isLastInput = segments.length == INPUT_FIELD_LENGTH &&
-                segments[INPUT_FIELD_LENGTH - 1].equals(INPUT_FIELD_NAME);
-        int first = 0;
-        int second = 1;
-        if (isLastInput) {
-            ydtBuilder.addChild(segments[first], null, SINGLE_INSTANCE_NODE);
-            rpcModule = ydtBuilder.getCurNode();
-            ydtBuilder.addChild(segments[second], null, SINGLE_INSTANCE_NODE);
-        } else {
-            ydtBuilder.addChild(fieldName, null, SINGLE_INSTANCE_NODE);
-        }
-    }
-
-    private void processArrayNode(String fieldName, JsonNode node) {
-        ArrayNode arrayNode = (ArrayNode) node;
         Set<String> sets = new HashSet<>();
         Iterator<JsonNode> elements = arrayNode.elements();
         boolean isLeafList = true;
@@ -155,9 +161,12 @@
         }
         if (isLeafList) {
             //leaf-list
-            ydtBuilder.addLeaf(fieldName, null, sets);
+            ydtBuilder.addLeaf(normalizedNode.getName(),
+                               normalizedNode.getNamespace(), sets);
+            isListArray = true;
         } else {
-            this.defaultMultiInsNodeName = fieldName;
+            defaultMultiInsNode = normalizedNode;
+            nameStack.push(defaultMultiInsNode);
         }
     }
 }
diff --git a/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/ParserUtils.java b/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/ParserUtils.java
old mode 100644
new mode 100755
index fa8b133..bc959f0
--- a/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/ParserUtils.java
+++ b/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/ParserUtils.java
@@ -21,6 +21,7 @@
 import com.google.common.collect.Lists;
 import org.onosproject.protocol.restconf.server.utils.exceptions.JsonParseException;
 import org.onosproject.protocol.restconf.server.utils.parser.api.JsonBuilder;
+import org.onosproject.protocol.restconf.server.utils.parser.api.NormalizedYangNode;
 import org.onosproject.yms.ydt.YdtBuilder;
 import org.onosproject.yms.ydt.YdtContext;
 import org.onosproject.yms.ydt.YdtContextOperationType;
@@ -142,25 +143,6 @@
         return builder;
     }
 
-    private static YdtBuilder addModule(YdtBuilder builder, String path) {
-        String moduleName = getPreSegment(path, COLON);
-        if (moduleName == null) {
-            throw new JsonParseException(ERROR_MODULE_MSG);
-        }
-        builder.addChild(moduleName, null, YdtType.SINGLE_INSTANCE_NODE);
-        return builder;
-    }
-
-    private static YdtBuilder addNode(String path, YdtBuilder builder,
-                                      YdtContextOperationType opType) {
-        String nodeName = getLatterSegment(path, COLON);
-        builder.addChild(nodeName,
-                         null,
-                         YdtType.SINGLE_INSTANCE_NODE,
-                         opType);
-        return builder;
-    }
-
     private static YdtBuilder addListOrLeafList(String path,
                                                 YdtBuilder builder,
                                                 YdtContextOperationType opType) {
@@ -188,6 +170,25 @@
         return builder;
     }
 
+    private static YdtBuilder addModule(YdtBuilder builder, String path) {
+        String moduleName = getPreSegment(path, COLON);
+        if (moduleName == null) {
+            throw new JsonParseException(ERROR_MODULE_MSG);
+        }
+        builder.addChild(moduleName, null, YdtType.SINGLE_INSTANCE_NODE);
+        return builder;
+    }
+
+    private static YdtBuilder addNode(String path, YdtBuilder builder,
+                                      YdtContextOperationType opType) {
+        String nodeName = getLatterSegment(path, COLON);
+        builder.addChild(nodeName,
+                         null,
+                         YdtType.SINGLE_INSTANCE_NODE,
+                         opType);
+        return builder;
+    }
+
     /**
      * Returns the previous segment of a path which is separated by a split char.
      * For example:
@@ -256,4 +257,18 @@
                                                  paths + "': ", e);
         }
     }
+
+    /**
+     * Converts a field to a simple YANG node description which contains the
+     * namespace and name information.
+     *
+     * @param field field name of a JSON body, or a segment of a URI
+     *              in a request of RESTCONF
+     * @return a simple normalized YANG node
+     */
+    public static NormalizedYangNode buildNormalizedNode(String field) {
+        String namespace = getPreSegment(field, COLON);
+        String name = getLatterSegment(field, COLON);
+        return new NormalizedYangNode(namespace, name);
+    }
 }