handling of unique

Change-Id: Iadd216f2c8ada19a3b3c11a670497d1a493b8237
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangDeviateAdd.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangDeviateAdd.java
index 87603fd..de6f35c 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangDeviateAdd.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangDeviateAdd.java
@@ -76,9 +76,9 @@
     private List<YangMust> mustConstraintList;
 
     /**
-     * List of unique leaf names.
+     * List of unique atomic path list.
      */
-    private List<String> uniqueList;
+    private List<List<YangAtomicPath>> pathList;
 
     /**
      * Default value in string, needs to be converted to the target object,
@@ -107,11 +107,17 @@
     private YangMinElement minElements;
 
     /**
+     * List of unique leaves.
+     */
+    private List<YangLeaf> uniqueLeaves;
+
+    /**
      * Creates a YANG deviate add object.
      */
     public YangDeviateAdd() {
         mustConstraintList = new LinkedList<>();
-        uniqueList = new LinkedList<>();
+        pathList = new LinkedList<>();
+        uniqueLeaves = new LinkedList<>();
     }
 
     @Override
@@ -255,37 +261,52 @@
     }
 
     /**
-     * Returns the list of unique field names.
+     * Adds unique path in data holder.
      *
-     * @return the list of unique field names
+     * @param path unique path
      */
     @Override
-    public List<String> getUniqueList() {
-        return uniqueList;
+    public void addUnique(List<YangAtomicPath> path) {
+        pathList.add(path);
     }
 
     /**
-     * Sets the list of unique field names.
+     * Sets the list of unique path.
      *
-     * @param uniqueList the list of unique field names
+     * @param pathList unique path list
      */
     @Override
-    public void setUniqueList(List<String> uniqueList) {
-        this.uniqueList = uniqueList;
+    public void setPathList(List<List<YangAtomicPath>> pathList) {
+        this.pathList = pathList;
     }
 
     /**
-     * Adds a unique field name.
+     * Returns the list of unique path from data holder.
      *
-     * @param unique unique field name
-     * @throws DataModelException a violation of data model rules
+     * @return unique path list
      */
     @Override
-    public void addUnique(String unique) throws DataModelException {
-        if (uniqueList.contains(unique)) {
-            throw new DataModelException("A leaf identifier must not appear more than once in the\n" +
-                                                 " unique");
-        }
-        uniqueList.add(unique);
+    public List<List<YangAtomicPath>> getPathList() {
+        return pathList;
+    }
+
+    /**
+     * Returns the list of unique leaves.
+     *
+     * @return unique leaves
+     */
+    @Override
+    public List<YangLeaf> getUniqueLeaves() {
+        return uniqueLeaves;
+    }
+
+    /**
+     * Adds unique leaf to the unique leaves.
+     *
+     * @param uniqueLeaf YANG leaf
+     */
+    @Override
+    public void addUniqueLeaf(YangLeaf uniqueLeaf) {
+        uniqueLeaves.add(uniqueLeaf);
     }
 }
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangDeviateDelete.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangDeviateDelete.java
index d93cd93..47a3d8a 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangDeviateDelete.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangDeviateDelete.java
@@ -75,9 +75,9 @@
     private List<YangMust> mustConstraintList;
 
     /**
-     * List of unique leaf names.
+     * List of unique atomic path list.
      */
-    private List<String> uniqueList;
+    private List<List<YangAtomicPath>> pathList;
 
     /**
      * Default value in string, needs to be converted to the target object,
@@ -86,11 +86,17 @@
     private String defaultValueInString;
 
     /**
+     * List of unique leaves.
+     */
+    private List<YangLeaf> uniqueLeaves;
+
+    /**
      * Creates a YANG deviate delete object.
      */
     public YangDeviateDelete() {
         mustConstraintList = new LinkedList<>();
-        uniqueList = new LinkedList<>();
+        pathList = new LinkedList<>();
+        uniqueLeaves = new LinkedList<>();
     }
 
     @Override
@@ -144,39 +150,31 @@
     }
 
     /**
+     * Adds a unique path to the list.
+     *
+     * @param path unique path
+     */
+    @Override
+    public void addUnique(List<YangAtomicPath> path) {
+        pathList.add(path);
+    }
+
+    /**
+     * Sets the list of unique path list.
+     *
+     * @param pathList the list of unique path list
+     */
+    public void setPathList(List<List<YangAtomicPath>> pathList) {
+        this.pathList = pathList;
+    }
+
+    /**
      * Returns the list of unique field names.
      *
      * @return the list of unique field names
      */
-    @Override
-    public List<String> getUniqueList() {
-        return uniqueList;
-    }
-
-    /**
-     * Sets the list of unique field names.
-     *
-     * @param uniqueList the list of unique field names
-     */
-    @Override
-    public void setUniqueList(List<String> uniqueList) {
-        this.uniqueList = uniqueList;
-    }
-
-    /**
-     * Adds a unique field name.
-     *
-     * @param unique unique field name
-     * @throws DataModelException a violation of data model rules
-     */
-    @Override
-    public void addUnique(String unique)
-            throws DataModelException {
-        if (uniqueList.contains(unique)) {
-            throw new DataModelException("A leaf identifier must not appear more than once in the\n" +
-                                                 " unique");
-        }
-        uniqueList.add(unique);
+    public List<List<YangAtomicPath>> getPathList() {
+        return pathList;
     }
 
     /**
@@ -198,4 +196,24 @@
     public void setDefaultValueInString(String defaultValueInString) {
         this.defaultValueInString = defaultValueInString;
     }
+
+    /**
+     * Returns the list of unique leaves.
+     *
+     * @return the list of unique leves
+     */
+    @Override
+    public List<YangLeaf> getUniqueLeaves() {
+        return uniqueLeaves;
+    }
+
+    /**
+     * Adds a unique lead to unique leaves.
+     *
+     * @param uniqueLeaf YANG leaf
+     */
+    @Override
+    public void addUniqueLeaf(YangLeaf uniqueLeaf) {
+        uniqueLeaves.add(uniqueLeaf);
+    }
 }
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangList.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangList.java
index f7e63cb..1365b7e 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangList.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangList.java
@@ -148,9 +148,12 @@
      * default values, MUST be unique within all list entry instances in
      * which all referenced leafs exist.
      * <p>
-     * List of unique leaf/leaf-list names
      */
-    private List<String> uniqueList;
+
+    /**
+     * List of unique atomic path list.
+     */
+    private List<List<YangAtomicPath>> pathList;
 
     /**
      * List of leaves.
@@ -242,6 +245,11 @@
     private boolean defaultDenyAll;
 
     /**
+     * List of unique leaves.
+     */
+    private List<YangLeaf> uniqueLeaves;
+
+    /**
      * Creates a YANG list object.
      */
     public YangList() {
@@ -250,7 +258,8 @@
         listOfLeafList = new LinkedList<>();
         mustConstraintList = new LinkedList<>();
         ifFeatureList = new LinkedList<>();
-        uniqueList = new LinkedList<>();
+        pathList = new LinkedList<>();
+        uniqueLeaves = new LinkedList<>();
         keyList = new LinkedHashSet<>();
     }
 
@@ -354,26 +363,6 @@
     }
 
     /**
-     * Returns the list of unique field names.
-     *
-     * @return the list of unique field names
-     */
-    @Override
-    public List<String> getUniqueList() {
-        return uniqueList;
-    }
-
-    /**
-     * Sets the list of unique field names.
-     *
-     * @param uniqueList the list of unique field names
-     */
-    @Override
-    public void setUniqueList(List<String> uniqueList) {
-        this.uniqueList = uniqueList;
-    }
-
-    /**
      * Returns the set of key field names.
      *
      * @return the set of key field names
@@ -421,26 +410,31 @@
     }
 
     /**
-     * Adds a unique field name.
+     * Adds a unique path to the list.
      *
-     * @param unique unique field name.
-     * @throws DataModelException a violation of data model rules
+     * @param path unique path
      */
     @Override
-    public void addUnique(String unique)
-            throws DataModelException {
-        if (getUniqueList() == null) {
-            setUniqueList(new LinkedList<>());
-        }
-        if (getUniqueList().contains(unique)) {
-            throw new DataModelException("A leaf identifier must not appear more than once in the\n" +
-                                                 "   unique" +
-                                                 getName() + " in " +
-                                                 getLineNumber() + " at " +
-                                                 getCharPosition() +
-                                                 " in " + getFileName() + "\"");
-        }
-        getUniqueList().add(unique);
+    public void addUnique(List<YangAtomicPath> path) {
+        pathList.add(path);
+    }
+
+    /**
+     * Sets the list of unique path list.
+     *
+     * @param pathList the list of unique path list
+     */
+    public void setPathList(List<List<YangAtomicPath>> pathList) {
+        this.pathList = pathList;
+    }
+
+    /**
+     * Returns the list of unique field names.
+     *
+     * @return the list of unique field names
+     */
+    public List<List<YangAtomicPath>> getPathList() {
+        return pathList;
     }
 
     /**
@@ -464,6 +458,26 @@
     }
 
     /**
+     * Returns a list of unique leaves.
+     *
+     * @return the list of unique leaves
+     */
+    @Override
+    public List<YangLeaf> getUniqueLeaves() {
+        return uniqueLeaves;
+    }
+
+    /**
+     * Adds a unique leaf to unique leaves.
+     *
+     * @param uniqueLeaf YANG leaf
+     */
+    @Override
+    public void addUniqueLeaf(YangLeaf uniqueLeaf) {
+        uniqueLeaves.add(uniqueLeaf);
+    }
+
+    /**
      * Adds a leaf.
      *
      * @param leaf the leaf to be added
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangModule.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangModule.java
index 4509e59..9bf8b2d 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangModule.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangModule.java
@@ -39,6 +39,7 @@
 import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.detectCollidingChildUtil;
 import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.linkInterFileReferences;
 import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.resolveLinkingForResolutionList;
+import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.validateUniqueInList;
 import static org.onosproject.yang.compiler.datamodel.utils.YangConstructType.MODULE_DATA;
 
 /*-
@@ -271,6 +272,11 @@
     private final List<YangAugment> augments;
 
     /**
+     * List of unique identifiers List.
+     */
+    private List<YangUniqueHolder> uniqueHolderList;
+
+    /**
      * YANG defined namespace.
      */
     private String namespace;
@@ -310,6 +316,7 @@
         listOfFeature = new LinkedList<>();
         notificationEnumMap = new HashMap<>();
         augments = new LinkedList<>();
+        uniqueHolderList = new LinkedList<>();
     }
 
     @Override
@@ -423,6 +430,16 @@
     }
 
     /**
+     * Adds a unique holder to a unique holder list.
+     *
+     * @param uniqueHolder
+     */
+    @Override
+    public void addToUniqueHolderList(YangUniqueHolder uniqueHolder) {
+        uniqueHolderList.add(uniqueHolder);
+    }
+
+    /**
      * Returns the list of leaves in module.
      *
      * @return the list of leaves
@@ -657,6 +674,17 @@
     }
 
     /**
+     * Validates each yang unique holder in the unique holder list.
+     *
+     * @throws DataModelException a violation of data model rules
+     */
+    public void resolveUniqueLinking() throws DataModelException {
+        for (YangUniqueHolder holder : uniqueHolderList) {
+            validateUniqueInList(holder);
+        }
+    }
+
+    /**
      * Returns the type of the parsed data.
      *
      * @return returns MODULE_DATA
@@ -865,6 +893,15 @@
         return unmodifiableList(augments);
     }
 
+    /**
+     * Returns a list of uniqueholders.
+     *
+     * @return unique holder list
+     */
+    public List<YangUniqueHolder> getUniqueHolderList() {
+        return uniqueHolderList;
+    }
+
     @Override
     public String getModuleNamespace() {
         return namespace;
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangReferenceResolver.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangReferenceResolver.java
index d47387e..0e1eee5 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangReferenceResolver.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangReferenceResolver.java
@@ -45,6 +45,13 @@
                              ResolvableType type);
 
     /**
+     * Adds a unique holder to unique holder list.
+     *
+     * @param uniqueHolder yanguniqueholder
+     */
+    void addToUniqueHolderList(YangUniqueHolder uniqueHolder);
+
+    /**
      * Creates resolution list.
      *
      * @param resolutionList resolution list
@@ -82,6 +89,13 @@
     List<YangInclude> getIncludeList();
 
     /**
+     * Returns list of unique holders.
+     *
+     * @return unique holder list
+     */
+    List<YangUniqueHolder> getUniqueHolderList();
+
+    /**
      * Adds to the include list.
      *
      * @param yangInclude include to be added
@@ -128,6 +142,13 @@
             throws DataModelException;
 
     /**
+     * Resolves unique linking.
+     *
+     * @throws DataModelException a violation in data model rule
+     */
+    void resolveUniqueLinking() throws DataModelException;
+
+    /**
      * Adds references to include.
      *
      * @param yangNodeSet YANG node info set
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangSubModule.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangSubModule.java
index e960fbd..4911ed4 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangSubModule.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangSubModule.java
@@ -40,6 +40,7 @@
 import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.detectCollidingChildUtil;
 import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.linkInterFileReferences;
 import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.resolveLinkingForResolutionList;
+import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.validateUniqueInList;
 import static org.onosproject.yang.compiler.datamodel.utils.YangConstructType.SUB_MODULE_DATA;
 
 /*
@@ -270,6 +271,11 @@
     private final List<YangAugment> augments;
 
     /**
+     * List of unique identifiers List.
+     */
+    private List<YangUniqueHolder> uniqueHolderList;
+
+    /**
      * YANG defined namespace.
      */
     private String namespace;
@@ -313,6 +319,7 @@
         listOfFeature = new LinkedList<>();
         notificationEnumMap = new HashMap<>();
         augments = new LinkedList<>();
+        uniqueHolderList = new LinkedList<>();
     }
 
     @Override
@@ -870,6 +877,25 @@
         return unmodifiableList(augments);
     }
 
+    /**
+     * Returns a list of unique holders.
+     *
+     * @return uniqueHolderList
+     */
+    public List<YangUniqueHolder> getUniqueHolderList() {
+        return uniqueHolderList;
+    }
+
+    /**
+     * Add a unique holder to unique holder list.
+     *
+     * @param uniqueHolder yanguniqueholder
+     */
+    @Override
+    public void addToUniqueHolderList(YangUniqueHolder uniqueHolder) {
+        uniqueHolderList.add(uniqueHolder);
+    }
+
     @Override
     public String getModuleNamespace() {
         return namespace;
@@ -905,6 +931,18 @@
     }
 
     /**
+     * Resolve unique linking.
+     *
+     * @throws DataModelException a violation in data model rule
+     */
+    @Override
+    public void resolveUniqueLinking() throws DataModelException {
+        for (YangUniqueHolder holder : uniqueHolderList) {
+            validateUniqueInList(holder);
+        }
+    }
+
+    /**
      * Returns true if rpc is present.
      *
      * @param rpcPresent true if rpc is present
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangUniqueHolder.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangUniqueHolder.java
index 40fc343..0907856 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangUniqueHolder.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangUniqueHolder.java
@@ -16,8 +16,6 @@
 
 package org.onosproject.yang.compiler.datamodel;
 
-import org.onosproject.yang.compiler.datamodel.exceptions.DataModelException;
-
 import java.util.List;
 
 /**
@@ -27,24 +25,37 @@
 public interface YangUniqueHolder {
 
     /**
-     * Adds unique in data holder like list.
+     * Adds unique path in data holder like list.
      *
-     * @param unique the unique to be added
-     * @throws DataModelException if any violation of data model rules
+     * @param path unique path
      */
-    void addUnique(String unique) throws DataModelException;
+    void addUnique(List<YangAtomicPath> path);
 
     /**
-     * Sets the list of unique.
+     * Sets the list of unique path.
      *
-     * @param uniqueList the list of unique to set
+     * @param pathList unique path list
      */
-    void setUniqueList(List<String> uniqueList);
+    void setPathList(List<List<YangAtomicPath>> pathList);
 
     /**
-     * Returns the list of unique from data holder like list.
+     * Returns the list of unique path from data holder like list.
      *
-     * @return the list of unique
+     * @return unique path list
      */
-    List<String> getUniqueList();
+    List<List<YangAtomicPath>> getPathList();
+
+    /**
+     * Returns the list of YANG leaves, unique was referring to.
+     *
+     * @return YANG leaves list
+     */
+    List<YangLeaf> getUniqueLeaves();
+
+    /**
+     * Adds the YANG leaf, unique is referring to.
+     *
+     * @param uniqueLeaf YANG leaf
+     */
+    void addUniqueLeaf(YangLeaf uniqueLeaf);
 }
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/utils/DataModelUtils.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/utils/DataModelUtils.java
index 929b587..6b74df1 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/utils/DataModelUtils.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/utils/DataModelUtils.java
@@ -48,6 +48,7 @@
 import org.onosproject.yang.compiler.datamodel.YangMust;
 import org.onosproject.yang.compiler.datamodel.YangMustHolder;
 import org.onosproject.yang.compiler.datamodel.YangNode;
+import org.onosproject.yang.compiler.datamodel.YangNodeIdentifier;
 import org.onosproject.yang.compiler.datamodel.YangNotification;
 import org.onosproject.yang.compiler.datamodel.YangOutput;
 import org.onosproject.yang.compiler.datamodel.YangReferenceResolver;
@@ -75,9 +76,11 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Enumeration;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.ListIterator;
 import java.util.Map;
 import java.util.Set;
 import java.util.jar.JarEntry;
@@ -119,6 +122,12 @@
     private static final String E_DATATYPE = "Data type not supported.";
     public static final String E_ID = "Schema id should not be null.";
     private static final String DATE_FORMAT = "yyyy-MM-dd";
+    private static final String E_INVALID_REF = "YANG file error: A leaf " +
+            "reference, in unique, does not refer to a leaf under the list";
+    private static final String E_UNIQUE = "YANG file error: Same leaf " +
+            "cannot be mentioned more than one time in the unique statement";
+    private static final String E_TARGET_NODE = "YANG file error: The target" +
+            " node in unique reference path is invalid";
 
     /**
      * Creates a new data model tree utility.
@@ -1088,8 +1097,8 @@
 
         // delete unique statement
         if (targetNode instanceof YangUniqueHolder
-                && !deviateDelete.getUniqueList().isEmpty()) {
-            deviateDelete.setUniqueList(new LinkedList<>());
+                && !deviateDelete.getPathList().isEmpty()) {
+            deviateDelete.setPathList(new LinkedList<>());
         }
 
         // delete units statement
@@ -1125,9 +1134,9 @@
 
         // update unique statement
         if (targetNode instanceof YangUniqueHolder
-                && !deviateAdd.getUniqueList().isEmpty()) {
-            Iterator<String> uniqueList = deviateAdd.getUniqueList()
-                    .listIterator();
+                && !deviateAdd.getPathList().isEmpty()) {
+            ListIterator<List<YangAtomicPath>> uniqueList = deviateAdd
+                    .getPathList().listIterator();
             while (uniqueList.hasNext()) {
                 ((YangUniqueHolder) targetNode).addUnique(uniqueList.next());
             }
@@ -1390,6 +1399,105 @@
     }
 
     /**
+     * Validates the path in unique and gets the referred leaf.
+     *
+     * @param holder holder of unique
+     * @throws DataModelException a violation of data model rules
+     */
+    public static void validateUniqueInList(YangUniqueHolder holder)
+            throws DataModelException {
+        YangLeaf leaf;
+        List<List<YangAtomicPath>> uniques = holder.getPathList();
+        if (uniques != null && !uniques.isEmpty()) {
+            for (List<YangAtomicPath> path : uniques) {
+                List<YangAtomicPath> newPath = new LinkedList<>(path);
+                YangAtomicPath pLeaf = newPath.get(newPath.size() - 1);
+                if (newPath.size() == 1) {
+                    leaf = getLeaf((YangNode) holder, pLeaf);
+                } else {
+                    newPath.remove(newPath.size() - 1);
+                    YangNode leafHolder = getRefNode(newPath, (YangNode) holder);
+                    leaf = getLeaf(leafHolder, pLeaf);
+                }
+                if (leaf == null) {
+                    throw new DataModelException(E_INVALID_REF);
+                }
+                holder.addUniqueLeaf(leaf);
+            }
+            List<YangLeaf> leaves = holder.getUniqueLeaves();
+            Map<YangLeaf, Integer> map = new HashMap<YangLeaf, Integer>();
+            for (YangLeaf lf : leaves) {
+                if (map.containsKey(lf)) {
+                    throw new DataModelException(E_UNIQUE);
+                }
+                map.put(lf, 0);
+            }
+        }
+    }
+
+    /**
+     * Returns the leaf from leaves holder.
+     *
+     * @param holder root node from where it starts searching
+     * @param pLeaf  yang atomic path
+     * @return yang leaf from leaves holder
+     */
+    private static YangLeaf getLeaf(YangNode holder, YangAtomicPath pLeaf) {
+        YangLeavesHolder leavesHolder = (YangLeavesHolder) holder;
+        List<YangLeaf> leaves = leavesHolder.getListOfLeaf();
+        if (leaves != null && !leaves.isEmpty()) {
+            for (YangLeaf leaf : leaves) {
+                if (pLeaf.getNodeIdentifier().getName()
+                        .equals(leaf.getName())) {
+                    return leaf;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the last node under the unique path.
+     *
+     * @param path   atomic path list
+     * @param holder root node
+     * @return last node in the list
+     * @throws DataModelException a violation of data model rules
+     */
+    private static YangNode getRefNode(List<YangAtomicPath> path, YangNode holder)
+            throws DataModelException {
+        Iterator<YangAtomicPath> nodes = path.listIterator();
+        YangNode potRefNode = null;
+        while (nodes.hasNext()) {
+            potRefNode = holder.getChild();
+            YangAtomicPath node = nodes.next();
+            potRefNode = getNode(node.getNodeIdentifier(), potRefNode);
+            if (potRefNode == null) {
+                throw new DataModelException(E_TARGET_NODE);
+            }
+        }
+        return potRefNode;
+    }
+
+    /**
+     * Returns referred node.
+     *
+     * @param nodeId     node identifier
+     * @param potRefNode potential referred node
+     * @return potential referred node
+     */
+    private static YangNode getNode(YangNodeIdentifier nodeId,
+                                    YangNode potRefNode) {
+        while (potRefNode != null) {
+            if (potRefNode.getName().equals(nodeId.getName())) {
+                return potRefNode;
+            }
+            potRefNode = potRefNode.getNextSibling();
+        }
+        return null;
+    }
+
+    /**
      * Returns date in string format.
      *
      * @param schemaNode schema node
diff --git a/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangLinkerManager.java b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangLinkerManager.java
index 2761480..32beed1 100644
--- a/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangLinkerManager.java
+++ b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangLinkerManager.java
@@ -93,6 +93,8 @@
 
         // Carry out inter-file linking.
         processInterFileLinking(yangNodeSet);
+
+        processUniqueLinking(yangNodeSet);
     }
 
     /**
@@ -208,4 +210,40 @@
             }
         }
     }
+
+    /**
+     * Processes unique linking, which takes place after all linking.
+     *
+     * @param nodeSet set of YANG files info
+     * @throws LinkerException a violation in linker execution
+     */
+    public void processUniqueLinking(Set<YangNode> nodeSet)
+            throws LinkerException {
+        List<YangNode> list = new LinkedList<>();
+        list.addAll(nodeSet);
+        sort(list);
+        for (YangNode yangNode : list) {
+            try {
+                YangReferenceResolver resolver =
+                        ((YangReferenceResolver) yangNode);
+                resolver.resolveUniqueLinking();
+            } catch (DataModelException e) {
+                String errorInfo = "Error in file: " + yangNode.getName() +
+                        " in " + yangNode.getFileName() + " at " +
+                        "line: " + e.getLineNumber() + " at position: " +
+                        e.getCharPositionInLine() + NEW_LINE +
+                        e.getLocalizedMessage();
+                throw new LinkerException(errorInfo);
+                // TODO add file path in exception message in util manager.
+            } catch (LinkerException e) {
+                String errorInfo = "Error in file: " + yangNode.getName() +
+                        " in " + yangNode.getFileName() + " at " +
+                        "line: " + e.getLineNumber() + " at position: " +
+                        e.getCharPositionInLine() + NEW_LINE +
+                        e.getLocalizedMessage();
+                throw new LinkerException(errorInfo);
+                // TODO add file path in exception message in util manager.
+            }
+        }
+    }
 }
diff --git a/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/ListListener.java b/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/ListListener.java
index b7758db..633567e 100644
--- a/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/ListListener.java
+++ b/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/ListListener.java
@@ -52,8 +52,8 @@
 import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerErrorType.MISSING_CURRENT_HOLDER;
 import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER;
 import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerErrorType.UNHANDLED_PARSED_DATA;
+import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerUtil.addUniqueHolderToRoot;
 import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerUtil.getValidIdentifier;
-import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerUtil.validateUniqueInList;
 import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty;
 import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerValidation.getParentNodeConfig;
 import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerValidation.validateCardinalityMaxOne;
@@ -163,33 +163,38 @@
     }
 
     /**
-     * It is called when parser exits from grammar rule (list), it performs
-     * validation and updates the data model tree.
+     * Processes parser exits from grammar rule (list), performing validation
+     * and update on the date model tree.
      *
      * @param listener listener's object
-     * @param ctx      context object of the grammar rule
+     * @param ctx      context object
      */
     public static void processListExit(TreeWalkListener listener,
                                        ListStatementContext ctx) {
 
-        checkStackIsNotEmpty(listener, MISSING_HOLDER, LIST_DATA, ctx.identifier().getText(), EXIT);
+        checkStackIsNotEmpty(listener, MISSING_HOLDER, LIST_DATA,
+                             ctx.identifier().getText(), EXIT);
 
         if (listener.getParsedDataStack().peek() instanceof YangList) {
             YangList yangList = (YangList) listener.getParsedDataStack().peek();
             try {
                 yangList.validateDataOnExit();
-                validateUniqueInList(yangList, ctx);
+                addUniqueHolderToRoot(yangList);
             } catch (DataModelException e) {
-                ParserException parserException = new ParserException(constructExtendedListenerErrorMessage(
-                        UNHANDLED_PARSED_DATA, LIST_DATA, ctx.identifier().getText(), EXIT, e.getMessage()));
-                parserException.setLine(ctx.getStart().getLine());
-                parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
-                throw parserException;
+                ParserException exc = new ParserException(
+                        constructExtendedListenerErrorMessage(
+                                UNHANDLED_PARSED_DATA, LIST_DATA,
+                                ctx.identifier().getText(), EXIT,
+                                e.getMessage()));
+                exc.setLine(ctx.getStart().getLine());
+                exc.setCharPosition(ctx.getStart().getCharPositionInLine());
+                throw exc;
             }
             listener.getParsedDataStack().pop();
         } else {
-            throw new ParserException(constructListenerErrorMessage(MISSING_CURRENT_HOLDER, LIST_DATA,
-                                                                    ctx.identifier().getText(), EXIT));
+            throw new ParserException(constructListenerErrorMessage(
+                    MISSING_CURRENT_HOLDER, LIST_DATA,
+                    ctx.identifier().getText(), EXIT));
         }
     }
 
diff --git a/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/UniqueListener.java b/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/UniqueListener.java
index c97d272..7a89c71 100644
--- a/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/UniqueListener.java
+++ b/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/UniqueListener.java
@@ -16,22 +16,25 @@
 
 package org.onosproject.yang.compiler.parser.impl.listeners;
 
+import org.onosproject.yang.compiler.datamodel.YangAtomicPath;
+import org.onosproject.yang.compiler.datamodel.YangDeviateAdd;
+import org.onosproject.yang.compiler.datamodel.YangDeviateDelete;
 import org.onosproject.yang.compiler.datamodel.YangUniqueHolder;
-import org.onosproject.yang.compiler.datamodel.exceptions.DataModelException;
 import org.onosproject.yang.compiler.datamodel.utils.Parsable;
-import org.onosproject.yang.compiler.parser.antlrgencode.GeneratedYangParser;
+import org.onosproject.yang.compiler.parser.antlrgencode.GeneratedYangParser.UniqueStatementContext;
 import org.onosproject.yang.compiler.parser.exceptions.ParserException;
 import org.onosproject.yang.compiler.parser.impl.TreeWalkListener;
 
+import java.util.List;
+
 import static org.onosproject.yang.compiler.datamodel.utils.YangConstructType.UNIQUE_DATA;
 import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerErrorLocation.ENTRY;
-import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerErrorMessageConstruction.constructExtendedListenerErrorMessage;
 import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerErrorMessageConstruction.constructListenerErrorMessage;
 import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerErrorType.INVALID_HOLDER;
 import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER;
-import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerErrorType.UNHANDLED_PARSED_DATA;
 import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerUtil.SPACE;
 import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerUtil.removeQuotesAndHandleConcat;
+import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerUtil.validateUniqueInList;
 import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty;
 
 /*
@@ -46,65 +49,50 @@
  */
 
 /**
- * Represesnts listener based call back function corresponding to the "unique" rule
- * defined in ANTLR grammar file for corresponding ABNF rule in RFC 6020.
+ * Represents listener based call back function corresponding to the "unique"
+ * rule defined in ANTLR grammar file for corresponding ABNF rule in RFC 6020.
  */
 public final class UniqueListener {
 
     /**
-     * Creates a new unique listener.
+     * Creates unique listener.
      */
     private UniqueListener() {
     }
 
     /**
-     * It is called when parser receives an input matching the grammar rule
+     * Processes when parser receives an input matching the grammar rule
      * (unique), perform validations and updates the data model tree.
      *
      * @param listener listener's object
-     * @param ctx      context object of the grammar rule
+     * @param ctx      context object
      */
     public static void processUniqueEntry(TreeWalkListener listener,
-                                          GeneratedYangParser.UniqueStatementContext ctx) {
+                                          UniqueStatementContext ctx) {
 
         // Check for stack to be non empty.
-        checkStackIsNotEmpty(listener, MISSING_HOLDER, UNIQUE_DATA, ctx.unique()
-                .getText(), ENTRY);
+        checkStackIsNotEmpty(listener, MISSING_HOLDER, UNIQUE_DATA,
+                             ctx.unique().getText(), ENTRY);
 
         Parsable tmpData = listener.getParsedDataStack().peek();
-        if (listener.getParsedDataStack().peek() instanceof YangUniqueHolder) {
-            YangUniqueHolder uniqueHolder = (YangUniqueHolder) tmpData;
-            String tmpUniqueValue = removeQuotesAndHandleConcat(
-                    ctx.unique().getText());
+        if (!(tmpData instanceof YangUniqueHolder)) {
+            throw new ParserException(constructListenerErrorMessage(
+                    INVALID_HOLDER, UNIQUE_DATA, ctx.unique().getText(),
+                    ENTRY));
+        }
 
-            if (tmpUniqueValue.contains(SPACE)) {
-                String[] uniqueValues = tmpUniqueValue.split(SPACE);
-                for (String uniqueValue : uniqueValues) {
-                    try {
-                        uniqueHolder.addUnique(uniqueValue);
-                    } catch (DataModelException e) {
-                        throw new ParserException(
-                                constructExtendedListenerErrorMessage(UNHANDLED_PARSED_DATA,
-                                                                      UNIQUE_DATA,
-                                                                      ctx.unique().getText(),
-                                                                      ENTRY, e.getMessage()));
-                    }
-                }
-            } else {
-                try {
-                    uniqueHolder.addUnique(tmpUniqueValue);
-                } catch (DataModelException e) {
-                    throw new ParserException(
-                            constructExtendedListenerErrorMessage(
-                                    UNHANDLED_PARSED_DATA, UNIQUE_DATA,
-                                    ctx.unique().getText(), ENTRY, e.getMessage()));
-                }
-            }
-        } else {
-            throw new ParserException(
-                    constructListenerErrorMessage(INVALID_HOLDER, UNIQUE_DATA,
-                                                  ctx.unique().getText(),
-                                                  ENTRY));
+        YangUniqueHolder holder = (YangUniqueHolder) tmpData;
+        if (holder instanceof YangDeviateAdd ||
+                holder instanceof YangDeviateDelete) {
+            return;
+        }
+        String tmpVal = removeQuotesAndHandleConcat(ctx.unique().getText());
+
+        String[] values = tmpVal.split(SPACE);
+        for (String val : values) {
+            List<YangAtomicPath> atomicPath = validateUniqueInList(
+                    holder, val, ctx);
+            holder.addUnique(atomicPath);
         }
     }
 }
\ No newline at end of file
diff --git a/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/parserutils/ListenerUtil.java b/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/parserutils/ListenerUtil.java
index 1e367a4..f566545 100644
--- a/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/parserutils/ListenerUtil.java
+++ b/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/parserutils/ListenerUtil.java
@@ -19,10 +19,7 @@
 import org.antlr.v4.runtime.ParserRuleContext;
 import org.onosproject.yang.compiler.datamodel.YangAtomicPath;
 import org.onosproject.yang.compiler.datamodel.YangImport;
-import org.onosproject.yang.compiler.datamodel.YangLeaf;
 import org.onosproject.yang.compiler.datamodel.YangLeafRef;
-import org.onosproject.yang.compiler.datamodel.YangLeavesHolder;
-import org.onosproject.yang.compiler.datamodel.YangList;
 import org.onosproject.yang.compiler.datamodel.YangModule;
 import org.onosproject.yang.compiler.datamodel.YangNode;
 import org.onosproject.yang.compiler.datamodel.YangNodeIdentifier;
@@ -31,6 +28,7 @@
 import org.onosproject.yang.compiler.datamodel.YangReferenceResolver;
 import org.onosproject.yang.compiler.datamodel.YangRelativePath;
 import org.onosproject.yang.compiler.datamodel.YangSubModule;
+import org.onosproject.yang.compiler.datamodel.YangUniqueHolder;
 import org.onosproject.yang.compiler.datamodel.utils.YangConstructType;
 import org.onosproject.yang.compiler.parser.exceptions.ParserException;
 import org.slf4j.Logger;
@@ -40,7 +38,6 @@
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -99,6 +96,8 @@
     public static final String LINE_NUMBER = "line number ";
     public static final String CHARACTER_POSITION = "character position ";
     public static final String FILE = "file ";
+    private static final String E_LEAF_REF = "YANG file error : A leaf " +
+            "reference, in unique, must refer to a leaf in the list";
 
     // No instantiation.
     private ListenerUtil() {
@@ -435,135 +434,56 @@
     /**
      * Validates the unique syntax from the reference path.
      *
-     * @param uniquePath   path of unique
-     * @param prefixOfFile current file's prefix
-     * @param ctx          yang construct's context to get the line number and character position
+     * @param val    path of unique
+     * @param prefix current file's prefix
+     * @param ctx    yang construct's context to get the line number and character position
      * @return list of absolute path
      */
-    private static List<YangAtomicPath> validateUniqueValues(String uniquePath, String prefixOfFile,
+    private static List<YangAtomicPath> validateUniqueValues(String val,
+                                                             String prefix,
                                                              ParserRuleContext ctx) {
-        List<YangAtomicPath> atomicPath = new LinkedList<>();
-        String[] pathInUnique = uniquePath.split(SLASH_FOR_STRING);
-        for (String uniqueValue : pathInUnique) {
-            YangAtomicPath yangAtomicPathPath = new YangAtomicPath();
-            YangNodeIdentifier nodeIdentifier = getValidNodeIdentifier(uniqueValue, UNIQUE_DATA, ctx);
-            yangAtomicPathPath.setNodeIdentifier(nodeIdentifier);
-            atomicPath.add(yangAtomicPathPath);
-            if (nodeIdentifier.getPrefix() != null && nodeIdentifier.getPrefix() != prefixOfFile) {
-                ParserException parserException =
-                        new ParserException("YANG file error : A leaf reference, in unique," +
-                                                    " must refer to a leaf in the list");
-                parserException.setLine(ctx.getStart().getLine());
-                parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
-                throw parserException;
+        List<YangAtomicPath> pathList = new LinkedList<>();
+        String[] path = val.split(SLASH_FOR_STRING);
+        for (String uniVal : path) {
+            YangAtomicPath atomicPath = new YangAtomicPath();
+            YangNodeIdentifier nodeId = getValidNodeIdentifier(
+                    uniVal, UNIQUE_DATA, ctx);
+            atomicPath.setNodeIdentifier(nodeId);
+            pathList.add(atomicPath);
+            if (nodeId.getPrefix() != null &&
+                    !nodeId.getPrefix().equals(prefix)) {
+                ParserException exc = new ParserException(E_LEAF_REF);
+                exc.setLine(ctx.getStart().getLine());
+                exc.setCharPosition(ctx.getStart().getCharPositionInLine());
+                throw exc;
             }
         }
-        return atomicPath;
+        return pathList;
     }
 
-    /**
-     * Validates unique field from the list.
-     *
-     * @param yangList instance of YANG list
-     * @param ctx      yang construct's context to get the line number and character position
-     */
-    public static void validateUniqueInList(YangList yangList, ParserRuleContext ctx) {
-        YangLeaf leaf;
-        // Returns the prefix for the file where unique is present.
-        String prefixOfTheFile = getRootPrefix(yangList);
-        List<String> uniques = yangList.getUniqueList();
+    public static void addUniqueHolderToRoot(YangUniqueHolder holder) {
+        List<List<YangAtomicPath>> uniques = holder.getPathList();
         if (uniques != null && !uniques.isEmpty()) {
-            Iterator<String> uniqueList = uniques.listIterator();
-            while (uniqueList.hasNext()) {
-                String pathInUnique = uniqueList.next();
-                List<YangAtomicPath> atomicPathInUnique = validateUniqueValues(pathInUnique, prefixOfTheFile, ctx);
-                YangAtomicPath leafInPath = atomicPathInUnique.get(atomicPathInUnique.size() - 1);
-                if (atomicPathInUnique.size() == 1) {
-                    leaf = getReferenceLeafFromUnique(yangList, leafInPath);
-                } else {
-                    atomicPathInUnique.remove(atomicPathInUnique.size() - 1);
-                    YangNode holderOfLeaf = getNodeUnderListFromPath(atomicPathInUnique, yangList, ctx);
-                    leaf = getReferenceLeafFromUnique(holderOfLeaf, leafInPath);
-                }
-                if (leaf == null) {
-                    ParserException parserException =
-                            new ParserException("YANG file error : A leaf reference, in unique," +
-                                                        " must refer to a leaf under the list");
-                    parserException.setLine(ctx.getStart().getLine());
-                    parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
-                    throw parserException;
-                }
-            }
+            YangReferenceResolver root = (YangReferenceResolver) getRootNode(
+                    (YangNode) holder);
+            root.addToUniqueHolderList(holder);
         }
     }
 
     /**
-     * Returns the last node under the unique path.
+     * Validates unique from the list.
      *
-     * @param uniquePath atomic path list
-     * @param node       root node from where it starts searching
-     * @param ctx        yang construct's context to get the line number and character position
-     * @return last node in the list
+     * @param holder unique holder
+     * @param val    path of unique
+     * @param ctx    yang construct's context
+     * @return list of yang atomic path
      */
-    private static YangNode getNodeUnderListFromPath(List<YangAtomicPath> uniquePath, YangNode node,
-                                                     ParserRuleContext ctx) {
-        Iterator<YangAtomicPath> nodesInReference = uniquePath.listIterator();
-        YangNode potentialReferredNode = node.getChild();
-        while (nodesInReference.hasNext()) {
-            YangAtomicPath nodeInUnique = nodesInReference.next();
-            YangNode referredNode = getReferredNodeFromTheUniqueNodes(nodeInUnique.getNodeIdentifier(),
-                                                                      potentialReferredNode);
-            if (referredNode == null) {
-                ParserException parserException =
-                        new ParserException("YANG file error : The target node in unique " +
-                                                    "reference path is invalid");
-                parserException.setLine(ctx.getStart().getLine());
-                parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
-                throw parserException;
-            } else {
-                potentialReferredNode = referredNode.getChild();
-            }
-        }
-        return potentialReferredNode;
-    }
-
-    /**
-     * Returns the node that matches with the name of the node in path.
-     *
-     * @param nodeInUnique          node name in path
-     * @param potentialReferredNode node under which it has to match
-     * @return referred node
-     */
-    private static YangNode getReferredNodeFromTheUniqueNodes(YangNodeIdentifier nodeInUnique, YangNode
-            potentialReferredNode) {
-        while (potentialReferredNode != null) {
-            // Check if the potential referred node is the actual referred node
-            if (potentialReferredNode.getName().equals(nodeInUnique.getName())) {
-                return potentialReferredNode;
-            }
-            potentialReferredNode = potentialReferredNode.getNextSibling();
-        }
-        return null;
-    }
-
-    /**
-     * Returns the leaf which unique refers.
-     *
-     * @param nodeForLeaf  last node where leaf is referred
-     * @param leafInUnique leaf in unique path
-     * @return YANG leaf
-     */
-    private static YangLeaf getReferenceLeafFromUnique(YangNode nodeForLeaf, YangAtomicPath leafInUnique) {
-        YangLeavesHolder leavesHolder = (YangLeavesHolder) nodeForLeaf;
-        List<YangLeaf> leaves = leavesHolder.getListOfLeaf();
-        if (leaves != null && !leaves.isEmpty()) {
-            for (YangLeaf leaf : leaves) {
-                if (leafInUnique.getNodeIdentifier().getName().equals(leaf.getName())) {
-                    return leaf;
-                }
-            }
-        }
-        return null;
+    public static List<YangAtomicPath> validateUniqueInList(YangUniqueHolder holder,
+                                                            String val,
+                                                            ParserRuleContext ctx) {
+        YangNode node = (YangNode) holder;
+        String rootPre = getRootPrefix(node);
+        return validateUniqueValues(val, rootPre, ctx);
     }
 
     /**
@@ -572,7 +492,7 @@
      * @param curNode YANG node
      * @return prefix of the root node
      */
-    public static String getRootPrefix(YangNode curNode) {
+    private static String getRootPrefix(YangNode curNode) {
 
         String prefix;
         YangNode node = getRootNode(curNode);
diff --git a/compiler/base/parser/src/test/java/org/onosproject/yang/compiler/parser/impl/listeners/DeviationListenerTest.java b/compiler/base/parser/src/test/java/org/onosproject/yang/compiler/parser/impl/listeners/DeviationListenerTest.java
index cca24d1..8b8e5ba 100644
--- a/compiler/base/parser/src/test/java/org/onosproject/yang/compiler/parser/impl/listeners/DeviationListenerTest.java
+++ b/compiler/base/parser/src/test/java/org/onosproject/yang/compiler/parser/impl/listeners/DeviationListenerTest.java
@@ -115,7 +115,6 @@
         assertThat(deviateAdd.getUnits(), is("\"units\""));
         assertThat(deviateAdd.getListOfMust().get(0).getConstraint(),
                    is("/base:system"));
-        assertThat(deviateAdd.getUniqueList().get(0), is("id"));
         assertThat(deviateAdd.getDefaultValueInString(), is("admin"));
         assertThat(deviateAdd.isConfig(), is(true));
         assertThat(deviateAdd.isMandatory(), is(true));
@@ -152,7 +151,6 @@
         assertThat(deviateDelete.getUnits(), is("\"units\""));
         assertThat(deviateDelete.getListOfMust().get(0).getConstraint(),
                    is("daytime or time"));
-        assertThat(deviateDelete.getUniqueList().get(0), is("id"));
         assertThat(deviateDelete.getDefaultValueInString(), is("defaultValue"));
         assertThat(deviation.getResolvableStatus(), is(UNRESOLVED));
     }
diff --git a/compiler/base/parser/src/test/java/org/onosproject/yang/compiler/parser/impl/listeners/UniqueListenerTest.java b/compiler/base/parser/src/test/java/org/onosproject/yang/compiler/parser/impl/listeners/UniqueListenerTest.java
index ababd08..7eeef04 100644
--- a/compiler/base/parser/src/test/java/org/onosproject/yang/compiler/parser/impl/listeners/UniqueListenerTest.java
+++ b/compiler/base/parser/src/test/java/org/onosproject/yang/compiler/parser/impl/listeners/UniqueListenerTest.java
@@ -19,6 +19,8 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.onosproject.yang.compiler.datamodel.YangAtomicPath;
+import org.onosproject.yang.compiler.datamodel.YangLeaf;
 import org.onosproject.yang.compiler.datamodel.YangList;
 import org.onosproject.yang.compiler.datamodel.YangModule;
 import org.onosproject.yang.compiler.datamodel.YangNode;
@@ -27,7 +29,8 @@
 import org.onosproject.yang.compiler.parser.impl.YangUtilsParserManager;
 
 import java.io.IOException;
-import java.util.ListIterator;
+import java.util.Iterator;
+import java.util.List;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.core.Is.is;
@@ -62,7 +65,10 @@
         // Check whether the list is child of module
         YangList yangList = (YangList) yangNode.getChild();
         assertThat(yangList.getName(), is("valid"));
-        assertThat(yangList.getUniqueList().listIterator().next(), is("invalid-interval"));
+        List<YangLeaf> leaves = yangList.getListOfLeaf();
+        YangLeaf leaf = leaves.iterator().next();
+
+        List<List<YangAtomicPath>> uniLeaves = yangList.getPathList();
     }
 
     /**
@@ -85,12 +91,85 @@
         // Check whether the list is child of module
         YangList yangList = (YangList) yangNode.getChild();
         assertThat(yangList.getName(), is("valid"));
-        ListIterator<String> listIterator;
-        String list;
-        listIterator = yangList.getUniqueList().listIterator();
-        list = listIterator.next();
-        assertThat(list, is("ospf"));
-        list = listIterator.next();
-        assertThat(list, is("isis"));
+
+        Iterator<List<YangAtomicPath>> pathListIt;
+        Iterator<YangAtomicPath> pathIt;
+        List<YangAtomicPath> path;
+        YangAtomicPath atPath;
+
+        pathListIt = yangList.getPathList().iterator();
+        path = pathListIt.next();
+        assertThat(path.size(), is(1));
+        pathIt = path.iterator();
+        atPath = pathIt.next();
+        assertThat(atPath.getNodeIdentifier().getName(), is("ospf"));
+        path = pathListIt.next();
+        assertThat(path.size(), is(1));
+        pathIt = path.iterator();
+        atPath = pathIt.next();
+        assertThat(atPath.getNodeIdentifier().getName(), is("isis"));
+    }
+
+
+    /**
+     * Check single unique along its atomic path.
+     */
+    @Test
+    public void processParsingUniqueValues() throws IOException,
+            ParserException {
+        YangNode node = manager.getDataModel(
+                "src/test/resources/UniqueError.yang");
+        assertThat((node instanceof YangModule), is(true));
+
+        //Check whether the node type is set properly to module.
+        assertThat(node.getNodeType(), is(YangNodeType.MODULE_NODE));
+
+        //Check whether the module name is set correctly.
+        YangModule yangNode = (YangModule) node;
+        assertThat(yangNode.getName(), is("TestUnique"));
+
+        //Check whether the list is child of module.
+        YangList yangList = (YangList) yangNode.getChild();
+        assertThat(yangList.getName(), is("resources"));
+
+        Iterator<List<YangAtomicPath>> pathListIt;
+        Iterator<YangAtomicPath> pathIt;
+        List<YangAtomicPath> path;
+        YangAtomicPath atPath;
+
+        pathListIt = yangList.getPathList().iterator();
+        path = pathListIt.next();
+        assertThat(path.size(), is(3));
+        pathIt = path.iterator();
+        atPath = pathIt.next();
+        assertThat(atPath.getNodeIdentifier().getName(), is("animal"));
+        atPath = pathIt.next();
+        assertThat(atPath.getNodeIdentifier().getName(), is("mammal"));
+        atPath = pathIt.next();
+        assertThat(atPath.getNodeIdentifier().getName(), is("abc"));
+    }
+
+    /**
+     * Check unique for its descendent.
+     */
+    @Test
+    public void processParsingUniqueDescendent() throws IOException,
+            ParserException {
+        thrown.expect(ParserException.class);
+        thrown.expectMessage("YANG file error : unique name  is" +
+                                     " not valid.");
+        YangNode node = manager.getDataModel(
+                "src/test/resources/UniqueDescendent.yang");
+    }
+
+    /**
+     * Check the error for wrong holder of unique.
+     */
+    @Test
+    public void processWrongHolderOfUnique() throws IOException,
+            ParserException {
+        thrown.expect(ParserException.class);
+        YangNode node = manager.getDataModel(
+                "src/test/resources/WrongHolderOfUnique.yang");
     }
 }
\ No newline at end of file
diff --git a/compiler/base/parser/src/test/resources/UniqueDescendent.yang b/compiler/base/parser/src/test/resources/UniqueDescendent.yang
new file mode 100644
index 0000000..20409cb
--- /dev/null
+++ b/compiler/base/parser/src/test/resources/UniqueDescendent.yang
@@ -0,0 +1,12 @@
+module TestDescendent {
+    yang-version 1;
+    namespace http://huawei.com;
+    prefix Ant;
+    list networks {
+        key "abc";
+        unique "/abc";
+        leaf abc {
+        type "String";
+        }
+    }
+}
\ No newline at end of file
diff --git a/compiler/base/parser/src/test/resources/UniqueError.yang b/compiler/base/parser/src/test/resources/UniqueError.yang
new file mode 100644
index 0000000..cd15de1
--- /dev/null
+++ b/compiler/base/parser/src/test/resources/UniqueError.yang
@@ -0,0 +1,20 @@
+module TestUnique {
+    yang-version 1;
+    namespace http://huawei.com;
+    prefix Anim;
+    list resources {
+        key "count";
+        leaf count {
+            type int;
+        }
+        unique "animal/mammal/abc";
+        container animal {
+            list mammal {
+                key "abc";
+                leaf abc {
+                    type "String";
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/compiler/base/parser/src/test/resources/WrongHolderOfUnique.yang b/compiler/base/parser/src/test/resources/WrongHolderOfUnique.yang
new file mode 100644
index 0000000..b259cc1
--- /dev/null
+++ b/compiler/base/parser/src/test/resources/WrongHolderOfUnique.yang
@@ -0,0 +1,11 @@
+module TestHolder {
+    yang-version 1;
+    namespace http://huawei.com;
+    prefix Hold;
+    container birds {
+            unique "abc"
+            leaf abc {
+                type "String";
+            }
+    }
+}
\ No newline at end of file
diff --git a/compiler/plugin/maven/src/test/java/org/onosproject/yang/compiler/plugin/maven/UniqueLinkingTest.java b/compiler/plugin/maven/src/test/java/org/onosproject/yang/compiler/plugin/maven/UniqueLinkingTest.java
new file mode 100644
index 0000000..0133b61
--- /dev/null
+++ b/compiler/plugin/maven/src/test/java/org/onosproject/yang/compiler/plugin/maven/UniqueLinkingTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.yang.compiler.plugin.maven;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.onosproject.yang.compiler.datamodel.YangAtomicPath;
+import org.onosproject.yang.compiler.datamodel.YangLeaf;
+import org.onosproject.yang.compiler.datamodel.YangList;
+import org.onosproject.yang.compiler.datamodel.YangNode;
+import org.onosproject.yang.compiler.linker.impl.YangLinkerManager;
+import org.onosproject.yang.compiler.parser.exceptions.ParserException;
+import org.onosproject.yang.compiler.tool.YangCompilerManager;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.onosproject.yang.compiler.linker.impl.YangLinkerUtils.updateFilePriority;
+import static org.onosproject.yang.compiler.utils.io.impl.YangFileScanner.getYangFiles;
+
+/**
+ * Test cases for testing the unique statement validation after linking.
+ */
+public class UniqueLinkingTest {
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+
+    private final YangCompilerManager utilMgr = new YangCompilerManager();
+    private final YangLinkerManager linkerMgr = new YangLinkerManager();
+
+    /**
+     * Checks grouping linking of unique.
+     */
+    @Test
+    public void processGroupingLinkingForUnique()
+            throws IOException, ParserException, MojoExecutionException {
+
+        String searchDir = "src/test/resources/groupingforunique";
+
+        Set<Path> paths = new HashSet<>();
+        for (String file : getYangFiles(searchDir)) {
+            paths.add(Paths.get(file));
+        }
+
+        utilMgr.createYangFileInfoSet(paths);
+        utilMgr.parseYangFileInfoSet();
+        utilMgr.createYangNodeSet();
+        Set<YangNode> yangSet = utilMgr.getYangNodeSet();
+
+        YangNode refNode = null;
+        YangNode selfNode = null;
+
+        linkerMgr.createYangNodeSet(yangSet);
+        linkerMgr.addRefToYangFilesImportList(yangSet);
+        updateFilePriority(yangSet);
+        linkerMgr.processInterFileLinking(yangSet);
+        linkerMgr.processUniqueLinking(yangSet);
+
+        Iterator<YangNode> yangNodeIterator = utilMgr.getYangNodeSet().iterator();
+        YangNode rootNode = yangNodeIterator.next();
+
+        List<YangLeaf> leaves;
+        Iterator<YangLeaf> it;
+        YangNode list = rootNode.getChild();
+        assertThat(list instanceof YangList, is(true));
+        leaves = ((YangList) list).getUniqueLeaves();
+        assertThat(leaves.size(), is(1));
+        it = leaves.iterator();
+        YangLeaf groupingLeaf = it.next();
+        assertThat(groupingLeaf.getName(), is("groupingleaf"));
+
+        Iterator<List<YangAtomicPath>> pathListIt;
+        Iterator<YangAtomicPath> pathIt;
+        List<YangAtomicPath> path;
+        YangAtomicPath atPath;
+
+        pathListIt = ((YangList) list).getPathList().iterator();
+        path = pathListIt.next();
+        assertThat(path.size(), is(1));
+        pathIt = path.iterator();
+        atPath = pathIt.next();
+        assertThat(atPath.getNodeIdentifier().getName(), is("groupingleaf"));
+    }
+}
diff --git a/compiler/plugin/maven/src/test/resources/groupingforunique/ietf-network.yang b/compiler/plugin/maven/src/test/resources/groupingforunique/ietf-network.yang
new file mode 100644
index 0000000..0ecdbfa
--- /dev/null
+++ b/compiler/plugin/maven/src/test/resources/groupingforunique/ietf-network.yang
@@ -0,0 +1,19 @@
+module ietf-network {
+    yang-version 1;
+    namespace http://huawei.com;
+    prefix net;
+    list networks {
+        key "val";
+        unique "groupingleaf";
+        leaf val {
+            type string;
+        }
+        uses forgrouping;
+    }
+
+    grouping forgrouping {
+        leaf groupingleaf {
+            type string;
+        }
+    }
+}