Fix test failure by ordering leaf-lists
[cps.git] / cps-service / src / main / java / org / onap / cps / spi / model / DataNodeBuilder.java
index eaa2d77..9859acd 100644 (file)
@@ -2,7 +2,8 @@
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2021 Bell Canada. All rights reserved.
  *  Modifications Copyright (C) 2021 Pantheon.tech
- *  Modifications Copyright (C) 2022 Nordix Foundation.
+ *  Modifications Copyright (C) 2022-2024 Nordix Foundation.
+ *  Modifications Copyright (C) 2022-2023 TechMahindra Ltd.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -23,6 +24,7 @@ package org.onap.cps.spi.model;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
+import java.io.Serializable;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -32,7 +34,10 @@ import java.util.stream.Collectors;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.spi.exceptions.DataValidationException;
 import org.onap.cps.utils.YangUtils;
+import org.opendaylight.yangtools.yang.common.Ordering;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
@@ -44,12 +49,14 @@ import org.opendaylight.yangtools.yang.data.api.schema.ValueNode;
 @Slf4j
 public class DataNodeBuilder {
 
-    private NormalizedNode normalizedNodeTree;
+    private ContainerNode containerNode;
     private String xpath;
     private String moduleNamePrefix;
     private String parentNodeXpath = "";
-    private Map<String, Object> leaves = Collections.emptyMap();
+    private Map<String, Serializable> leaves = Collections.emptyMap();
     private Collection<DataNode> childDataNodes = Collections.emptySet();
+    private String dataspaceName;
+    private String anchorName;
 
     /**
      * To use parent node xpath for creating {@link DataNode}.
@@ -62,15 +69,14 @@ public class DataNodeBuilder {
         return this;
     }
 
-
     /**
-     * To use {@link NormalizedNode} for creating {@link DataNode}.
+     * To use {@link Collection} of Normalized Nodes for creating {@link DataNode}.
      *
-     * @param normalizedNodeTree used for creating the Data Node
+     * @param containerNode used for creating the Data Node
      * @return this {@link DataNodeBuilder} object
      */
-    public DataNodeBuilder withNormalizedNodeTree(final NormalizedNode normalizedNodeTree) {
-        this.normalizedNodeTree = normalizedNodeTree;
+    public DataNodeBuilder withContainerNode(final ContainerNode containerNode) {
+        this.containerNode = containerNode;
         return this;
     }
 
@@ -85,6 +91,28 @@ public class DataNodeBuilder {
         return this;
     }
 
+    /**
+     * To use dataspace name for creating {@link DataNode}.
+     *
+     * @param dataspaceName dataspace name for the data node
+     * @return DataNodeBuilder
+     */
+    public DataNodeBuilder withDataspace(final String dataspaceName) {
+        this.dataspaceName = dataspaceName;
+        return this;
+    }
+
+    /**
+     * To use anchor name for creating {@link DataNode}.
+     *
+     * @param anchorName anchor name for the data node
+     * @return DataNodeBuilder
+     */
+    public DataNodeBuilder withAnchor(final String anchorName) {
+        this.anchorName = anchorName;
+        return this;
+    }
+
     /**
      * To use module name for prefix for creating {@link DataNode}.
      *
@@ -102,7 +130,7 @@ public class DataNodeBuilder {
      * @param leaves for the data node
      * @return DataNodeBuilder
      */
-    public DataNodeBuilder withLeaves(final Map<String, Object> leaves) {
+    public DataNodeBuilder withLeaves(final Map<String, Serializable> leaves) {
         this.leaves = leaves;
         return this;
     }
@@ -126,11 +154,10 @@ public class DataNodeBuilder {
      * @return {@link DataNode}
      */
     public DataNode build() {
-        if (normalizedNodeTree != null) {
-            return buildFromNormalizedNodeTree();
-        } else {
-            return buildFromAttributes();
+        if (containerNode != null) {
+            return buildFromContainerNode();
         }
+        return buildFromAttributes();
     }
 
     /**
@@ -139,11 +166,10 @@ public class DataNodeBuilder {
      * @return {@link DataNode} {@link Collection}
      */
     public Collection<DataNode> buildCollection() {
-        if (normalizedNodeTree != null) {
-            return buildCollectionFromNormalizedNodeTree();
-        } else {
-            return Set.of(buildFromAttributes());
+        if (containerNode != null) {
+            return buildCollectionFromContainerNode();
         }
+        return Collections.emptySet();
     }
 
     private DataNode buildFromAttributes() {
@@ -152,35 +178,42 @@ public class DataNodeBuilder {
         dataNode.setModuleNamePrefix(moduleNamePrefix);
         dataNode.setLeaves(leaves);
         dataNode.setChildDataNodes(childDataNodes);
+        dataNode.setDataspace(dataspaceName);
+        dataNode.setAnchorName(anchorName);
         return dataNode;
     }
 
-    private DataNode buildFromNormalizedNodeTree() {
-        final Collection<DataNode> dataNodeCollection = buildCollectionFromNormalizedNodeTree();
-        if (!dataNodeCollection.iterator().hasNext()) {
-            throw new DataValidationException(
-                "Unsupported xpath: ", "Unsupported xpath as it is referring to one element");
+    private DataNode buildFromContainerNode() {
+        final Collection<DataNode> dataNodeCollection = buildCollectionFromContainerNode();
+        if (dataNodeCollection.isEmpty()) {
+            throw new DataValidationException("Unsupported Normalized Node", "No valid node found");
         }
         return dataNodeCollection.iterator().next();
     }
 
-    private Collection<DataNode> buildCollectionFromNormalizedNodeTree() {
+    private Collection<DataNode> buildCollectionFromContainerNode() {
         final var parentDataNode = new DataNodeBuilder().withXpath(parentNodeXpath).build();
-        addDataNodeFromNormalizedNode(parentDataNode, normalizedNodeTree);
+        if (containerNode.body() != null) {
+            for (final NormalizedNode normalizedNode: containerNode.body()) {
+                addDataNodeFromNormalizedNode(parentDataNode, normalizedNode);
+            }
+        }
         return parentDataNode.getChildDataNodes();
     }
 
     private static void addDataNodeFromNormalizedNode(final DataNode currentDataNode,
         final NormalizedNode normalizedNode) {
 
-        if (normalizedNode instanceof DataContainerNode) {
+        if (normalizedNode instanceof ChoiceNode) {
+            addChoiceNode(currentDataNode, (ChoiceNode) normalizedNode);
+        } else if (normalizedNode instanceof DataContainerNode) {
             addYangContainer(currentDataNode, (DataContainerNode) normalizedNode);
         } else if (normalizedNode instanceof MapNode) {
             addDataNodeForEachListElement(currentDataNode, (MapNode) normalizedNode);
         } else if (normalizedNode instanceof ValueNode) {
             final ValueNode<NormalizedNode> valuesNode = (ValueNode) normalizedNode;
             addYangLeaf(currentDataNode, valuesNode.getIdentifier().getNodeType().getLocalName(),
-                    valuesNode.body());
+                    (Serializable) valuesNode.body());
         } else if (normalizedNode instanceof LeafSetNode) {
             addYangLeafList(currentDataNode, (LeafSetNode<?>) normalizedNode);
         } else {
@@ -199,8 +232,9 @@ public class DataNodeBuilder {
         }
     }
 
-    private static void addYangLeaf(final DataNode currentDataNode, final String leafName, final Object leafValue) {
-        final Map<String, Object> leaves = new ImmutableMap.Builder<String, Object>()
+    private static void addYangLeaf(final DataNode currentDataNode, final String leafName,
+                                    final Serializable leafValue) {
+        final Map<String, Serializable> leaves = new ImmutableMap.Builder<String, Serializable>()
             .putAll(currentDataNode.getLeaves())
             .put(leafName, leafValue)
             .build();
@@ -209,11 +243,15 @@ public class DataNodeBuilder {
 
     private static void addYangLeafList(final DataNode currentDataNode, final LeafSetNode<?> leafSetNode) {
         final String leafListName = leafSetNode.getIdentifier().getNodeType().getLocalName();
-        final List<?> leafListValues = ((Collection<? extends NormalizedNode>) leafSetNode.body())
+        List<?> leafListValues = ((Collection<? extends NormalizedNode>) leafSetNode.body())
                 .stream()
-                .map(normalizedNode -> (normalizedNode).body())
-                .collect(Collectors.toUnmodifiableList());
-        addYangLeaf(currentDataNode, leafListName, leafListValues);
+                .map(NormalizedNode::body)
+                .collect(Collectors.toList());
+        if (leafSetNode.ordering() == Ordering.SYSTEM) {
+            leafListValues.sort(null);
+        }
+        leafListValues = Collections.unmodifiableList(leafListValues);
+        addYangLeaf(currentDataNode, leafListName, (Serializable) leafListValues);
     }
 
     private static void addDataNodeForEachListElement(final DataNode currentDataNode, final MapNode mapNode) {
@@ -236,4 +274,12 @@ public class DataNodeBuilder {
         return newChildDataNode;
     }
 
+    private static void addChoiceNode(final DataNode currentDataNode, final ChoiceNode choiceNode) {
+
+        final Collection<DataContainerChild> normalizedChildNodes = choiceNode.body();
+        for (final NormalizedNode normalizedNode : normalizedChildNodes) {
+            addDataNodeFromNormalizedNode(currentDataNode, normalizedNode);
+        }
+    }
+
 }