Update the Netconf custom rpc as follows:
1) Create a message/field YANG reference.  This is used to keep the
XML tags in the same order as the fields appear in the YANG schema.
This applies only for custom RPCs (one of Netconf twist)
2) Annotate the proto RPCs with custom annotations which are used
when constructing an XML response

Change-Id: I07a8a3f2a44b7081c78e00dab05734a7c6b0a358
diff --git a/netconf/nc_rpc/base/get.py b/netconf/nc_rpc/base/get.py
index 6337b5f..19535f5 100644
--- a/netconf/nc_rpc/base/get.py
+++ b/netconf/nc_rpc/base/get.py
@@ -63,7 +63,7 @@
             self.metadata = self.request['metadata']
 
         # Execute the request
-        res_dict = yield self.grpc_client.invoke_voltha_rpc(
+        res_dict, yang_options = yield self.grpc_client.invoke_voltha_rpc(
             service=self.service,
             method=self.method,
             params=self.params,
@@ -77,7 +77,7 @@
 
         # Build the yang response
         self.rpc_response.node = self.rpc_response.build_yang_response(
-            root_elem, self.request)
+            root_elem, self.request, yang_options=yang_options)
         self.rpc_response.is_error = False
 
         returnValue(self.rpc_response)
@@ -158,9 +158,9 @@
             {'subclass': 'device_groups',
              'rpc': 'VolthaLocalService-ListDeviceGroups'
              },
-        ]
-        # 'VolthaInstances': [
-        #     {'subclass': None,
-        #      'rpc': 'VolthaGlobalService-ListVolthaInstances'
-        #      }],
+        ],
+        'VolthaInstances': [
+            {'subclass': None,
+             'rpc': 'VolthaGlobalService-ListVolthaInstances'
+             }],
     }
diff --git a/netconf/nc_rpc/base/get_config.py b/netconf/nc_rpc/base/get_config.py
index 7b89ded..ba281e4 100644
--- a/netconf/nc_rpc/base/get_config.py
+++ b/netconf/nc_rpc/base/get_config.py
@@ -23,8 +23,10 @@
 
 
 class GetConfig(Rpc):
-    def __init__(self, request, request_xml, grpc_client, session, capabilities):
-        super(GetConfig, self).__init__(request, request_xml, grpc_client, session)
+    def __init__(self, request, request_xml, grpc_client, session,
+                 capabilities):
+        super(GetConfig, self).__init__(request, request_xml, grpc_client,
+                                        session, capabilities)
         self._validate_parameters()
 
     def execute(self):
@@ -44,7 +46,8 @@
             self.rpc_response.node = ncerror.BadMsg(self.rpc_request)
             return
 
-        self.source_param = self.rpc_method.find(C.NC_SOURCE, namespaces=C.NS_MAP)
+        self.source_param = self.rpc_method.find(C.NC_SOURCE,
+                                                 namespaces=C.NS_MAP)
         # if self.source_param is None:
         # 	self.rpc_response.is_error = True
         # 	self.rpc_response.node = ncerror.MissingElement(
diff --git a/netconf/nc_rpc/ext/voltha_rpc.py b/netconf/nc_rpc/ext/voltha_rpc.py
index 37ba305..835f900 100644
--- a/netconf/nc_rpc/ext/voltha_rpc.py
+++ b/netconf/nc_rpc/ext/voltha_rpc.py
@@ -48,7 +48,7 @@
                  request=self.request)
 
         # Execute the request
-        res_dict = yield self.grpc_client.invoke_voltha_rpc(
+        res_dict, yang_options = yield self.grpc_client.invoke_voltha_rpc(
             service=self.service,
             method=self.method,
             params=self.request['params'],
@@ -62,7 +62,7 @@
 
         # Build the yang response
         self.rpc_response.node = self.rpc_response.build_yang_response(
-            root_elem, self.request, custom_rpc=True)
+            root_elem, self.request, yang_options=yang_options, custom_rpc=True)
         self.rpc_response.is_error = False
 
         returnValue(self.rpc_response)
diff --git a/netconf/nc_rpc/rpc_response.py b/netconf/nc_rpc/rpc_response.py
index 2d60d77..3b2deba 100644
--- a/netconf/nc_rpc/rpc_response.py
+++ b/netconf/nc_rpc/rpc_response.py
@@ -47,6 +47,10 @@
         elif voltha_xml_string.startswith('<yang/>'):
             voltha_xml_string = ''
 
+        # Replace any True/False data to true/false
+        voltha_xml_string = voltha_xml_string.replace('>False<', '>false<')
+        voltha_xml_string = voltha_xml_string.replace('>True<', '>true<')
+
         if not custom_rpc:
             # Create the xml body as
             if request.has_key('subclass'):
@@ -127,10 +131,11 @@
         if (attrib == 'list'):
             if list(elem) is None:
                 return self.copy_basic_element(elem)
-            if elem.tag == 'items':
-                new_elem = etree.Element('items')
-            else:
-                new_elem = etree.Element('ignore')
+                # if elem.tag == 'items':
+                # new_elem = etree.Element('items')
+            new_elem = etree.Element('ignore')
+            # else:
+            # new_elem = etree.Element('ignore')
             for elm in list(elem):
                 elm.tag = elem.tag
                 if elm.get('type') in ['list', 'dict']:
@@ -155,7 +160,8 @@
         else:
             return self.copy_basic_element(elem)
 
-    def to_yang_xml(self, from_xml, request, custom_rpc=False):
+    def to_yang_xml(self, from_xml, request, yang_options=None,
+                    custom_rpc=False):
         # Parse from_xml as follows:
         # 1.  Any element having a list attribute shoud have each item move 1 level
         #     up and retag using the parent tag
@@ -163,20 +169,27 @@
         #     sub-element should have all it's items move to teh parent level
         top = etree.Element('yang')
         elms = list(from_xml)
-
+        xml_tag = yang_options[0]
+        list_items_name = yang_options[1]
         # special case the xml contain a list type
-        if len(elms) == 1 and not custom_rpc:
+        if len(elms) == 1:
             item = elms[0]
-            # TODO: Address name 'items' clash when a list name is actually
-            # 'items'.
             if item.get('type') == 'list':
-                if request.has_key('subclass'):
-                    item.tag = request['subclass']
-                    # remove the subclass element in request to avoid duplicate tag
-                    del request['subclass']
+                if list_items_name == 'items':
+                    # Create a new parent element
+                    new_elem = etree.Element(xml_tag)
+                    self.add_node(self.process_element(item), new_elem)
+                    top.append(new_elem)
                 else:
-                    item.tag = 'ignore'
-                self.add_node(self.process_element(item), top)
+                    if xml_tag and custom_rpc:
+                        item.tag = xml_tag
+                    elif request.has_key('subclass'):
+                        item.tag = request['subclass']
+                        # remove the subclass element in request to avoid duplicate tag
+                        del request['subclass']
+                    else:
+                        item.tag = 'ignore'
+                    self.add_node(self.process_element(item), top)
                 return top
 
         # Process normally for all other cases
@@ -185,12 +198,20 @@
 
         return top
 
+    # Helper method to sort the xml message based on the xml tags
+    def sort_xml_response(self, xml):
+        for parent in xml.xpath('//*[./*]'):  # Search for parent elements
+            parent[:] = sorted(parent, key=lambda x: x.tag)
+        return xml
+
     # custom_rpc refers to custom RPCs different from Netconf default RPCs
     # like get, get-config, edit-config, etc
-    def build_yang_response(self, root, request, custom_rpc=False):
+    def build_yang_response(self, root, request, yang_options=None,
+                            custom_rpc=False):
         try:
             self.custom_rpc = custom_rpc
-            yang_xml = self.to_yang_xml(root, request, custom_rpc)
+            yang_xml = self.to_yang_xml(root, request, yang_options,
+                                        custom_rpc)
             log.info('yang-xml', yang_xml=etree.tounicode(yang_xml,
                                                           pretty_print=True))
             return self.build_xml_response(request, yang_xml, custom_rpc)