[ONOS-5785] Refactor code into new folder structure

Change-Id: I115d5af1cd7bfbde71a3092973fe160ec1d9bae5
diff --git a/compiler/base/linker/pom.xml b/compiler/base/linker/pom.xml
new file mode 100644
index 0000000..7cd5222
--- /dev/null
+++ b/compiler/base/linker/pom.xml
@@ -0,0 +1,74 @@
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.onosproject</groupId>
+        <artifactId>onos-yang-compiler-base</artifactId>
+        <version>1.12-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>onos-yang-compiler-linker</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-yang-compiler-datamodel</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-yang-compiler-utils</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-yang-compiler-translator</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.8.2</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>3.0.2</version>
+                <configuration>
+                    <skipIfEmpty>true</skipIfEmpty>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>default</id>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/YangLinker.java b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/YangLinker.java
new file mode 100644
index 0000000..b82e21e
--- /dev/null
+++ b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/YangLinker.java
@@ -0,0 +1,35 @@
+/*
+ * 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.yang.compiler.linker;
+
+import org.onosproject.yang.compiler.datamodel.YangNode;
+
+import java.util.Set;
+
+/**
+ * Abstraction of entity which provides linking service of YANG files.
+ */
+public interface YangLinker {
+
+    /**
+     * Resolve the import and include dependencies for a given resolution
+     * information.
+     *
+     * @param yangNodeSet set of all dependent YANG nodes
+     */
+    void resolveDependencies(Set<YangNode> yangNodeSet);
+}
diff --git a/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/YangLinkingPhase.java b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/YangLinkingPhase.java
new file mode 100644
index 0000000..bd7ecea
--- /dev/null
+++ b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/YangLinkingPhase.java
@@ -0,0 +1,34 @@
+/*
+ * 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.yang.compiler.linker;
+
+/**
+ * Represents the phase of YANG file reference linking.
+ */
+public enum YangLinkingPhase {
+
+    /**
+     * Linking the reference within the files.
+     */
+    INTRA_FILE,
+
+    /**
+     * Linking the reference across the files.
+     */
+    INTER_FILE
+
+}
diff --git a/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/exceptions/LinkerException.java b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/exceptions/LinkerException.java
new file mode 100644
index 0000000..9bc3e5b
--- /dev/null
+++ b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/exceptions/LinkerException.java
@@ -0,0 +1,117 @@
+/*
+ * 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.yang.compiler.linker.exceptions;
+
+/**
+ * Represents base class for exceptions in linker operations.
+ */
+public class LinkerException extends RuntimeException {
+
+    private static final long serialVersionUID = 20160211L;
+    private transient int lineNumber;
+    private transient int charPositionInLine;
+    private transient String fileName;
+
+    /**
+     * Creates a new linker exception.
+     */
+    public LinkerException() {
+        super();
+    }
+
+    /**
+     * Creates a new linker exception with given message.
+     *
+     * @param message the detail of exception in string
+     */
+    public LinkerException(String message) {
+        super(message);
+    }
+
+    /**
+     * Creates a new linker exception from given message and cause.
+     *
+     * @param message the detail of exception in string
+     * @param cause   underlying cause of the error
+     */
+    public LinkerException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * Creates a new linker exception from cause.
+     *
+     * @param cause underlying cause of the error
+     */
+    public LinkerException(final Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Returns line number of the exception.
+     *
+     * @return line number of the exception
+     */
+    public int getLineNumber() {
+        return this.lineNumber;
+    }
+
+    /**
+     * Returns YANG file name of the exception.
+     *
+     * @return YANG file name of the exception
+     */
+    public String getFileName() {
+        return this.fileName;
+    }
+
+    /**
+     * Returns position of the exception.
+     *
+     * @return position of the exception
+     */
+    public int getCharPositionInLine() {
+        return this.charPositionInLine;
+    }
+
+    /**
+     * Sets line number of YANG file.
+     *
+     * @param line line number of YANG file
+     */
+    public void setLine(int line) {
+        this.lineNumber = line;
+    }
+
+    /**
+     * Sets position of exception.
+     *
+     * @param charPosition position of exception
+     */
+    public void setCharPosition(int charPosition) {
+        this.charPositionInLine = charPosition;
+    }
+
+    /**
+     * Sets file name in parser exception.
+     *
+     * @param fileName YANG file name
+     */
+    public void setFileName(String fileName) {
+        this.fileName = fileName;
+    }
+}
diff --git a/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/exceptions/package-info.java b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/exceptions/package-info.java
new file mode 100644
index 0000000..a3de887
--- /dev/null
+++ b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/exceptions/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Custom linker exceptions.
+ */
+package org.onosproject.yang.compiler.linker.exceptions;
diff --git a/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/PrefixResolverType.java b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/PrefixResolverType.java
new file mode 100644
index 0000000..a7896b7
--- /dev/null
+++ b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/PrefixResolverType.java
@@ -0,0 +1,48 @@
+/*
+ * 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.yang.compiler.linker.impl;
+
+/**
+ * Enum for prefix resolver type when augment has come in path.
+ */
+enum PrefixResolverType {
+
+    /**
+     * When prefix changes from inter file to intra file.
+     */
+    INTER_TO_INTRA,
+
+    /**
+     * When prefix changes from intra file to inter file.
+     */
+    INTRA_TO_INTER,
+
+    /**
+     * When prefix changes from one inter file to other inter file.
+     */
+    INTER_TO_INTER,
+
+    /**
+     * When no prefix change occurs.
+     */
+    NO_PREFIX_CHANGE_FOR_INTRA,
+
+    /**
+     * When no prefix change occurs.
+     */
+    NO_PREFIX_CHANGE_FOR_INTER
+}
diff --git a/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/XpathLinkingTypes.java b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/XpathLinkingTypes.java
new file mode 100644
index 0000000..a4345cf
--- /dev/null
+++ b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/XpathLinkingTypes.java
@@ -0,0 +1,31 @@
+/*
+ * 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.yang.compiler.linker.impl;
+
+/**
+ * Represents x path linking types.
+ */
+public enum XpathLinkingTypes {
+
+    // Augment path linking.
+    AUGMENT_LINKING,
+
+    // Leaf ref path linking.
+    LEAF_REF_LINKING,
+
+    // Compiler annotation linking.
+    COMPILER_ANNOTATION_LINKING
+}
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
new file mode 100644
index 0000000..61528be
--- /dev/null
+++ b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangLinkerManager.java
@@ -0,0 +1,215 @@
+/*
+ * 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.yang.compiler.linker.impl;
+
+import org.onosproject.yang.compiler.datamodel.YangNode;
+import org.onosproject.yang.compiler.datamodel.YangReferenceResolver;
+import org.onosproject.yang.compiler.datamodel.YangSubModule;
+import org.onosproject.yang.compiler.datamodel.exceptions.DataModelException;
+import org.onosproject.yang.compiler.linker.YangLinker;
+import org.onosproject.yang.compiler.linker.exceptions.LinkerException;
+
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import static java.util.Collections.sort;
+import static org.onosproject.yang.compiler.datamodel.ResolvableType.YANG_AUGMENT;
+import static org.onosproject.yang.compiler.datamodel.ResolvableType.YANG_BASE;
+import static org.onosproject.yang.compiler.datamodel.ResolvableType.YANG_COMPILER_ANNOTATION;
+import static org.onosproject.yang.compiler.datamodel.ResolvableType.YANG_DERIVED_DATA_TYPE;
+import static org.onosproject.yang.compiler.datamodel.ResolvableType.YANG_IDENTITYREF;
+import static org.onosproject.yang.compiler.datamodel.ResolvableType.YANG_IF_FEATURE;
+import static org.onosproject.yang.compiler.datamodel.ResolvableType.YANG_LEAFREF;
+import static org.onosproject.yang.compiler.datamodel.ResolvableType.YANG_USES;
+import static org.onosproject.yang.compiler.linker.impl.YangLinkerUtils.updateFilePriority;
+import static org.onosproject.yang.compiler.utils.UtilConstants.NEW_LINE;
+
+/**
+ * Representation of entity which provides linking service of YANG files.
+ */
+public class YangLinkerManager
+        implements YangLinker {
+
+    /*
+     * Set of all the YANG nodes, corresponding to the YANG files parsed by
+     * parser.
+     */
+    private Set<YangNode> yangNodeSet = new HashSet<>();
+
+    /**
+     * Returns set of YANG node.
+     *
+     * @return set of YANG node
+     */
+    public Set<YangNode> getYangNodeSet() {
+        return yangNodeSet;
+    }
+
+    /**
+     * Creates YANG nodes set.
+     *
+     * @param yangNodeSet YANG node information set
+     */
+    public void createYangNodeSet(Set<YangNode> yangNodeSet) {
+        getYangNodeSet().addAll(yangNodeSet);
+    }
+
+    @Override
+    public void resolveDependencies(Set<YangNode> yangNodeSet) {
+
+        // Create YANG node set.
+        createYangNodeSet(yangNodeSet);
+
+        // Carry out linking of sub module with module.
+        linkSubModulesToParentModule(yangNodeSet);
+
+        // Add references to import list.
+        addRefToYangFilesImportList(yangNodeSet);
+
+        // Add reference to include list.
+        addRefToYangFilesIncludeList(yangNodeSet);
+
+        // Update the priority for all the files.
+        updateFilePriority(yangNodeSet);
+
+        // TODO check for circular import/include.
+
+        // Carry out inter-file linking.
+        processInterFileLinking(yangNodeSet);
+    }
+
+    /**
+     * Resolves sub-module linking by linking sub module with parent module.
+     *
+     * @param yangNodeSet set of YANG files info
+     * @throws LinkerException fails to link sub-module to parent module
+     */
+    public void linkSubModulesToParentModule(Set<YangNode> yangNodeSet)
+            throws LinkerException {
+        for (YangNode yangNode : yangNodeSet) {
+            if (yangNode instanceof YangSubModule) {
+                try {
+                    ((YangSubModule) yangNode).linkWithModule(getYangNodeSet());
+                } 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.
+                }
+            }
+        }
+    }
+
+    /**
+     * Adds imported node information to the import list.
+     *
+     * @param yangNodeSet set of YANG files info
+     * @throws LinkerException fails to find imported module
+     */
+    public void addRefToYangFilesImportList(Set<YangNode> yangNodeSet)
+            throws LinkerException {
+        for (YangNode yangNode : yangNodeSet) {
+            if (yangNode instanceof YangReferenceResolver) {
+                try {
+                    ((YangReferenceResolver) yangNode).addReferencesToImportList(getYangNodeSet());
+                } 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.
+                }
+            }
+        }
+    }
+
+    /**
+     * Adds included node information to the include list.
+     *
+     * @param yangNodeSet set of YANG files info
+     * @throws LinkerException fails to find included sub-module
+     */
+    public void addRefToYangFilesIncludeList(Set<YangNode> yangNodeSet)
+            throws LinkerException {
+        for (YangNode yangNode : yangNodeSet) {
+            if (yangNode instanceof YangReferenceResolver) {
+                try {
+                    ((YangReferenceResolver) yangNode).addReferencesToIncludeList(getYangNodeSet());
+                } 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.
+                }
+            }
+        }
+    }
+
+    /**
+     * Processes inter file linking for type and uses.
+     *
+     * @param yangNodeSet set of YANG files info
+     * @throws LinkerException a violation in linker execution
+     */
+    public void processInterFileLinking(Set<YangNode> yangNodeSet)
+            throws LinkerException {
+        List<YangNode> yangNodeSortedList = new LinkedList<>();
+        yangNodeSortedList.addAll(yangNodeSet);
+        sort(yangNodeSortedList);
+        for (YangNode yangNode : yangNodeSortedList) {
+            try {
+                ((YangReferenceResolver) yangNode)
+                        .resolveInterFileLinking(YANG_IF_FEATURE);
+                ((YangReferenceResolver) yangNode)
+                        .resolveInterFileLinking(YANG_USES);
+                ((YangReferenceResolver) yangNode)
+                        .resolveInterFileLinking(YANG_AUGMENT);
+                ((YangReferenceResolver) yangNode)
+                        .resolveInterFileLinking(YANG_DERIVED_DATA_TYPE);
+                ((YangReferenceResolver) yangNode)
+                        .resolveInterFileLinking(YANG_BASE);
+                ((YangReferenceResolver) yangNode)
+                        .resolveInterFileLinking(YANG_IDENTITYREF);
+                ((YangReferenceResolver) yangNode)
+                        .resolveInterFileLinking(YANG_LEAFREF);
+                ((YangReferenceResolver) yangNode)
+                        .resolveInterFileLinking(YANG_COMPILER_ANNOTATION);
+            } 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/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangLinkerUtils.java b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangLinkerUtils.java
new file mode 100644
index 0000000..7783328
--- /dev/null
+++ b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangLinkerUtils.java
@@ -0,0 +1,934 @@
+/*
+ * 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.yang.compiler.linker.impl;
+
+import org.onosproject.yang.compiler.datamodel.TraversalType;
+import org.onosproject.yang.compiler.datamodel.YangAtomicPath;
+import org.onosproject.yang.compiler.datamodel.YangAugment;
+import org.onosproject.yang.compiler.datamodel.YangAugmentableNode;
+import org.onosproject.yang.compiler.datamodel.YangBase;
+import org.onosproject.yang.compiler.datamodel.YangCase;
+import org.onosproject.yang.compiler.datamodel.YangChoice;
+import org.onosproject.yang.compiler.datamodel.YangGrouping;
+import org.onosproject.yang.compiler.datamodel.YangIdentityRef;
+import org.onosproject.yang.compiler.datamodel.YangIfFeature;
+import org.onosproject.yang.compiler.datamodel.YangImport;
+import org.onosproject.yang.compiler.datamodel.YangInclude;
+import org.onosproject.yang.compiler.datamodel.YangLeaf;
+import org.onosproject.yang.compiler.datamodel.YangLeafList;
+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.YangNode;
+import org.onosproject.yang.compiler.datamodel.YangNodeIdentifier;
+import org.onosproject.yang.compiler.datamodel.YangPathPredicate;
+import org.onosproject.yang.compiler.datamodel.YangReferenceResolver;
+import org.onosproject.yang.compiler.datamodel.YangRelativePath;
+import org.onosproject.yang.compiler.datamodel.YangType;
+import org.onosproject.yang.compiler.datamodel.YangTypeDef;
+import org.onosproject.yang.compiler.datamodel.YangUses;
+import org.onosproject.yang.compiler.datamodel.exceptions.DataModelException;
+import org.onosproject.yang.compiler.datamodel.utils.YangConstructType;
+import org.onosproject.yang.compiler.linker.exceptions.LinkerException;
+import org.onosproject.yang.compiler.translator.exception.TranslatorException;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import static org.onosproject.yang.compiler.datamodel.TraversalType.CHILD;
+import static org.onosproject.yang.compiler.datamodel.TraversalType.PARENT;
+import static org.onosproject.yang.compiler.datamodel.TraversalType.ROOT;
+import static org.onosproject.yang.compiler.datamodel.TraversalType.SIBILING;
+import static org.onosproject.yang.compiler.datamodel.exceptions.ErrorMessages.COLLISION_DETECTION;
+import static org.onosproject.yang.compiler.datamodel.exceptions.ErrorMessages.FAILED_TO_ADD_CASE;
+import static org.onosproject.yang.compiler.datamodel.exceptions.ErrorMessages.TARGET_NODE;
+import static org.onosproject.yang.compiler.datamodel.exceptions.ErrorMessages.TARGET_NODE_LEAF_INFO;
+import static org.onosproject.yang.compiler.datamodel.exceptions.ErrorMessages.getErrorMsg;
+import static org.onosproject.yang.compiler.datamodel.exceptions.ErrorMessages.getErrorMsgCollision;
+import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.addResolutionInfo;
+import static org.onosproject.yang.compiler.datamodel.utils.GeneratedLanguage.JAVA_GENERATION;
+import static org.onosproject.yang.compiler.datamodel.utils.ResolvableStatus.RESOLVED;
+import static org.onosproject.yang.compiler.datamodel.utils.YangConstructType.getYangConstructType;
+import static org.onosproject.yang.compiler.datamodel.utils.builtindatatype.YangDataTypes.DERIVED;
+import static org.onosproject.yang.compiler.datamodel.utils.builtindatatype.YangDataTypes.IDENTITYREF;
+import static org.onosproject.yang.compiler.translator.tojava.YangDataModelFactory.getYangCaseNode;
+import static org.onosproject.yang.compiler.utils.UtilConstants.BASE_LINKER_ERROR;
+import static org.onosproject.yang.compiler.utils.UtilConstants.COLON;
+import static org.onosproject.yang.compiler.utils.UtilConstants.COMMA;
+import static org.onosproject.yang.compiler.utils.UtilConstants.EMPTY_STRING;
+import static org.onosproject.yang.compiler.utils.UtilConstants.FEATURE_LINKER_ERROR;
+import static org.onosproject.yang.compiler.utils.UtilConstants.GROUPING_LINKER_ERROR;
+import static org.onosproject.yang.compiler.utils.UtilConstants.IDENTITYREF_LINKER_ERROR;
+import static org.onosproject.yang.compiler.utils.UtilConstants.INVALID_TREE;
+import static org.onosproject.yang.compiler.utils.UtilConstants.IS_INVALID;
+import static org.onosproject.yang.compiler.utils.UtilConstants.LEAFREF_ERROR;
+import static org.onosproject.yang.compiler.utils.UtilConstants.LEAFREF_LINKER_ERROR;
+import static org.onosproject.yang.compiler.utils.UtilConstants.TYPEDEF_LINKER_ERROR;
+
+/**
+ * Represent utilities for YANG linker.
+ */
+public final class YangLinkerUtils {
+
+    private static final int IDENTIFIER_LENGTH = 64;
+    private static final Pattern IDENTIFIER_PATTERN =
+            Pattern.compile("[a-zA-Z_][a-zA-Z0-9_.-]*");
+    private static final String XML = "xml";
+    private static final String INVALID_PATH_PRE =
+            "YANG file error: The path predicate of the leafref has an " +
+                    "invalid path in ";
+    private static final String EMPTY_PATH_LIST_ERR =
+            "YANG file error : The atomic path list cannot be empty of the " +
+                    "leafref in the path ";
+    private static final String TGT_LEAF_ERR =
+            "YANG file error: There is no leaf/leaf-list in YANG node as " +
+                    "mentioned in the path predicate of the leafref path ";
+    private static final String LEAF_REF_LIST_ERR =
+            "YANG file error: Path predicates are only applicable for YANG " +
+                    "list. The leafref path has path predicate for non-list " +
+                    "node in the path ";
+
+    // No instantiation.
+    private YangLinkerUtils() {
+    }
+
+    /**
+     * Detects collision between target nodes leaf/leaf-list or child node with augmented leaf/leaf-list or child node.
+     *
+     * @param targetNode target node
+     * @param augment    augment node
+     */
+    private static void detectCollision(YangNode targetNode, YangAugment augment) {
+        YangNode targetNodesChild = targetNode.getChild();
+        YangNode augmentsChild = augment.getChild();
+        if (targetNode instanceof YangChoice) {
+            addCaseNodeToChoiceTarget(augment);
+        } else {
+            detectCollisionInLeaveHolders(targetNode, augment);
+            while (augmentsChild != null) {
+                detectCollisionInChildNodes(targetNodesChild, augmentsChild);
+                augmentsChild = augmentsChild.getNextSibling();
+            }
+        }
+    }
+
+    /*Detects collision between leaves/leaf-lists*/
+    private static void detectCollisionInLeaveHolders(YangNode targetNode, YangAugment augment) {
+        YangLeavesHolder targetNodesLeavesHolder = (YangLeavesHolder) targetNode;
+        if (augment.getListOfLeaf() != null && augment.getListOfLeaf().isEmpty() &&
+                targetNodesLeavesHolder.getListOfLeaf() != null) {
+            for (YangLeaf leaf : augment.getListOfLeaf()) {
+                for (YangLeaf targetLeaf : targetNodesLeavesHolder.getListOfLeaf()) {
+                    detectCollision(targetLeaf.getName(), leaf.getName(),
+                                    leaf.getLineNumber(),
+                                    leaf.getCharPosition(),
+                                    leaf.getFileName(), TARGET_NODE_LEAF_INFO);
+                }
+            }
+        }
+        if (augment.getListOfLeafList() != null &&
+                augment.getListOfLeafList().isEmpty() &&
+                targetNodesLeavesHolder.getListOfLeafList() != null) {
+            for (YangLeafList leafList : augment.getListOfLeafList()) {
+                for (YangLeafList targetLeafList : targetNodesLeavesHolder.getListOfLeafList()) {
+                    detectCollision(targetLeafList.getName(), leafList.getName(),
+                                    leafList.getLineNumber(),
+                                    leafList.getCharPosition(),
+                                    leafList.getFileName(), TARGET_NODE_LEAF_INFO);
+                }
+            }
+        }
+    }
+
+
+    private static void detectCollision(String first, String second,
+                                        int line, int position, String
+                                                fileName, String type) {
+        if (first.equals(second)) {
+            throw new LinkerException(getErrorMsgCollision(
+                    COLLISION_DETECTION, second, line, position, type,
+                    fileName));
+        }
+    }
+
+    /*Detects collision for child nodes.*/
+    private static void detectCollisionInChildNodes(YangNode targetNodesChild,
+                                                    YangNode augmentsChild) {
+        while (augmentsChild != null) {
+            while (targetNodesChild != null) {
+                if (targetNodesChild.getName().equals(augmentsChild.getName())) {
+                    detectCollision(targetNodesChild.getName(), augmentsChild.getName(),
+                                    augmentsChild.getLineNumber(),
+                                    augmentsChild.getCharPosition(),
+                                    augmentsChild.getFileName(), TARGET_NODE);
+                }
+                targetNodesChild = targetNodesChild.getNextSibling();
+            }
+            augmentsChild = augmentsChild.getNextSibling();
+        }
+    }
+
+    /**
+     * Adds a case node in augment when augmenting a choice node.
+     *
+     * @param augment augment node
+     */
+    private static void addCaseNodeToChoiceTarget(YangAugment augment) {
+        try {
+            YangNode child = augment.getChild();
+            List<YangNode> childNodes = new ArrayList<>();
+            List<YangNode> caseNodes = new ArrayList<>();
+            while (child != null) {
+                if (!(child instanceof YangCase)) {
+                    childNodes.add(child);
+                } else {
+                    caseNodes.add(child);
+                }
+                child = child.getNextSibling();
+            }
+            augment.setChild(null);
+
+            for (YangNode node : childNodes) {
+                Map<YangNode, List<YangNode>> map = new LinkedHashMap<>();
+                node.setNextSibling(null);
+                node.setPreviousSibling(null);
+                node.setParent(null);
+                YangCase javaCase = getYangCaseNode(JAVA_GENERATION);
+                javaCase.setName(node.getName());
+                //Break the tree to from a new tree.
+                traverseAndBreak(node, map);
+                augment.addChild(javaCase);
+                node.setParent(javaCase);
+                javaCase.addChild(node);
+                //Connect each node to its correct parent again.
+                connectTree(map);
+            }
+
+            for (YangNode node : caseNodes) {
+                Map<YangNode, List<YangNode>> map = new LinkedHashMap<>();
+                node.setNextSibling(null);
+                node.setPreviousSibling(null);
+                node.setParent(null);
+                //Break the tree to from a new tree.
+                traverseAndBreak(node, map);
+                augment.addChild(node);
+                node.setParent(augment);
+                //Connect each node to its correct parent again.
+                connectTree(map);
+            }
+            if (augment.getListOfLeaf() != null) {
+                for (YangLeaf leaf : augment.getListOfLeaf()) {
+                    YangCase javaCase = getYangCaseNode(JAVA_GENERATION);
+                    javaCase.setName(leaf.getName());
+                    javaCase.addLeaf(leaf);
+                    augment.addChild(javaCase);
+                }
+                augment.getListOfLeaf().clear();
+            }
+            if (augment.getListOfLeafList() != null) {
+                for (YangLeafList leafList : augment.getListOfLeafList()) {
+                    YangCase javaCase = getYangCaseNode(JAVA_GENERATION);
+                    javaCase.setName(leafList.getName());
+                    javaCase.addLeafList(leafList);
+                    augment.addChild(javaCase);
+                }
+                augment.getListOfLeafList().clear();
+            }
+        } catch (DataModelException e) {
+            throw new TranslatorException(
+                    getErrorMsg(FAILED_TO_ADD_CASE, augment.getName(),
+                                augment.getLineNumber(), augment.getCharPosition(),
+                                augment.getFileName()));
+        }
+    }
+
+    private static void connectTree(Map<YangNode, List<YangNode>> map)
+            throws DataModelException {
+        ArrayList<YangNode> keys = new ArrayList<>(map.keySet());
+        int size = keys.size();
+        for (int i = size - 1; i >= 0; i--) {
+            YangNode curNode = keys.get(i);
+            List<YangNode> nodes = map.get(curNode);
+            if (nodes != null) {
+                for (YangNode node : nodes) {
+                    curNode.addChild(node);
+                }
+            }
+        }
+        map.clear();
+    }
+
+    private static void processHierarchyChild(YangNode node,
+                                              Map<YangNode, List<YangNode>> map) {
+        YangNode child = node.getChild();
+        if (child != null) {
+            List<YangNode> nodes = new ArrayList<>();
+            while (child != null) {
+                nodes.add(child);
+                child.setParent(null);
+                child = child.getNextSibling();
+                if (child != null) {
+                    child.getPreviousSibling().setNextSibling(null);
+                    child.setPreviousSibling(null);
+                }
+            }
+            map.put(node, nodes);
+        }
+        node.setChild(null);
+    }
+
+    private static void traverseAndBreak(YangNode rootNode,
+                                         Map<YangNode, List<YangNode>> map) {
+
+        YangNode curNode = rootNode;
+        TraversalType curTraversal = ROOT;
+        while (curNode != null) {
+            if (curTraversal != PARENT && curNode.getChild() != null) {
+                curTraversal = CHILD;
+                curNode = curNode.getChild();
+            } else if (curNode.getNextSibling() != null) {
+                curTraversal = SIBILING;
+                curNode = curNode.getNextSibling();
+            } else {
+                curTraversal = PARENT;
+                curNode = curNode.getParent();
+                if (curNode != null) {
+                    processHierarchyChild(curNode, map);
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns error messages.
+     *
+     * @param resolvable resolvable entity
+     * @return error message
+     */
+    static String getErrorInfoForLinker(Object resolvable) {
+        if (resolvable instanceof YangType) {
+            return TYPEDEF_LINKER_ERROR;
+        }
+        if (resolvable instanceof YangUses) {
+            return GROUPING_LINKER_ERROR;
+        }
+        if (resolvable instanceof YangIfFeature) {
+            return FEATURE_LINKER_ERROR;
+        }
+        if (resolvable instanceof YangBase) {
+            return BASE_LINKER_ERROR;
+        }
+        if (resolvable instanceof YangIdentityRef) {
+            return IDENTITYREF_LINKER_ERROR;
+        }
+        return LEAFREF_LINKER_ERROR;
+    }
+
+    /**
+     * Returns leafref's error message.
+     *
+     * @param leafref leaf ref
+     * @return error message
+     */
+    static String getLeafRefErrorInfo(YangLeafRef leafref) {
+        return getErrorMsg(
+                LEAFREF_ERROR + leafref.getPath() + COMMA + IS_INVALID, EMPTY_STRING,
+                leafref.getLineNumber(), leafref.getCharPosition(), leafref
+                        .getFileName());
+    }
+
+    /**
+     * Detects collision between target nodes and its all leaf/leaf-list or child node with augmented leaf/leaf-list or
+     * child node.
+     *
+     * @param targetNode target node
+     * @param augment    augment node
+     */
+    static void detectCollisionForAugmentedNode(YangNode targetNode, YangAugment augment) {
+        // Detect collision for target node and augment node.
+        detectCollision(targetNode, augment);
+        List<YangAugment> yangAugmentedInfo = ((YangAugmentableNode) targetNode).getAugmentedInfoList();
+        // Detect collision for target augment node and current augment node.
+        for (YangAugment info : yangAugmentedInfo) {
+            detectCollision(info, augment);
+        }
+    }
+
+    /**
+     * Returns list of path names that are needed from augment.
+     *
+     * @param augment            instance of YANG augment
+     * @param remainingAncestors ancestor count to move in augment path
+     * @return list of path names needed in leafref
+     */
+    static List<String> getPathWithAugment(YangAugment augment, int remainingAncestors) {
+        List<String> listOfPathName = new ArrayList<>();
+        for (YangAtomicPath atomicPath : augment.getTargetNode()) {
+            if (atomicPath.getNodeIdentifier().getPrefix() != null &&
+                    !atomicPath.getNodeIdentifier().getPrefix().equals(EMPTY_STRING)) {
+                listOfPathName.add(atomicPath.getNodeIdentifier().getPrefix()
+                                           + COLON + atomicPath.getNodeIdentifier().getName());
+            } else {
+                listOfPathName.add(atomicPath.getNodeIdentifier().getName());
+            }
+        }
+        for (int countOfAncestor = 0; countOfAncestor < remainingAncestors; countOfAncestor++) {
+            listOfPathName.remove(listOfPathName.size() - 1);
+        }
+        return listOfPathName;
+    }
+
+    /**
+     * Skips the invalid nodes which cannot have data from YANG.
+     *
+     * @param curParent current parent
+     * @param leafRef   YANG leaf-ref
+     * @return parent node which can hold data
+     * @throws LinkerException if linker rules are violated
+     */
+    public static YangNode skipInvalidDataNodes(YangNode curParent,
+                                                YangLeafRef leafRef)
+            throws LinkerException {
+
+        YangNode node = curParent;
+        while (node instanceof YangChoice ||
+                node instanceof YangCase) {
+
+            if (node.getParent() == null) {
+                throw new LinkerException(getLeafRefErrorInfo(leafRef));
+            }
+            node = node.getParent();
+        }
+        return node;
+    }
+
+    /**
+     * Checks and return valid node identifier.
+     *
+     * @param nodeIdentifierString string from yang file
+     * @param yangConstruct        yang construct for creating error message
+     * @return valid node identifier
+     */
+    static YangNodeIdentifier getValidNodeIdentifier(String nodeIdentifierString,
+                                                     YangConstructType yangConstruct) {
+        String[] tmpData = nodeIdentifierString.split(Pattern.quote(COLON));
+        if (tmpData.length == 1) {
+            YangNodeIdentifier nodeIdentifier = new YangNodeIdentifier();
+            nodeIdentifier.setName(getValidIdentifier(tmpData[0], yangConstruct));
+            return nodeIdentifier;
+        } else if (tmpData.length == 2) {
+            YangNodeIdentifier nodeIdentifier = new YangNodeIdentifier();
+            nodeIdentifier.setPrefix(getValidIdentifier(tmpData[0], yangConstruct));
+            nodeIdentifier.setName(getValidIdentifier(tmpData[1], yangConstruct));
+            return nodeIdentifier;
+        } else {
+            throw new LinkerException("YANG file error : " +
+                                              getYangConstructType(yangConstruct) + " name " + nodeIdentifierString +
+                                              " is not valid.");
+        }
+    }
+
+    /**
+     * Validates identifier and returns concatenated string if string contains plus symbol.
+     *
+     * @param identifier    string from yang file
+     * @param yangConstruct yang construct for creating error message=
+     * @return concatenated string after removing double quotes
+     */
+    public static String getValidIdentifier(String identifier, YangConstructType yangConstruct) {
+
+        if (identifier.length() > IDENTIFIER_LENGTH) {
+            throw new LinkerException("YANG file error : " +
+                                              getYangConstructType(yangConstruct) + " name " + identifier + " is " +
+                                              "greater than 64 characters.");
+        } else if (!IDENTIFIER_PATTERN.matcher(identifier).matches()) {
+            throw new LinkerException("YANG file error : " +
+                                              getYangConstructType(yangConstruct) + " name " + identifier + " is not " +
+                                              "valid.");
+        } else if (identifier.toLowerCase().startsWith(XML)) {
+            throw new LinkerException("YANG file error : " +
+                                              getYangConstructType(yangConstruct) + " identifier " + identifier +
+                                              " must not start with (('X'|'x') ('M'|'m') ('L'|'l')).");
+        } else {
+            return identifier;
+        }
+    }
+
+    /**
+     * Updates the priority for all the input files.
+     *
+     * @param yangNodeSet set of YANG files info
+     */
+    public static void updateFilePriority(Set<YangNode> yangNodeSet) {
+        for (YangNode yangNode : yangNodeSet) {
+            updateFilePriorityOfNode(yangNode);
+        }
+    }
+
+    /**
+     * Updates priority of the node.
+     *
+     * @param yangNode YANG node information
+     */
+    private static void updateFilePriorityOfNode(YangNode yangNode) {
+        int curNodePriority = yangNode.getPriority();
+        if (yangNode instanceof YangReferenceResolver) {
+            List<YangImport> yangImportList = ((YangReferenceResolver) yangNode).getImportList();
+            Iterator<YangImport> importInfoIterator = yangImportList.iterator();
+            // Run through the imported list to update priority.
+            while (importInfoIterator.hasNext()) {
+                YangImport yangImport = importInfoIterator.next();
+                YangNode importedNode = yangImport.getImportedNode();
+                if (curNodePriority >= importedNode.getPriority()) {
+                    importedNode.setPriority(curNodePriority + 1);
+                    updateFilePriorityOfNode(importedNode);
+                }
+            }
+
+            List<YangInclude> yangIncludeList = ((YangReferenceResolver) yangNode).getIncludeList();
+            Iterator<YangInclude> includeInfoIterator = yangIncludeList.iterator();
+            // Run through the imported list to update priority.
+            while (includeInfoIterator.hasNext()) {
+                YangInclude yangInclude = includeInfoIterator.next();
+                YangNode includedNode = yangInclude.getIncludedNode();
+                if (curNodePriority >= includedNode.getPriority()) {
+                    includedNode.setPriority(curNodePriority + 1);
+                    updateFilePriorityOfNode(includedNode);
+                }
+            }
+        }
+    }
+
+    /**
+     * Add the unresolved data under the root leve grouping to be resolved, since it will be used in interfile uses.
+     *
+     * @param referenceResolver module / sub-module
+     */
+    public static void resolveGroupingInDefinationScope(YangReferenceResolver referenceResolver) {
+        YangNode potentialInterFileGrouping = ((YangNode) referenceResolver).getChild();
+
+        while (potentialInterFileGrouping != null) {
+            if (potentialInterFileGrouping instanceof YangGrouping) {
+                addGroupingResolvableEntitiesToResolutionList((YangGrouping) potentialInterFileGrouping);
+            }
+
+            potentialInterFileGrouping = potentialInterFileGrouping.getNextSibling();
+        }
+    }
+
+    /**
+     * Add the interfile grouping resolvable entities to reesolution list.
+     *
+     * @param interFileGrouping interfile grouping
+     */
+    private static void addGroupingResolvableEntitiesToResolutionList(YangGrouping interFileGrouping) {
+        YangNode curNode = interFileGrouping;
+        TraversalType curTraversal = ROOT;
+        addResolvableLeavesToResolutionList((YangLeavesHolder) curNode);
+        curTraversal = CHILD;
+        curNode = interFileGrouping.getChild();
+        if (curNode == null) {
+            return;
+        }
+        while (curNode != interFileGrouping) {
+            if (curTraversal != PARENT) {
+                if (curNode instanceof YangGrouping || curNode instanceof YangUses) {
+                    if (curNode.getNextSibling() != null) {
+                        curTraversal = SIBILING;
+                        curNode = curNode.getNextSibling();
+                    } else {
+                        curTraversal = PARENT;
+                        curNode = curNode.getParent();
+                    }
+                    continue;
+                }
+
+                if (curNode instanceof YangLeavesHolder) {
+                    addResolvableLeavesToResolutionList((YangLeavesHolder) curNode);
+                } else if (curNode instanceof YangTypeDef) {
+                    List<YangType<?>> typeList = ((YangTypeDef) curNode).getTypeList();
+                    if (!typeList.isEmpty()) {
+                        YangType<?> type = typeList.get(0);
+                        if (type.getDataType() == DERIVED) {
+                            if (type.getResolvableStatus() != RESOLVED) {
+
+                                type.setTypeForInterFileGroupingResolution(true);
+
+                                // Add resolution information to the list
+                                YangResolutionInfoImpl resolutionInfo =
+                                        new YangResolutionInfoImpl<YangType>(type, curNode, type.getLineNumber(),
+                                                                             type.getCharPosition());
+                                try {
+                                    addResolutionInfo(resolutionInfo);
+                                } catch (DataModelException e) {
+                                    String errorInfo = "Error in file: " + curNode.getName() + " in " +
+                                            curNode.getFileName() + " at " +
+                                            "line: " + e.getLineNumber() +
+                                            " at position: " + e.getCharPositionInLine()
+                                            + e.getLocalizedMessage();
+                                    throw new LinkerException("Failed to add type info in grouping to resolution "
+                                                                      + errorInfo);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            if (curTraversal != PARENT && curNode.getChild() != null) {
+                curTraversal = CHILD;
+                curNode = curNode.getChild();
+            } else if (curNode.getNextSibling() != null) {
+
+                curTraversal = SIBILING;
+                curNode = curNode.getNextSibling();
+            } else {
+                curTraversal = PARENT;
+                curNode = curNode.getParent();
+            }
+        }
+    }
+
+    /**
+     * Add resolvable leaves type info to resolution list.
+     *
+     * @param leavesHolder leaves holder node
+     */
+    private static void addResolvableLeavesToResolutionList(YangLeavesHolder leavesHolder) {
+        if (leavesHolder.getListOfLeaf() != null && !leavesHolder.getListOfLeaf().isEmpty()) {
+            for (YangLeaf leaf : leavesHolder.getListOfLeaf()) {
+                YangType type = leaf.getDataType();
+                if (type.getDataType() == DERIVED) {
+
+                    type.setTypeForInterFileGroupingResolution(true);
+
+                    // Add resolution information to the list
+                    YangResolutionInfoImpl resolutionInfo =
+                            new YangResolutionInfoImpl<>(type, (YangNode) leavesHolder,
+                                                         type.getLineNumber(), type.getCharPosition());
+                    try {
+                        addResolutionInfo(resolutionInfo);
+                    } catch (DataModelException e) {
+                        throw new LinkerException("Failed to add leaf type info in grouping, to resolution ");
+                    }
+                } else if (type.getDataType() == IDENTITYREF) {
+                    YangIdentityRef identityRef = (YangIdentityRef) type.getDataTypeExtendedInfo();
+
+                    identityRef.setIdentityForInterFileGroupingResolution(true);
+
+                    // Add resolution information to the list
+                    YangResolutionInfoImpl resolutionInfo =
+                            new YangResolutionInfoImpl<YangIdentityRef>(identityRef, (YangNode) leavesHolder,
+                                                                        identityRef.getLineNumber(), identityRef.getCharPosition());
+                    try {
+                        addResolutionInfo(resolutionInfo);
+                    } catch (DataModelException e) {
+                        throw new LinkerException("Failed to add leaf identity ref info in grouping, to resolution ");
+                    }
+                }
+            }
+        }
+
+        if (leavesHolder.getListOfLeafList() != null && !leavesHolder.getListOfLeafList().isEmpty()) {
+            for (YangLeafList leafList : leavesHolder.getListOfLeafList()) {
+                YangType type = leafList.getDataType();
+                if (type.getDataType() == DERIVED) {
+
+                    type.setTypeForInterFileGroupingResolution(true);
+
+                    // Add resolution information to the list
+                    YangResolutionInfoImpl resolutionInfo =
+                            new YangResolutionInfoImpl<YangType>(type, (YangNode) leavesHolder,
+                                                                 type.getLineNumber(), type.getCharPosition());
+                    try {
+                        addResolutionInfo(resolutionInfo);
+                    } catch (DataModelException e) {
+                        throw new LinkerException("Failed to add leaf type info in grouping, to resolution ");
+                    }
+                } else if (type.getDataType() == IDENTITYREF) {
+                    YangIdentityRef identityRef = (YangIdentityRef) type.getDataTypeExtendedInfo();
+
+                    identityRef.setIdentityForInterFileGroupingResolution(true);
+                    // Add resolution information to the list
+                    YangResolutionInfoImpl resolutionInfo =
+                            new YangResolutionInfoImpl<YangIdentityRef>(identityRef, (YangNode) leavesHolder,
+                                                                        identityRef.getLineNumber(), identityRef.getCharPosition());
+                    try {
+                        addResolutionInfo(resolutionInfo);
+                    } catch (DataModelException e) {
+                        throw new LinkerException("Failed to add leaf identity ref info in grouping, to resolution ");
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Fills the path predicates of the leaf-ref with right axis node and
+     * left axis node, after linking the nodes.
+     *
+     * @param leafRef YANG leaf-ref
+     * @throws DataModelException if there is a data model error
+     */
+    public static void fillPathPredicates(YangLeafRef<?> leafRef)
+            throws DataModelException {
+
+        List<YangAtomicPath> atomics = leafRef.getAtomicPath();
+        if (atomics != null) {
+            for (YangAtomicPath atom : atomics) {
+                List<YangPathPredicate> predicates =
+                        atom.getPathPredicatesList();
+
+                if (predicates != null) {
+                    for (YangPathPredicate predicate : predicates) {
+                        setLeftAxisNode(leafRef, atom, predicate);
+                        setRightAxisNode(leafRef, predicate);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Sets the left axis node in the YANG path predicate after finding it
+     * under the YANG list node.
+     *
+     * @param leafRef   YANG leaf-ref
+     * @param atom      atomic path content
+     * @param predicate predicate in the atomic path
+     * @throws DataModelException if there is a data model error
+     */
+    private static void setLeftAxisNode(YangLeafRef<?> leafRef,
+                                        YangAtomicPath atom,
+                                        YangPathPredicate predicate)
+            throws DataModelException {
+        YangNode resolvedNode = atom.getResolvedNode();
+        if (!(resolvedNode instanceof YangList)) {
+            throw getDataModelExc(LEAF_REF_LIST_ERR, leafRef);
+        }
+
+        YangNodeIdentifier leftAxisName = predicate.getNodeId();
+        Object target = getTarget(leftAxisName, resolvedNode, leafRef);
+        predicate.setLeftAxisNode(target);
+    }
+
+    /**
+     * Returns the target leaf/leaf-list from the provided YANG node.
+     *
+     * @param leftAxisName name of node
+     * @param node         node having target
+     * @param leafRef      YANG leaf-ref
+     * @return target leaf/leaf-list
+     * @throws DataModelException if there is a data model error
+     */
+    private static Object getTarget(YangNodeIdentifier leftAxisName,
+                                    YangNode node, YangLeafRef leafRef)
+            throws DataModelException {
+
+        YangLeaf leaf = getLeaf(leftAxisName, (YangLeavesHolder) node);
+        if (leaf != null) {
+            return leaf;
+        }
+        YangLeafList leafList = getLeafList(leftAxisName,
+                                            (YangLeavesHolder) node);
+        if (leafList == null) {
+            throw getDataModelExc(TGT_LEAF_ERR, leafRef);
+        }
+        return leafList;
+    }
+
+    /**
+     * Returns the leaf by searching it in the node by the leaf name. Returns
+     * null when the name doesn't match.
+     *
+     * @param name   leaf name
+     * @param holder holder of leaf
+     * @return YANG leaf
+     */
+    private static YangLeaf getLeaf(YangNodeIdentifier name,
+                                    YangLeavesHolder holder) {
+
+        List<YangLeaf> listOfLeaf = holder.getListOfLeaf();
+        if (listOfLeaf != null) {
+            for (YangLeaf yangLeaf : listOfLeaf) {
+                if (yangLeaf.getName().equals(name.getName())) {
+                    return yangLeaf;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the leaf-list by searching it in the node by the leaf-list name.
+     * Returns null when the name doesn't match.
+     *
+     * @param name   leaf-list name
+     * @param holder holder of leaf-list
+     * @return YANG leaf-list
+     */
+    private static YangLeafList getLeafList(YangNodeIdentifier name,
+                                            YangLeavesHolder holder) {
+
+        List<YangLeafList> listOfLeafList = holder.getListOfLeafList();
+        if (listOfLeafList != null) {
+            for (YangLeafList yangLeafList : listOfLeafList) {
+                if (yangLeafList.getName().equals(name.getName())) {
+                    return yangLeafList;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the root node from which the path with the atomic node names
+     * has to be traversed through. With the ancestor count the nodes are
+     * moved upward.
+     *
+     * @param count   ancestor count
+     * @param node    current leaf-ref parent
+     * @param leafRef YANG leaf-ref
+     * @return root node from ancestor count
+     * @throws DataModelException if there is a data model error
+     */
+    private static YangNode getRootNode(int count, YangNode node,
+                                        YangLeafRef leafRef)
+            throws DataModelException {
+
+        YangNode curParent = node;
+        int curCount = 0;
+        while (curCount < count) {
+            curCount = curCount + 1;
+            if (curCount != 1) {
+                if (curParent.getParent() == null) {
+                    throw getDataModelExc(INVALID_TREE, leafRef);
+                }
+                curParent = curParent.getParent();
+            }
+            curParent = skipInvalidDataNodes(curParent, leafRef);
+            if (curParent instanceof YangAugment) {
+                YangAugment augment = (YangAugment) curParent;
+                curParent = augment.getAugmentedNode();
+                curCount = curCount + 1;
+            }
+        }
+        return curParent;
+    }
+
+    /**
+     * Returns the last node by traversing through the atomic node id by
+     * leaving the last target leaf/leaf-list.
+     *
+     * @param curNode current node
+     * @param relPath relative path
+     * @param leafRef YANG leaf-ref
+     * @return last YANG node
+     * @throws DataModelException if there is a data model error
+     */
+    private static Object getLastNode(YangNode curNode,
+                                      YangRelativePath relPath,
+                                      YangLeafRef leafRef)
+            throws DataModelException {
+
+        YangNode node = curNode;
+        List<YangAtomicPath> atomics = new ArrayList<>();
+        atomics.addAll(relPath.getAtomicPathList());
+
+        if (atomics.isEmpty()) {
+            throw getDataModelExc(EMPTY_PATH_LIST_ERR, leafRef);
+        }
+
+        YangAtomicPath pathTgt = atomics.get(atomics.size() - 1);
+        if (atomics.size() == 1) {
+            return getTarget(pathTgt.getNodeIdentifier(), node, leafRef);
+        }
+
+        atomics.remove(atomics.size() - 1);
+        for (YangAtomicPath atomicPath : atomics) {
+            node = getNode(node.getChild(), atomicPath.getNodeIdentifier());
+            if (node == null) {
+                throw getDataModelExc(INVALID_PATH_PRE, leafRef);
+            }
+        }
+        return getTarget(pathTgt.getNodeIdentifier(), node, leafRef);
+    }
+
+    /**
+     * Returns the node from the parent node by matching it with the atomic
+     * name. If no child node matches the name then it returns null.
+     *
+     * @param curNode    current node
+     * @param identifier atomic name
+     * @return node to be traversed
+     */
+    private static YangNode getNode(YangNode curNode,
+                                    YangNodeIdentifier identifier) {
+        YangNode node = curNode;
+        while (node != null) {
+            if (node.getName().equals(identifier.getName())) {
+                return node;
+            }
+            node = node.getNextSibling();
+        }
+        return null;
+    }
+
+    /**
+     * Sets the right axis node in the YANG path predicate after finding it
+     * from the relative path.
+     *
+     * @param leafRef   YANG leaf-ref
+     * @param predicate YANG path predicate
+     * @throws DataModelException if there is a data model error
+     */
+    private static void setRightAxisNode(YangLeafRef leafRef,
+                                         YangPathPredicate predicate)
+            throws DataModelException {
+
+        YangNode parentNode = leafRef.getParentNode();
+        YangRelativePath relPath = predicate.getRelPath();
+        int ancestor = relPath.getAncestorNodeCount();
+
+        YangNode rootNode = getRootNode(ancestor, parentNode, leafRef);
+        Object target = getLastNode(rootNode, relPath, leafRef);
+        if (target == null) {
+            throw getDataModelExc(INVALID_PATH_PRE, leafRef);
+        }
+        predicate.setRightAxisNode(target);
+    }
+
+    /**
+     * Returns data model error messages for leaf-ref with the path.
+     *
+     * @param msg     error message
+     * @param leafRef YANG leaf-ref
+     * @return data model exception
+     */
+    private static DataModelException getDataModelExc(String msg,
+                                                      YangLeafRef leafRef) {
+        DataModelException exc = new DataModelException(
+                msg + leafRef.getPath());
+        exc.setCharPosition(leafRef.getCharPosition());
+        exc.setLine(leafRef.getLineNumber());
+        return exc;
+    }
+}
diff --git a/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangResolutionInfoImpl.java b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangResolutionInfoImpl.java
new file mode 100644
index 0000000..3c1542c
--- /dev/null
+++ b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangResolutionInfoImpl.java
@@ -0,0 +1,1623 @@
+/*
+ * 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.yang.compiler.linker.impl;
+
+import org.onosproject.yang.compiler.datamodel.DefaultLocationInfo;
+import org.onosproject.yang.compiler.datamodel.Resolvable;
+import org.onosproject.yang.compiler.datamodel.RpcNotificationContainer;
+import org.onosproject.yang.compiler.datamodel.TraversalType;
+import org.onosproject.yang.compiler.datamodel.YangAtomicPath;
+import org.onosproject.yang.compiler.datamodel.YangAugment;
+import org.onosproject.yang.compiler.datamodel.YangAugmentableNode;
+import org.onosproject.yang.compiler.datamodel.YangBase;
+import org.onosproject.yang.compiler.datamodel.YangCompilerAnnotation;
+import org.onosproject.yang.compiler.datamodel.YangDerivedInfo;
+import org.onosproject.yang.compiler.datamodel.YangEntityToResolveInfoImpl;
+import org.onosproject.yang.compiler.datamodel.YangFeature;
+import org.onosproject.yang.compiler.datamodel.YangFeatureHolder;
+import org.onosproject.yang.compiler.datamodel.YangGrouping;
+import org.onosproject.yang.compiler.datamodel.YangIdentity;
+import org.onosproject.yang.compiler.datamodel.YangIdentityRef;
+import org.onosproject.yang.compiler.datamodel.YangIfFeature;
+import org.onosproject.yang.compiler.datamodel.YangImport;
+import org.onosproject.yang.compiler.datamodel.YangInclude;
+import org.onosproject.yang.compiler.datamodel.YangInput;
+import org.onosproject.yang.compiler.datamodel.YangLeaf;
+import org.onosproject.yang.compiler.datamodel.YangLeafList;
+import org.onosproject.yang.compiler.datamodel.YangLeafRef;
+import org.onosproject.yang.compiler.datamodel.YangList;
+import org.onosproject.yang.compiler.datamodel.YangNode;
+import org.onosproject.yang.compiler.datamodel.YangNodeIdentifier;
+import org.onosproject.yang.compiler.datamodel.YangReferenceResolver;
+import org.onosproject.yang.compiler.datamodel.YangRelativePath;
+import org.onosproject.yang.compiler.datamodel.YangResolutionInfo;
+import org.onosproject.yang.compiler.datamodel.YangType;
+import org.onosproject.yang.compiler.datamodel.YangTypeDef;
+import org.onosproject.yang.compiler.datamodel.YangUses;
+import org.onosproject.yang.compiler.datamodel.YangXPathResolver;
+import org.onosproject.yang.compiler.datamodel.exceptions.DataModelException;
+import org.onosproject.yang.compiler.datamodel.utils.ResolvableStatus;
+import org.onosproject.yang.compiler.datamodel.utils.builtindatatype.YangDataTypes;
+import org.onosproject.yang.compiler.linker.exceptions.LinkerException;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Stack;
+
+import static org.onosproject.yang.compiler.datamodel.ResolvableType.YANG_LEAFREF;
+import static org.onosproject.yang.compiler.datamodel.TraversalType.CHILD;
+import static org.onosproject.yang.compiler.datamodel.TraversalType.PARENT;
+import static org.onosproject.yang.compiler.datamodel.TraversalType.ROOT;
+import static org.onosproject.yang.compiler.datamodel.TraversalType.SIBILING;
+import static org.onosproject.yang.compiler.datamodel.YangPathArgType.ABSOLUTE_PATH;
+import static org.onosproject.yang.compiler.datamodel.YangPathArgType.RELATIVE_PATH;
+import static org.onosproject.yang.compiler.datamodel.exceptions.ErrorMessages.getErrorMsg;
+import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.addResolutionInfo;
+import static org.onosproject.yang.compiler.datamodel.utils.ResolvableStatus.INTER_FILE_LINKED;
+import static org.onosproject.yang.compiler.datamodel.utils.ResolvableStatus.INTRA_FILE_RESOLVED;
+import static org.onosproject.yang.compiler.datamodel.utils.ResolvableStatus.LINKED;
+import static org.onosproject.yang.compiler.datamodel.utils.ResolvableStatus.RESOLVED;
+import static org.onosproject.yang.compiler.datamodel.utils.ResolvableStatus.UNDEFINED;
+import static org.onosproject.yang.compiler.datamodel.utils.ResolvableStatus.UNRESOLVED;
+import static org.onosproject.yang.compiler.datamodel.utils.YangConstructType.PATH_DATA;
+import static org.onosproject.yang.compiler.linker.impl.XpathLinkingTypes.AUGMENT_LINKING;
+import static org.onosproject.yang.compiler.linker.impl.XpathLinkingTypes.LEAF_REF_LINKING;
+import static org.onosproject.yang.compiler.linker.impl.YangLinkerUtils.detectCollisionForAugmentedNode;
+import static org.onosproject.yang.compiler.linker.impl.YangLinkerUtils.fillPathPredicates;
+import static org.onosproject.yang.compiler.linker.impl.YangLinkerUtils.getErrorInfoForLinker;
+import static org.onosproject.yang.compiler.linker.impl.YangLinkerUtils.getLeafRefErrorInfo;
+import static org.onosproject.yang.compiler.linker.impl.YangLinkerUtils.getPathWithAugment;
+import static org.onosproject.yang.compiler.linker.impl.YangLinkerUtils.getValidNodeIdentifier;
+import static org.onosproject.yang.compiler.linker.impl.YangLinkerUtils.skipInvalidDataNodes;
+import static org.onosproject.yang.compiler.utils.UtilConstants.EMPTY_STRING;
+import static org.onosproject.yang.compiler.utils.UtilConstants.FAILED_TO_FIND_ANNOTATION;
+import static org.onosproject.yang.compiler.utils.UtilConstants.FAILED_TO_FIND_LEAD_INFO_HOLDER;
+import static org.onosproject.yang.compiler.utils.UtilConstants.FAILED_TO_LINK;
+import static org.onosproject.yang.compiler.utils.UtilConstants.INVALID_ENTITY;
+import static org.onosproject.yang.compiler.utils.UtilConstants.INVALID_LINKER_STATE;
+import static org.onosproject.yang.compiler.utils.UtilConstants.INVALID_RESOLVED_ENTITY;
+import static org.onosproject.yang.compiler.utils.UtilConstants.INVALID_TARGET;
+import static org.onosproject.yang.compiler.utils.UtilConstants.INVALID_TREE;
+import static org.onosproject.yang.compiler.utils.UtilConstants.LEAFREF;
+import static org.onosproject.yang.compiler.utils.UtilConstants.LINKER_ERROR;
+import static org.onosproject.yang.compiler.utils.UtilConstants.SLASH_FOR_STRING;
+import static org.onosproject.yang.compiler.utils.UtilConstants.UNRESOLVABLE;
+
+/**
+ * Represents implementation of resolution object which will be resolved by
+ * linker.
+ *
+ * @param <T> type of resolution entity uses / type
+ */
+public class YangResolutionInfoImpl<T> extends DefaultLocationInfo
+        implements YangResolutionInfo<T>, Serializable {
+
+    private static final long serialVersionUID = 806201658L;
+
+    /**
+     * Information about the entity that needs to be resolved.
+     */
+    private YangEntityToResolveInfoImpl<T> entityToResolveInfo;
+
+    /**
+     * Current module/sub-module reference, will be used in inter-file/
+     * inter-jar scenario to get the import/include list.
+     */
+    private YangReferenceResolver curRefResolver;
+
+    /**
+     * Stack for type/uses is maintained for hierarchical references, this is
+     * used during resolution.
+     */
+    private Stack<YangEntityToResolveInfoImpl<T>> partialResolvedStack;
+
+    /**
+     * It is private to ensure the overloaded method be invoked to create an
+     * object.
+     */
+    @SuppressWarnings("unused")
+    private YangResolutionInfoImpl() {
+    }
+
+    /**
+     * Creates a resolution information object with all the inputs.
+     *
+     * @param dataNode           current parsable data node
+     * @param holderNode         parent YANG node
+     * @param lineNumber         error line number
+     * @param charPositionInLine error character position in line
+     */
+    public YangResolutionInfoImpl(T dataNode, YangNode holderNode, int lineNumber,
+                                  int charPositionInLine) {
+        entityToResolveInfo = new YangEntityToResolveInfoImpl<>();
+        entityToResolveInfo.setEntityToResolve(dataNode);
+        entityToResolveInfo.setHolderOfEntityToResolve(holderNode);
+        setLineNumber(lineNumber);
+        setCharPosition(charPositionInLine);
+        partialResolvedStack = new Stack<>();
+    }
+
+    @Override
+    public void resolveLinkingForResolutionInfo(YangReferenceResolver dataModelRootNode)
+            throws DataModelException {
+
+        curRefResolver = dataModelRootNode;
+    /*
+         * Current node to resolve, it can be a YANG type, YANG uses or YANG if-feature or
+         * YANG leafref or YANG base or YANG identityref.
+         */
+        T entityToResolve = entityToResolveInfo.getEntityToResolve();
+
+        // Check if linking is already done
+        if (entityToResolve instanceof Resolvable) {
+            Resolvable resolvable = (Resolvable) entityToResolve;
+            if (resolvable.getResolvableStatus() == RESOLVED) {
+                /*
+                 * entity is already resolved, so nothing to do
+                 */
+                return;
+            }
+        } else {
+            throw new DataModelException(LINKER_ERROR);
+        }
+        // Push the initial entity to resolve in stack.
+        addInPartialResolvedStack(entityToResolveInfo);
+        linkAndResolvePartialResolvedStack();
+        addDerivedRefTypeToRefTypeResolutionList();
+    }
+
+    /**
+     * Resolves linking with ancestors.
+     *
+     * @throws DataModelException a violation of data model rules
+     */
+    private void linkAndResolvePartialResolvedStack()
+            throws DataModelException {
+
+        while (!partialResolvedStack.isEmpty()) {
+            /*
+             * Current node to resolve, it can be a YANG type or YANG uses or
+             * YANG if-feature or YANG leafref or YANG base or YANG identityref.
+             */
+            T entityToResolve = getCurEntityToResolveFromStack();
+            if (!(entityToResolve instanceof Resolvable)) {
+                throw new DataModelException(LINKER_ERROR);
+            }
+            // Check if linking is already done
+            Resolvable resolvable = (Resolvable) entityToResolve;
+            switch (resolvable.getResolvableStatus()) {
+                case RESOLVED:
+                        /*
+                         * If the entity is already resolved in the stack, then pop
+                         * it and continue with the remaining stack elements to
+                         * resolve
+                         */
+                    partialResolvedStack.pop();
+                    break;
+
+                case LINKED:
+                        /*
+                         * If the top of the stack is already linked then resolve
+                         * the references and pop the entity and continue with
+                         * remaining stack elements to resolve.
+                         */
+                    resolveTopOfStack();
+                    partialResolvedStack.pop();
+                    break;
+
+                case INTRA_FILE_RESOLVED:
+                        /*
+                         * Pop the top of the stack.
+                         */
+                    partialResolvedStack.pop();
+                    break;
+
+                case UNRESOLVED:
+                    linkTopOfStackReferenceUpdateStack();
+
+                    if (resolvable.getResolvableStatus() == UNRESOLVED) {
+                        // If current entity is still not resolved, then
+                        // linking/resolution has failed.
+                        DataModelException ex =
+                                new DataModelException
+                                        (getErrorInfoForLinker(resolvable));
+                        ex.setLine(getLineNumber());
+                        ex.setCharPosition(getCharPosition());
+                        throw ex;
+                    }
+                    break;
+
+                default:
+                    throw new DataModelException(INVALID_LINKER_STATE);
+            }
+        }
+    }
+
+    /**
+     * Adds leaf-ref to the resolution list, with different context if
+     * leaf-ref is defined under derived type. Leaf-ref must be resolved from
+     * where the typedef is referenced.
+     */
+    private void addDerivedRefTypeToRefTypeResolutionList()
+            throws DataModelException {
+
+        YangNode refNode = entityToResolveInfo.getHolderOfEntityToResolve();
+        YangDerivedInfo info = getValidResolvableType();
+
+        if (info == null) {
+            return;
+        }
+
+        YangType<T> type =
+                (YangType<T>) entityToResolveInfo.getEntityToResolve();
+
+        T extType = (T) info.getReferredTypeDef().getTypeDefBaseType()
+                .getDataTypeExtendedInfo();
+
+        while (extType instanceof YangDerivedInfo) {
+            info = (YangDerivedInfo) extType;
+            extType = (T) info.getReferredTypeDef().getTypeDefBaseType()
+                    .getDataTypeExtendedInfo();
+        }
+        /*
+         * Backup the leaf-ref info from derived type and deletes the derived
+         * type info. Copies the backed up leaf-ref data to the actual type in
+         * replacement of derived type. Adds to the resolution list in this
+         * context.
+         */
+        addRefTypeInfo(extType, type, refNode);
+    }
+
+    /**
+     * Returns the derived info if the holder is typedef, the entity is type
+     * and the effective type is leaf-ref; null otherwise.
+     *
+     * @return derived info
+     */
+    private YangDerivedInfo<?> getValidResolvableType() {
+
+        YangNode refNode = entityToResolveInfo.getHolderOfEntityToResolve();
+        T entity = entityToResolveInfo.getEntityToResolve();
+
+        if (!(refNode instanceof YangTypeDef) && entity instanceof YangType) {
+            YangType<?> type = (YangType) entity;
+            YangDerivedInfo<?> info =
+                    (YangDerivedInfo) type.getDataTypeExtendedInfo();
+            YangDataTypes dataType = info.getEffectiveBuiltInType();
+            if ((type.getResolvableStatus() == RESOLVED) &&
+                    (dataType == YangDataTypes.LEAFREF)) {
+                return info;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Adds resolvable type (leaf-ref) info to resolution list.
+     *
+     * @param extType resolvable type
+     * @param type    YANG type
+     * @param holder  holder node
+     * @throws DataModelException if there is a data model error
+     */
+    private void addRefTypeInfo(T extType, YangType<T> type, YangNode holder)
+            throws DataModelException {
+
+        type.resetYangType();
+        type.setResolvableStatus(RESOLVED);
+        type.setDataType(YangDataTypes.LEAFREF);
+        type.setDataTypeName(LEAFREF);
+        type.setDataTypeExtendedInfo(extType);
+
+        YangLeafRef leafRef = (YangLeafRef) extType;
+        (leafRef).setResolvableStatus(UNRESOLVED);
+        leafRef.setParentNode(holder);
+
+        YangResolutionInfoImpl info = new YangResolutionInfoImpl<>(
+                leafRef, holder, getLineNumber(), getCharPosition());
+        curRefResolver.addToResolutionList(info, YANG_LEAFREF);
+        curRefResolver.resolveSelfFileLinking(YANG_LEAFREF);
+    }
+
+    /**
+     * Resolves the current entity in the stack.
+     */
+    private void resolveTopOfStack()
+            throws DataModelException {
+        T entity = getCurEntityToResolveFromStack();
+        List<T> entityToResolve = (List<T>) ((Resolvable) entity).resolve();
+        if (entityToResolve != null && !entityToResolve.isEmpty()) {
+            for (T anEntityToResolve : entityToResolve) {
+                addUnresolvedEntitiesToResolutionList(anEntityToResolve);
+            }
+        }
+        if (((Resolvable) entity).getResolvableStatus() != INTRA_FILE_RESOLVED &&
+                ((Resolvable) entity).getResolvableStatus() != UNDEFINED) {
+            // Sets the resolution status in inside the type/uses/if-feature/leafref.
+            ((Resolvable) entity).setResolvableStatus(RESOLVED);
+        }
+    }
+
+    /**
+     * Adds the unresolved entities to the resolution list.
+     *
+     * @param entityToResolve entity to resolve
+     * @throws DataModelException a violation of data model rules
+     */
+    private void addUnresolvedEntitiesToResolutionList(T entityToResolve)
+            throws DataModelException {
+        if (entityToResolve instanceof YangEntityToResolveInfoImpl) {
+            YangEntityToResolveInfoImpl entityToResolveInfo
+                    = (YangEntityToResolveInfoImpl) entityToResolve;
+            if (entityToResolveInfo.getEntityToResolve() instanceof YangLeafRef) {
+                YangLeafRef leafref = (YangLeafRef) entityToResolveInfo
+                        .getEntityToResolve();
+                YangNode parentNodeOfLeafref = entityToResolveInfo
+                        .getHolderOfEntityToResolve();
+                leafref.setParentNode(parentNodeOfLeafref);
+                if (leafref.getResolvableStatus() == UNRESOLVED) {
+                    leafref.setResolvableStatus(INTRA_FILE_RESOLVED);
+                }
+            }
+
+            // Add resolution information to the list.
+            YangResolutionInfoImpl resolutionInfoImpl = new YangResolutionInfoImpl<>(
+                    entityToResolveInfo.getEntityToResolve(),
+                    entityToResolveInfo.getHolderOfEntityToResolve(),
+                    entityToResolveInfo.getLineNumber(),
+                    entityToResolveInfo.getCharPosition());
+            addResolutionInfo(resolutionInfoImpl);
+        }
+    }
+
+    /**
+     * Resolves linking for a node child and siblings.
+     *
+     * @throws DataModelException data model error
+     */
+    private void linkTopOfStackReferenceUpdateStack()
+            throws DataModelException {
+        T entity = getCurEntityToResolveFromStack();
+        if (entity instanceof YangLeafRef) {
+            ((Resolvable) entity).setResolvableStatus(INTRA_FILE_RESOLVED);
+            return;
+        }
+        /*
+         * Check if self file reference is there, this will not check for the
+         * scenario when prefix is not present and type/uses is present in
+         * sub-module from include list.
+         */
+        if (!isCandidateForSelfFileReference()) {
+            ((Resolvable) entity).setResolvableStatus(INTRA_FILE_RESOLVED);
+            return;
+        }
+
+        /*
+         * Try to resolve the top of the stack and update partial resolved stack
+         * if there is recursive references
+         */
+        YangNode ancestorRefNode = partialResolvedStack.peek()
+                .getHolderOfEntityToResolve();
+
+        if (entity instanceof YangIfFeature) {
+            resolveSelfFileLinkingForIfFeature(ancestorRefNode);
+            return;
+        }
+        if (entity instanceof YangIdentityRef || entity instanceof YangBase) {
+            resolveSelfFileLinkingForBaseAndIdentityref();
+            return;
+        }
+        YangType type = null;
+        if (entity instanceof YangType) {
+            type = (YangType) entity;
+        }
+            /*
+             * Traverse up in the ancestor tree to check if the referred node is
+             * defined
+             */
+        while (ancestorRefNode != null) {
+                /*
+                 * Check for the referred node defined in a ancestor scope
+                 */
+            YangNode curRefNode = ancestorRefNode.getChild();
+            if (isReferredNodeInSiblingListProcessed(curRefNode)) {
+                return;
+            }
+            ancestorRefNode = ancestorRefNode.getParent();
+            if (type != null && ancestorRefNode != null) {
+                if (ancestorRefNode.getParent() == null) {
+                    type.setTypeNotResolvedTillRootNode(true);
+                }
+            }
+        }
+
+        /*
+         * In case prefix is not present or it's self prefix it's a candidate for inter-file
+         * resolution via include list.
+         */
+        if (getRefPrefix() == null ||
+                getRefPrefix().contentEquals(curRefResolver.getPrefix())) {
+            ((Resolvable) entity).setResolvableStatus(INTRA_FILE_RESOLVED);
+        }
+    }
+
+    /**
+     * Resolves self file linking for base/identityref.
+     *
+     * @throws DataModelException a violation of data model rules
+     */
+    private void resolveSelfFileLinkingForBaseAndIdentityref()
+            throws DataModelException {
+
+        boolean refIdentity = false;
+        String nodeName = null;
+        T entity = getCurEntityToResolveFromStack();
+        if (entity instanceof YangIdentityRef) {
+            nodeName = ((YangIdentityRef) entity).getName();
+        } else if (entity instanceof YangBase) {
+            nodeName = ((YangBase) entity).getBaseIdentifier().getName();
+        }
+        if (curRefResolver instanceof RpcNotificationContainer) {
+            // Sends list of nodes for finding the target identity.
+            refIdentity = isIdentityReferenceFound(nodeName, (YangNode) curRefResolver);
+        }
+        if (refIdentity) {
+            return;
+        }
+
+        /*
+         * In case prefix is not present or it's self prefix it's a candidate for inter-file
+         * resolution via include list.
+         */
+        if (getRefPrefix() == null || getRefPrefix()
+                .contentEquals(curRefResolver.getPrefix())) {
+            ((Resolvable) entity).setResolvableStatus(INTRA_FILE_RESOLVED);
+        }
+    }
+
+    /**
+     * Resolves self file linking for if-feature.
+     *
+     * @param ancestorRefNode if-feature holder node
+     * @throws DataModelException DataModelException a violation of data model
+     *                            rules
+     */
+    private void resolveSelfFileLinkingForIfFeature(YangNode ancestorRefNode)
+            throws DataModelException {
+
+        YangFeatureHolder featureHolder = getFeatureHolder(ancestorRefNode);
+        YangNode curRefNode = (YangNode) featureHolder;
+        if (isReferredNode(curRefNode)) {
+
+            // Adds reference link of entity to the node under resolution.
+            addReferredEntityLink(curRefNode, LINKED);
+
+            /*
+             * resolve the reference and update the partial resolution stack
+             * with any further recursive references
+             */
+            addUnresolvedRecursiveReferenceToStack(curRefNode);
+            return;
+        }
+
+        /*
+         * In case prefix is not present or it's self prefix it's a candidate for inter-file
+         * resolution via include list.
+         */
+        if (getRefPrefix() == null || getRefPrefix()
+                .contentEquals(curRefResolver.getPrefix())) {
+            ((Resolvable) getCurEntityToResolveFromStack())
+                    .setResolvableStatus(INTRA_FILE_RESOLVED);
+        }
+    }
+
+    /**
+     * Returns the status of the referred identity found for base/identityref.
+     *
+     * @param nodeName        the name of the base node
+     *                        identifier/identityref node identifier
+     * @param ancestorRefNode the parent node of base/identityref
+     * @return status of referred base/identityref
+     * @throws DataModelException a violation of data model rules
+     */
+    private boolean isIdentityReferenceFound(String nodeName, YangNode ancestorRefNode)
+            throws DataModelException {
+
+        // When child is not present return.
+        if (ancestorRefNode.getChild() == null) {
+            return false;
+        }
+
+        ancestorRefNode = ancestorRefNode.getChild();
+
+        // Checks all the siblings under the node and returns the matched node.
+        YangNode nodeFound = isReferredNodeInSiblingProcessedForIdentity(ancestorRefNode,
+                                                                         nodeName);
+
+        if (nodeFound != null) {
+            // Adds reference link of entity to the node under resolution.
+            addReferredEntityLink(nodeFound, LINKED);
+
+            /*
+             * resolve the reference and update the partial resolution stack with any further recursive references
+             */
+            addUnresolvedRecursiveReferenceToStack(nodeFound);
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Adds the unresolved constructs to stack which has to be resolved for leafref.
+     *
+     * @param leavesInfo      YANG leaf or leaf list which holds the type
+     * @param ancestorRefNode holder of the YANG leaf or leaf list
+     */
+    private void addUnResolvedLeafRefTypeToStack(T leavesInfo, YangNode ancestorRefNode) {
+
+        YangType refType;
+        T extendedInfo;
+        if (leavesInfo instanceof YangLeaf) {
+            YangLeaf leaf = (YangLeaf) leavesInfo;
+            refType = leaf.getDataType();
+        } else {
+            YangLeafList leafList = (YangLeafList) leavesInfo;
+            refType = leafList.getDataType();
+        }
+        extendedInfo = (T) refType.getDataTypeExtendedInfo();
+        addUnResolvedTypeDataToStack(refType, ancestorRefNode, extendedInfo);
+    }
+
+    //Adds unresolved type info to stack.
+    private void addUnResolvedTypeDataToStack(YangType refType, YangNode
+            ancestorRefNode, T extendedInfo) {
+        YangEntityToResolveInfoImpl<YangLeafRef<?>> unResolvedLeafRef =
+                new YangEntityToResolveInfoImpl<>();
+        YangEntityToResolveInfoImpl<YangType<?>> unResolvedTypeDef =
+                new YangEntityToResolveInfoImpl<>();
+        if (refType.getDataType() == YangDataTypes.LEAFREF) {
+            unResolvedLeafRef.setEntityToResolve((YangLeafRef<?>) extendedInfo);
+            unResolvedLeafRef.setHolderOfEntityToResolve(ancestorRefNode);
+            addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedLeafRef);
+        } else if (refType.getDataType() == YangDataTypes.DERIVED) {
+            unResolvedTypeDef.setEntityToResolve(refType);
+            unResolvedTypeDef.setHolderOfEntityToResolve(ancestorRefNode);
+            addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedTypeDef);
+        }
+    }
+
+    /**
+     * Returns feature holder(module/sub-module node) .
+     *
+     * @param ancestorRefNode if-feature holder node
+     */
+    private YangFeatureHolder getFeatureHolder(YangNode ancestorRefNode) {
+        while (ancestorRefNode != null) {
+            if (ancestorRefNode instanceof YangFeatureHolder) {
+                return (YangFeatureHolder) ancestorRefNode;
+            }
+            ancestorRefNode = ancestorRefNode.getParent();
+        }
+        return null;
+    }
+
+    /**
+     * Checks if the reference in self file or in external file.
+     *
+     * @return true if self file reference, false otherwise
+     * @throws DataModelException a violation of data model rules
+     */
+    private boolean isCandidateForSelfFileReference()
+            throws DataModelException {
+        String prefix = getRefPrefix();
+        return prefix == null || prefix.contentEquals(curRefResolver.getPrefix());
+    }
+
+    /**
+     * Checks for the referred parent node for the base/identity.
+     *
+     * @param refNode potential referred node
+     * @return the referred parent node of base/identity.
+     * @throws DataModelException data model errors
+     */
+    private YangNode isReferredNodeInSiblingProcessedForIdentity(YangNode refNode,
+                                                                 String refName)
+            throws DataModelException {
+
+        while (refNode != null) {
+            if (refNode instanceof YangIdentity) {
+                // Check if the potential referred node is the actual referred node
+                if (isReferredNodeForIdentity(refNode, refName)) {
+                    return refNode;
+                }
+            }
+            refNode = refNode.getNextSibling();
+        }
+        return null;
+    }
+
+    /**
+     * Checks if the current reference node name and the name in the base/identityref base are equal.
+     *
+     * @param curRefNode the node where the reference is pointed
+     * @param name       name of the base in the base/identityref base
+     * @return status of the match between the name
+     * @throws DataModelException a violation of data model rules
+     */
+    private boolean isReferredNodeForIdentity(YangNode curRefNode, String name)
+            throws DataModelException {
+        T entity = getCurEntityToResolveFromStack();
+        if (entity instanceof YangIdentityRef || entity instanceof YangBase) {
+
+            //Check if name of node name matches with the current reference node.
+            return curRefNode.getName().contentEquals(name);
+        } else {
+            throw new DataModelException(getErrorMsg(
+                    INVALID_ENTITY, curRefNode.getName(), curRefNode.getLineNumber(),
+                    curRefNode.getCharPosition(), curRefNode.getFileName()));
+        }
+    }
+
+    /**
+     * Checks for the referred node defined in a ancestor scope.
+     *
+     * @param refNode potential referred node
+     * @return status of resolution and updating the partial resolved stack with
+     * the any recursive references
+     * @throws DataModelException a violation of data model rules
+     */
+    private boolean isReferredNodeInSiblingListProcessed(YangNode refNode)
+            throws DataModelException {
+        while (refNode != null) {
+
+            // Check if the potential referred node is the actual referred node
+            if (isReferredNode(refNode)) {
+
+                // Adds reference link of entity to the node under resolution.
+                addReferredEntityLink(refNode, LINKED);
+
+                /*
+                 * resolve the reference and update the partial resolution stack
+                 * with any further recursive references
+                 */
+                addUnresolvedRecursiveReferenceToStack(refNode);
+
+                /*
+                 * return true, since the reference is linked and any recursive
+                 * unresolved references is added to the stack
+                 */
+                return true;
+            }
+
+            refNode = refNode.getNextSibling();
+        }
+        return false;
+    }
+
+    /**
+     * Checks if the potential referred node is the actual referred node.
+     *
+     * @param refNode typedef/grouping node
+     * @return true if node is of resolve type otherwise false
+     * @throws DataModelException a violation of data model rules
+     */
+    private boolean isReferredNode(YangNode refNode)
+            throws DataModelException {
+        T entity = getCurEntityToResolveFromStack();
+        if (entity instanceof YangType) {
+            if (refNode instanceof YangTypeDef) {
+                return isNodeNameSameAsResolutionInfoName(refNode);
+            }
+        } else if (entity instanceof YangUses) {
+            if (refNode instanceof YangGrouping) {
+                return isNodeNameSameAsResolutionInfoName(refNode);
+            }
+        } else if (entity instanceof YangIfFeature) {
+            if (refNode instanceof YangFeatureHolder) {
+                return isNodeNameSameAsResolutionInfoName(refNode);
+            }
+        } else if (entity instanceof YangBase || entity instanceof YangIdentityRef) {
+            if (refNode instanceof YangIdentity) {
+                return isNodeNameSameAsResolutionInfoName(refNode);
+            }
+        } else {
+            throw new DataModelException(getErrorMsg(
+                    LINKER_ERROR, refNode.getName(), refNode.getLineNumber(),
+                    refNode.getCharPosition(), refNode.getFileName()));
+        }
+        return false;
+    }
+
+    /**
+     * Checks if node name is same as name in resolution info, i.e. name of
+     * typedef/grouping is same as name of type/uses.
+     *
+     * @param node typedef/grouping node
+     * @return true if node name is same as name in resolution info, otherwise
+     * false
+     * @throws DataModelException a violation of data model rules
+     */
+
+    private boolean isNodeNameSameAsResolutionInfoName(YangNode node)
+            throws DataModelException {
+        T entity = getCurEntityToResolveFromStack();
+        if (entity instanceof YangType) {
+            return node.getName().contentEquals(((YangType<?>) entity)
+                                                        .getDataTypeName());
+        }
+        if (entity instanceof YangUses) {
+            return node.getName().contentEquals(((YangUses) entity).getName());
+        }
+        if (entity instanceof YangIfFeature) {
+            return isFeatureDefinedInNode(node);
+        }
+        if (entity instanceof YangBase) {
+            return node.getName().contentEquals(((
+                    YangBase) entity).getBaseIdentifier().getName());
+        }
+        if (entity instanceof YangIdentityRef) {
+            return node.getName().contentEquals(((YangIdentityRef) entity).getName());
+        }
+        throw new DataModelException(getErrorMsg(
+                INVALID_RESOLVED_ENTITY, node.getName(), node.getLineNumber(),
+                node.getCharPosition(), node.getFileName()));
+    }
+
+    private boolean isFeatureDefinedInNode(YangNode node) {
+        T entity = getCurEntityToResolveFromStack();
+        YangNodeIdentifier ifFeature = ((YangIfFeature) entity).getName();
+        List<YangFeature> featureList = ((YangFeatureHolder) node).getFeatureList();
+        if (featureList != null && !featureList.isEmpty()) {
+            Iterator<YangFeature> iterator = featureList.iterator();
+            while (iterator.hasNext()) {
+                YangFeature feature = iterator.next();
+                if (ifFeature.getName().equals(feature.getName())) {
+                    ((YangIfFeature) entity).setReferredFeature(feature);
+                    ((YangIfFeature) entity).setReferredFeatureHolder(node);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Adds reference of grouping/typedef in uses/type.
+     *
+     * @param refNode      grouping/typedef node being referred
+     * @param linkedStatus linked status if success.
+     * @throws DataModelException a violation of data model rules
+     */
+    private void addReferredEntityLink(YangNode refNode, ResolvableStatus linkedStatus)
+            throws DataModelException {
+        T entity = getCurEntityToResolveFromStack();
+        if (entity instanceof YangType) {
+            YangDerivedInfo<?> derivedInfo = (YangDerivedInfo<?>) ((
+                    YangType<?>) entity).getDataTypeExtendedInfo();
+            derivedInfo.setReferredTypeDef((YangTypeDef) refNode);
+        } else if (entity instanceof YangUses) {
+            ((YangUses) entity).setRefGroup((YangGrouping) refNode);
+        } else if (entity instanceof YangBase) {
+            ((YangBase) entity).setReferredIdentity((YangIdentity) refNode);
+        } else if (entity instanceof YangIdentityRef) {
+            ((YangIdentityRef) entity).setReferredIdentity((YangIdentity) refNode);
+        } else if (!(entity instanceof YangIfFeature) &&
+                !(entity instanceof YangLeafRef)) {
+            throw new DataModelException(getErrorMsg(
+                    LINKER_ERROR, refNode.getName(), refNode.getLineNumber(),
+                    refNode.getCharPosition(), refNode.getFileName()));
+        }
+        // Sets the resolution status in inside the type/uses.
+        ((Resolvable) entity).setResolvableStatus(linkedStatus);
+    }
+
+    /**
+     * Checks if type/grouping has further reference to typedef/ unresolved
+     * uses. Add it to the partial resolve stack and return the status of
+     * addition to stack.
+     *
+     * @param refNode grouping/typedef node
+     * @throws DataModelException a violation of data model rules
+     */
+    private void addUnresolvedRecursiveReferenceToStack(YangNode refNode)
+            throws DataModelException {
+        T entity = getCurEntityToResolveFromStack();
+        if (entity instanceof YangType) {
+
+            //Checks if typedef type is derived
+            if (((YangTypeDef) refNode).getTypeDefBaseType()
+                    .getDataType() == YangDataTypes.DERIVED) {
+                addEntityToStack((T) ((YangTypeDef) refNode).getTypeDefBaseType(),
+                                 refNode);
+            }
+        } else if (entity instanceof YangUses) {
+            /*
+             * Search if the grouping has any un resolved uses child, if so
+             * return true, else return false.
+             */
+            addUnResolvedUsesToStack(refNode);
+        } else if (entity instanceof YangIfFeature) {
+            addUnResolvedIfFeatureToStack(refNode);
+        } else if (entity instanceof YangLeafRef) {
+            // do nothing , referred node is already set
+            throw new DataModelException(getErrorMsg(
+                    INVALID_RESOLVED_ENTITY, refNode.getName(), refNode.getLineNumber(),
+                    refNode.getCharPosition(), refNode.getFileName()));
+        } else if (entity instanceof YangBase || entity instanceof YangIdentityRef) {
+
+            //Search if the identity has any un resolved base, if so return true, else return false.
+            addUnResolvedBaseToStack(refNode);
+        } else {
+            throw new DataModelException(getErrorMsg(
+                    LINKER_ERROR, refNode.getName(), refNode.getLineNumber(),
+                    refNode.getCharPosition(), refNode.getFileName()));
+        }
+    }
+
+    /**
+     * Returns if there is any unresolved uses in grouping.
+     *
+     * @param node grouping/typedef node
+     */
+    private void addUnResolvedUsesToStack(YangNode node) {
+
+        //Search the grouping node's children for presence of uses node.
+        TraversalType curTraversal = ROOT;
+        YangNode curNode = node.getChild();
+        while (curNode != null) {
+            if (curNode.getName().equals(node.getName())) {
+                // if we have traversed all the child nodes, then exit from loop
+                return;
+            }
+
+            // if child nodes has uses, then add it to resolution stack
+            if (curNode instanceof YangUses) {
+                addEntityToStack((T) curNode, node);
+            }
+
+            // Traversing all the child nodes of grouping
+            if (curTraversal != PARENT && curNode.getChild() != null) {
+                curTraversal = CHILD;
+                curNode = curNode.getChild();
+            } else if (curNode.getNextSibling() != null) {
+                curTraversal = SIBILING;
+                curNode = curNode.getNextSibling();
+            } else {
+                curTraversal = PARENT;
+                curNode = curNode.getParent();
+            }
+        }
+    }
+
+    /**
+     * Returns if there is any unresolved if-feature in feature.
+     *
+     * @param node module/submodule node
+     */
+    private void addUnResolvedIfFeatureToStack(YangNode node) {
+        YangFeature refFeature = ((YangIfFeature) getCurEntityToResolveFromStack())
+                .getReferredFeature();
+        List<YangIfFeature> ifFeatureList = refFeature.getIfFeatureList();
+        if (ifFeatureList != null && !ifFeatureList.isEmpty()) {
+            Iterator<YangIfFeature> ifFeatureIterator = ifFeatureList.iterator();
+            while (ifFeatureIterator.hasNext()) {
+                addEntityToStack((T) ifFeatureIterator.next(), node);
+            }
+        }
+    }
+
+    /**
+     * Returns if there is any unresolved base in identity.
+     *
+     * @param node module/submodule node
+     */
+    private void addUnResolvedBaseToStack(YangNode node) {
+
+        YangIdentity curNode = (YangIdentity) node;
+        if (curNode.getBaseNode() != null) {
+            if (curNode.getBaseNode().getResolvableStatus() != RESOLVED) {
+                addEntityToStack((T) curNode.getBaseNode(), node);
+            }
+        }
+    }
+
+    private void addEntityToStack(T entity, YangNode holder) {
+        YangEntityToResolveInfoImpl<T> unResolvedEntityInfo =
+                new YangEntityToResolveInfoImpl<>();
+        unResolvedEntityInfo.setEntityToResolve(entity);
+        unResolvedEntityInfo.setHolderOfEntityToResolve(holder);
+        addInPartialResolvedStack(unResolvedEntityInfo);
+    }
+
+    /**
+     * Sets stack of YANG type with partially resolved YANG construct hierarchy.
+     *
+     * @param partialResolvedInfo partial resolved YANG construct stack
+     */
+    private void addInPartialResolvedStack(YangEntityToResolveInfoImpl<T> partialResolvedInfo) {
+        partialResolvedStack.push(partialResolvedInfo);
+    }
+
+    /**
+     * Retrieves the next entity in the stack that needs to be resolved. It is
+     * assumed that the caller ensures that the stack is not empty.
+     *
+     * @return next entity in the stack that needs to be resolved
+     */
+    private T getCurEntityToResolveFromStack() {
+        return partialResolvedStack.peek().getEntityToResolve();
+    }
+
+    @Override
+    public YangEntityToResolveInfoImpl<T> getEntityToResolveInfo() {
+        return entityToResolveInfo;
+    }
+
+    @Override
+    public void linkInterFile(YangReferenceResolver dataModelRootNode)
+            throws DataModelException {
+
+        curRefResolver = dataModelRootNode;
+
+        // Current node to resolve, it can be a YANG type or YANG uses.
+        T entityToResolve = entityToResolveInfo.getEntityToResolve();
+
+        // Check if linking is already done
+        if (entityToResolve instanceof Resolvable) {
+            Resolvable resolvable = (Resolvable) entityToResolve;
+            if (resolvable.getResolvableStatus() == RESOLVED) {
+                return;
+            }
+        } else {
+            throw new DataModelException(UNRESOLVABLE);
+        }
+
+        if (entityToResolve instanceof YangXPathResolver &&
+                !(entityToResolve instanceof YangLeafRef)) {
+            //Process x-path linking.
+            processXPathLinking(entityToResolve, dataModelRootNode);
+        } else {
+            // Push the initial entity to resolve in stack.
+            addInPartialResolvedStack(entityToResolveInfo);
+            // Inter file linking and resolution.
+            linkInterFileAndResolve();
+            addDerivedRefTypeToRefTypeResolutionList();
+        }
+    }
+
+    /**
+     * Process x-path linking for augment and leaf-ref.
+     *
+     * @param entityToResolve entity to resolve
+     * @param root            root node
+     * @throws DataModelException if there is a data model error
+     */
+    private void processXPathLinking(T entityToResolve,
+                                     YangReferenceResolver root)
+            throws DataModelException {
+
+        YangXpathLinker<T> xPathLinker = new YangXpathLinker<T>();
+
+        if (entityToResolve instanceof YangAugment) {
+            YangNode targetNode;
+            YangAugment augment = (YangAugment) entityToResolve;
+            targetNode = xPathLinker
+                    .processXpathLinking(augment.getTargetNode(), (YangNode)
+                            root, AUGMENT_LINKING);
+            if (targetNode != null) {
+                if (targetNode instanceof YangAugmentableNode) {
+                    detectCollisionForAugmentedNode(targetNode, augment);
+                    ((YangAugmentableNode) targetNode).addAugmentation(augment);
+                    augment.setAugmentedNode(targetNode);
+                    setAugmentedFlagInAncestors(targetNode);
+                    Resolvable resolvable = (Resolvable) entityToResolve;
+                    resolvable.setResolvableStatus(RESOLVED);
+                    if (targetNode instanceof YangInput) {
+                        xPathLinker.addInModuleIfInput(augment, (YangNode) root);
+                    }
+                } else {
+                    throw new LinkerException(getErrorMsg(
+                            INVALID_TARGET + targetNode.getNodeType(),
+                            augment.getName(), augment.getLineNumber(),
+                            augment.getCharPosition(), augment.getFileName()));
+                }
+            } else {
+                throw new LinkerException(getErrorMsg(
+                        FAILED_TO_LINK, augment.getName(), augment
+                                .getLineNumber(), augment.getCharPosition(),
+                        augment.getFileName()));
+            }
+        } else if (entityToResolve instanceof YangCompilerAnnotation) {
+            YangNode targetNode;
+            YangCompilerAnnotation ca = (YangCompilerAnnotation) entityToResolve;
+            targetNode = xPathLinker.processXpathLinking(ca.getAtomicPathList(),
+                                                         (YangNode) root,
+                                                         AUGMENT_LINKING);
+            if (targetNode != null) {
+                if (targetNode instanceof YangList) {
+                    ((YangList) targetNode).setCompilerAnnotation(
+                            (YangCompilerAnnotation) entityToResolve);
+                    Resolvable resolvable = (Resolvable) entityToResolve;
+                    resolvable.setResolvableStatus(RESOLVED);
+                } else {
+                    throw new LinkerException(getErrorMsg(
+                            INVALID_TARGET + targetNode.getNodeType(), ca.getPath(),
+                            ca.getLineNumber(), ca.getCharPosition(), ca.getFileName()));
+                }
+            } else {
+                throw new LinkerException(getErrorMsg(
+                        FAILED_TO_FIND_ANNOTATION, ca.getPath(), ca.getLineNumber(),
+                        ca.getCharPosition(), ca.getFileName()));
+            }
+        } else if (entityToResolve instanceof YangLeafRef) {
+            YangLeafRef leafRef = (YangLeafRef) entityToResolve;
+            Object target = xPathLinker.processLeafRefXpathLinking(
+                    leafRef.getAtomicPath(), (YangNode) root, leafRef, LEAF_REF_LINKING);
+            if (target != null) {
+                YangLeaf leaf;
+                YangLeafList leafList;
+                leafRef.setReferredLeafOrLeafList(target);
+                if (target instanceof YangLeaf) {
+                    leaf = (YangLeaf) target;
+                    leafRef.setResolvableStatus(INTER_FILE_LINKED);
+                    addUnResolvedLeafRefTypeToStack((T) leaf, entityToResolveInfo
+                            .getHolderOfEntityToResolve());
+                } else {
+                    leafList = (YangLeafList) target;
+                    leafRef.setResolvableStatus(INTER_FILE_LINKED);
+                    addUnResolvedLeafRefTypeToStack(
+                            (T) leafList, entityToResolveInfo.getHolderOfEntityToResolve());
+                }
+                fillPathPredicates(leafRef);
+            } else {
+                LinkerException ex = new LinkerException(
+                        FAILED_TO_FIND_LEAD_INFO_HOLDER + leafRef.getPath());
+                ex.setCharPosition(leafRef.getCharPosition());
+                ex.setLine(leafRef.getLineNumber());
+                ex.setFileName(leafRef.getFileName());
+                throw ex;
+            }
+        }
+    }
+
+    /**
+     * Returns the referenced prefix of entity under resolution.
+     *
+     * @return referenced prefix of entity under resolution
+     * @throws DataModelException a violation in data model rule
+     */
+    private String getRefPrefix()
+            throws DataModelException {
+        T entity = getCurEntityToResolveFromStack();
+        if (entity instanceof YangType) {
+            return ((YangType<?>) entity).getPrefix();
+        }
+        if (entity instanceof YangUses) {
+            return ((YangUses) entity).getPrefix();
+        }
+        if (entity instanceof YangIfFeature) {
+            return ((YangIfFeature) entity).getPrefix();
+        }
+        if (entity instanceof YangBase) {
+            return ((YangBase) entity).getBaseIdentifier()
+                    .getPrefix();
+        }
+        if (entity instanceof YangIdentityRef) {
+            return ((YangIdentityRef) entity).getPrefix();
+        }
+        throw new DataModelException(LINKER_ERROR);
+    }
+
+    /**
+     * Performs inter file linking and resolution.
+     *
+     * @throws DataModelException a violation in data model rule
+     */
+    private void linkInterFileAndResolve()
+            throws DataModelException {
+
+        while (!partialResolvedStack.isEmpty()) {
+
+            // Current node to resolve, it can be a YANG type or YANG uses.
+            T entityToResolve = getCurEntityToResolveFromStack();
+            // Check if linking is already done
+            if (entityToResolve instanceof Resolvable) {
+
+                Resolvable resolvable = (Resolvable) entityToResolve;
+                switch (resolvable.getResolvableStatus()) {
+                    case RESOLVED:
+                        /*
+                         * If the entity is already resolved in the stack, then pop
+                         * it and continue with the remaining stack elements to
+                         * resolve
+                         */
+                        partialResolvedStack.pop();
+                        break;
+
+                    case INTER_FILE_LINKED:
+                        /*
+                         * If the top of the stack is already linked then resolve
+                         * the references and pop the entity and continue with
+                         * remaining stack elements to resolve
+                         */
+                        resolveTopOfStack();
+                        partialResolvedStack.pop();
+                        break;
+
+                    case INTRA_FILE_RESOLVED:
+                        /*
+                         * If the top of the stack is intra file resolved then check
+                         * if top of stack is linked, if not link it using
+                         * import/include list and push the linked referred entity
+                         * to the stack, otherwise only push it to the stack.
+                         */
+                        linkInterFileTopOfStackRefUpdateStack();
+                        break;
+
+                    case UNDEFINED:
+                        /*
+                         * In case of if-feature resolution, if referred "feature" is not
+                         * defined then the resolvable status will be undefined.
+                         */
+                        partialResolvedStack.pop();
+                        break;
+
+                    default:
+                        throw new DataModelException(INVALID_LINKER_STATE);
+                }
+            } else {
+                throw new DataModelException(INVALID_RESOLVED_ENTITY);
+            }
+        }
+    }
+
+    /**
+     * Links the top of the stack if it's inter-file and update stack.
+     *
+     * @throws DataModelException data model error
+     */
+    private void linkInterFileTopOfStackRefUpdateStack()
+            throws DataModelException {
+        T entity = getCurEntityToResolveFromStack();
+        if (entity instanceof YangLeafRef) {
+            // When leafref path comes with relative path, it will be converted to absolute path.
+            setAbsolutePathFromRelativePathInLeafref(entity);
+            processXPathLinking(entity, curRefResolver);
+            return;
+        }
+        /*
+         * Obtain the referred node of top of stack entity under resolution
+         */
+        T refNode = getRefNode();
+
+        /*
+         * Check for null for scenario when it's not linked and inter-file
+         * linking is required.
+         */
+        if (refNode == null) {
+
+            /*
+             * Check if prefix is null or not, to identify whether to search in
+             * import list or include list.
+             */
+            if (getRefPrefix() != null && !getRefPrefix()
+                    .contentEquals(curRefResolver.getPrefix())) {
+                if (resolveWithImport()) {
+                    return;
+                }
+            } else {
+                if (resolveWithInclude()) {
+                    return;
+                }
+            }
+
+            if (entity instanceof YangIfFeature) {
+                ((YangIfFeature) entity).setResolvableStatus(UNDEFINED);
+                return;
+            }
+            // If current entity is still not resolved, then
+            // linking/resolution has failed.
+
+            DataModelException ex = new DataModelException(
+                    getErrorInfoForLinker(entity));
+            ex.setLine(getLineNumber());
+            ex.setCharPosition(getCharPosition());
+            throw ex;
+        } else {
+            ((Resolvable) entity).setResolvableStatus(INTER_FILE_LINKED);
+            addUnresolvedRecursiveReferenceToStack((YangNode) refNode);
+        }
+    }
+
+    /**
+     * Sets the leafref with absolute path from the relative path.
+     *
+     * @param resolutionInfo information about the YANG construct which has to be resolved
+     * @throws DataModelException a violation of data model rules
+     */
+    private void setAbsolutePathFromRelativePathInLeafref(T resolutionInfo)
+            throws DataModelException {
+        if (resolutionInfo instanceof YangLeafRef) {
+
+            YangNode leafParent = ((YangLeafRef) resolutionInfo)
+                    .getParentNode();
+            YangLeafRef leafref = (YangLeafRef) resolutionInfo;
+
+            // Checks if the leafref has relative path in it.
+            if (leafref.getPathType() == RELATIVE_PATH) {
+                YangRelativePath relativePath = leafref.getRelativePath();
+                List<YangAtomicPath> absoluteInRelative = relativePath.getAtomicPathList();
+                int ancestorCount = relativePath.getAncestorNodeCount();
+
+                // Gets the root node from the ancestor count.
+                T nodeOrAugmentList =
+                        getRootNodeWithAncestorCountForLeafref(ancestorCount, leafParent,
+                                                               leafref);
+                if (nodeOrAugmentList instanceof YangNode) {
+                    StringBuilder name = new StringBuilder();
+                    StringBuilder prefix = new StringBuilder();
+                    YangNode rootNode = (YangNode) nodeOrAugmentList;
+                    // Forms a new absolute path from the relative path
+                    while (!(rootNode instanceof YangReferenceResolver)) {
+                        name.append(rootNode.getName());
+                        prefix.append(SLASH_FOR_STRING).append(name.reverse());
+                        name.delete(0, name.length());
+                        rootNode = rootNode.getParent();
+                        if (rootNode == null) {
+                            throw new DataModelException(INVALID_TREE);
+                        }
+                    }
+                    prefix.reverse();
+                    fillAbsolutePathValuesInLeafref(leafref, prefix.toString(),
+                                                    absoluteInRelative);
+                } else {
+                    List<String> listOfAugment = (List<String>) nodeOrAugmentList;
+                    Iterator<String> listOfAugmentIterator = listOfAugment.listIterator();
+                    StringBuilder augment = new StringBuilder(EMPTY_STRING);
+                    while (listOfAugmentIterator.hasNext()) {
+                        augment.append(SLASH_FOR_STRING)
+                                .append(listOfAugmentIterator.next());
+                    }
+                    fillAbsolutePathValuesInLeafref(leafref, augment.toString(),
+                                                    absoluteInRelative);
+                }
+            }
+        }
+    }
+
+    /**
+     * Fills the absolute path values in the leafref from relative path.
+     *
+     * @param leafref  instance of YANG leafref
+     * @param path     path name which has to be prefixed to relative path
+     * @param relative atomic paths in relative
+     * @throws DataModelException a violation of data model rules
+     */
+    private void fillAbsolutePathValuesInLeafref(YangLeafRef leafref, String path,
+                                                 List<YangAtomicPath> relative)
+            throws DataModelException {
+        leafref.setPathType(ABSOLUTE_PATH);
+        String[] pathName = new String[0];
+        if (path != null && !path.equals(EMPTY_STRING)) {
+            pathName = path.split(SLASH_FOR_STRING);
+        }
+        List<YangAtomicPath> finalListForAbsolute = new LinkedList<>();
+        for (String value : pathName) {
+            if (value != null && !value.isEmpty() && !value.equals(EMPTY_STRING)) {
+                YangNodeIdentifier nodeId = getValidNodeIdentifier(value, PATH_DATA);
+                YangAtomicPath atomicPath = new YangAtomicPath();
+                atomicPath.setNodeIdentifier(nodeId);
+                finalListForAbsolute.add(atomicPath);
+            }
+        }
+        if (relative != null && !relative.isEmpty()) {
+            Iterator<YangAtomicPath> pathIt = relative.listIterator();
+            while (pathIt.hasNext()) {
+                YangAtomicPath yangAtomicPath = pathIt.next();
+                finalListForAbsolute.add(yangAtomicPath);
+            }
+            leafref.setAtomicPath(finalListForAbsolute);
+        } else {
+            DataModelException ex = new DataModelException(getLeafRefErrorInfo(leafref));
+            ex.setCharPosition(leafref.getCharPosition());
+            ex.setLine(leafref.getLineNumber());
+            ex.setFileName(leafref.getFileName());
+            throw ex;
+        }
+    }
+
+    /**
+     * Returns the root parent with respect to the ancestor count from leafref.
+     *
+     * @param ancestorCount count of node where parent node can be reached
+     * @param curParent     current parent node
+     * @param leafref       instance of YANG leafref
+     * @return node where the ancestor count stops or augment path name list
+     * @throws DataModelException a violation of data model rules
+     */
+    private T getRootNodeWithAncestorCountForLeafref(
+            int ancestorCount, YangNode curParent, YangLeafRef leafref)
+            throws DataModelException {
+
+        int curParentCount = 1;
+        curParent = skipInvalidDataNodes(curParent, leafref);
+        if (curParent instanceof YangAugment) {
+            YangAugment augment = (YangAugment) curParent;
+            List<String> valueInAugment = getPathWithAugment(augment,
+                                                             ancestorCount - curParentCount);
+            return (T) valueInAugment;
+        } else {
+            while (curParentCount < ancestorCount) {
+                YangNode currentSkippedParent = skipInvalidDataNodes(curParent, leafref);
+                if (currentSkippedParent == curParent) {
+                    if (curParent.getParent() == null) {
+                        throw new DataModelException(getLeafRefErrorInfo(leafref));
+                    }
+                    curParent = curParent.getParent();
+                } else {
+                    curParent = currentSkippedParent;
+                    continue;
+                }
+                curParentCount = curParentCount + 1;
+                if (curParent instanceof YangAugment) {
+                    YangAugment augment = (YangAugment) curParent;
+                    List<String> valueInAugment = getPathWithAugment(
+                            augment, ancestorCount - curParentCount);
+                    return (T) valueInAugment;
+                }
+            }
+        }
+        return (T) curParent;
+    }
+
+    /**
+     * Finds and resolves with include list.
+     *
+     * @return true if resolved, false otherwise
+     * @throws DataModelException a violation in data model rule
+     */
+    private boolean resolveWithInclude() throws DataModelException {
+        /*
+         * Run through all the nodes in include list and search for referred
+         * typedef/grouping at the root level.
+         */
+        for (YangInclude yangInclude : curRefResolver.getIncludeList()) {
+            YangNode linkedNode = getLinkedNode(yangInclude.getIncludedNode());
+            if (linkedNode != null) {
+                return addUnResolvedRefToStack(linkedNode);
+            }
+        }
+        // If referred node can't be found return false.
+        return false;
+    }
+
+    /**
+     * Finds and resolves with import list.
+     *
+     * @return true if resolved, false otherwise
+     * @throws DataModelException a violation in data model rule
+     */
+    private boolean resolveWithImport() throws DataModelException {
+
+        // Run through import list to find the referred typedef/grouping.
+        for (YangImport yangImport : curRefResolver.getImportList()) {
+            /*
+             * Match the prefix attached to entity under resolution with the
+             * imported/included module/sub-module's prefix. If found, search
+             * for the referred typedef/grouping at the root level.
+             */
+            if (yangImport.getPrefixId().contentEquals(getRefPrefix())) {
+                YangNode linkedNode = getLinkedNode(yangImport.getImportedNode());
+                if (linkedNode != null) {
+                    return addUnResolvedRefToStack(linkedNode);
+                }
+                /*
+                 * If referred node can't be found at root level break for loop,
+                 * and return false.
+                 */
+                break;
+            }
+        }
+        // If referred node can't be found return false.
+        return false;
+    }
+
+    //Add unresolved constructs to stack.
+    private boolean addUnResolvedRefToStack(YangNode linkedNode)
+            throws DataModelException {
+        // Add the link to external entity.
+        addReferredEntityLink(linkedNode, INTER_FILE_LINKED);
+
+        // Add the type/uses of referred typedef/grouping to the stack.
+        addUnresolvedRecursiveReferenceToStack(linkedNode);
+        return true;
+    }
+
+    //Returns linked node from entity of stack.
+    private YangNode getLinkedNode(YangNode node) {
+        T entity = getCurEntityToResolveFromStack();
+        if (entity instanceof YangType) {
+            return findRefTypedef(node);
+        }
+        if (entity instanceof YangUses) {
+            return findRefGrouping(node);
+        }
+        if (entity instanceof YangIfFeature) {
+            return findRefFeature(node);
+        }
+        if (entity instanceof YangBase) {
+            return findRefIdentity(node);
+        }
+        if (entity instanceof YangIdentityRef) {
+            return findRefIdentityRef(node);
+        }
+        return null;
+    }
+
+    /**
+     * Returns referred typedef/grouping node.
+     *
+     * @return referred typedef/grouping node
+     * @throws DataModelException a violation in data model rule
+     */
+    private T getRefNode() throws DataModelException {
+        T entity = getCurEntityToResolveFromStack();
+        if (entity instanceof YangType) {
+            YangDerivedInfo<?> derivedInfo = (YangDerivedInfo<?>)
+                    ((YangType<?>) entity).getDataTypeExtendedInfo();
+            return (T) derivedInfo.getReferredTypeDef();
+        }
+        if (entity instanceof YangUses) {
+            return (T) ((YangUses) entity).getRefGroup();
+        }
+        if (entity instanceof YangIfFeature) {
+            return (T) ((YangIfFeature) entity).getReferredFeatureHolder();
+        }
+        if (entity instanceof YangLeafRef) {
+            return (T) ((YangLeafRef) entity).getReferredLeafOrLeafList();
+        }
+        if (entity instanceof YangBase) {
+            return (T) ((YangBase) entity).getReferredIdentity();
+        }
+        if (entity instanceof YangIdentityRef) {
+            return (T) ((YangIdentityRef) entity).getReferredIdentity();
+        }
+        throw new DataModelException(LINKER_ERROR);
+    }
+
+    /**
+     * Finds the referred grouping node at the root level of imported/included node.
+     *
+     * @param refNode module/sub-module node
+     * @return referred grouping
+     */
+    private YangNode findRefGrouping(YangNode refNode) {
+        YangNode tmpNode = refNode.getChild();
+        while (tmpNode != null) {
+            if (tmpNode instanceof YangGrouping) {
+                if (tmpNode.getName()
+                        .equals(((YangUses) getCurEntityToResolveFromStack())
+                                        .getName())) {
+                    return tmpNode;
+                }
+            }
+            tmpNode = tmpNode.getNextSibling();
+        }
+        return null;
+    }
+
+    /**
+     * Finds the referred feature node at the root level of imported/included node.
+     *
+     * @param refNode module/sub-module node
+     * @return referred feature
+     */
+    private YangNode findRefFeature(YangNode refNode) {
+        T entity = getCurEntityToResolveFromStack();
+        YangNodeIdentifier ifFeature = ((YangIfFeature) entity).getName();
+        List<YangFeature> featureList = ((YangFeatureHolder) refNode)
+                .getFeatureList();
+        if (featureList != null && !featureList.isEmpty()) {
+            for (YangFeature feature : featureList) {
+                if (ifFeature.getName().equals(feature.getName())) {
+                    ((YangIfFeature) entity).setReferredFeature(feature);
+                    return refNode;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Finds the referred typedef node at the root level of imported/included node.
+     *
+     * @param refNode module/sub-module node
+     * @return referred typedef
+     */
+    private YangNode findRefTypedef(YangNode refNode) {
+        YangNode tmpNode = refNode.getChild();
+        while (tmpNode != null) {
+            if (tmpNode instanceof YangTypeDef) {
+                if (tmpNode.getName()
+                        .equals(((YangType) getCurEntityToResolveFromStack())
+                                        .getDataTypeName())) {
+                    return tmpNode;
+                }
+            }
+            tmpNode = tmpNode.getNextSibling();
+        }
+        return null;
+    }
+
+    /**
+     * Finds the referred identity node at the root level of imported/included node.
+     *
+     * @param refNode module/sub-module node
+     * @return referred identity
+     */
+    private YangNode findRefIdentity(YangNode refNode) {
+        YangNode tmpNode = refNode.getChild();
+        while (tmpNode != null) {
+            if (tmpNode instanceof YangIdentity) {
+                if (tmpNode.getName()
+                        .equals(((YangBase) getCurEntityToResolveFromStack())
+                                        .getBaseIdentifier().getName())) {
+                    return tmpNode;
+                }
+            }
+            tmpNode = tmpNode.getNextSibling();
+        }
+        return null;
+    }
+
+    /**
+     * Finds the referred identity node at the root level of imported/included node.
+     *
+     * @param refNode module/sub-module node
+     * @return referred identity
+     */
+    private YangNode findRefIdentityRef(YangNode refNode) {
+        YangNode tmpNode = refNode.getChild();
+        while (tmpNode != null) {
+            if (tmpNode instanceof YangIdentity) {
+                if (tmpNode.getName()
+                        .equals(((YangIdentityRef) getCurEntityToResolveFromStack())
+                                        .getBaseIdentity().getName())) {
+                    return tmpNode;
+                }
+            }
+            tmpNode = tmpNode.getNextSibling();
+        }
+        return null;
+    }
+
+    /**
+     * Sets descendant node augmented flag in ancestors.
+     *
+     * @param targetNode augmented YANG node
+     */
+    private void setAugmentedFlagInAncestors(YangNode targetNode) {
+        targetNode = targetNode.getParent();
+        while (targetNode != null) {
+            targetNode.setDescendantNodeAugmented(true);
+            targetNode = targetNode.getParent();
+        }
+    }
+}
\ No newline at end of file
diff --git a/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangXpathLinker.java b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangXpathLinker.java
new file mode 100644
index 0000000..02d1beb
--- /dev/null
+++ b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangXpathLinker.java
@@ -0,0 +1,774 @@
+/*
+ * 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.yang.compiler.linker.impl;
+
+import org.onosproject.yang.compiler.datamodel.LeafRefInvalidHolder;
+import org.onosproject.yang.compiler.datamodel.RpcNotificationContainer;
+import org.onosproject.yang.compiler.datamodel.YangAtomicPath;
+import org.onosproject.yang.compiler.datamodel.YangAugment;
+import org.onosproject.yang.compiler.datamodel.YangGrouping;
+import org.onosproject.yang.compiler.datamodel.YangImport;
+import org.onosproject.yang.compiler.datamodel.YangInclude;
+import org.onosproject.yang.compiler.datamodel.YangInput;
+import org.onosproject.yang.compiler.datamodel.YangLeaf;
+import org.onosproject.yang.compiler.datamodel.YangLeafList;
+import org.onosproject.yang.compiler.datamodel.YangLeafRef;
+import org.onosproject.yang.compiler.datamodel.YangLeavesHolder;
+import org.onosproject.yang.compiler.datamodel.YangModule;
+import org.onosproject.yang.compiler.datamodel.YangNode;
+import org.onosproject.yang.compiler.datamodel.YangNodeIdentifier;
+import org.onosproject.yang.compiler.datamodel.YangOutput;
+import org.onosproject.yang.compiler.datamodel.YangSubModule;
+import org.onosproject.yang.compiler.datamodel.YangUses;
+import org.onosproject.yang.compiler.linker.exceptions.LinkerException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+
+import static org.onosproject.yang.compiler.datamodel.exceptions.ErrorMessages.getErrorMsg;
+import static org.onosproject.yang.compiler.linker.impl.PrefixResolverType.INTER_TO_INTER;
+import static org.onosproject.yang.compiler.linker.impl.PrefixResolverType.INTER_TO_INTRA;
+import static org.onosproject.yang.compiler.linker.impl.PrefixResolverType.INTRA_TO_INTER;
+import static org.onosproject.yang.compiler.linker.impl.PrefixResolverType.NO_PREFIX_CHANGE_FOR_INTER;
+import static org.onosproject.yang.compiler.linker.impl.PrefixResolverType.NO_PREFIX_CHANGE_FOR_INTRA;
+import static org.onosproject.yang.compiler.linker.impl.XpathLinkingTypes.AUGMENT_LINKING;
+import static org.onosproject.yang.compiler.utils.UtilConstants.COLON;
+import static org.onosproject.yang.compiler.utils.UtilConstants.ERROR_MSG_FOR_AUGMENT_LINKING;
+import static org.onosproject.yang.compiler.utils.UtilConstants.FAILED_TO_FIND_LEAD_INFO_HOLDER;
+import static org.onosproject.yang.compiler.utils.UtilConstants.INPUT;
+import static org.onosproject.yang.compiler.utils.UtilConstants.IS_INVALID;
+import static org.onosproject.yang.compiler.utils.UtilConstants.LEAFREF_ERROR;
+import static org.onosproject.yang.compiler.utils.UtilConstants.LEAF_HOLDER_ERROR;
+import static org.onosproject.yang.compiler.utils.UtilConstants.OUTPUT;
+import static org.onosproject.yang.compiler.utils.UtilConstants.SLASH_FOR_STRING;
+
+/**
+ * Represents x-path linking.
+ *
+ * @param <T> x-path linking can be done for target node or for target leaf/leaf-list
+ */
+public class YangXpathLinker<T> {
+
+    private List<YangAtomicPath> absPaths;
+    private YangNode rootNode;
+    private Map<YangAtomicPath, PrefixResolverType> prefixResolverTypes;
+    private String curPrefix;
+    private String constructsParentsPrefix;
+    private XpathLinkingTypes linkingType;
+
+    /**
+     * Creates an instance of x-path linker.
+     */
+    public YangXpathLinker() {
+        absPaths = new ArrayList<>();
+    }
+
+    /**
+     * Returns list of augment nodes.
+     *
+     * @param node root node
+     * @return list of augment nodes
+     */
+    public List<YangAugment> getListOfYangAugment(YangNode node) {
+        node = node.getChild();
+        List<YangAugment> augments = new ArrayList<>();
+        while (node != null) {
+            if (node instanceof YangAugment) {
+                augments.add((YangAugment) node);
+            }
+            node = node.getNextSibling();
+        }
+        return augments;
+    }
+
+    /**
+     * Process absolute node path for target leaf.
+     *
+     * @param atomicPaths atomic path node list
+     * @param root        root node
+     * @param leafref     instance of YANG leafref
+     * @param curLinking  x path linking type
+     * @return linked target node
+     */
+    T processLeafRefXpathLinking(List<YangAtomicPath> atomicPaths, YangNode root,
+                                 YangLeafRef leafref, XpathLinkingTypes curLinking) {
+
+        YangNode targetNode;
+        rootNode = root;
+        prefixResolverTypes = new HashMap<>();
+        linkingType = curLinking;
+        parsePrefixResolverList(atomicPaths);
+        YangAtomicPath leafRefPath = atomicPaths.get(atomicPaths.size() - 1);
+
+        // When leaf-ref path contains only one absolute path.
+        if (atomicPaths.size() == 1) {
+            targetNode = getTargetNodeWhenPathSizeIsOne(atomicPaths);
+        } else {
+            for (YangAtomicPath atomicPath : atomicPaths) {
+                if (atomicPath != leafRefPath) {
+                    absPaths.add(atomicPath);
+                }
+            }
+            targetNode = parseData(root);
+        }
+        if (targetNode == null) {
+            targetNode = searchInSubModule(root);
+        }
+
+        // Invalid path presence in the node list is checked.
+        validateInvalidNodesInThePath(leafref);
+
+        if (targetNode != null) {
+            YangLeaf targetLeaf = searchReferredLeaf(targetNode, leafRefPath
+                    .getNodeIdentifier().getName());
+            if (targetLeaf == null) {
+                YangLeafList targetLeafList = searchReferredLeafList(
+                        targetNode, leafRefPath.getNodeIdentifier().getName());
+                if (targetLeafList != null) {
+                    return (T) targetLeafList;
+                } else {
+                    LinkerException ex = new LinkerException(
+                            FAILED_TO_FIND_LEAD_INFO_HOLDER + leafref.getPath());
+                    ex.setCharPosition(leafref.getCharPosition());
+                    ex.setLine(leafref.getLineNumber());
+                    ex.setFileName(leafref.getFileName());
+                    throw ex;
+                }
+            }
+            return (T) targetLeaf;
+        }
+        return null;
+    }
+
+    /**
+     * Validates the nodes in the path for any invalid node.
+     *
+     * @param leafref instance of YANG leafref
+     */
+    private void validateInvalidNodesInThePath(YangLeafRef leafref) {
+        for (YangAtomicPath absolutePath : (Iterable<YangAtomicPath>) leafref
+                .getAtomicPath()) {
+            YangNode nodeInPath = absolutePath.getResolvedNode();
+
+            if (nodeInPath instanceof LeafRefInvalidHolder) {
+                LinkerException ex = new LinkerException(
+                        LEAFREF_ERROR + leafref.getPath() + IS_INVALID);
+                ex.setCharPosition(leafref.getCharPosition());
+                ex.setLine(leafref.getLineNumber());
+                ex.setFileName(leafref.getFileName());
+                throw ex;
+            }
+        }
+    }
+
+    /**
+     * Returns target node when leaf-ref has only one absolute path in list.
+     *
+     * @param paths absolute paths
+     * @return target node
+     */
+    private YangNode getTargetNodeWhenPathSizeIsOne(List<YangAtomicPath> paths) {
+        if (paths.get(0).getNodeIdentifier().getPrefix() != null
+                && !paths.get(0).getNodeIdentifier().getPrefix().equals
+                (getRootsPrefix(rootNode))) {
+            return getImportedNode(rootNode, paths.get(0).getNodeIdentifier());
+        }
+        return rootNode;
+    }
+
+    /**
+     * Process absolute node path linking for augment.
+     *
+     * @param paths      absolute path node list
+     * @param root       root node
+     * @param curLinking x path linker type
+     * @return linked target node
+     */
+    public YangNode processXpathLinking(List<YangAtomicPath> paths,
+                                        YangNode root, XpathLinkingTypes curLinking) {
+        absPaths = paths;
+        rootNode = root;
+        prefixResolverTypes = new HashMap<>();
+        linkingType = curLinking;
+        parsePrefixResolverList(paths);
+        YangNode targetNode = parseData(root);
+        if (targetNode == null) {
+            targetNode = searchInSubModule(root);
+        }
+        return targetNode;
+    }
+
+    /**
+     * Searches for the referred leaf in target node.
+     *
+     * @param targetNode target node
+     * @param leafName   leaf name
+     * @return target leaf
+     */
+    private YangLeaf searchReferredLeaf(YangNode targetNode, String leafName) {
+        if (!(targetNode instanceof YangLeavesHolder)) {
+            throw new LinkerException(getErrorMsg(
+                    LEAF_HOLDER_ERROR, targetNode.getName(), targetNode
+                            .getLineNumber(), targetNode.getCharPosition(),
+                    targetNode.getFileName()));
+        }
+        YangLeavesHolder holder = (YangLeavesHolder) targetNode;
+        List<YangLeaf> leaves = holder.getListOfLeaf();
+        if (leaves != null && !leaves.isEmpty()) {
+            for (YangLeaf leaf : leaves) {
+                if (leaf.getName().equals(leafName)) {
+                    return leaf;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Searches for the referred leaf-list in target node.
+     *
+     * @param targetNode target node
+     * @param name       leaf-list name
+     * @return target leaf-list
+     */
+    private YangLeafList searchReferredLeafList(YangNode targetNode, String name) {
+        if (!(targetNode instanceof YangLeavesHolder)) {
+            throw new LinkerException(getErrorMsg(
+                    LEAF_HOLDER_ERROR, targetNode.getName(), targetNode
+                            .getLineNumber(), targetNode.getCharPosition(),
+                    targetNode.getFileName()));
+        }
+        YangLeavesHolder holder = (YangLeavesHolder) targetNode;
+        List<YangLeafList> leavesList = holder.getListOfLeafList();
+        if (leavesList != null && !leavesList.isEmpty()) {
+            for (YangLeafList leafList : leavesList) {
+                if (leafList.getName().equals(name)) {
+                    return leafList;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Process linking using for node identifier for inter/intra file.
+     *
+     * @param root root node
+     * @return linked target node
+     */
+    private YangNode parseData(YangNode root) {
+        String rootPrefix = getRootsPrefix(root);
+        constructsParentsPrefix = rootPrefix;
+        Iterator<YangAtomicPath> pathIterator = absPaths.iterator();
+        YangAtomicPath path = pathIterator.next();
+        if (path.getNodeIdentifier().getPrefix() != null
+                && !path.getNodeIdentifier().getPrefix().equals(rootPrefix)) {
+            return parsePath(getImportedNode(root, path.getNodeIdentifier()));
+        } else {
+            return parsePath(root);
+        }
+    }
+
+    /**
+     * Process linking of target node in root node.
+     *
+     * @param root root node
+     * @return linked target node
+     */
+    private YangNode parsePath(YangNode root) {
+
+        YangNode tempNode = root;
+        Stack<YangNode> linkerStack = new Stack<>();
+        Iterator<YangAtomicPath> pathIterator = absPaths.iterator();
+        YangAtomicPath tempPath = pathIterator.next();
+        YangNodeIdentifier nodeId;
+        curPrefix = tempPath.getNodeIdentifier().getPrefix();
+        int index = 0;
+        YangNode tempAugment;
+        do {
+            nodeId = tempPath.getNodeIdentifier();
+            if (tempPath.getNodeIdentifier().getPrefix() == null) {
+                tempAugment = resolveIntraFileAugment(tempPath, root);
+            } else {
+                tempAugment = resolveInterFileAugment(tempPath, root);
+            }
+            if (tempAugment != null) {
+                linkerStack.push(tempNode);
+                tempNode = tempAugment;
+            }
+
+            tempNode = searchTargetNode(tempNode, nodeId);
+
+            if (tempNode == null && !linkerStack.isEmpty()) {
+                tempNode = linkerStack.peek();
+                linkerStack.pop();
+                tempNode = searchTargetNode(tempNode, nodeId);
+            }
+
+            if (tempNode != null) {
+                tempPath.setResolvedNode(tempNode);
+                validateTempPathNode(tempNode);
+            }
+
+            if (index == absPaths.size() - 1) {
+                break;
+            }
+            tempPath = pathIterator.next();
+            index++;
+        } while (validate(tempNode, index));
+        return tempNode;
+    }
+
+    /**
+     * Validates temp path nodes for augment linking.
+     *
+     * @param node temp path node
+     */
+    private void validateTempPathNode(YangNode node) {
+
+        if (linkingType != AUGMENT_LINKING) {
+            return;
+        }
+        if (node instanceof YangGrouping) {
+            LinkerException ex = new LinkerException(
+                    ERROR_MSG_FOR_AUGMENT_LINKING +
+                            getAugmentNodeIdentifier(
+                                    absPaths.get(absPaths.size() - 1).getNodeIdentifier(),
+                                    absPaths,
+                                    rootNode));
+            ex.setFileName(rootNode.getFileName());
+            throw ex;
+        }
+    }
+
+    /**
+     * Resolves intra file augment linking.
+     *
+     * @param tempPath temporary absolute path
+     * @param root     root node
+     * @return linked target node
+     */
+    private YangNode resolveIntraFileAugment(YangAtomicPath tempPath, YangNode root) {
+        YangNode tempAugment;
+        if (curPrefix != tempPath.getNodeIdentifier().getPrefix()) {
+            root = getIncludedNode(rootNode, tempPath.getNodeIdentifier().getName());
+            if (root == null) {
+                root = getIncludedNode(rootNode, getAugmentNodeIdentifier(
+                        tempPath.getNodeIdentifier(), absPaths, rootNode));
+                if (root == null) {
+                    root = rootNode;
+                }
+            }
+        } else {
+            if (curPrefix != null) {
+                root = getImportedNode(root, tempPath.getNodeIdentifier());
+            }
+        }
+
+        curPrefix = tempPath.getNodeIdentifier().getPrefix();
+        tempAugment = getAugment(tempPath.getNodeIdentifier(), root, absPaths);
+        if (tempAugment == null) {
+            tempAugment = getAugment(tempPath.getNodeIdentifier(), rootNode,
+                                     absPaths);
+        }
+        return tempAugment;
+    }
+
+    /**
+     * Resolves inter file augment linking.
+     *
+     * @param tempPath temporary absolute path
+     * @param root     root node
+     * @return linked target node
+     */
+    private YangNode resolveInterFileAugment(YangAtomicPath tempPath, YangNode root) {
+
+        YangNode tempAugment;
+        if (!tempPath.getNodeIdentifier().getPrefix().equals(curPrefix)) {
+            curPrefix = tempPath.getNodeIdentifier().getPrefix();
+            root = getImportedNode(rootNode, tempPath.getNodeIdentifier());
+        }
+        tempAugment = getAugment(tempPath.getNodeIdentifier(), root, absPaths);
+        if (tempAugment == null) {
+            return resolveInterToInterFileAugment(root);
+        }
+        return tempAugment;
+    }
+
+    /**
+     * Resolves augment when prefix changed from inter file to inter file.
+     * it may be possible that the prefix used in imported module is different the
+     * given list of node identifiers.
+     *
+     * @param root root node
+     * @return target node
+     */
+    private YangNode resolveInterToInterFileAugment(YangNode root) {
+        List<YangAugment> augments = getListOfYangAugment(root);
+        int index;
+        List<YangAtomicPath> paths = new ArrayList<>();
+        for (YangAugment augment : augments) {
+            index = 0;
+
+            for (YangAtomicPath path : augment.getTargetNode()) {
+
+                if (!searchForAugmentInImportedNode(path.getNodeIdentifier(), index)) {
+                    paths.clear();
+                    break;
+                }
+                paths.add(path);
+                index++;
+            }
+            if (!paths.isEmpty() && paths.size() == absPaths.size() - 1) {
+                return augment;
+            } else {
+                paths.clear();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Searches for the augment node in imported module when prefix has changed from
+     * inter file to inter file.
+     *
+     * @param nodeId node id
+     * @param index  index
+     * @return true if found
+     */
+    private boolean searchForAugmentInImportedNode(YangNodeIdentifier nodeId,
+                                                   int index) {
+        if (index == absPaths.size()) {
+            return false;
+        }
+        YangNodeIdentifier tempNodeId = absPaths.get(index).getNodeIdentifier();
+        return nodeId.getName().equals(tempNodeId.getName());
+    }
+
+    /**
+     * Returns augment node.
+     *
+     * @param tempNodeId temporary absolute path id
+     * @param root       root node
+     * @return linked target node
+     */
+    private YangNode getAugment(YangNodeIdentifier tempNodeId, YangNode root,
+                                List<YangAtomicPath> absPaths) {
+        String augmentName = getAugmentNodeIdentifier(tempNodeId, absPaths, root);
+        if (augmentName != null) {
+            return searchAugmentNode(root, augmentName);
+        }
+        return null;
+    }
+
+    /**
+     * Process linking using import list.
+     *
+     * @param root   root node
+     * @param nodeId node identifier
+     * @return linked target node
+     */
+    private YangNode getImportedNode(YangNode root, YangNodeIdentifier nodeId) {
+
+        List<YangImport> importList;
+
+        if (root instanceof YangModule) {
+            importList = ((YangModule) root).getImportList();
+        } else {
+            importList = ((YangSubModule) root).getImportList();
+        }
+
+        for (YangImport imported : importList) {
+            if (imported.getPrefixId().equals(nodeId.getPrefix())) {
+                return imported.getImportedNode();
+            }
+        }
+
+        if (nodeId.getName() != null && nodeId.getPrefix()
+                .equals(constructsParentsPrefix)) {
+            return rootNode;
+        }
+        return root;
+    }
+
+    /**
+     * Searches in sub-module node.
+     *
+     * @param root root node
+     * @return target linked node
+     */
+    private YangNode searchInSubModule(YangNode root) {
+        List<YangInclude> includeList;
+        YangNode tempNode;
+        if (root instanceof YangModule) {
+            includeList = ((YangModule) root).getIncludeList();
+        } else {
+            includeList = ((YangSubModule) root).getIncludeList();
+        }
+
+        for (YangInclude included : includeList) {
+            tempNode = parseData(included.getIncludedNode());
+            if (tempNode != null) {
+                return tempNode;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Process linking using include list.
+     *
+     * @param root         root node
+     * @param tempPathName temporary path node name
+     * @return linked target node
+     */
+    private YangNode getIncludedNode(YangNode root, String tempPathName) {
+
+        List<YangInclude> includeList;
+
+        if (root instanceof YangModule) {
+            includeList = ((YangModule) root).getIncludeList();
+        } else {
+            includeList = ((YangSubModule) root).getIncludeList();
+        }
+
+        for (YangInclude included : includeList) {
+            if (verifyChildNode(included.getIncludedNode(), tempPathName)) {
+                return included.getIncludedNode();
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Verifies for child nodes in sub module.
+     *
+     * @param node submodule node
+     * @param name name of child node
+     * @return true if child node found
+     */
+    private boolean verifyChildNode(YangNode node, String name) {
+        node = node.getChild();
+        while (node != null) {
+            if (node.getName().equals(name)) {
+                return true;
+            }
+            node = node.getNextSibling();
+        }
+        return false;
+    }
+
+
+    /**
+     * Returns augment's node id.
+     *
+     * @param nodeId   node identifier
+     * @param absPaths absolute paths
+     * @param root     root node
+     * @return augment's node id
+     */
+    private String getAugmentNodeIdentifier(
+            YangNodeIdentifier nodeId, List<YangAtomicPath> absPaths, YangNode root) {
+        Iterator<YangAtomicPath> nodeIdIterator = absPaths.iterator();
+        YangAtomicPath tempNodeId;
+        StringBuilder builder = new StringBuilder();
+        String name;
+        String prefix;
+        String id;
+        PrefixResolverType type;
+        while (nodeIdIterator.hasNext()) {
+            tempNodeId = nodeIdIterator.next();
+            name = tempNodeId.getNodeIdentifier().getName();
+            prefix = tempNodeId.getNodeIdentifier().getPrefix();
+            if (!tempNodeId.getNodeIdentifier().equals(nodeId)) {
+                type = prefixResolverTypes.get(tempNodeId);
+                switch (type) {
+                    case INTER_TO_INTRA:
+                        id = SLASH_FOR_STRING + name;
+                        break;
+                    case INTRA_TO_INTER:
+                        if (!getRootsPrefix(root).equals(prefix)) {
+                            id = SLASH_FOR_STRING + prefix + COLON + name;
+                        } else {
+                            id = SLASH_FOR_STRING + name;
+                        }
+                        break;
+                    case INTER_TO_INTER:
+                        id = SLASH_FOR_STRING + prefix + COLON + name;
+                        break;
+                    case NO_PREFIX_CHANGE_FOR_INTRA:
+                        id = SLASH_FOR_STRING + name;
+                        break;
+                    case NO_PREFIX_CHANGE_FOR_INTER:
+                        if (!getRootsPrefix(root).equals(prefix)) {
+                            id = SLASH_FOR_STRING + prefix + COLON + name;
+                        } else {
+                            id = SLASH_FOR_STRING + name;
+                        }
+                        break;
+                    default:
+                        id = SLASH_FOR_STRING + name;
+                        break;
+                }
+                builder.append(id);
+            } else {
+                return builder.toString();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Searches augment node in root node by name of the augment. For intra
+     * file augment, target augment name without prefix is taken and checked.
+     *
+     * @param root    root node
+     * @param augName current augment name
+     * @return target augment node
+     */
+    private YangNode searchAugmentNode(YangNode root, String augName) {
+        YangNode node = root;
+        node = node.getChild();
+        while (node != null) {
+            if (node instanceof YangAugment) {
+                String name = ((YangAugment) node).getPrefixRemovedName();
+                if (node.getName().equals(augName) || name.equals(augName)) {
+                    return node;
+                }
+            }
+            node = node.getNextSibling();
+        }
+        return null;
+    }
+
+    /**
+     * Validates for target node if target node found or not.
+     *
+     * @param tempNode temporary node
+     * @param index    current index of list
+     * @return false if target node found
+     */
+    private boolean validate(YangNode tempNode, int index) {
+
+        int size = absPaths.size();
+        if (tempNode != null && index != size) {
+            return true;
+        } else if (tempNode != null) {
+            return false;
+            // this is your target node.
+        } else if (index != size) {
+            return true;
+            // this could be in submodule as well.
+        }
+        return false;
+    }
+
+    /**
+     * Searches target node in root node.
+     *
+     * @param node      root node
+     * @param curNodeId YANG node identifier
+     * @return linked target node
+     */
+    private YangNode searchTargetNode(YangNode node, YangNodeIdentifier curNodeId) {
+
+        if (node != null) {
+            node = node.getChild();
+        }
+        while (node != null) {
+            if (node instanceof YangInput) {
+                if (curNodeId.getName().equalsIgnoreCase(INPUT)) {
+                    return node;
+                }
+            } else if (node instanceof YangOutput) {
+                if (curNodeId.getName().equalsIgnoreCase(OUTPUT)) {
+                    return node;
+                }
+            }
+            if (node.getName().equals(curNodeId.getName()) &&
+                    !(node instanceof YangUses)) {
+                return node;
+            }
+            node = node.getNextSibling();
+        }
+        return null;
+    }
+
+    /**
+     * Returns root prefix.
+     *
+     * @param root root node
+     * @return root prefix
+     */
+    private String getRootsPrefix(YangNode root) {
+        if (root instanceof YangModule) {
+            return ((YangModule) root).getPrefix();
+        } else {
+            return ((YangSubModule) root).getPrefix();
+        }
+    }
+
+    /**
+     * Resolves prefix and provides prefix resolver list.
+     *
+     * @param absolutePaths absolute paths
+     */
+    private void parsePrefixResolverList(List<YangAtomicPath> absolutePaths) {
+        Iterator<YangAtomicPath> pathIterator = absolutePaths.iterator();
+        YangAtomicPath absPath;
+        String prePrefix;
+        String curPrefix = null;
+        while (pathIterator.hasNext()) {
+            prePrefix = curPrefix;
+            absPath = pathIterator.next();
+            curPrefix = absPath.getNodeIdentifier().getPrefix();
+            if (curPrefix != null) {
+                if (!curPrefix.equals(prePrefix)) {
+                    if (prePrefix != null) {
+                        prefixResolverTypes.put(absPath, INTER_TO_INTER);
+                    } else {
+                        prefixResolverTypes.put(absPath, INTRA_TO_INTER);
+                    }
+                } else {
+                    prefixResolverTypes.put(absPath, NO_PREFIX_CHANGE_FOR_INTER);
+                }
+            } else {
+                if (prePrefix != null) {
+                    prefixResolverTypes.put(absPath, INTER_TO_INTRA);
+                } else {
+                    prefixResolverTypes.put(absPath, NO_PREFIX_CHANGE_FOR_INTRA);
+                }
+            }
+        }
+    }
+
+    /**
+     * Adds augment to rpc augmented list of input.
+     *
+     * @param augment  augment
+     * @param rootNode root node
+     */
+    void addInModuleIfInput(YangAugment augment,
+                            YangNode rootNode) {
+        ((RpcNotificationContainer) rootNode).addToAugmentList(augment);
+    }
+}
\ No newline at end of file
diff --git a/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/package-info.java b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/package-info.java
new file mode 100644
index 0000000..7ddaed2
--- /dev/null
+++ b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Provide intra/inter file and inter jar linking implementation.
+ */
+package org.onosproject.yang.compiler.linker.impl;
diff --git a/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/package-info.java b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/package-info.java
new file mode 100644
index 0000000..5cef2e8
--- /dev/null
+++ b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Provide inter jar and inter file linking abstract interface.
+ */
+package org.onosproject.yang.compiler.linker;
\ No newline at end of file