/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.onosproject.yangutils.linker.impl;

import org.onosproject.yangutils.datamodel.DefaultLocationInfo;
import org.onosproject.yangutils.datamodel.Resolvable;
import org.onosproject.yangutils.datamodel.ResolvableType;
import org.onosproject.yangutils.datamodel.RpcNotificationContainer;
import org.onosproject.yangutils.datamodel.TraversalType;
import org.onosproject.yangutils.datamodel.YangAtomicPath;
import org.onosproject.yangutils.datamodel.YangAugment;
import org.onosproject.yangutils.datamodel.YangAugmentableNode;
import org.onosproject.yangutils.datamodel.YangBase;
import org.onosproject.yangutils.datamodel.YangCompilerAnnotation;
import org.onosproject.yangutils.datamodel.YangDerivedInfo;
import org.onosproject.yangutils.datamodel.YangEntityToResolveInfoImpl;
import org.onosproject.yangutils.datamodel.YangFeature;
import org.onosproject.yangutils.datamodel.YangFeatureHolder;
import org.onosproject.yangutils.datamodel.YangGrouping;
import org.onosproject.yangutils.datamodel.YangIdentity;
import org.onosproject.yangutils.datamodel.YangIdentityRef;
import org.onosproject.yangutils.datamodel.YangIfFeature;
import org.onosproject.yangutils.datamodel.YangImport;
import org.onosproject.yangutils.datamodel.YangInclude;
import org.onosproject.yangutils.datamodel.YangInput;
import org.onosproject.yangutils.datamodel.YangLeaf;
import org.onosproject.yangutils.datamodel.YangLeafList;
import org.onosproject.yangutils.datamodel.YangLeafRef;
import org.onosproject.yangutils.datamodel.YangList;
import org.onosproject.yangutils.datamodel.YangNode;
import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
import org.onosproject.yangutils.datamodel.YangReferenceResolver;
import org.onosproject.yangutils.datamodel.YangRelativePath;
import org.onosproject.yangutils.datamodel.YangResolutionInfo;
import org.onosproject.yangutils.datamodel.YangType;
import org.onosproject.yangutils.datamodel.YangTypeDef;
import org.onosproject.yangutils.datamodel.YangUses;
import org.onosproject.yangutils.datamodel.YangXPathResolver;
import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
import org.onosproject.yangutils.datamodel.utils.ResolvableStatus;
import org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes;
import org.onosproject.yangutils.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.yangutils.datamodel.ResolvableType.YANG_IDENTITYREF;
import static org.onosproject.yangutils.datamodel.ResolvableType.YANG_LEAFREF;
import static org.onosproject.yangutils.datamodel.TraversalType.CHILD;
import static org.onosproject.yangutils.datamodel.TraversalType.PARENT;
import static org.onosproject.yangutils.datamodel.TraversalType.ROOT;
import static org.onosproject.yangutils.datamodel.TraversalType.SIBILING;
import static org.onosproject.yangutils.datamodel.YangPathArgType.ABSOLUTE_PATH;
import static org.onosproject.yangutils.datamodel.YangPathArgType.RELATIVE_PATH;
import static org.onosproject.yangutils.datamodel.exceptions.ErrorMessages.getErrorMsg;
import static org.onosproject.yangutils.datamodel.utils.DataModelUtils.addResolutionInfo;
import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.INTER_FILE_LINKED;
import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.INTRA_FILE_RESOLVED;
import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.LINKED;
import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.RESOLVED;
import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.UNDEFINED;
import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.UNRESOLVED;
import static org.onosproject.yangutils.datamodel.utils.YangConstructType.PATH_DATA;
import static org.onosproject.yangutils.linker.impl.YangLinkerUtils.detectCollisionForAugmentedNode;
import static org.onosproject.yangutils.linker.impl.YangLinkerUtils.getErrorInfoForLinker;
import static org.onosproject.yangutils.linker.impl.YangLinkerUtils.getLeafRefErrorInfo;
import static org.onosproject.yangutils.linker.impl.YangLinkerUtils.getPathWithAugment;
import static org.onosproject.yangutils.linker.impl.YangLinkerUtils.getValidNodeIdentifier;
import static org.onosproject.yangutils.linker.impl.YangLinkerUtils.skipInvalidDataNodes;
import static org.onosproject.yangutils.utils.UtilConstants.EMPTY_STRING;
import static org.onosproject.yangutils.utils.UtilConstants.FAILED_TO_FIND_ANNOTATION;
import static org.onosproject.yangutils.utils.UtilConstants.FAILED_TO_FIND_LEAD_INFO_HOLDER;
import static org.onosproject.yangutils.utils.UtilConstants.FAILED_TO_LINK;
import static org.onosproject.yangutils.utils.UtilConstants.IDENTITYREF;
import static org.onosproject.yangutils.utils.UtilConstants.INVALID_ENTITY;
import static org.onosproject.yangutils.utils.UtilConstants.INVALID_LINKER_STATE;
import static org.onosproject.yangutils.utils.UtilConstants.INVALID_RESOLVED_ENTITY;
import static org.onosproject.yangutils.utils.UtilConstants.INVALID_TARGET;
import static org.onosproject.yangutils.utils.UtilConstants.INVALID_TREE;
import static org.onosproject.yangutils.utils.UtilConstants.LEAFREF;
import static org.onosproject.yangutils.utils.UtilConstants.LINKER_ERROR;
import static org.onosproject.yangutils.utils.UtilConstants.SLASH_FOR_STRING;
import static org.onosproject.yangutils.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 the leafref/identityref type to the type, which has derived type referring to
     * typedef with leafref/identityref type.
     */
    private void addDerivedRefTypeToRefTypeResolutionList()
            throws DataModelException {

        YangNode refNode = entityToResolveInfo.getHolderOfEntityToResolve();
        YangType yangType = getValidateResolvableType();

        if (yangType == null) {
            return;
        }

        YangDerivedInfo derivedInfo = (YangDerivedInfo) yangType
                .getDataTypeExtendedInfo();

        YangDataTypes dataType = derivedInfo.getEffectiveBuiltInType();
        // If the derived types referred type is not leafref/identityref return
        if (dataType != YangDataTypes.LEAFREF &&
                dataType != YangDataTypes.IDENTITYREF) {
            return;
        }

        T extendedInfo = (T) derivedInfo.getReferredTypeDef()
                .getTypeDefBaseType().getDataTypeExtendedInfo();

        while (extendedInfo instanceof YangDerivedInfo) {
            YangDerivedInfo derivedInfoFromTypedef = (YangDerivedInfo) extendedInfo;
            extendedInfo = (T) derivedInfoFromTypedef.getReferredTypeDef()
                    .getTypeDefBaseType().getDataTypeExtendedInfo();
        }

        /*
         * Backup the derived types leafref/identityref info, delete all the info in current type,
         * but for resolution status as resolved. Copy the backed up leafref/identityref to types extended info,
         * create a leafref/identityref resolution info using the current resolution info and
         * add to leafref/identityref resolution list.
         */
        if (dataType == YangDataTypes.LEAFREF) {
            YangLeafRef leafRefInTypeDef = (YangLeafRef) extendedInfo;
            addRefTypeInfo(YangDataTypes.LEAFREF, LEAFREF, extendedInfo,
                           yangType, refNode, YANG_LEAFREF);
            leafRefInTypeDef.setParentNodeOfLeafref(refNode);
        } else {
            addRefTypeInfo(YangDataTypes.IDENTITYREF, IDENTITYREF, extendedInfo,
                           yangType, refNode, YANG_IDENTITYREF);
        }
    }

    //Validates entity to resolve for YANG type and returns type
    private YangType getValidateResolvableType() {
        YangNode refNode = entityToResolveInfo.getHolderOfEntityToResolve();
        T entity = entityToResolveInfo.getEntityToResolve();
        // If holder is typedef return.
        if (!(refNode instanceof YangTypeDef) && entity instanceof YangType) {
            YangType yangType = (YangType) entity;

            // If type is not resolved return.
            if (yangType.getResolvableStatus() == RESOLVED) {
                return (YangType) entity;
            }
        }
        return null;
    }

    /**
     * Adds referred type(leafref/identityref) info to resolution list.
     *
     * @param type     data type
     * @param typeName type name
     * @param info     extended info
     * @param yangType YANG type
     * @param refNode  referred node
     * @param resType  resolution type
     * @throws DataModelException when fails to do data model operations
     */
    private void addRefTypeInfo(YangDataTypes type, String typeName, T info,
                                YangType yangType, YangNode refNode,
                                ResolvableType resType) throws DataModelException {
        yangType.resetYangType();
        yangType.setResolvableStatus(RESOLVED);
        yangType.setDataType(type);
        yangType.setDataTypeName(typeName);
        yangType.setDataTypeExtendedInfo(info);
        ((Resolvable) info).setResolvableStatus(UNRESOLVED);
        YangResolutionInfoImpl resolutionInfoImpl
                = new YangResolutionInfoImpl<>(info, refNode,
                                               getLineNumber(), getCharPosition());
        curRefResolver.addToResolutionList(resolutionInfoImpl, resType);
        curRefResolver.resolveSelfFileLinking(resType);
    }

    /**
     * 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.setParentNodeOfLeafref(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
     */
    private void processXPathLinking(T entityToResolve,
                                     YangReferenceResolver root) {

        YangXpathLinker<T> xPathLinker = new YangXpathLinker<T>();

        if (entityToResolve instanceof YangAugment) {
            YangNode targetNode;
            YangAugment augment = (YangAugment) entityToResolve;
            targetNode = xPathLinker
                    .processAugmentXpathLinking(augment.getTargetNode(), (YangNode) root);
            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.processAugmentXpathLinking(ca.getAtomicPathList(),
                                                                (YangNode) root);
            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);
            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());
                }
                //TODO: add logic for leaf-ref for path predicates.
            } 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 referredNode = getRefNode();

        /*
         * Check for null for scenario when it's not linked and inter-file
         * linking is required.
         */
        if (referredNode == 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) referredNode);
        }
    }

    /**
     * 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)
                    .getParentNodeOfLeafref();
            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();
        }
    }
}