[ONOS-4842] Leafref implementation for augment and uses
Change-Id: I919553a64d683aff65a8f16e2de783702dd5a45f
diff --git a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/TreeWalkListener.java b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/TreeWalkListener.java
index 26e41c6..7b0d17f 100644
--- a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/TreeWalkListener.java
+++ b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/TreeWalkListener.java
@@ -16,8 +16,6 @@
 
 package org.onosproject.yangutils.parser.impl;
 
-import java.util.Stack;
-
 import org.antlr.v4.runtime.ParserRuleContext;
 import org.antlr.v4.runtime.tree.ErrorNode;
 import org.antlr.v4.runtime.tree.TerminalNode;
@@ -42,12 +40,14 @@
 import org.onosproject.yangutils.parser.impl.listeners.DescriptionListener;
 import org.onosproject.yangutils.parser.impl.listeners.EnumListener;
 import org.onosproject.yangutils.parser.impl.listeners.EnumerationListener;
+import org.onosproject.yangutils.parser.impl.listeners.ErrorAppTagListener;
+import org.onosproject.yangutils.parser.impl.listeners.ErrorMessageListener;
 import org.onosproject.yangutils.parser.impl.listeners.FeatureListener;
 import org.onosproject.yangutils.parser.impl.listeners.FractionDigitsListener;
 import org.onosproject.yangutils.parser.impl.listeners.GroupingListener;
+import org.onosproject.yangutils.parser.impl.listeners.IdentityListener;
 import org.onosproject.yangutils.parser.impl.listeners.IdentityrefListener;
 import org.onosproject.yangutils.parser.impl.listeners.IfFeatureListener;
-import org.onosproject.yangutils.parser.impl.listeners.IdentityListener;
 import org.onosproject.yangutils.parser.impl.listeners.ImportListener;
 import org.onosproject.yangutils.parser.impl.listeners.IncludeListener;
 import org.onosproject.yangutils.parser.impl.listeners.InputListener;
@@ -83,13 +83,15 @@
 import org.onosproject.yangutils.parser.impl.listeners.TypeDefListener;
 import org.onosproject.yangutils.parser.impl.listeners.TypeListener;
 import org.onosproject.yangutils.parser.impl.listeners.UnionListener;
+import org.onosproject.yangutils.parser.impl.listeners.UniqueListener;
 import org.onosproject.yangutils.parser.impl.listeners.UnitsListener;
 import org.onosproject.yangutils.parser.impl.listeners.UsesListener;
 import org.onosproject.yangutils.parser.impl.listeners.ValueListener;
 import org.onosproject.yangutils.parser.impl.listeners.VersionListener;
 import org.onosproject.yangutils.parser.impl.listeners.WhenListener;
-import org.onosproject.yangutils.parser.impl.listeners.ErrorMessageListener;
-import org.onosproject.yangutils.parser.impl.listeners.ErrorAppTagListener;
+
+import java.util.Stack;
+
 import static org.onosproject.yangutils.parser.impl.parserutils.ListenerUtil.handleUnsupportedYangConstruct;
 import static org.onosproject.yangutils.utils.UtilConstants.CURRENTLY_UNSUPPORTED;
 import static org.onosproject.yangutils.utils.UtilConstants.UNSUPPORTED_YANG_CONSTRUCT;
@@ -109,6 +111,34 @@
     private YangNode rootNode;
 
     /**
+     * Parent depth of grouping count for any node.
+     */
+    private int groupingDepth;
+
+    /**
+     * Returns number of grouping parents, by a node, at any level.
+     *
+     * @return depth of grouping
+     */
+    public int getGroupingDepth() {
+        return groupingDepth;
+    }
+
+    /**
+     * Sets number of grouping parents by a node at any level.
+     */
+    public void increaseGroupingDepth() {
+        groupingDepth++;
+    }
+
+    /**
+     * Sets number of grouping parents by a node at any level.
+     */
+    public void decreaseGroupingDepth() {
+        groupingDepth--;
+    }
+
+    /**
      * Returns stack of parsable data.
      *
      * @return stack of parsable data
@@ -956,7 +986,7 @@
 
     @Override
     public void enterUniqueStatement(GeneratedYangParser.UniqueStatementContext ctx) {
-        handleUnsupportedYangConstruct(YangConstructType.UNIQUE_DATA, ctx, CURRENTLY_UNSUPPORTED);
+        UniqueListener.processUniqueEntry(this, ctx);
     }
 
     @Override
diff --git a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/GroupingListener.java b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/GroupingListener.java
index 5171e2f..04d7f50 100644
--- a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/GroupingListener.java
+++ b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/GroupingListener.java
@@ -106,6 +106,8 @@
         // Validate sub statement cardinality.
         validateSubStatementsCardinality(ctx);
 
+        // Increase the grouping count by one.
+        listener.increaseGroupingDepth();
         Parsable curData = listener.getParsedDataStack().peek();
 
         // Check for identifier collision
@@ -149,6 +151,8 @@
         // Check for stack to be non empty.
         checkStackIsNotEmpty(listener, MISSING_HOLDER, GROUPING_DATA, ctx.identifier().getText(), EXIT);
 
+        // Decrease the grouping count by one.
+        listener.decreaseGroupingDepth();
         if (listener.getParsedDataStack().peek() instanceof YangGrouping) {
             listener.getParsedDataStack().pop();
         } else {
diff --git a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/LeafrefListener.java b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/LeafrefListener.java
index 6ada8c5..ef4237b 100644
--- a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/LeafrefListener.java
+++ b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/LeafrefListener.java
@@ -100,6 +100,8 @@
 
         YangLeafRef<?> leafRef = new YangLeafRef<>();
 
+        leafRef.setLineNumber(errorLine);
+        leafRef.setCharPosition(errorPosition);
         Parsable typeData = listener.getParsedDataStack().pop();
 
         if (!(typeData instanceof YangType)) {
@@ -130,11 +132,13 @@
                 }
 
                 leafRef.setResolvableStatus(UNRESOLVED);
-
-                // Add resolution information to the list.
-                YangResolutionInfoImpl resolutionInfo = new YangResolutionInfoImpl<YangLeafRef>(leafRef,
-                        (YangNode) parentNodeOfLeaf, errorLine, errorPosition);
-                addToResolutionList(resolutionInfo);
+                leafRef.setParentNodeOfLeafref((YangNode) parentNodeOfLeaf);
+                if (listener.getGroupingDepth() == 0) {
+                    // Add resolution information to the list.
+                    YangResolutionInfoImpl resolutionInfo = new YangResolutionInfoImpl<YangLeafRef>(leafRef,
+                            (YangNode) parentNodeOfLeaf, errorLine, errorPosition);
+                    addToResolutionList(resolutionInfo);
+                }
                 break;
 
             case LEAF_LIST_DATA:
@@ -151,14 +155,19 @@
                 }
 
                 leafRef.setResolvableStatus(UNRESOLVED);
+                leafRef.setParentNodeOfLeafref((YangNode) parentNodeOfLeafList);
 
-                // Add resolution information to the list.
-                YangResolutionInfoImpl resolutionInfoImpl = new YangResolutionInfoImpl<YangLeafRef>(leafRef,
-                        (YangNode) parentNodeOfLeafList, errorLine, errorPosition);
-                addToResolutionList(resolutionInfoImpl);
+                if (listener.getGroupingDepth() == 0) {
+                    // Add resolution information to the list.
+                    YangResolutionInfoImpl resolutionInfoImpl = new YangResolutionInfoImpl<YangLeafRef>(leafRef,
+                            (YangNode) parentNodeOfLeafList, errorLine, errorPosition);
+                    addToResolutionList(resolutionInfoImpl);
+                }
                 break;
 
             case TYPEDEF_DATA:
+                Parsable parentNodeOfLeafref = listener.getParsedDataStack().peek();
+                leafRef.setParentNodeOfLeafref((YangNode) parentNodeOfLeafref);
                 /*
                  * Do not add the leaf ref to resolution list. It needs to be
                  * added to resolution list, when leaf/leaf list references to
diff --git a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/ListListener.java b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/ListListener.java
index d0e7300..1891595 100644
--- a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/ListListener.java
+++ b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/ListListener.java
@@ -54,6 +54,7 @@
 import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER;
 import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.UNHANDLED_PARSED_DATA;
 import static org.onosproject.yangutils.parser.impl.parserutils.ListenerUtil.getValidIdentifier;
+import static org.onosproject.yangutils.parser.impl.parserutils.ListenerUtil.validateUniqueInList;
 import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty;
 import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.validateCardinalityMaxOne;
 import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.validateCardinalityNonZero;
@@ -174,6 +175,7 @@
             YangList yangList = (YangList) listener.getParsedDataStack().peek();
             try {
                 yangList.validateDataOnExit();
+                validateUniqueInList(yangList, ctx);
             } catch (DataModelException e) {
                 throw new ParserException(constructExtendedListenerErrorMessage(UNHANDLED_PARSED_DATA,
                         LIST_DATA, ctx.identifier().getText(), EXIT, e.getMessage()));
diff --git a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/UniqueListener.java b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/UniqueListener.java
new file mode 100644
index 0000000..59920fe
--- /dev/null
+++ b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/UniqueListener.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2016-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.yangutils.parser.impl.listeners;
+
+import org.onosproject.yangutils.datamodel.YangList;
+import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
+import org.onosproject.yangutils.datamodel.utils.Parsable;
+import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser;
+import org.onosproject.yangutils.parser.exceptions.ParserException;
+import org.onosproject.yangutils.parser.impl.TreeWalkListener;
+
+import static org.onosproject.yangutils.datamodel.utils.YangConstructType.UNIQUE_DATA;
+import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.ENTRY;
+import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction
+        .constructExtendedListenerErrorMessage;
+import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction
+        .constructListenerErrorMessage;
+import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_HOLDER;
+import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER;
+import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.UNHANDLED_PARSED_DATA;
+import static org.onosproject.yangutils.parser.impl.parserutils.ListenerUtil.removeQuotesAndHandleConcat;
+import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty;
+
+/*
+ * Reference: RFC6020 and YANG ANTLR Grammar
+ *
+ * ABNF grammar as per RFC6020
+ * unique-stmt         = unique-keyword sep unique-arg-str stmtend
+ *
+ * ANTLR grammar rule
+ * uniqueStatement: UNIQUE_KEYWORD unique STMTEND;
+ * unique : string;
+ */
+
+/**
+ * Represesnts 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.
+     */
+    private UniqueListener() {
+    }
+
+    /**
+     * It is called 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
+     */
+    public static void processUniqueEntry(TreeWalkListener listener,
+                                          GeneratedYangParser.UniqueStatementContext ctx) {
+
+        // Check for stack to be non empty.
+        checkStackIsNotEmpty(listener, MISSING_HOLDER, UNIQUE_DATA, ctx.unique().getText(), ENTRY);
+
+        Parsable tmpData = listener.getParsedDataStack().peek();
+        if (listener.getParsedDataStack().peek() instanceof YangList) {
+            YangList yangList = (YangList) tmpData;
+            String tmpUniqueValue = removeQuotesAndHandleConcat(ctx.unique().getText());
+
+            if (tmpUniqueValue.contains(" ")) {
+                String[] uniqueValues = tmpUniqueValue.split(" ");
+                for (String uniqueValue : uniqueValues) {
+                    try {
+                        yangList.addUnique(uniqueValue);
+                    } catch (DataModelException e) {
+                        throw new ParserException(constructExtendedListenerErrorMessage(UNHANDLED_PARSED_DATA,
+                                UNIQUE_DATA,
+                                ctx.unique().getText(), ENTRY, e.getMessage()));
+                    }
+                }
+            } else {
+                try {
+                    yangList.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));
+        }
+    }
+}
\ No newline at end of file
diff --git a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/UsesListener.java b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/UsesListener.java
index 2240c16..6e27a1b 100644
--- a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/UsesListener.java
+++ b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/listeners/UsesListener.java
@@ -137,6 +137,7 @@
             YangUses usesNode = getYangUsesNode(JAVA_GENERATION);
             YangNodeIdentifier nodeIdentifier = getValidNodeIdentifier(ctx.string().getText(), USES_DATA, ctx);
             usesNode.setNodeIdentifier(nodeIdentifier);
+            usesNode.setCurrentGroupingDepth(listener.getGroupingDepth());
             YangNode curNode = (YangNode) curData;
 
             try {
diff --git a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/parserutils/ListenerUtil.java b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/parserutils/ListenerUtil.java
index 5ad6133..aa38b87 100644
--- a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/parserutils/ListenerUtil.java
+++ b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/parser/impl/parserutils/ListenerUtil.java
@@ -16,25 +16,34 @@
 
 package org.onosproject.yangutils.parser.impl.parserutils;
 
+import org.antlr.v4.runtime.ParserRuleContext;
+import org.onosproject.yangutils.datamodel.YangAtomicPath;
+import org.onosproject.yangutils.datamodel.YangImport;
+import org.onosproject.yangutils.datamodel.YangLeaf;
+import org.onosproject.yangutils.datamodel.YangLeafRef;
+import org.onosproject.yangutils.datamodel.YangLeavesHolder;
+import org.onosproject.yangutils.datamodel.YangList;
+import org.onosproject.yangutils.datamodel.YangModule;
+import org.onosproject.yangutils.datamodel.YangNode;
+import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
+import org.onosproject.yangutils.datamodel.YangPathPredicate;
+import org.onosproject.yangutils.datamodel.YangReferenceResolver;
+import org.onosproject.yangutils.datamodel.YangRelativePath;
+import org.onosproject.yangutils.datamodel.YangSubModule;
+import org.onosproject.yangutils.datamodel.utils.YangConstructType;
+import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser;
+import org.onosproject.yangutils.parser.exceptions.ParserException;
+
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 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.regex.Pattern;
 
-import org.antlr.v4.runtime.ParserRuleContext;
-import org.onosproject.yangutils.datamodel.YangAtomicPath;
-import org.onosproject.yangutils.datamodel.YangLeafRef;
-import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
-import org.onosproject.yangutils.datamodel.YangPathPredicate;
-import org.onosproject.yangutils.datamodel.YangRelativePath;
-import org.onosproject.yangutils.datamodel.utils.YangConstructType;
-import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser;
-import org.onosproject.yangutils.parser.exceptions.ParserException;
-
 import static org.onosproject.yangutils.datamodel.YangPathArgType.ABSOLUTE_PATH;
 import static org.onosproject.yangutils.datamodel.YangPathArgType.RELATIVE_PATH;
 import static org.onosproject.yangutils.datamodel.YangPathOperator.EQUALTO;
@@ -98,9 +107,9 @@
     /**
      * Validates identifier and returns concatenated string if string contains plus symbol.
      *
-     * @param identifier string from yang file
+     * @param identifier    string from yang file
      * @param yangConstruct yang construct for creating error message
-     * @param ctx yang construct's context to get the line number and character position
+     * @param ctx           yang construct's context to get the line number and character position
      * @return concatenated string after removing double quotes
      */
     public static String getValidIdentifier(String identifier, YangConstructType yangConstruct, ParserRuleContext ctx) {
@@ -132,14 +141,14 @@
     /**
      * Validates identifier and returns concatenated string if string contains plus symbol.
      *
-     * @param identifier string from yang file
+     * @param identifier    string from yang file
      * @param yangConstruct yang construct for creating error message
-     * @param ctx yang construct's context to get the line number and character position
-     * @param yangLeafRef instance of leafref where the path argument has to be set
+     * @param ctx           yang construct's context to get the line number and character position
+     * @param yangLeafRef   instance of leafref where the path argument has to be set
      * @return concatenated string after removing double quotes
      */
     public static String getValidIdentifierForLeafref(String identifier, YangConstructType yangConstruct,
-            ParserRuleContext ctx, YangLeafRef yangLeafRef) {
+                                                      ParserRuleContext ctx, YangLeafRef yangLeafRef) {
 
         String identifierString = removeQuotesAndHandleConcat(identifier);
         ParserException parserException;
@@ -211,13 +220,13 @@
     /**
      * Validates non negative integer value.
      *
-     * @param integerValue integer to be validated
+     * @param integerValue  integer to be validated
      * @param yangConstruct yang construct for creating error message
-     * @param ctx context object of the grammar rule
+     * @param ctx           context object of the grammar rule
      * @return valid non negative integer value
      */
     public static int getValidNonNegativeIntegerValue(String integerValue, YangConstructType yangConstruct,
-            ParserRuleContext ctx) {
+                                                      ParserRuleContext ctx) {
 
         String value = removeQuotesAndHandleConcat(integerValue);
         if (!value.matches(NON_NEGATIVE_INTEGER_PATTERN)) {
@@ -246,13 +255,13 @@
     /**
      * Validates integer value.
      *
-     * @param integerValue integer to be validated
+     * @param integerValue  integer to be validated
      * @param yangConstruct yang construct for creating error message
-     * @param ctx context object of the grammar rule
+     * @param ctx           context object of the grammar rule
      * @return valid integer value
      */
     public static int getValidIntegerValue(String integerValue, YangConstructType yangConstruct,
-                                                      ParserRuleContext ctx) {
+                                           ParserRuleContext ctx) {
 
         String value = removeQuotesAndHandleConcat(integerValue);
         if (!INTEGER_PATTERN.matcher(value).matches()) {
@@ -281,13 +290,13 @@
     /**
      * Validates boolean value.
      *
-     * @param booleanValue value to be validated
+     * @param booleanValue  value to be validated
      * @param yangConstruct yang construct for creating error message
-     * @param ctx context object of the grammar rule
+     * @param ctx           context object of the grammar rule
      * @return boolean value either true or false
      */
     public static boolean getValidBooleanValue(String booleanValue, YangConstructType yangConstruct,
-            ParserRuleContext ctx) {
+                                               ParserRuleContext ctx) {
 
         String value = removeQuotesAndHandleConcat(booleanValue);
         if (value.equals(TRUE)) {
@@ -329,12 +338,12 @@
      * Checks and return valid node identifier.
      *
      * @param nodeIdentifierString string from yang file
-     * @param yangConstruct yang construct for creating error message
-     * @param ctx yang construct's context to get the line number and character position
+     * @param yangConstruct        yang construct for creating error message
+     * @param ctx                  yang construct's context to get the line number and character position
      * @return valid node identifier
      */
     public static YangNodeIdentifier getValidNodeIdentifier(String nodeIdentifierString,
-            YangConstructType yangConstruct, ParserRuleContext ctx) {
+                                                            YangConstructType yangConstruct, ParserRuleContext ctx) {
         String tmpIdentifierString = removeQuotesAndHandleConcat(nodeIdentifierString);
         String[] tmpData = tmpIdentifierString.split(Pattern.quote(COLON));
         if (tmpData.length == 1) {
@@ -360,13 +369,14 @@
      * Checks and return valid node identifier specific to nodes in leafref path.
      *
      * @param nodeIdentifierString string from yang file
-     * @param yangConstruct yang construct for creating error message
-     * @param ctx yang construct's context to get the line number and character position
-     * @param yangLeafRef instance of leafref where the path argument has to be set
+     * @param yangConstruct        yang construct for creating error message
+     * @param ctx                  yang construct's context to get the line number and character position
+     * @param yangLeafRef          instance of leafref where the path argument has to be set
      * @return valid node identifier
      */
     public static YangNodeIdentifier getValidNodeIdentifierForLeafref(String nodeIdentifierString,
-            YangConstructType yangConstruct, ParserRuleContext ctx, YangLeafRef yangLeafRef) {
+                                                                      YangConstructType yangConstruct,
+                                                                      ParserRuleContext ctx, YangLeafRef yangLeafRef) {
 
         String tmpIdentifierString = removeQuotesAndHandleConcat(nodeIdentifierString);
         String[] tmpData = tmpIdentifierString.split(Pattern.quote(COLON));
@@ -392,13 +402,13 @@
     /**
      * Validates the path argument. It can be either absolute or relative path.
      *
-     * @param pathString the path string from the path type
+     * @param pathString    the path string from the path type
      * @param yangConstruct yang construct for creating error message
-     * @param ctx yang construct's context to get the line number and character position
-     * @param yangLeafRef instance of leafref where the path argument has to be set
+     * @param ctx           yang construct's context to get the line number and character position
+     * @param yangLeafRef   instance of leafref where the path argument has to be set
      */
     public static void validatePathArgument(String pathString, YangConstructType yangConstruct,
-            ParserRuleContext ctx, YangLeafRef yangLeafRef) {
+                                            ParserRuleContext ctx, YangLeafRef yangLeafRef) {
 
         String completePathString = removeQuotesAndHandleConcat(pathString);
         yangLeafRef.setPath(completePathString);
@@ -406,6 +416,7 @@
             yangLeafRef.setPathType(ABSOLUTE_PATH);
             List<YangAtomicPath> yangAtomicPathListList = validateAbsolutePath(completePathString, yangConstruct, ctx,
                     yangLeafRef);
+            validatePrefixAndYangNode(yangAtomicPathListList, yangLeafRef);
             yangLeafRef.setAtomicPath(yangAtomicPathListList);
         } else if (completePathString.startsWith(ANCESTOR_ACCESSOR)) {
             yangLeafRef.setPathType(RELATIVE_PATH);
@@ -421,15 +432,239 @@
     }
 
     /**
+     * Validates the prefixes in the leafref and assigns them to the respective imported name in map.
+     *
+     * @param yangAtomicPathList list of atomic poth
+     * @param yangLeafRef      instance YANG leafref
+     */
+    private static void validatePrefixAndYangNode(List<YangAtomicPath> yangAtomicPathList, YangLeafRef yangLeafRef) {
+        Iterator<YangAtomicPath> yangAtomicPathIterator = yangAtomicPathList.listIterator();
+        while (yangAtomicPathIterator.hasNext()) {
+            YangAtomicPath atomicPath = yangAtomicPathIterator.next();
+            String prefix = atomicPath.getNodeIdentifier().getPrefix();
+            YangNode parentNodeOfLeafref = yangLeafRef.getParentNodeOfLeafref();
+            YangNode moduleOrSubModule = getModuleOrSubmoduleInFileOfTheCurrentNode(parentNodeOfLeafref);
+            YangModule moduleNode = null;
+            if (moduleOrSubModule instanceof YangModule) {
+                moduleNode = (YangModule) moduleOrSubModule;
+            }
+            if (moduleNode != null) {
+                updatePrefixWithTheImportedList(moduleNode, prefix, yangLeafRef);
+            }
+        }
+    }
+
+    /**
+     * Updates the prefix with the imported list in the module.
+     *
+     * @param moduleNode   root node of the leafref
+     * @param prefixInPath prefix in the path
+     * @param yangLeafRef  instance YANG leafref
+     */
+    private static void updatePrefixWithTheImportedList(YangModule moduleNode, String prefixInPath, YangLeafRef
+            yangLeafRef) {
+        if (prefixInPath != null && prefixInPath != EMPTY_STRING && !prefixInPath.equals(moduleNode.getPrefix())) {
+            List<YangImport> moduleImportList = moduleNode.getImportList();
+            if (moduleImportList != null && !moduleImportList.isEmpty()) {
+                Iterator<YangImport> yangImportIterator = moduleImportList.listIterator();
+                while (yangImportIterator.hasNext()) {
+                    YangImport yangImport = yangImportIterator.next();
+                    if (yangImport.getPrefixId().equals(prefixInPath)) {
+                        HashMap prefixMap = new HashMap();
+                        prefixMap.put(prefixInPath, yangImport.getModuleName());
+                        yangLeafRef.setPrefixAndItsImportedModule(prefixMap);
+                    }
+                }
+            }
+        } else {
+            HashMap prefixMap = new HashMap();
+            prefixMap.put(prefixInPath, moduleNode.getName());
+            yangLeafRef.setPrefixAndItsImportedModule(prefixMap);
+        }
+    }
+
+    /**
+     * Returns module or submodule node from the current node.
+     *
+     * @param node current node
+     * @return root node
+     */
+    private static YangNode getModuleOrSubmoduleInFileOfTheCurrentNode(YangNode node) {
+        while (!(node instanceof YangModule) && !(node instanceof YangSubModule)) {
+            if (node == null) {
+                throw new ParserException("Internal datamodel error: Datamodel tree is not correct");
+            }
+            node = node.getParent();
+        }
+        return node;
+    }
+
+    /**
+     * 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
+     * @return list of absolute path
+     */
+    private static List<YangAtomicPath> validateUniqueValues(String uniquePath, String prefixOfFile,
+                                                               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, YangConstructType.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;
+            }
+        }
+        return atomicPath;
+    }
+
+    /**
+     * 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 = getPrefixInFileOfTheCurrentNode(yangList);
+        List<String> uniques = yangList.getUniqueList();
+        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;
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns the last node under the unique path.
+     *
+     * @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
+     */
+    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;
+    }
+
+    /**
+     * Returns the prefix of the current file.
+     *
+     * @param node node where it needs to find the root node
+     * @return prefix of root node
+     */
+    public static String getPrefixInFileOfTheCurrentNode(YangNode node) {
+        String prefixInFile;
+        while (!(node instanceof YangReferenceResolver)) {
+            node = node.getParent();
+            if (node == null) {
+                throw new ParserException("Internal datamodel error: Datamodel tree is not correct");
+            }
+        }
+        if (node instanceof YangModule) {
+            YangModule yangModule = (YangModule) node;
+            prefixInFile = yangModule.getPrefix();
+        } else {
+            YangSubModule yangSubModule = (YangSubModule) node;
+            prefixInFile = yangSubModule.getPrefix();
+        }
+        return prefixInFile;
+    }
+
+    /**
      * Validates the relative path.
      *
      * @param completePathString the path string of relative path
-     * @param yangConstruct yang construct for creating error message
-     * @param ctx yang construct's context to get the line number and character position
-     * @param yangLeafRef instance of leafref where the path argument has to be set
+     * @param yangConstruct      yang construct for creating error message
+     * @param ctx                yang construct's context to get the line number and character position
+     * @param yangLeafRef        instance of leafref where the path argument has to be set
      */
     private static void validateRelativePath(String completePathString, YangConstructType yangConstruct,
-            ParserRuleContext ctx, YangLeafRef yangLeafRef) {
+                                             ParserRuleContext ctx, YangLeafRef yangLeafRef) {
 
         YangRelativePath relativePath = new YangRelativePath();
         int numberOfAncestors = 0;
@@ -449,6 +684,7 @@
         List<YangAtomicPath> atomicPath = validateAbsolutePath(SLASH_FOR_STRING + completePathString,
                 yangConstruct,
                 ctx, yangLeafRef);
+        validatePrefixAndYangNode(atomicPath, yangLeafRef);
         relativePath.setAtomicPathList(atomicPath);
         yangLeafRef.setRelativePath(relativePath);
     }
@@ -457,13 +693,14 @@
      * Validates the absolute path.
      *
      * @param completePathString the path string of absolute path
-     * @param yangConstruct yang construct for creating error message
-     * @param ctx yang construct's context to get the line number and character position
-     * @param yangLeafRef instance of leafref where the path argument has to be set
+     * @param yangConstruct      yang construct for creating error message
+     * @param ctx                yang construct's context to get the line number and character position
+     * @param yangLeafRef        instance of leafref where the path argument has to be set
      * @return list of object of node in absolute path
      */
     private static List<YangAtomicPath> validateAbsolutePath(String completePathString,
-            YangConstructType yangConstruct, ParserRuleContext ctx, YangLeafRef yangLeafRef) {
+                                                               YangConstructType yangConstruct, ParserRuleContext
+                                                                       ctx, YangLeafRef yangLeafRef) {
 
         List<YangAtomicPath> absolutePathList = new LinkedList<>();
         YangPathPredicate yangPathPredicate = new YangPathPredicate();
@@ -555,16 +792,17 @@
     /**
      * Validates path predicate in the absolute path's node.
      *
-     * @param pathPredicate list of path predicates in the node of absolute path
-     * @param yangConstruct yang construct for creating error message
-     * @param ctx yang construct's context to get the line number and character position
+     * @param pathPredicate     list of path predicates in the node of absolute path
+     * @param yangConstruct     yang construct for creating error message
+     * @param ctx               yang construct's context to get the line number and character position
      * @param yangPathPredicate instance of path predicate where it has to be set
-     * @param yangLeafRef instance of leafref where the path argument has to be set
+     * @param yangLeafRef       instance of leafref where the path argument has to be set
      * @return list of object of path predicates in absolute path's node
      */
     private static List<YangPathPredicate> validatePathPredicate(List<String> pathPredicate,
-            YangConstructType yangConstruct, ParserRuleContext ctx, YangPathPredicate yangPathPredicate,
-            YangLeafRef yangLeafRef) {
+                                                                 YangConstructType yangConstruct, ParserRuleContext
+                                                                         ctx, YangPathPredicate yangPathPredicate,
+                                                                 YangLeafRef yangLeafRef) {
 
         Iterator<String> pathPredicateString = pathPredicate.iterator();
         List<String> pathEqualityExpression = new ArrayList<>();
@@ -585,15 +823,17 @@
      * Validates the path equality expression.
      *
      * @param pathEqualityExpression list of path equality expression in the path predicates of the node
-     * @param yangConstruct yang construct for creating error message
-     * @param ctx yang construct's context to get the line number and character position
-     * @param yangPathPredicate instance of path predicate where it has to be set
-     * @param yangLeafRef instance of leafref where the path argument has to be set
+     * @param yangConstruct          yang construct for creating error message
+     * @param ctx                    yang construct's context to get the line number and character position
+     * @param yangPathPredicate      instance of path predicate where it has to be set
+     * @param yangLeafRef            instance of leafref where the path argument has to be set
      * @return list of object of path predicates in absolute path's node
      */
     private static List<YangPathPredicate> validatePathEqualityExpression(List<String> pathEqualityExpression,
-            YangConstructType yangConstruct, ParserRuleContext ctx, YangPathPredicate yangPathPredicate,
-            YangLeafRef yangLeafRef) {
+                                                                          YangConstructType yangConstruct,
+                                                                          ParserRuleContext ctx, YangPathPredicate
+                                                                                  yangPathPredicate,
+                                                                          YangLeafRef yangLeafRef) {
 
         Iterator<String> pathEqualityExpressionString = pathEqualityExpression.iterator();
         List<YangPathPredicate> yangPathPredicateList = new ArrayList<>();
@@ -620,13 +860,14 @@
      * Validate the path key expression.
      *
      * @param rightRelativePath relative path in the path predicate
-     * @param yangConstruct yang construct for creating error message
-     * @param ctx yang construct's context to get the line number and character position
-     * @param yangLeafRef instance of leafref where the path argument has to be set
+     * @param yangConstruct     yang construct for creating error message
+     * @param ctx               yang construct's context to get the line number and character position
+     * @param yangLeafRef       instance of leafref where the path argument has to be set
      * @return object of right relative path in path predicate
      */
     private static YangRelativePath validatePathKeyExpression(String rightRelativePath,
-            YangConstructType yangConstruct, ParserRuleContext ctx, YangLeafRef yangLeafRef) {
+                                                              YangConstructType yangConstruct, ParserRuleContext ctx,
+                                                              YangLeafRef yangLeafRef) {
 
         YangRelativePath yangRelativePath = new YangRelativePath();
         String[] relativePath = rightRelativePath.split(SLASH_FOR_STRING);
@@ -650,13 +891,15 @@
      * Validates the relative path key expression.
      *
      * @param rightAbsolutePath absolute path nodes present in the relative path
-     * @param yangConstruct yang construct for creating error message
-     * @param ctx yang construct's context to get the line number and character position
-     * @param yangLeafRef instance of leafref where the path argument has to be set
+     * @param yangConstruct     yang construct for creating error message
+     * @param ctx               yang construct's context to get the line number and character position
+     * @param yangLeafRef       instance of leafref where the path argument has to be set
      * @return list of object of absolute path nodes present in the relative path
      */
     private static List<YangAtomicPath> validateRelativePathKeyExpression(List<String> rightAbsolutePath,
-            YangConstructType yangConstruct, ParserRuleContext ctx, YangLeafRef yangLeafRef) {
+                                                                            YangConstructType yangConstruct,
+                                                                            ParserRuleContext ctx, YangLeafRef
+                                                                                    yangLeafRef) {
 
         List<YangAtomicPath> atomicPathList = new ArrayList<>();
         YangNodeIdentifier yangNodeIdentifier;
@@ -704,13 +947,14 @@
     /**
      * Checks and return valid absolute schema node id.
      *
-     * @param argumentString string from yang file
+     * @param argumentString    string from yang file
      * @param yangConstructType yang construct for creating error message
-     * @param ctx yang construct's context to get the line number and character position
+     * @param ctx               yang construct's context to get the line number and character position
      * @return target nodes list of absolute schema node id
      */
     public static List<YangAtomicPath> getValidAbsoluteSchemaNodeId(String argumentString,
-            YangConstructType yangConstructType, ParserRuleContext ctx) {
+                                                                      YangConstructType yangConstructType,
+                                                                      ParserRuleContext ctx) {
 
         List<YangAtomicPath> targetNodes = new ArrayList<>();
         YangNodeIdentifier yangNodeIdentifier;
@@ -739,11 +983,11 @@
      * Throws parser exception for unsupported YANG constructs.
      *
      * @param yangConstructType yang construct for creating error message
-     * @param ctx yang construct's context to get the line number and character position
-     * @param errorInfo error information
+     * @param ctx               yang construct's context to get the line number and character position
+     * @param errorInfo         error information
      */
     public static void handleUnsupportedYangConstruct(YangConstructType yangConstructType,
-        ParserRuleContext ctx, String errorInfo) {
+                                                      ParserRuleContext ctx, String errorInfo) {
         ParserException parserException = new ParserException(YANG_FILE_ERROR
                 + QUOTES + YangConstructType.getYangConstructType(yangConstructType) + QUOTES
                 + errorInfo);