/*
 * 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 java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;

import org.onosproject.yangutils.datamodel.Resolvable;
import org.onosproject.yangutils.datamodel.ResolvableType;
import org.onosproject.yangutils.datamodel.YangAtomicPath;
import org.onosproject.yangutils.datamodel.YangDerivedInfo;
import org.onosproject.yangutils.datamodel.YangEntityToResolveInfo;
import org.onosproject.yangutils.datamodel.YangFeature;
import org.onosproject.yangutils.datamodel.YangFeatureHolder;
import org.onosproject.yangutils.datamodel.YangGrouping;
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.YangLeavesHolder;
import org.onosproject.yangutils.datamodel.YangList;
import org.onosproject.yangutils.datamodel.YangModule;
import org.onosproject.yangutils.datamodel.YangNode;
import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
import org.onosproject.yangutils.datamodel.YangOutput;
import org.onosproject.yangutils.datamodel.YangPathArgType;
import org.onosproject.yangutils.datamodel.YangPathPredicate;
import org.onosproject.yangutils.datamodel.YangReferenceResolver;
import org.onosproject.yangutils.datamodel.YangRelativePath;
import org.onosproject.yangutils.datamodel.YangResolutionInfo;
import org.onosproject.yangutils.datamodel.YangRpc;
import org.onosproject.yangutils.datamodel.YangSubModule;
import org.onosproject.yangutils.datamodel.YangType;
import org.onosproject.yangutils.datamodel.YangTypeDef;
import org.onosproject.yangutils.datamodel.YangUses;
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.YangLinkingPhase;

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.linker.YangLinkingPhase.INTER_FILE;
import static org.onosproject.yangutils.linker.YangLinkingPhase.INTRA_FILE;
import static org.onosproject.yangutils.utils.UtilConstants.FEATURE_LINKER_ERROR;
import static org.onosproject.yangutils.utils.UtilConstants.GROUPING_LINKER_ERROR;
import static org.onosproject.yangutils.utils.UtilConstants.INPUT;
import static org.onosproject.yangutils.utils.UtilConstants.LEAFREF;
import static org.onosproject.yangutils.utils.UtilConstants.LEAFREF_LINKER_ERROR;
import static org.onosproject.yangutils.utils.UtilConstants.OUTPUT;
import static org.onosproject.yangutils.utils.UtilConstants.TYPEDEF_LINKER_ERROR;

/**
 * Represents implementation of resolution object which will be resolved by
 * linker.
 *
 * @param <T> type of resolution entity uses / type
 */
public class YangResolutionInfoImpl<T>
        implements YangResolutionInfo<T>, Serializable {

    private static final long serialVersionUID = 806201658L;

    /**
     * Information about the entity that needs to be resolved.
     */
    private YangEntityToResolveInfoImpl<T> entityToResolveInfo;

    /**
     * Error line number.
     */
    private transient int lineNumber;

    /**
     * Error character position in number.
     */
    private transient int charPosition;

    /**
     * Current module/sub-module reference, will be used in inter-file/
     * inter-jar scenario to get the import/include list.
     */
    private transient YangReferenceResolver curReferenceResolver;

    /**
     * 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) {
        setEntityToResolveInfo(new YangEntityToResolveInfoImpl<>());
        getEntityToResolveInfo().setEntityToResolve(dataNode);
        getEntityToResolveInfo().setHolderOfEntityToResolve(holderNode);
        this.setLineNumber(lineNumber);
        this.setCharPosition(charPositionInLine);
        setPartialResolvedStack(new Stack<>());
    }

    @Override
    public void resolveLinkingForResolutionInfo(YangReferenceResolver dataModelRootNode)
            throws DataModelException {

        setCurReferenceResolver(dataModelRootNode);

        // Current node to resolve, it can be a YANG type, YANG uses or YANG if-feature or YANG leafref.
        T entityToResolve = getEntityToResolveInfo().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("Data Model Exception: Entity to resolved is other than " +
                    "type/uses/if-feature/leafref");
        }

        // Push the initial entity to resolve in stack.
        addInPartialResolvedStack(getEntityToResolveInfo());

        linkAndResolvePartialResolvedStack();

        addDerivedRefTypeToRefTypeResolutionList();
    }

    /**
     * Resolves linking with ancestors.
     *
     * @throws DataModelException a violation of data model rules
     */
    private void linkAndResolvePartialResolvedStack()
            throws DataModelException {

        while (getPartialResolvedStack().size() != 0) {

            // Current node to resolve, it can be a YANG type or YANG uses.
            T entityToResolve = getCurrentEntityToResolveFromStack();
            // 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
                         */
                        getPartialResolvedStack().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(INTRA_FILE);
                        getPartialResolvedStack().pop();
                        break;
                    }

                    case INTRA_FILE_RESOLVED: {
                        /*
                         * Pop the top of the stack.
                         */
                        getPartialResolvedStack().pop();
                        break;
                    }

                    case UNRESOLVED: {
                        linkTopOfStackReferenceUpdateStack();

                        if (resolvable.getResolvableStatus() == UNRESOLVED) {
                            // If current entity is still not resolved, then
                            // linking/resolution has failed.
                            String errorInfo;
                            if (resolvable instanceof YangType) {
                                errorInfo = TYPEDEF_LINKER_ERROR;
                            } else if (resolvable instanceof YangUses) {
                                errorInfo = GROUPING_LINKER_ERROR;
                            } else if (resolvable instanceof YangIfFeature) {
                                errorInfo = FEATURE_LINKER_ERROR;
                            } else {
                                errorInfo = LEAFREF_LINKER_ERROR;
                            }
                            DataModelException dataModelException =
                                    new DataModelException(errorInfo);
                            dataModelException.setLine(getLineNumber());
                            dataModelException.setCharPosition(getCharPosition());
                            throw dataModelException;
                        }
                        break;
                    }
                    default: {
                        throw new DataModelException("Data Model Exception: Unsupported, linker state");
                    }

                }

            } else {
                throw new DataModelException(
                        "Data Model Exception: Entity to resolved is other than type/uses/if-feature/leafref");
            }
        }

    }

    /**
     * Adds the leafref type to the type, which has derived type referring to typedef with leafref type.
     */
    private void addDerivedRefTypeToRefTypeResolutionList() throws DataModelException {

        YangNode potentialAncestorWithReferredNode = getEntityToResolveInfo().getHolderOfEntityToResolve();

        // If holder is typedef return.
        if (potentialAncestorWithReferredNode instanceof YangTypeDef) {
            return;
        }

        // If entity is not type return.
        if (!(getEntityToResolveInfo().getEntityToResolve() instanceof YangType)) {
            return;
        }

        YangType yangType = (YangType) getEntityToResolveInfo().getEntityToResolve();

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

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

        /*
         * If the derived types referred type is not leaf ref return
         */
        if (derivedInfo.getEffectiveBuiltInType() != YangDataTypes.LEAFREF) {
            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 leaf ref info, delete all the info in
         * current type, but for resolution status as resolved. Copy the backed
         * up leaf ref to types extended info, create a leaf ref resolution info
         * using the current resolution info and add to leaf ref resolution
         * list.
         */
        YangLeafRef leafRefInTypeDef = (YangLeafRef) extendedInfo;
        yangType.resetYangType();

        yangType.setResolvableStatus(RESOLVED);
        yangType.setDataType(YangDataTypes.LEAFREF);
        yangType.setDataTypeName(LEAFREF);
        yangType.setDataTypeExtendedInfo(leafRefInTypeDef);
        leafRefInTypeDef.setResolvableStatus(UNRESOLVED);

        // Add resolution information to the list.
        YangResolutionInfoImpl resolutionInfoImpl = new YangResolutionInfoImpl<>(leafRefInTypeDef,
                potentialAncestorWithReferredNode, getLineNumber(), getCharPosition());
        getCurReferenceResolver().addToResolutionList(resolutionInfoImpl,
                ResolvableType.YANG_LEAFREF);
        getCurReferenceResolver().resolveSelfFileLinking(ResolvableType.YANG_LEAFREF);
    }

    /**
     * Resolves the current entity in the stack.
     */
    private void resolveTopOfStack(YangLinkingPhase linkingPhase)
            throws DataModelException {
        ((Resolvable) getCurrentEntityToResolveFromStack()).resolve();
        if (((Resolvable) getCurrentEntityToResolveFromStack()).getResolvableStatus() != INTRA_FILE_RESOLVED
                && ((Resolvable) getCurrentEntityToResolveFromStack()).getResolvableStatus() != UNDEFINED) {
            // Sets the resolution status in inside the type/uses/if-feature/leafref.
            ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(RESOLVED);
        }
    }

    /**
     * Resolves linking for a node child and siblings.
     *
     * @throws DataModelException data model error
     */
    private void linkTopOfStackReferenceUpdateStack()
            throws DataModelException {

        /*
         * 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) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
            return;
        }

        /**
         * Try to resolve the top of the stack and update partial resolved stack
         * if there is recursive references
         */
        YangNode potentialAncestorWithReferredNode = getPartialResolvedStack().peek()
                .getHolderOfEntityToResolve();

        if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
            resolveSelfFileLinkingForIfFeature(potentialAncestorWithReferredNode);
            return;
        } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
            resolveSelfFileLinkingForLeafref(potentialAncestorWithReferredNode);
            return;
        } else {

            /**
             * Traverse up in the ancestor tree to check if the referred node is
             * defined
             */
            while (potentialAncestorWithReferredNode != null) {

                /**
                 * Check for the referred node defined in a ancestor scope
                 */
                YangNode potentialReferredNode = potentialAncestorWithReferredNode.getChild();
                if (isReferredNodeInSiblingListProcessed(potentialReferredNode)) {
                    return;
                }

                potentialAncestorWithReferredNode = potentialAncestorWithReferredNode.getParent();
            }
        }

        /*
         * In case prefix is not present it's a candidate for inter-file
         * resolution via include list.
         */
        if (getRefPrefix() == null) {
            ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
        }
    }

    /**
     * Resolves self file linking for leafref.
     *
     * @param potentialAncestorWithReferredNode leafref holder node
     * @throws DataModelException a violation of data model rules
     */
    private void resolveSelfFileLinkingForLeafref(YangNode potentialAncestorWithReferredNode)
            throws DataModelException {

        YangNode ancestorWithTheReferredNode = potentialAncestorWithReferredNode;
        YangLeafRef leafref = (YangLeafRef) getCurrentEntityToResolveFromStack();
        boolean referredLeafFound = false;

        /*
         * Takes absolute path and takes the root node as module/sub-module,
         * then sends the list of nodes for finding the target leaf.
         */
        if (leafref.getPathType() == YangPathArgType.ABSOLUTE_PATH) {
            List<YangAtomicPath> atomicPathList = leafref.getAtomicPath();
            if (atomicPathList != null && !atomicPathList.isEmpty()) {
                Iterator<YangAtomicPath> listOfYangAtomicPath = atomicPathList.listIterator();
                if (getCurReferenceResolver() instanceof YangModule) {
                    YangModule rootNode = (YangModule) getCurReferenceResolver();
                    // Sends list of nodes for finding the target leaf.
                    referredLeafFound = isLeafReferenceFound(listOfYangAtomicPath, rootNode,
                            referredLeafFound, potentialAncestorWithReferredNode);
                } else if (getCurReferenceResolver() instanceof YangSubModule) {
                    YangSubModule rootNode = (YangSubModule) getCurReferenceResolver();
                    // Sends list of nodes for finding the target leaf.
                    referredLeafFound = isLeafReferenceFound(listOfYangAtomicPath, rootNode,
                            referredLeafFound, potentialAncestorWithReferredNode);
                }
            }
            /*
             * Takes relative path, goes to the parent node by using the
             * ancestor count and sends the list of nodes for finding the target
             * leaf.
             */
        } else if (leafref.getPathType() == YangPathArgType.RELATIVE_PATH) {
            YangRelativePath yangRelativePath = leafref.getRelativePath();
            int parentNodes = yangRelativePath.getAncestorNodeCount();
            List<YangAtomicPath> atomicPathList = yangRelativePath.getAtomicPathList();
            if (atomicPathList != null && !atomicPathList.isEmpty()) {
                Iterator<YangAtomicPath> listOfAtomicPath = atomicPathList.listIterator();
                // Gets the root node from ancestor count.
                YangNode rootparentNode = getRootNodeWithAncestorCount(parentNodes, ancestorWithTheReferredNode);
                // Sends list of nodes for finding the target leaf.
                referredLeafFound = isLeafReferenceFound(listOfAtomicPath, rootparentNode,
                        referredLeafFound, potentialAncestorWithReferredNode);
            }
        }
        if (referredLeafFound) {
            return;
        }
        /*
         * In case prefix is not present it's a candidate for inter-file
         * resolution via include list.
         */
        if (getRefPrefix() == null) {
            ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
        }
    }

    /**
     * Returns the root parent with respect to the ancestor count from leafref.
     *
     * @param ancestorCount count of node where parent node can be reached
     * @param currentParent current parent node
     * @return root node
     * @throws DataModelException a violation of data model rules
     */
    private YangNode getRootNodeWithAncestorCount(int ancestorCount, YangNode currentParent)
            throws DataModelException {

        int currentParentCount = 1;
        while (currentParentCount < ancestorCount) {
            if (currentParent.getParent() == null) {
                throw new DataModelException("YANG file error: The target node of leafref is invalid.");
            }
            currentParent = currentParent.getParent();
            currentParentCount = currentParentCount + 1;
        }
        return currentParent;
    }

    /**
     * Resolves self file linking for if-feature.
     *
     * @param potentialAncestorWithReferredNode if-feature holder node
     * @throws DataModelException DataModelException a violation of data model
     *                            rules
     */
    private void resolveSelfFileLinkingForIfFeature(YangNode potentialAncestorWithReferredNode)
            throws DataModelException {

        YangFeatureHolder featureHolder = getFeatureHolder(potentialAncestorWithReferredNode);
        YangNode potentialReferredNode = (YangNode) featureHolder;
        if (isReferredNode(potentialReferredNode)) {

            // Adds reference link of entity to the node under resolution.
            addReferredEntityLink(potentialReferredNode, LINKED);

            /**
             * resolve the reference and update the partial resolution stack
             * with any further recursive references
             */
            addUnresolvedRecursiveReferenceToStack(potentialReferredNode);
            return;
        }

        /*
         * In case prefix is not present it's a candidate for inter-file
         * resolution via include list.
         */
        if (getRefPrefix() == null) {
            ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
        }
    }

    /**
     * Returns the status of the referred leaf/leaf-list found for leafref.
     *
     * @param listOfYangAtomicPath list of atomic paths
     * @param ancestorWithTheReferredNode the parent node of leafref
     * @param referredLeafFound status of referred leaf/leaf-list
     * @param potentialAncestorWithReferredNode holder of the leafref leaf
     * @return status of referred leaf
     * @throws DataModelException a violation of data model rules
     */
    private boolean isLeafReferenceFound(Iterator<YangAtomicPath> listOfYangAtomicPath,
            YangNode ancestorWithTheReferredNode, boolean referredLeafFound, YangNode potentialAncestorWithReferredNode)
            throws DataModelException {

        while (listOfYangAtomicPath.hasNext()) {
            YangAtomicPath atomicPath = listOfYangAtomicPath.next();
            String nodeName = atomicPath.getNodeIdentifier().getName();

            // When child is not present, only leaf/leaf-list is available in the node.
            if (ancestorWithTheReferredNode.getChild() == null) {
                referredLeafFound = isReferredLeafOrLeafListFound(ancestorWithTheReferredNode, nodeName, (T) LINKED);
                break;
            }
            ancestorWithTheReferredNode = ancestorWithTheReferredNode.getChild();

            // Checks all the siblings under the node and returns the matched node.
            YangNode nodeFound = isReferredNodeInSiblingProcessedForLeafref(ancestorWithTheReferredNode, nodeName);

            // When node is not found in all the siblings, leaf-list may be the node we have to find.
            if (nodeFound == null) {
                referredLeafFound = isReferredLeafOrLeafListFound(ancestorWithTheReferredNode.getParent(), nodeName,
                        (T) LINKED);
            } else {
                ancestorWithTheReferredNode = nodeFound;

                // For the node check if path predicate is present and fill its values.
                List<YangPathPredicate> pathPredicateList = atomicPath.getPathPredicatesList();
                if (pathPredicateList != null && !pathPredicateList.isEmpty()) {
                    Iterator<YangPathPredicate> listOfYangPathPredicate = pathPredicateList.listIterator();
                    fillPathPredicatesForTheNode(ancestorWithTheReferredNode, listOfYangPathPredicate,
                            potentialAncestorWithReferredNode);
                }
            }

            // If leaf is also not found and node is also not found return the status as false.
            if (!referredLeafFound && nodeFound == null) {
                break;
            }
        }
        return referredLeafFound;
    }

    /**
     * Fills the referred leaf or leaf-list inside the path predicates.
     *
     * @param ancestorWithTheReferredNode the actual node where YANG list will be present
     * @param listOfYangPathPredicate the path predicates present for the node
     * @param potentialAncestorWithReferredNode the current leaf node parent
     * @throws DataModelException a violation of data model rules
     */
    private void fillPathPredicatesForTheNode(YangNode ancestorWithTheReferredNode,
            Iterator<YangPathPredicate> listOfYangPathPredicate, YangNode potentialAncestorWithReferredNode)
            throws DataModelException {

        while (listOfYangPathPredicate.hasNext()) {
            if (!(ancestorWithTheReferredNode instanceof YangList)) {
                throw new DataModelException("YANG file error: The path predicates are applicable only for list");
            }
            YangPathPredicate pathPredicate = listOfYangPathPredicate.next();
            YangNodeIdentifier leftNode = pathPredicate.getNodeIdentifier();
            YangRelativePath relativePath = pathPredicate.getRightRelativePath();

            // Checks that the left axis is filled in the path predicate.
            boolean isLeftLeafOrLeafListSetForLeftAxis = getLeftLeafOrLeafListInPredicate(
                    (YangList) ancestorWithTheReferredNode, pathPredicate, leftNode);
            if (!isLeftLeafOrLeafListSetForLeftAxis) {
                throw new DataModelException(
                        "YANG file error: The path predicate is not referring to an existing leaf/leaflist");
            }
            int parentNodes = relativePath.getAncestorNodeCount();

            // Finds the root node for the right relative path.
            YangNode rootParentNode = getRootNodeWithAncestorCount(parentNodes, potentialAncestorWithReferredNode);

            // Finds the leaf/leaf-list from the right side relative path.
            resolveRightAxisNodeInPathPredicate(relativePath, rootParentNode, pathPredicate);
        }
    }

    /**
     * Resolves the right axis node in the path predicate.
     *
     * @param relativePath the relative path in the path predicate
     * @param rootParentNode parent node from where the node has to be found
     * @param pathPredicate data tree reference in YANG list
     * @throws DataModelException a violation of data model rules
     */
    private void resolveRightAxisNodeInPathPredicate(YangRelativePath relativePath, YangNode rootParentNode,
            YangPathPredicate pathPredicate) throws DataModelException {

        List<YangAtomicPath> absolutePathList = relativePath.getAtomicPathList();
        if (absolutePathList != null && !absolutePathList.isEmpty()) {
            Iterator<YangAtomicPath> listOfYangAtomicPathForRightRelative = absolutePathList.listIterator();
            while (listOfYangAtomicPathForRightRelative.hasNext()) {
                boolean isRightAxisNodeFound = false;
                YangAtomicPath absolutePathInPredicate = listOfYangAtomicPathForRightRelative.next();
                String nodeNameInAtomicPath = absolutePathInPredicate.getNodeIdentifier().getName();

                // When child is not there check the leaf/leaf-list.
                if (rootParentNode.getChild() == null) {
                    isRightAxisNodeFound = isReferredLeafOrLeafListFound(rootParentNode,
                            nodeNameInAtomicPath, (T) pathPredicate);
                    if (!isRightAxisNodeFound) {
                        throw new DataModelException(
                                "YANG file error: The path predicates is not referring to an existing leaf/leaflist");
                    }
                    break;
                }
                rootParentNode = rootParentNode.getChild();
                YangNode nodeFoundInTheRelativePath = isReferredNodeInSiblingProcessedForLeafref(
                        rootParentNode, nodeNameInAtomicPath);

                if (nodeFoundInTheRelativePath == null) {

                    // When node is not found check the leaf/leaf-list.
                    isRightAxisNodeFound = isReferredLeafOrLeafListFound(rootParentNode.getParent(),
                            nodeNameInAtomicPath, (T) pathPredicate);
                } else {
                    rootParentNode = nodeFoundInTheRelativePath;
                }
                if (!isRightAxisNodeFound && nodeFoundInTheRelativePath == null) {
                    throw new DataModelException(
                            "YANG file error: The path predicates is not referring to an existing leaf/leaflist");
                }
            }
        }
    }

    /**
     * Returns the status, if referred leaf/leaf-list is found.
     *
     * @param ancestorWithTheReferredNode the parent node of leaf/leaf-list
     * @param nodeName the name of the leaf/leaf-list
     * @param statusOrPathPredicate the status to be set for the leaf-ref or the path predicate
     * @return status of the target node is found
     * @throws DataModelException a violation of data model rules
     */
    private boolean isReferredLeafOrLeafListFound(YangNode ancestorWithTheReferredNode, String nodeName,
            T statusOrPathPredicate) throws DataModelException {

        if (!(ancestorWithTheReferredNode instanceof YangLeavesHolder)) {
            throw new DataModelException("Yang file error: The target node of leafref is invalid.");
        }
        YangLeavesHolder leavesHolder = (YangLeavesHolder) ancestorWithTheReferredNode;
        if (leavesHolder.getListOfLeaf() != null) {
            Iterator<YangLeaf> yangLeavesList = leavesHolder.getListOfLeaf().listIterator();
            while (yangLeavesList.hasNext()) {
                YangLeaf yangleaf = yangLeavesList.next();
                if (yangleaf.getName().contentEquals(nodeName)) {
                    if (statusOrPathPredicate instanceof ResolvableStatus) {
                        ResolvableStatus status = (ResolvableStatus) statusOrPathPredicate;

                        // Sets the referred leaf to YANG leafref.
                        ((YangLeafRef) getCurrentEntityToResolveFromStack()).setReferredLeafOrLeafList(yangleaf);

                        // Adds reference link of entity to the node under resolution.
                        addReferredEntityLink(ancestorWithTheReferredNode, status);
                        addUnResolvedLeafRefTypeToStack((T) yangleaf, ancestorWithTheReferredNode);
                        return true;
                    } else if (statusOrPathPredicate instanceof YangPathPredicate) {
                        YangPathPredicate pathPredicate = (YangPathPredicate) statusOrPathPredicate;

                        // Sets the right axis node.
                        pathPredicate.setRightAxisNode(yangleaf);
                        return true;
                    } else {
                        throw new DataModelException("YANG file error: The target node of leafref is invalid.");
                    }
                }
            }
        }
        if (leavesHolder.getListOfLeafList() != null) {
            Iterator<YangLeafList> yangLeafListList = leavesHolder.getListOfLeafList().listIterator();
            while (yangLeafListList.hasNext()) {
                YangLeafList yangLeaflist = yangLeafListList.next();
                if (yangLeaflist.getName().contentEquals(nodeName)) {
                    if (statusOrPathPredicate instanceof ResolvableStatus) {
                        ResolvableStatus status = (ResolvableStatus) statusOrPathPredicate;

                        // Sets the referred leaf-list to YANG leafref.
                        ((YangLeafRef) getCurrentEntityToResolveFromStack()).setReferredLeafOrLeafList(yangLeaflist);

                        // Adds reference link of entity to the node under resolution.
                        addReferredEntityLink(ancestorWithTheReferredNode, status);
                        addUnResolvedLeafRefTypeToStack((T) yangLeaflist, ancestorWithTheReferredNode);
                        return true;
                    } else if (statusOrPathPredicate instanceof YangPathPredicate) {
                        YangPathPredicate pathPredicate = (YangPathPredicate) statusOrPathPredicate;
                        pathPredicate.setRightAxisNode(yangLeaflist);
                        return true;
                    } else {
                        throw new DataModelException("YANG file error: The target node of leafref is invalid.");
                    }
                }
            }
        }
        return false;
    }

    /**
     * Adds the unresolved constructs to stack which has to be resolved for leafref.
     *
     * @param yangleafOrLeafList YANG leaf or leaf list which holds the type
     * @param ancestorWithTheReferredNode holder of the YANG leaf or leaf list
     */
    private void addUnResolvedLeafRefTypeToStack(T yangleafOrLeafList, YangNode ancestorWithTheReferredNode) {

        YangType referredTypeInLeafOrLeafList;
        if (yangleafOrLeafList instanceof YangLeaf) {
            YangLeaf leaf = (YangLeaf) yangleafOrLeafList;
            referredTypeInLeafOrLeafList = leaf.getDataType();
            if (referredTypeInLeafOrLeafList.getDataType() == YangDataTypes.LEAFREF) {
                YangEntityToResolveInfoImpl<YangLeafRef<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
                unResolvedEntityInfo.setEntityToResolve((YangLeafRef<?>) leaf.getDataType().getDataTypeExtendedInfo());
                unResolvedEntityInfo.setHolderOfEntityToResolve(ancestorWithTheReferredNode);
                addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
            } else if (referredTypeInLeafOrLeafList.getDataType() == YangDataTypes.DERIVED) {
                YangEntityToResolveInfoImpl<YangType<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
                unResolvedEntityInfo.setEntityToResolve(referredTypeInLeafOrLeafList);
                unResolvedEntityInfo.setHolderOfEntityToResolve(ancestorWithTheReferredNode);
                addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
            }
        } else {
            YangLeafList leafList = (YangLeafList) yangleafOrLeafList;
            referredTypeInLeafOrLeafList = leafList.getDataType();
            if (referredTypeInLeafOrLeafList.getDataType() == YangDataTypes.LEAFREF) {
                YangEntityToResolveInfoImpl<YangLeafRef<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
                unResolvedEntityInfo
                        .setEntityToResolve((YangLeafRef<?>) leafList.getDataType().getDataTypeExtendedInfo());
                unResolvedEntityInfo.setHolderOfEntityToResolve(ancestorWithTheReferredNode);
                addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
            } else if (referredTypeInLeafOrLeafList.getDataType() == YangDataTypes.DERIVED) {
                YangEntityToResolveInfoImpl<YangType<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
                unResolvedEntityInfo.setEntityToResolve(referredTypeInLeafOrLeafList);
                unResolvedEntityInfo.setHolderOfEntityToResolve(ancestorWithTheReferredNode);
                addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
            }
        }
    }

    /**
     * Returns true if referred leaf/leaf-list is found in a particular node. This is for path in path predicate.
     *
     * @param listForLeaf list node where referred leaf is found
     * @param pathPredicate path predicate instance where the value of nodes to be found are available
     * @param leftNode node identifier of the left side parameter in path predicate
     * @return status of the leaf/leaf-list found
     */
    private boolean getLeftLeafOrLeafListInPredicate(YangList listForLeaf, YangPathPredicate pathPredicate,
            YangNodeIdentifier leftNode) {

        if (listForLeaf.getListOfLeaf() != null) {
            Iterator<YangLeaf> yangLeavesUnderList = listForLeaf.getListOfLeaf().listIterator();
            while (yangLeavesUnderList.hasNext()) {
                YangLeaf yangleafUnderList = yangLeavesUnderList.next();
                if (yangleafUnderList.getName().contentEquals(leftNode.getName())) {
                    pathPredicate.setLeftAxisNode(yangleafUnderList);
                    return true;
                }
            }
        }
        if (listForLeaf.getListOfLeafList() != null) {
            Iterator<YangLeafList> yangLeavesListUnderList = listForLeaf.getListOfLeafList().listIterator();
            while (yangLeavesListUnderList.hasNext()) {
                YangLeafList yangleafListUnderList = yangLeavesListUnderList.next();
                if (yangleafListUnderList.getName().contentEquals(leftNode.getName())) {
                    pathPredicate.setLeftAxisNode(yangleafListUnderList);
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Returns feature holder(module/sub-module node) .
     *
     * @param potentialAncestorWithReferredNode if-feature holder node
     */
    private YangFeatureHolder getFeatureHolder(YangNode potentialAncestorWithReferredNode) {
        while (potentialAncestorWithReferredNode != null) {
            if (potentialAncestorWithReferredNode instanceof YangFeatureHolder) {
                return (YangFeatureHolder) potentialAncestorWithReferredNode;
            }
            potentialAncestorWithReferredNode = potentialAncestorWithReferredNode.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(getCurReferenceResolver().getPrefix());
    }

    /**
     * Checks for the referred parent node for the leafref path.
     *
     * @param potentialReferredNode potential referred node
     * @return the reffered parent node of leaf/leaf-list
     * @throws DataModelException data model errors
     */
    private YangNode isReferredNodeInSiblingProcessedForLeafref(YangNode potentialReferredNode, String referredNodeName)
            throws DataModelException {

        while (potentialReferredNode != null) {
            if (potentialReferredNode instanceof YangInput) {
                if (referredNodeName.equalsIgnoreCase(INPUT)) {
                    return potentialReferredNode;
                }
            } else if (potentialReferredNode instanceof YangOutput) {
                if (referredNodeName.equalsIgnoreCase(OUTPUT)) {
                    return potentialReferredNode;
                }
            }
            // Check if the potential referred node is the actual referred node
            if (isReferredNodeForLeafref(potentialReferredNode, referredNodeName)) {
                if (potentialReferredNode instanceof YangGrouping || potentialReferredNode instanceof YangTypeDef) {
                    if (potentialReferredNode.getParent() instanceof YangRpc) {
                        potentialReferredNode = potentialReferredNode.getNextSibling();
                    } else {
                        throw new DataModelException("YANG file error: The target node of leafref is invalid.");
                    }
                }
                return potentialReferredNode;
            }
            potentialReferredNode = potentialReferredNode.getNextSibling();
        }
        return null;
    }

    /**
     * Checks if the current reference node name and the name in the path are equal.
     *
     * @param currentReferredNode the node where the reference is pointed
     * @param nameOfNodeinPath name of the node in the path
     * @return status of the match between the name
     * @throws DataModelException a violation of data model rules
     */
    private boolean isReferredNodeForLeafref(YangNode currentReferredNode, String nameOfNodeinPath)
            throws DataModelException {

        if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
            /*
             * Check if name of node name matches with the current reference
             * node.
             */
            return currentReferredNode.getName().contentEquals(nameOfNodeinPath);
        } else {
            throw new DataModelException("Data Model Exception: Entity to resolved is other than leafref");
        }
    }

    /**
     * Checks for the referred node defined in a ancestor scope.
     *
     * @param potentialReferredNode 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 potentialReferredNode)
            throws DataModelException {
        while (potentialReferredNode != null) {

            // Check if the potential referred node is the actual referred node
            if (isReferredNode(potentialReferredNode)) {

                // Adds reference link of entity to the node under resolution.
                addReferredEntityLink(potentialReferredNode, LINKED);

                /**
                 * resolve the reference and update the partial resolution stack
                 * with any further recursive references
                 */
                addUnresolvedRecursiveReferenceToStack(potentialReferredNode);

                /*
                 * return true, since the reference is linked and any recursive
                 * unresolved references is added to the stack
                 */
                return true;
            }

            potentialReferredNode = potentialReferredNode.getNextSibling();
        }
        return false;
    }

    /**
     * Checks if the potential referred node is the actual referred node.
     *
     * @param potentialReferredNode 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 potentialReferredNode)
            throws DataModelException {
        if (getCurrentEntityToResolveFromStack() instanceof YangType) {
            if (potentialReferredNode instanceof YangTypeDef) {
                /*
                 * Check if name of node name matches with the entity being
                 * resolved
                 */
                return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
            }
        } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
            if (potentialReferredNode instanceof YangGrouping) {
                /*
                 * Check if name of node name matches with the entity being
                 * resolved
                 */
                return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
            }
        } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
            if (potentialReferredNode instanceof YangFeatureHolder) {
                /*
                 * Check if name of node name matches with the entity being
                 * resolved
                 */
                return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
            }
        } else {
            throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
        }
        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 {
        if (getCurrentEntityToResolveFromStack() instanceof YangType) {
            if (node.getName().contentEquals(
                    ((YangType<?>) getCurrentEntityToResolveFromStack())
                            .getDataTypeName())) {
                return true;
            }
        } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
            if (node.getName().contentEquals(
                    ((YangUses) getCurrentEntityToResolveFromStack()).getName())) {
                return true;
            }
        } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
            return isFeatureDefinedInNode(node);
        } else {
            throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
        }
        return false;
    }

    private boolean isFeatureDefinedInNode(YangNode node) throws DataModelException {
        YangNodeIdentifier ifFeature = ((YangIfFeature) getCurrentEntityToResolveFromStack()).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) getCurrentEntityToResolveFromStack()).setReferredFeature(feature);
                    ((YangIfFeature) getCurrentEntityToResolveFromStack()).setReferredFeatureHolder(node);
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Adds reference of grouping/typedef in uses/type.
     *
     * @param referredNode grouping/typedef node being referred
     * @param linkedStatus linked status if success.
     * @throws DataModelException a violation of data model rules
     */
    private void addReferredEntityLink(YangNode referredNode, ResolvableStatus linkedStatus)
            throws DataModelException {
        if (getCurrentEntityToResolveFromStack() instanceof YangType) {
            YangDerivedInfo<?> derivedInfo = (YangDerivedInfo<?>) ((YangType<?>) getCurrentEntityToResolveFromStack())
                    .getDataTypeExtendedInfo();
            derivedInfo.setReferredTypeDef((YangTypeDef) referredNode);
        } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
            ((YangUses) getCurrentEntityToResolveFromStack())
                    .setRefGroup((YangGrouping) referredNode);
        } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
            // do nothing , referred node is already set
        } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
            // do nothing , referred node is already set
        } else {
            throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
        }

        // Sets the resolution status in inside the type/uses.
        ((Resolvable) getCurrentEntityToResolveFromStack()).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 referredNode grouping/typedef node
     * @throws DataModelException a violation of data model rules
     */
    private void addUnresolvedRecursiveReferenceToStack(YangNode referredNode)
            throws DataModelException {
        if (getCurrentEntityToResolveFromStack() instanceof YangType) {
            /*
             * Checks if typedef type is derived
             */
            if (((YangTypeDef) referredNode).getTypeDefBaseType().getDataType() == YangDataTypes.DERIVED) {

                YangEntityToResolveInfoImpl<YangType<?>> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
                unResolvedEntityInfo.setEntityToResolve(((YangTypeDef) referredNode)
                        .getTypeDefBaseType());
                unResolvedEntityInfo.setHolderOfEntityToResolve(referredNode);
                addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
            }

        } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
            /*
             * Search if the grouping has any un resolved uses child, if so
             * return true, else return false.
             */
            addUnResolvedUsesToStack(referredNode);
        } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
            addUnResolvedIfFeatureToStack(referredNode);
        } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
            // do nothing , referred node is already set
            throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
        }
    }

    /**
     * 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.
         */
        YangNode curNode = node.getChild();
        while (curNode != null) {
            if (curNode instanceof YangUses) {
                YangEntityToResolveInfoImpl<YangUses> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
                unResolvedEntityInfo.setEntityToResolve((YangUses) curNode);
                unResolvedEntityInfo.setHolderOfEntityToResolve(node);
                addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);

            }
            curNode = curNode.getNextSibling();
        }
    }

    /**
     * Returns if there is any unresolved if-feature in feature.
     *
     * @param node module/submodule node
     */
    private void addUnResolvedIfFeatureToStack(YangNode node) {
        YangFeature refFeature = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getReferredFeature();
        List<YangIfFeature> ifFeatureList = refFeature.getIfFeatureList();
        if (ifFeatureList != null && !ifFeatureList.isEmpty()) {
            Iterator<YangIfFeature> ifFeatureIterator = ifFeatureList.iterator();
            while (ifFeatureIterator.hasNext()) {
                YangIfFeature ifFeature = ifFeatureIterator.next();
                YangEntityToResolveInfo<YangIfFeature> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
                unResolvedEntityInfo.setEntityToResolve(ifFeature);
                unResolvedEntityInfo.setHolderOfEntityToResolve(node);
                addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
            }
        }
    }

    /**
     * Returns stack of YANG type with partially resolved YANG construct
     * hierarchy.
     *
     * @return partial resolved YANG construct stack
     */
    private Stack<YangEntityToResolveInfoImpl<T>> getPartialResolvedStack() {
        return partialResolvedStack;
    }

    /**
     * Sets stack of YANG type with partially resolved YANG construct hierarchy.
     *
     * @param partialResolvedStack partial resolved YANG construct stack
     */
    private void setPartialResolvedStack(Stack<YangEntityToResolveInfoImpl<T>> partialResolvedStack) {
        this.partialResolvedStack = partialResolvedStack;
    }

    /**
     * Sets stack of YANG type with partially resolved YANG construct hierarchy.
     *
     * @param partialResolvedInfo partial resolved YANG construct stack
     */
    private void addInPartialResolvedStack(YangEntityToResolveInfoImpl<T> partialResolvedInfo) {
        getPartialResolvedStack().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 getCurrentEntityToResolveFromStack() {
        return getPartialResolvedStack().peek().getEntityToResolve();
    }

    @Override
    public YangEntityToResolveInfoImpl<T> getEntityToResolveInfo() {
        return entityToResolveInfo;
    }

    /**
     * Sets information about the entity that needs to be resolved.
     *
     * @param entityToResolveInfo information about the entity that needs to be
     *                            resolved
     */
    private void setEntityToResolveInfo(YangEntityToResolveInfoImpl<T> entityToResolveInfo) {
        this.entityToResolveInfo = entityToResolveInfo;
    }

    @Override
    public int getLineNumber() {
        return lineNumber;
    }

    @Override
    public int getCharPosition() {
        return charPosition;
    }

    @Override
    public void setLineNumber(int lineNumber) {
        this.lineNumber = lineNumber;
    }

    @Override
    public void setCharPosition(int charPositionInLine) {
        this.charPosition = charPositionInLine;
    }

    /**
     * Returns current module/sub-module reference, will be used in inter-file/
     * inter-jar scenario to get the import/include list.
     *
     * @return current module/sub-module reference
     */
    private YangReferenceResolver getCurReferenceResolver() {
        return curReferenceResolver;
    }

    /**
     * Sets current module/sub-module reference, will be used in inter-file/
     * inter-jar scenario to get the import/include list.
     *
     * @param curReferenceResolver current module/sub-module reference
     */
    private void setCurReferenceResolver(YangReferenceResolver curReferenceResolver) {
        this.curReferenceResolver = curReferenceResolver;
    }

    @Override
    public void linkInterFile(YangReferenceResolver dataModelRootNode)
            throws DataModelException {

        setCurReferenceResolver(dataModelRootNode);

        // Current node to resolve, it can be a YANG type or YANG uses.
        T entityToResolve = getEntityToResolveInfo().getEntityToResolve();

        // Check if linking is already done
        if (entityToResolve instanceof Resolvable) {
            Resolvable resolvable = (Resolvable) entityToResolve;
            if (resolvable.getResolvableStatus() == RESOLVED) {
                return;
            }
        } else {
            throw new DataModelException("Data Model Exception: Entity to resolved is not Resolvable");
        }

        // Push the initial entity to resolve in stack.
        addInPartialResolvedStack(getEntityToResolveInfo());

        // Inter file linking and resolution.
        linkInterFileAndResolve();

        // Resolve the derived types having leafref.
        addDerivedRefTypeToRefTypeResolutionList();
    }

    /**
     * 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 {
        String refPrefix;
        if (getCurrentEntityToResolveFromStack() instanceof YangType) {
            refPrefix = ((YangType<?>) getCurrentEntityToResolveFromStack()).getPrefix();
        } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
            refPrefix = ((YangUses) getCurrentEntityToResolveFromStack()).getPrefix();
        } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
            refPrefix = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getPrefix();
        } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
            refPrefix = refPrefixForLeafRef();
        } else {
            throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
        }
        return refPrefix;
    }

    /**
     * Returns the referenced prefix for leafref under resolution.
     *
     * @return referenced prefix of leafref under resolution
     */
    private String refPrefixForLeafRef() {

        String refPrefix;
        if (((YangLeafRef) getCurrentEntityToResolveFromStack()).getPathType() == YangPathArgType.ABSOLUTE_PATH) {
            List<YangAtomicPath> theList = ((YangLeafRef) getCurrentEntityToResolveFromStack()).getAtomicPath();
            YangAtomicPath absPath = theList.iterator().next();
            refPrefix = absPath.getNodeIdentifier().getPrefix();
        } else {
            YangRelativePath relativePath = ((YangLeafRef) getCurrentEntityToResolveFromStack()).getRelativePath();
            List<YangAtomicPath> theList = relativePath.getAtomicPathList();
            YangAtomicPath absPath = theList.iterator().next();
            refPrefix = absPath.getNodeIdentifier().getPrefix();
        }
        return refPrefix;
    }

    /**
     * Performs inter file linking and resolution.
     *
     * @throws DataModelException a violation in data model rule
     */
    private void linkInterFileAndResolve()
            throws DataModelException {

        while (getPartialResolvedStack().size() != 0) {

            // Current node to resolve, it can be a YANG type or YANG uses.
            T entityToResolve = getCurrentEntityToResolveFromStack();
            // 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
                         */
                        getPartialResolvedStack().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(INTER_FILE);
                        getPartialResolvedStack().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.
                         */
                        getPartialResolvedStack().pop();
                        break;
                    }

                    default: {
                        throw new DataModelException("Data Model Exception: Unsupported, linker state");
                    }

                }

            } else {
                throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
            }

        }

    }

    /**
     * Links the top of the stack if it's inter-file and update stack.
     *
     * @throws DataModelException data model error
     */
    private void linkInterFileTopOfStackRefUpdateStack()
            throws DataModelException {

        /*
         * 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(getCurReferenceResolver().getPrefix())) {
                if (resolveWithImport()) {
                    return;
                }
            } else {
                if (resolveWithInclude()) {
                    return;
                }
            }

            if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
                ((YangIfFeature) getCurrentEntityToResolveFromStack()).setResolvableStatus(UNDEFINED);
                return;
            }
            // If current entity is still not resolved, then
            // linking/resolution has failed.
            String errorInfo;
            if (getCurrentEntityToResolveFromStack() instanceof YangType) {
                errorInfo = TYPEDEF_LINKER_ERROR;
            } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
                errorInfo = GROUPING_LINKER_ERROR;
            } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
                errorInfo = FEATURE_LINKER_ERROR;
            } else {
                errorInfo = LEAFREF_LINKER_ERROR;
            }
            DataModelException dataModelException = new DataModelException(errorInfo);
            dataModelException.setLine(getLineNumber());
            dataModelException.setCharPosition(getCharPosition());
            throw dataModelException;
        } else {
            /*
             * If referred node is already linked, then just change the status
             * and push to the stack.
             */
            if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
                ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTER_FILE_LINKED);
                if (referredNode instanceof YangLeaf) {
                    YangLeaf yangleaf = (YangLeaf) referredNode;
                    addUnResolvedLeafRefTypeToStack((T) yangleaf, (YangNode) yangleaf.getContainedIn());
                } else if (referredNode instanceof YangLeafList) {
                    YangLeafList yangLeafList = (YangLeafList) referredNode;
                    addUnResolvedLeafRefTypeToStack((T) yangLeafList, (YangNode) yangLeafList.getContainedIn());
                }
            } else {
                ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTER_FILE_LINKED);
                addUnresolvedRecursiveReferenceToStack((YangNode) referredNode);
            }
        }
    }

    /**
     * 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 : getCurReferenceResolver().getIncludeList()) {
            YangNode linkedNode = null;
            if (getCurrentEntityToResolveFromStack() instanceof YangType) {
                linkedNode = findRefTypedef(yangInclude.getIncludedNode());
            } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
                linkedNode = findRefGrouping(yangInclude.getIncludedNode());
            } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
                linkedNode = findRefFeature(yangInclude.getIncludedNode());
            } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
                boolean referredNode = findRefLeaf(yangInclude.getIncludedNode());
                /*
                 * Update the current reference resolver to external
                 * module/sub-module containing the referred typedef/grouping.
                 */
                setCurReferenceResolver((YangReferenceResolver) yangInclude.getIncludedNode());

                return referredNode;
            }
            if (linkedNode != null) {
                // Add the link to external entity.
                addReferredEntityLink(linkedNode, INTER_FILE_LINKED);
                /*
                 * Update the current reference resolver to external
                 * module/sub-module containing the referred typedef/grouping.
                 */
                setCurReferenceResolver((YangReferenceResolver) yangInclude.getIncludedNode());
                // Add the type/uses of referred typedef/grouping to the stack.
                addUnresolvedRecursiveReferenceToStack(linkedNode);
                return true;
            }
        }
        // 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 : getCurReferenceResolver().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 = null;
                if (getCurrentEntityToResolveFromStack() instanceof YangType) {
                    linkedNode = findRefTypedef(yangImport.getImportedNode());
                } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
                    linkedNode = findRefGrouping(yangImport.getImportedNode());
                } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
                    linkedNode = findRefFeature(yangImport.getImportedNode());
                } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
                    boolean referredNode = findRefLeaf(yangImport.getImportedNode());
                    /*
                     * Update the current reference resolver to external
                     * module/sub-module containing the referred
                     * typedef/grouping.
                     */
                    setCurReferenceResolver((YangReferenceResolver) yangImport.getImportedNode());

                    return referredNode;
                }
                if (linkedNode != null) {
                    // Add the link to external entity.
                    addReferredEntityLink(linkedNode, INTER_FILE_LINKED);
                    /*
                     * Update the current reference resolver to external
                     * module/sub-module containing the referred
                     * typedef/grouping.
                     */
                    setCurReferenceResolver((YangReferenceResolver) yangImport.getImportedNode());
                    // Add the type/uses of referred typedef/grouping to the
                    // stack.
                    addUnresolvedRecursiveReferenceToStack(linkedNode);
                    return true;
                }
                /*
                 * 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;
    }

    /**
     * Returns the status of referred leaf.
     *
     * @param importedNode the root node from a YANG file
     * @return status of the referred leaf
     * @throws DataModelException
     */
    private boolean findRefLeaf(YangNode importedNode) throws DataModelException {

        boolean isReferredNodeFound = false;
        List<YangAtomicPath> absolutePathList = ((YangLeafRef) getCurrentEntityToResolveFromStack())
                .getAtomicPath();
        if (absolutePathList != null && !absolutePathList.isEmpty()) {
            Iterator<YangAtomicPath> listOfYangAtomicPath = absolutePathList.listIterator();

            while (listOfYangAtomicPath.hasNext()) {
                YangAtomicPath absolutePath = listOfYangAtomicPath.next();
                String nodeName = absolutePath.getNodeIdentifier().getName();

                if (importedNode.getChild() == null) {
                    isReferredNodeFound = isReferredLeafOrLeafListFound(importedNode, nodeName, (T) INTER_FILE_LINKED);
                    break;
                }
                importedNode = importedNode.getChild();

                YangNode nodeFound = isReferredNodeInSiblingProcessedForLeafref(importedNode, nodeName);
                if (nodeFound == null) {
                    isReferredNodeFound = isReferredLeafOrLeafListFound(importedNode.getParent(), nodeName,
                            (T) INTER_FILE_LINKED);
                } else {
                    importedNode = nodeFound;
                }
            }
        }
        // TODO: Path predicates filling for inter file has to be done.
        return isReferredNodeFound;
    }

    /**
     * Returns referred typedef/grouping node.
     *
     * @return referred typedef/grouping node
     * @throws DataModelException a violation in data model rule
     */
    private T getRefNode()
            throws DataModelException {
        if (getCurrentEntityToResolveFromStack() instanceof YangType) {
            YangDerivedInfo<?> derivedInfo = (YangDerivedInfo<?>) ((YangType<?>) getCurrentEntityToResolveFromStack())
                    .getDataTypeExtendedInfo();
            return (T) derivedInfo.getReferredTypeDef();
        } else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
            return (T) ((YangUses) getCurrentEntityToResolveFromStack()).getRefGroup();
        } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
            return (T) ((YangIfFeature) getCurrentEntityToResolveFromStack()).getReferredFeatureHolder();
        } else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
            return (T) ((YangLeafRef) getCurrentEntityToResolveFromStack()).getReferredLeafOrLeafList();
        } else {
            throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
        }
    }

    /**
     * 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) getCurrentEntityToResolveFromStack()).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) {
        YangNodeIdentifier ifFeature = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getName();
        List<YangFeature> featureList = ((YangFeatureHolder) refNode).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) getCurrentEntityToResolveFromStack()).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) getCurrentEntityToResolveFromStack()).getDataTypeName())) {
                    return tmpNode;
                }
            }
            tmpNode = tmpNode.getNextSibling();
        }
        return null;
    }
}
