YANG uses and UT

Change-Id: Id3ec5cfed2b8e2a7d2d580786c70b5804f03ecfa
diff --git a/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/YangNode.java b/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/YangNode.java
index 0413e653..ae29433 100644
--- a/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/YangNode.java
+++ b/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/YangNode.java
@@ -16,6 +16,7 @@
 package org.onosproject.yangutils.datamodel;
 
 import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
+import org.onosproject.yangutils.parser.Parsable;
 import org.onosproject.yangutils.translator.tojava.TraversalType;
 
 import static org.onosproject.yangutils.translator.tojava.TraversalType.CHILD;
@@ -281,9 +282,11 @@
                 if (nextNodeToClone == null) {
                     throw new DataModelException("Internal error: Cloning failed, source tree null pointer reached");
                 }
-
-                if (curTraversal == CHILD) {
+                if (curTraversal != PARENT) {
                     newNode = nextNodeToClone.clone();
+                    detectCollisionWhileCloning(clonedTreeCurNode, newNode, curTraversal);
+                }
+                if (curTraversal == CHILD) {
 
                     /**
                      * add the new node to the cloned tree.
@@ -295,7 +298,6 @@
                      */
                     clonedTreeCurNode = newNode;
                 } else if (curTraversal == SIBILING) {
-                    newNode = nextNodeToClone.clone();
 
                     clonedTreeCurNode.addNextSibling(newNode);
                     clonedTreeCurNode = newNode;
@@ -328,6 +330,38 @@
     }
 
     /**
+     * Detects collision when the grouping is deep copied to the uses's parent.
+     *
+     * @param currentNode parent/previous sibling node for the new node
+     * @param newNode node which has to be added
+     * @param addAs traversal type of the node
+     * @throws DataModelException data model error
+     */
+    private static void detectCollisionWhileCloning(YangNode currentNode, YangNode newNode, TraversalType addAs)
+            throws DataModelException {
+        if ((!(currentNode instanceof CollisionDetector))
+                || (!(newNode instanceof Parsable))) {
+            throw new DataModelException("Node in data model tree does not support collision detection");
+        }
+
+        CollisionDetector collisionDetector = (CollisionDetector) currentNode;
+        Parsable parsable = (Parsable) newNode;
+        if (addAs == TraversalType.CHILD) {
+            collisionDetector.detectCollidingChild(newNode.getName(), parsable.getYangConstructType());
+        } else if (addAs == TraversalType.SIBILING) {
+            currentNode = currentNode.getParent();
+            if (!(currentNode instanceof CollisionDetector)) {
+                throw new DataModelException("Node in data model tree does not support collision detection");
+            }
+            collisionDetector = (CollisionDetector) currentNode;
+            collisionDetector.detectCollidingChild(newNode.getName(), parsable.getYangConstructType());
+        } else {
+            throw new DataModelException("Errored tree cloning");
+        }
+
+    }
+
+    /**
      * Add a new next sibling.
      *
      * @param newSibling new sibling to be added
diff --git a/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/YangUses.java b/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/YangUses.java
index 7f9b4a3..16f45c4 100644
--- a/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/YangUses.java
+++ b/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/YangUses.java
@@ -19,6 +19,7 @@
 import org.onosproject.yangutils.parser.Parsable;
 import org.onosproject.yangutils.utils.YangConstructType;
 
+import static org.onosproject.yangutils.datamodel.utils.DataModelUtils.detectCollidingChildUtil;
 import static org.onosproject.yangutils.translator.tojava.utils.JavaIdentifierSyntax.getParentNodeInGenCode;
 
 /*-
@@ -56,7 +57,7 @@
  */
 public class YangUses
         extends YangNode
-        implements YangCommonInfo, Parsable, Resolvable {
+        implements YangCommonInfo, Parsable, Resolvable, CollisionDetector {
 
     /**
      * YANG node identifier.
@@ -267,18 +268,23 @@
         }
 
         YangNode usesParentNode = getParentNodeInGenCode(this);
-        if (!(usesParentNode instanceof YangLeavesHolder)) {
+        if ((!(usesParentNode instanceof YangLeavesHolder))
+                || (!(usesParentNode instanceof CollisionDetector))) {
             throw new DataModelException("YANG uses holder construct is wrong");
         }
 
         YangLeavesHolder usesParentLeavesHolder = (YangLeavesHolder) usesParentNode;
         if (referredGrouping.getListOfLeaf() != null) {
             for (YangLeaf leaf : referredGrouping.getListOfLeaf()) {
+                ((CollisionDetector) usesParentLeavesHolder).detectCollidingChild(leaf.getLeafName(),
+                        YangConstructType.LEAF_DATA);
                 usesParentLeavesHolder.addLeaf(leaf);
             }
         }
         if (referredGrouping.getListOfLeafList() != null) {
             for (YangLeafList leafList : referredGrouping.getListOfLeafList()) {
+                ((CollisionDetector) usesParentLeavesHolder).detectCollidingChild(leafList.getLeafName(),
+                        YangConstructType.LEAF_LIST_DATA);
                 usesParentLeavesHolder.addLeafList(leafList);
             }
         }
@@ -295,4 +301,19 @@
     public void setResolvableStatus(ResolvableStatus resolvableStatus) {
         this.resolvableStatus = resolvableStatus;
     }
+
+    @Override
+    public void detectCollidingChild(String identifierName, YangConstructType dataType) throws DataModelException {
+        detectCollidingChildUtil(identifierName, dataType, this);
+    }
+
+    @Override
+    public void detectSelfCollision(String identifierName, YangConstructType dataType) throws DataModelException {
+
+        if (getName().equals(identifierName)) {
+            throw new DataModelException("YANG file error: Duplicate input identifier detected, same as uses \""
+                    + getName() + "\"");
+        }
+    }
+
 }
diff --git a/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/utils/DataModelUtils.java b/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/utils/DataModelUtils.java
index 643eda5..e848299 100644
--- a/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/utils/DataModelUtils.java
+++ b/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/utils/DataModelUtils.java
@@ -27,9 +27,9 @@
 import org.onosproject.yangutils.datamodel.YangNode;
 import org.onosproject.yangutils.datamodel.YangResolutionInfo;
 import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
+import org.onosproject.yangutils.parser.Parsable;
 import org.onosproject.yangutils.utils.YangConstructType;
 
-
 /**
  * Represents utilities for data model tree.
  */
@@ -53,21 +53,44 @@
     public static void detectCollidingChildUtil(String identifierName, YangConstructType dataType, YangNode node)
             throws DataModelException {
 
-        if (dataType == YangConstructType.LEAF_DATA) {
-            YangLeavesHolder leavesHolder = (YangLeavesHolder) node;
-            if (leavesHolder.getListOfLeaf() != null) {
-                detectCollidingLeaf(leavesHolder, identifierName);
-            }
-        }
-        if (dataType == YangConstructType.LEAF_LIST_DATA) {
-            if (((YangLeavesHolder) node).getListOfLeafList() != null) {
+        if (dataType == YangConstructType.USES_DATA || dataType == YangConstructType.GROUPING_DATA) {
+            detectCollidingForUsesGrouping(identifierName, dataType, node);
+        } else {
+            if (node instanceof YangLeavesHolder) {
                 YangLeavesHolder leavesHolder = (YangLeavesHolder) node;
-                detectCollidingLeafList(leavesHolder, identifierName);
+                detectCollidingLeaf(leavesHolder.getListOfLeaf(), identifierName);
+                detectCollidingLeafList(leavesHolder.getListOfLeafList(), identifierName);
+            }
+            node = node.getChild();
+            while (node != null) {
+                Parsable parsable = (Parsable) node;
+                if (node instanceof CollisionDetector
+                        && (parsable.getYangConstructType() != YangConstructType.USES_DATA)
+                        && (parsable.getYangConstructType() != YangConstructType.GROUPING_DATA)) {
+                    ((CollisionDetector) node).detectSelfCollision(identifierName, dataType);
+                }
+                node = node.getNextSibling();
             }
         }
+    }
+
+    /**
+     * Detects colliding of uses and grouping only with uses and grouping respectively.
+     *
+     * @param identifierName name for which collision detection is to be
+     * checked
+     * @param dataType type of YANG node asking for detecting collision
+     * @param node node instance of calling node
+     * @throws DataModelException a violation of data model rules
+     */
+    public static void detectCollidingForUsesGrouping(String identifierName, YangConstructType dataType, YangNode node)
+            throws DataModelException {
+
         node = node.getChild();
         while (node != null) {
-            if (node instanceof CollisionDetector) {
+            Parsable parsable = (Parsable) node;
+            if (node instanceof CollisionDetector
+                    && (parsable.getYangConstructType() == dataType)) {
                 ((CollisionDetector) node).detectSelfCollision(identifierName, dataType);
             }
             node = node.getNextSibling();
@@ -77,15 +100,18 @@
     /**
      * Detects the colliding identifier name in a given leaf node.
      *
-     * @param leavesHolder leaves node against which collision to be checked
+     * @param listOfLeaf List of leaves to detect collision
      * @param identifierName name for which collision detection is to be
      * checked
      * @throws DataModelException a violation of data model rules
      */
-    private static void detectCollidingLeaf(YangLeavesHolder leavesHolder, String identifierName)
+    private static void detectCollidingLeaf(List<YangLeaf> listOfLeaf, String identifierName)
             throws DataModelException {
 
-        for (YangLeaf leaf : leavesHolder.getListOfLeaf()) {
+        if (listOfLeaf == null) {
+            return;
+        }
+        for (YangLeaf leaf : listOfLeaf) {
             if (leaf.getLeafName().equals(identifierName)) {
                 throw new DataModelException("YANG file error: Duplicate input identifier detected, same as leaf \""
                         + leaf.getLeafName() + "\"");
@@ -96,15 +122,18 @@
     /**
      * Detects the colliding identifier name in a given leaf-list node.
      *
-     * @param leavesHolder leaves node against which collision to be checked
+     * @param listOfLeafList list of leaf-lists to detect collision
      * @param identifierName name for which collision detection is to be
      * checked
      * @throws DataModelException a violation of data model rules
      */
-    private static void detectCollidingLeafList(YangLeavesHolder leavesHolder, String identifierName)
+    private static void detectCollidingLeafList(List<YangLeafList> listOfLeafList, String identifierName)
             throws DataModelException {
 
-        for (YangLeafList leafList : leavesHolder.getListOfLeafList()) {
+        if (listOfLeafList == null) {
+            return;
+        }
+       for (YangLeafList leafList : listOfLeafList) {
             if (leafList.getLeafName().equals(identifierName)) {
                 throw new DataModelException("YANG file error: Duplicate input identifier detected, same as leaf " +
                         "list \"" + leafList.getLeafName() + "\"");
@@ -122,8 +151,6 @@
     public static void addResolutionInfo(YangResolutionInfo resolutionInfo)
             throws DataModelException {
 
-
-
         /* get the module node to add maintain the list of nested reference */
         YangNode curNode = resolutionInfo.getEntityToResolveInfo()
                 .getHolderOfEntityToResolve();
@@ -142,6 +169,13 @@
         resolutionNode.addToResolutionList(resolutionInfo);
     }
 
+    /**
+     * Evaluates whether the prefix in uses/type is valid.
+     *
+     * @param entityPrefix prefix in the current module/sub-module
+     * @param resolutionNode uses/type node which has the prefix with it
+     * @return whether prefix is valid or not
+     */
     private static boolean isPrefixValid(String entityPrefix, HasResolutionInfo resolutionNode) {
         if (entityPrefix == null) {
             return true;