handling of unique

Change-Id: Iadd216f2c8ada19a3b3c11a670497d1a493b8237
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