[ONOS-4636]grouping and uses

Change-Id: Ic410d03a838003ad23b2b0e8874b91503da84153
diff --git a/utils/yangutils/datamodel/src/main/java/org/onosproject/yangutils/datamodel/utils/DataModelUtils.java b/utils/yangutils/datamodel/src/main/java/org/onosproject/yangutils/datamodel/utils/DataModelUtils.java
index 410e025..1e15d1d 100644
--- a/utils/yangutils/datamodel/src/main/java/org/onosproject/yangutils/datamodel/utils/DataModelUtils.java
+++ b/utils/yangutils/datamodel/src/main/java/org/onosproject/yangutils/datamodel/utils/DataModelUtils.java
@@ -20,6 +20,7 @@
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.util.ArrayList;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 
@@ -28,6 +29,7 @@
 import org.onosproject.yangutils.datamodel.YangIfFeature;
 import org.onosproject.yangutils.datamodel.YangAugment;
 import org.onosproject.yangutils.datamodel.YangBase;
+import org.onosproject.yangutils.datamodel.YangEnumeration;
 import org.onosproject.yangutils.datamodel.YangIdentityRef;
 import org.onosproject.yangutils.datamodel.YangLeaf;
 import org.onosproject.yangutils.datamodel.YangLeafList;
@@ -38,8 +40,10 @@
 import org.onosproject.yangutils.datamodel.YangResolutionInfo;
 import org.onosproject.yangutils.datamodel.YangRpc;
 import org.onosproject.yangutils.datamodel.YangType;
+import org.onosproject.yangutils.datamodel.YangUnion;
 import org.onosproject.yangutils.datamodel.YangUses;
 import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
+import org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes;
 
 /**
  * Represents utilities for data model tree.
@@ -307,4 +311,104 @@
         }
         return nodes;
     }
+
+    /**
+     * Clones the list of leaves and list of leaf list in the leaves holder.
+     *
+     * @param leavesHolder YANG node potentially containing leaves or leaf lists
+     * @throws CloneNotSupportedException clone is not supported
+     * @throws DataModelException         data model error
+     */
+    public static void cloneLeaves(YangLeavesHolder leavesHolder)
+            throws CloneNotSupportedException, DataModelException {
+        List<YangLeaf> currentListOfLeaves = leavesHolder.getListOfLeaf();
+        if (currentListOfLeaves != null) {
+            List<YangLeaf> clonedLeavesList = new LinkedList<YangLeaf>();
+            for (YangLeaf leaf : currentListOfLeaves) {
+                YangLeaf clonedLeaf = leaf.clone();
+                clonedLeaf.setContainedIn(leavesHolder);
+                clonedLeavesList.add(clonedLeaf);
+            }
+            leavesHolder.setListOfLeaf(clonedLeavesList);
+        }
+
+        List<YangLeafList> currentListOfLeafList = leavesHolder.getListOfLeafList();
+        if (currentListOfLeafList != null) {
+            List<YangLeafList> clonedListOfLeafList = new LinkedList<YangLeafList>();
+            for (YangLeafList leafList : currentListOfLeafList) {
+                YangLeafList clonedLeafList = leafList.clone();
+                clonedLeafList.setContainedIn(leavesHolder);
+                clonedListOfLeafList.add(clonedLeafList);
+            }
+            leavesHolder.setListOfLeafList(clonedListOfLeafList);
+        }
+    }
+
+    /**
+     * Clones the union or enum leaves. If there is any cloned leaves whose type is union/enum then the corresponding
+     * type info needs to be updated to the cloned new type node.
+     *
+     * @param leavesHolder cloned leaves holder, for whom the leaves reference needs to be updated
+     */
+    public static void updateClonedLeavesUnionEnumRef(YangLeavesHolder leavesHolder) throws DataModelException {
+        List<YangLeaf> currentListOfLeaves = leavesHolder.getListOfLeaf();
+        if (currentListOfLeaves != null) {
+            for (YangLeaf leaf : currentListOfLeaves) {
+                if (leaf.getDataType().getDataType() == YangDataTypes.ENUMERATION
+                        || leaf.getDataType().getDataType() == YangDataTypes.UNION) {
+                    try {
+                        updateClonedTypeRef(leaf.getDataType(), leavesHolder);
+                    } catch (DataModelException e) {
+                        throw e;
+                    }
+                }
+            }
+
+        }
+
+        List<YangLeafList> currentListOfLeafList = leavesHolder.getListOfLeafList();
+        if (currentListOfLeafList != null) {
+            for (YangLeafList leafList : currentListOfLeafList) {
+                if (leafList.getDataType().getDataType() == YangDataTypes.ENUMERATION
+                        || leafList.getDataType().getDataType() == YangDataTypes.UNION) {
+                    try {
+                        updateClonedTypeRef(leafList.getDataType(), leavesHolder);
+                    } catch (DataModelException e) {
+                        throw e;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Updates the types extended info pointer to point to the cloned type node.
+     *
+     * @param dataType     data type, whose extended info needs to be pointed to the cloned type
+     * @param leavesHolder the leaves holder having the cloned type
+     */
+    private static void updateClonedTypeRef(YangType dataType, YangLeavesHolder leavesHolder)
+            throws DataModelException {
+        if (!(leavesHolder instanceof YangNode)) {
+            throw new DataModelException("Data model error: cloned leaves holder is not a node");
+        }
+        YangNode potentialTypeNode = ((YangNode) leavesHolder).getChild();
+        while (potentialTypeNode != null) {
+            String dataTypeName = null;
+            if (dataType.getDataType() == YangDataTypes.ENUMERATION) {
+                YangEnumeration enumNode = (YangEnumeration) dataType.getDataTypeExtendedInfo();
+                dataTypeName = enumNode.getName();
+            } else if (dataType.getDataType() == YangDataTypes.UNION) {
+                YangUnion unionNode = (YangUnion) dataType.getDataTypeExtendedInfo();
+                dataTypeName = unionNode.getName();
+            }
+            if (potentialTypeNode.getName().contentEquals(dataTypeName)) {
+                dataType.setDataTypeExtendedInfo((Object) potentialTypeNode);
+                return;
+            }
+            potentialTypeNode = potentialTypeNode.getNextSibling();
+        }
+
+        throw new DataModelException("Data model error: cloned leaves type is not found");
+    }
 }