Bug 1848: Make sure that XmlStreamUtils preserve list key order. 87/11287/1
authorTony Tkacik <ttkacik@cisco.com>
Tue, 16 Sep 2014 10:28:58 +0000 (12:28 +0200)
committerTony Tkacik <ttkacik@cisco.com>
Wed, 17 Sep 2014 12:52:23 +0000 (12:52 +0000)
Change-Id: I3d7a91c9ae4ec74b1c7130c4af504af73a2f4507
Signed-off-by: Tony Tkacik <ttkacik@cisco.com>
(cherry picked from commit 2d56be8a89b494cd8423a6377c9574966067aa88)

yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlStreamUtils.java

index 8d3890980bfedc11d39b1dbb09efcd663d0c6885..9ee06ea0e533706277125b290cbef2366230521c 100644 (file)
@@ -4,6 +4,8 @@ import com.google.common.annotations.Beta;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import java.net.URI;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Map;
 import java.util.Map.Entry;
 import javax.annotation.Nonnull;
@@ -22,6 +24,7 @@ import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
@@ -189,16 +192,48 @@ public class XmlStreamUtils {
             }
         } else {
             // CompositeNode
-            for (Node<?> child : ((CompositeNode) data).getValue()) {
-                DataSchemaNode childSchema = null;
-                if (schema instanceof DataNodeContainer) {
-                    childSchema = SchemaUtils.findFirstSchema(child.getNodeType(), ((DataNodeContainer) schema).getChildNodes()).orNull();
-                } else if ((childSchema == null) && LOG.isDebugEnabled()) {
-                    LOG.debug("Probably the data node \"{}\" does not conform to schema", child == null ? "" : child.getNodeType().getLocalName());
+            final CompositeNode castedData = ((CompositeNode) data);
+            final DataNodeContainer castedSchema;
+            if (schema instanceof DataNodeContainer) {
+                castedSchema = (DataNodeContainer) schema;
+            } else {
+                castedSchema = null;
+            }
+            final Collection<QName> keyLeaves;
+            if (schema instanceof ListSchemaNode) {
+                keyLeaves = ((ListSchemaNode) schema).getKeyDefinition();
+
+            } else {
+                keyLeaves = Collections.emptyList();
+
+            }
+            for (QName key : keyLeaves) {
+                SimpleNode<?> keyLeaf = castedData.getFirstSimpleByName(key);
+                if(keyLeaf != null) {
+                    writeChildElement(writer,keyLeaf,castedSchema);
+                }
+            }
+
+            for (Node<?> child : castedData.getValue()) {
+
+                if(keyLeaves.contains(child.getNodeType())) {
+                    // Skip key leaf which was written by previous for loop.
+                    continue;
                 }
-                writeElement(writer, child, childSchema);
+                writeChildElement(writer,child,castedSchema);
+            }
+        }
+    }
+
+    private void writeChildElement(XMLStreamWriter writer, Node<?> child, DataNodeContainer parentSchema) throws XMLStreamException {
+        DataSchemaNode childSchema = null;
+        if (parentSchema != null) {
+            childSchema = SchemaUtils.findFirstSchema(child.getNodeType(), parentSchema.getChildNodes()).orNull();
+            if ((childSchema == null) && LOG.isDebugEnabled()) {
+                LOG.debug("Probably the data node \"{}\" does not conform to schema", child == null ? "" : child.getNodeType().getLocalName());
             }
         }
+        writeElement(writer, child, childSchema);
     }
 
     private static void writeAttributes(final XMLStreamWriter writer, final AttributesContainer data, final RandomPrefix randomPrefix) throws XMLStreamException {