[ONOS-5500] Properly encode namespaces in URI path segments

Change-Id: I166cbfb8e379a2029f0dab72be117a3afe74973e
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
index bc959f0..5ede187 100755
--- 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
@@ -70,7 +70,7 @@
         checkNotNull(id, "uri identifier should not be null");
         List<String> paths = urlPathArgsDecode(SLASH_SPLITTER.split(id));
         if (!paths.isEmpty()) {
-            processPathSegments(paths, builder, opType);
+            processPathSegments(paths, builder, opType, true);
         }
     }
 
@@ -110,40 +110,102 @@
     /**
      * Converts a list of path segments to a YDT builder tree.
      *
-     * @param paths   the list of path segments split from URI
-     * @param builder the base YDT builder
-     * @param opType  the YDT operation type for the Path segment
+     * @param paths            the list of path segments split from URI
+     * @param builder          the base YDT builder
+     * @param opType           the YDT operation type for the Path segment
+     * @param isFirstIteration true if paths contains all the URI segments
      * @return the YDT builder with the tree info of paths
      */
     private static YdtBuilder processPathSegments(List<String> paths,
                                                   YdtBuilder builder,
-                                                  YdtContextOperationType opType) {
+                                                  YdtContextOperationType opType,
+                                                  boolean isFirstIteration) {
         if (paths.isEmpty()) {
             return builder;
         }
-        boolean isLastNode = paths.size() == 1;
-        YdtContextOperationType opTypeForThisNode = isLastNode ? opType : NONE;
 
-        String path = paths.iterator().next();
-        if (path.contains(COLON)) {
-            addModule(builder, path);
-            addNode(path, builder, opTypeForThisNode);
-        } else if (path.contains(EQUAL)) {
-            addListOrLeafList(path, builder, opTypeForThisNode);
-        } else {
-            addLeaf(path, builder, opTypeForThisNode);
-        }
+        boolean isLastSegment = paths.size() == 1;
 
-        if (isLastNode) {
+        /*
+         * Process the first segment in path.
+         *
+         * BUG ONOS-5500: YMS requires the treatment for the very first
+         * segment in the URI path to be different than the rest. So,
+         * we added a parameter, isFirstIteration, to this function.
+         * It is set to true by the caller when this function is called
+         * the very first time (i.e,, "paths" contains all the segments).
+         *
+         */
+        YdtContextOperationType opTypeForThisSegment = isLastSegment ? opType : NONE;
+        String segment = paths.iterator().next();
+        processSinglePathSegment(segment, builder, opTypeForThisSegment, isFirstIteration);
+
+        if (isLastSegment) {
+            // We have hit the base case of recursion.
             return builder;
         }
+
+        /*
+         * Chop off the first segment, and recursively process the rest
+         * of the path segments.
+         */
         List<String> remainPaths = paths.subList(1, paths.size());
-        processPathSegments(remainPaths, builder, opType);
+        processPathSegments(remainPaths, builder, opType, false);
 
         return builder;
     }
 
+    private static void processSinglePathSegment(String pathSegment,
+                                                 YdtBuilder builder,
+                                                 YdtContextOperationType opType,
+                                                 boolean isTopLevelSegment) {
+        if (pathSegment.contains(COLON)) {
+            processPathSegmentWithNamespace(pathSegment, builder, opType, isTopLevelSegment);
+        } else {
+            processPathSegmentWithoutNamespace(pathSegment, builder, opType);
+        }
+    }
+
+    private static void processPathSegmentWithNamespace(String pathSegment,
+                                                        YdtBuilder builder,
+                                                        YdtContextOperationType opType,
+                                                        boolean isTopLevelSegment) {
+        if (isTopLevelSegment) {
+            /*
+             * BUG ONOS-5500: If this segment refers to the first node in
+             * the path (i.e., top level of the model hierarchy), then
+             * YMS requires 2 YDT nodes to be added instead of one. The
+             * first one contains the namespace, and the second contains
+             * the node name. For other segments in the path, only one
+             * YDT node is needed.
+             */
+            addModule(builder, pathSegment);
+        }
+
+        String nodeName = getLatterSegment(pathSegment, COLON);
+        String namespace = getPreSegment(pathSegment, COLON);
+        convertPathSegmentToYdtNode(nodeName, namespace, builder, opType);
+    }
+
+    private static void processPathSegmentWithoutNamespace(String pathSegment,
+                                                           YdtBuilder builder,
+                                                           YdtContextOperationType opType) {
+        convertPathSegmentToYdtNode(pathSegment, null, builder, opType);
+    }
+
+    private static void convertPathSegmentToYdtNode(String pathSegment,
+                                                    String namespace,
+                                                    YdtBuilder builder,
+                                                    YdtContextOperationType opType) {
+        if (pathSegment.contains(EQUAL)) {
+            addListOrLeafList(pathSegment, namespace, builder, opType);
+        } else {
+            addLeaf(pathSegment, namespace, builder, opType);
+        }
+    }
+
     private static YdtBuilder addListOrLeafList(String path,
+                                                String namespace,
                                                 YdtBuilder builder,
                                                 YdtContextOperationType opType) {
         String nodeName = getPreSegment(path, EQUAL);
@@ -155,18 +217,20 @@
         if (keyStr.contains(COMMA)) {
             List<String> keys = Lists.
                     newArrayList(COMMA_SPLITTER.split(keyStr));
-            builder.addMultiInstanceChild(nodeName, null, keys);
+            builder.addMultiInstanceChild(nodeName, namespace, keys);
         } else {
-            builder.addMultiInstanceChild(nodeName, null,
+            builder.addMultiInstanceChild(nodeName, namespace,
                                           Lists.newArrayList(keyStr));
         }
         return builder;
     }
 
-    private static YdtBuilder addLeaf(String path, YdtBuilder builder,
+    private static YdtBuilder addLeaf(String path,
+                                      String namespace,
+                                      YdtBuilder builder,
                                       YdtContextOperationType opType) {
         checkNotNull(path);
-        builder.addChild(path, null, opType);
+        builder.addChild(path, namespace, opType);
         return builder;
     }
 
diff --git a/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/YdtToJsonListener.java b/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/YdtToJsonListener.java
index b0ce26b..4ffd6f1 100644
--- a/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/YdtToJsonListener.java
+++ b/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/YdtToJsonListener.java
@@ -55,7 +55,7 @@
     public void enterYdtNode(YdtContext ydtContext) {
         String name = ydtContext.getName();
 
-        if (!isBegin && name.equals(rootName)) {
+        if (!isBegin && name != null && name.equals(rootName)) {
             isBegin = true;
         }
         if (!isBegin) {