/*
 * 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.yms.app.ytb;

import org.onosproject.yangutils.datamodel.YangAugment;
import org.onosproject.yangutils.datamodel.YangAugmentableNode;
import org.onosproject.yangutils.datamodel.YangCase;
import org.onosproject.yangutils.datamodel.YangChoice;
import org.onosproject.yangutils.datamodel.YangDerivedInfo;
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.YangNode;
import org.onosproject.yangutils.datamodel.YangSchemaNode;
import org.onosproject.yangutils.datamodel.YangSchemaNodeIdentifier;
import org.onosproject.yangutils.datamodel.YangType;
import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
import org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes;
import org.onosproject.yms.app.utils.TraversalType;
import org.onosproject.yms.app.ydt.YdtExtendedBuilder;
import org.onosproject.yms.app.ydt.YdtExtendedContext;
import org.onosproject.yms.app.ysr.YangSchemaRegistry;
import org.onosproject.yms.ydt.YdtContextOperationType;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.EMPTY;
import static org.onosproject.yangutils.utils.io.impl.YangIoUtils.getCapitalCase;
import static org.onosproject.yms.app.utils.TraversalType.CHILD;
import static org.onosproject.yms.app.utils.TraversalType.PARENT;
import static org.onosproject.yms.app.utils.TraversalType.ROOT;
import static org.onosproject.yms.app.utils.TraversalType.SIBLING;
import static org.onosproject.yms.app.ydt.AppType.YTB;
import static org.onosproject.yms.app.ytb.YtbUtil.PERIOD;
import static org.onosproject.yms.app.ytb.YtbUtil.STR_NULL;
import static org.onosproject.yms.app.ytb.YtbUtil.getAttributeFromInheritance;
import static org.onosproject.yms.app.ytb.YtbUtil.getAttributeOfObject;
import static org.onosproject.yms.app.ytb.YtbUtil.getClassLoaderForAugment;
import static org.onosproject.yms.app.ytb.YtbUtil.getInterfaceClassFromImplClass;
import static org.onosproject.yms.app.ytb.YtbUtil.getJavaName;
import static org.onosproject.yms.app.ytb.YtbUtil.getNodeOpType;
import static org.onosproject.yms.app.ytb.YtbUtil.getOpTypeName;
import static org.onosproject.yms.app.ytb.YtbUtil.getParentObjectOfNode;
import static org.onosproject.yms.app.ytb.YtbUtil.getStringFromType;
import static org.onosproject.yms.app.ytb.YtbUtil.isAugmentNode;
import static org.onosproject.yms.app.ytb.YtbUtil.isMultiInstanceNode;
import static org.onosproject.yms.app.ytb.YtbUtil.isNodeProcessCompleted;
import static org.onosproject.yms.app.ytb.YtbUtil.isNonProcessableNode;
import static org.onosproject.yms.app.ytb.YtbUtil.isTypePrimitive;
import static org.onosproject.yms.app.ytb.YtbUtil.isValueOrSelectLeafSet;
import static org.onosproject.yms.app.ytb.YtbUtil.nonEmpty;
import static org.onosproject.yms.ydt.YdtContextOperationType.NONE;

/**
 * Implements traversal of YANG node and its corresponding object, resulting
 * in building of the YDT tree.
 */
public class YdtBuilderFromYo {

    private static final String STR_TYPE = "type";
    private static final String STR_SUBJECT = "subject";
    private static final String TRUE = "true";
    private static final String IS_LEAF_VALUE_SET_METHOD = "isLeafValueSet";
    private static final String IS_SELECT_LEAF_SET_METHOD = "isSelectLeaf";
    private static final String OUTPUT = "output";
    private static final String YANG_AUGMENTED_INFO_MAP =
            "yangAugmentedInfoMap";
    private static final String FALSE = "false";

    /**
     * Application YANG schema registry.
     */
    private final YangSchemaRegistry registry;

    /**
     * Current instance of the YDT builder where the tree is built.
     */
    private final YdtExtendedBuilder extBuilder;

    /**
     * YANG root object that is required for walking along with the YANG node.
     */
    private Object rootObj;

    /**
     * YANG root node that is required for walking along with the YANG object.
     */
    private YangSchemaNode rootSchema;

    /**
     * Creates YDT builder from YANG object by assigning the mandatory values.
     *
     * @param rootBuilder root node builder
     * @param rootObj     root node object
     * @param registry    application schema registry
     */
    public YdtBuilderFromYo(YdtExtendedBuilder rootBuilder, Object rootObj,
                            YangSchemaRegistry registry) {
        extBuilder = rootBuilder;
        this.rootObj = rootObj;
        this.registry = registry;
    }

    /**
     * Returns schema root node, received from YSR, which searches based on
     * the object received from YAB or YCH.
     *
     * @param object root node object
     */
    public void getModuleNodeFromYsr(Object object) {
        Class interfaceClass = getInterfaceClassFromImplClass(object);
        rootSchema = registry
                .getYangSchemaNodeUsingGeneratedRootNodeInterfaceFileName(
                        interfaceClass.getName());
    }

    /**
     * Returns schema root node, received from YSR, which searches based on
     * the object received from YNH.
     *
     * @param object notification event object
     */
    public void getRootNodeWithNotificationFromYsr(Object object) {
        rootSchema = registry.getRootYangSchemaNodeForNotification(
                object.getClass().getName());
    }

    /**
     * Creates the module node for in YDT before beginning with notification
     * root node traversal. Collects sufficient information to fill YDT with
     * notification root node in the traversal.
     */
    public void createModuleInYdt() {
        extBuilder.addChild(NONE, rootSchema);
        rootSchema = getSchemaNodeOfNotification();
        rootObj = getObjOfNotification();
    }

    /**
     * Creates the module and RPC node, in YDT tree, from the logical root
     * node received from request workbench. The output schema node is taken
     * from the child schema of RPC YANG node.
     *
     * @param rootNode logical root node
     */
    public void createModuleAndRpcInYdt(YdtExtendedContext rootNode) {

        YdtExtendedContext moduleNode =
                (YdtExtendedContext) rootNode.getFirstChild();
        extBuilder.addChild(NONE, moduleNode.getYangSchemaNode());

        YdtExtendedContext rpcNode =
                (YdtExtendedContext) moduleNode.getFirstChild();
        YangSchemaNode rpcSchemaNode = rpcNode.getYangSchemaNode();
        extBuilder.addChild(NONE, rpcSchemaNode);

        // Defines a schema identifier for output node.
        YangSchemaNodeIdentifier schemaId = new YangSchemaNodeIdentifier();
        schemaId.setName(OUTPUT);
        schemaId.setNameSpace(rpcSchemaNode.getNameSpace());
        try {
            // Gets the output schema node from RPC child schema.
            rootSchema = rpcSchemaNode.getChildSchema(schemaId).getSchemaNode();
        } catch (DataModelException e) {
            throw new YtbException(e);
        }
    }

    /**
     * Creates YDT tree from the root object, by traversing through YANG data
     * model node, and simultaneously checking the object nodes presence and
     * walking the object.
     */
    public void createYdtFromRootObject() {
        YangNode curNode = (YangNode) rootSchema;
        TraversalType curTraversal = ROOT;
        YtbNodeInfo listNodeInfo = null;
        YtbNodeInfo augmentNodeInfo = null;

        while (curNode != null) {
            /*
             * Processes the node, if it is being visited for the first time in
             * the schema, also if the schema node is being retraced in a multi
             * instance node.
             */
            if (curTraversal != PARENT || isMultiInstanceNode(curNode)) {

                if (curTraversal == PARENT && isMultiInstanceNode(curNode)) {
                    /*
                     * If the schema is being retraced for a multi-instance
                     * node, it has already entered for this multi-instance
                     * node. Now this re-processes the same schema node for
                     * any additional list object.
                     */
                    listNodeInfo = getCurNodeInfoAndTraverseBack();
                }

                if (curTraversal == ROOT && !isAugmentNode(curNode)) {
                    /*
                     * In case of RPC output, the root node is augmentative,
                     * so when the root traversal is coming for augment this
                     * flow is skipped. This adds only the root node in the YDT.
                     */
                    processApplicationRootNode();
                } else {
                    /*
                     * Gets the object corresponding to current schema node.
                     * If object exists, this adds the corresponding YDT node
                     * to the tree and returns the object. Else returns null.
                     */
                    Object processedObject = processCurSchemaNodeAndAddToYdt(
                            curNode, listNodeInfo);
                    /*
                     * Clears the list info of processed node. The next time
                     * list info is taken newly and accordingly.
                     */
                    listNodeInfo = null;
                    if (processedObject == null && !isAugmentNode(curNode)) {
                        /*
                         * Checks the presence of next sibling of the node, by
                         * breaking the complete chain of the current node,
                         * when the object value is not present, or when the
                         * list entries are completely retraced. The augment
                         * may have sibling, so this doesn't process for
                         * augment.
                         */
                        YtbTraversalInfo traverseInfo =
                                getProcessableInfo(curNode);
                        curNode = traverseInfo.getYangNode();
                        curTraversal = traverseInfo.getTraverseType();
                        continue;
                        /*
                         * Irrespective of root or parent, sets the traversal
                         * type as parent, when augment node doesn't have any
                         * value. So, the other sibling augments can be
                         * processed, if present.
                         */
                    } else if (processedObject == null &&
                            isAugmentNode(curNode)) {
                        curTraversal = PARENT;
                        /*
                         * The second content in the list will be having
                         * parent traversal, in such case it cannot go to its
                         * child in the flow, so it is made as child
                         * traversal and proceeded to continue.
                         */
                    } else if (curTraversal == PARENT &&
                            isMultiInstanceNode(curNode)) {
                        curTraversal = CHILD;
                    }
                }
            }
            /*
             * Checks for the sibling augment when the first augment node is
             * getting completed. From the current augment node the previous
             * node info is taken for augment and the traversal is changed to
             * child, so as to check for the presence of sibling augment.
             */
            if (curTraversal == PARENT && isAugmentNode(curNode)) {
                curNode = ((YangAugment) curNode).getAugmentedNode();
                augmentNodeInfo = getParentYtbInfo();
                curTraversal = CHILD;
            }
            /*
             * Creates an augment iterator for the first time or takes the
             * previous augment iterator for more than one time, whenever an
             * augmentative node arrives. If augment is present it goes back
             * for processing. If its null, the augmentative nodes process is
             * continued.
             */
            if (curTraversal != PARENT &&
                    curNode instanceof YangAugmentableNode) {
                YangNode augmentNode = getAugmentInsideSchemaNode(
                        curNode, augmentNodeInfo);
                if (augmentNode != null) {
                    curNode = augmentNode;
                    continue;
                }
            }
            /*
             * Processes the child, after processing the node. If complete
             * child depth is over, it takes up sibling and processes it.
             * Once child and sibling is over, it is traversed back to the
             * parent, without processing. In multi instance case, before
             * going to parent or schema sibling, its own list sibling is
             * processed. Skips the processing of RPC,notification and
             * augment, as these nodes are dealt in a different flow.
             */
            if (curTraversal != PARENT && curNode.getChild() != null) {
                augmentNodeInfo = null;
                listNodeInfo = null;
                curTraversal = CHILD;
                curNode = curNode.getChild();
                if (isNonProcessableNode(curNode)) {
                    YtbTraversalInfo traverseInfo = getProcessableInfo(curNode);
                    curNode = traverseInfo.getYangNode();
                    curTraversal = traverseInfo.getTraverseType();
                }
            } else if (curNode.getNextSibling() != null) {
                if (isNodeProcessCompleted(curNode, curTraversal)) {
                    break;
                }
                if (isMultiInstanceNode(curNode)) {
                    listNodeInfo = getCurNodeInfoAndTraverseBack();
                    augmentNodeInfo = null;
                    continue;
                }
                curTraversal = SIBLING;
                augmentNodeInfo = null;
                traverseToParent(curNode);
                curNode = curNode.getNextSibling();
                if (isNonProcessableNode(curNode)) {
                    YtbTraversalInfo traverseInfo = getProcessableInfo(curNode);
                    curNode = traverseInfo.getYangNode();
                    curTraversal = traverseInfo.getTraverseType();
                }
            } else {
                if (isNodeProcessCompleted(curNode, curTraversal)) {
                    break;
                }
                if (isMultiInstanceNode(curNode)) {
                    listNodeInfo = getCurNodeInfoAndTraverseBack();
                    augmentNodeInfo = null;
                    continue;
                }
                curTraversal = PARENT;
                traverseToParent(curNode);
                curNode = curNode.getParent();
            }
        }
    }

    /**
     * Processes root YANG node and adds it as a child to the YDT
     * extended builder which is created earlier.
     */
    private void processApplicationRootNode() {

        YtbNodeInfo nodeInfo = new YtbNodeInfo();
        YangNode rootYang = (YangNode) rootSchema;
        addChildNodeInYdt(rootObj, rootYang, nodeInfo);
        // If root node has leaf or leaf-list those will be processed.
        processLeaves(rootYang);
        processLeavesList(rootYang);
    }

    /**
     * Traverses to parent, based on the schema node that requires to be
     * traversed. Skips traversal of parent for choice and case node, as they
     * don't get added to the YDT tree.
     *
     * @param curNode current YANG node
     */
    private void traverseToParent(YangNode curNode) {
        if (curNode instanceof YangCase || curNode instanceof YangChoice) {
            return;
        }
        extBuilder.traverseToParentWithoutValidation();
    }

    /**
     * Returns the current YTB info of the YDT builder, and then traverses back
     * to parent. In case of multi instance node the previous node info is
     * used for iterating through the list.
     *
     * @return current YTB app info
     */
    private YtbNodeInfo getCurNodeInfoAndTraverseBack() {
        YtbNodeInfo appInfo = getParentYtbInfo();
        extBuilder.traverseToParentWithoutValidation();
        return appInfo;
    }

    /**
     * Returns augment node for an augmented node. From the list of augment
     * nodes it has, one of the nodes is taken and provided linearly. If the
     * node is not augmented or the all the augment nodes are processed, then
     * it returns null.
     *
     * @param curNode         current YANG node
     * @param augmentNodeInfo previous augment node info
     * @return YANG augment node
     */
    private YangNode getAugmentInsideSchemaNode(YangNode curNode,
                                                YtbNodeInfo augmentNodeInfo) {
        if (augmentNodeInfo == null) {
            List<YangAugment> augmentList = ((YangAugmentableNode) curNode)
                    .getAugmentedInfoList();
            if (nonEmpty(augmentList)) {
                YtbNodeInfo parentNodeInfo = getParentYtbInfo();
                Iterator<YangAugment> augmentItr = augmentList.listIterator();
                parentNodeInfo.setAugmentIterator(augmentItr);
                return augmentItr.next();
            }
        } else if (augmentNodeInfo.getAugmentIterator() != null) {
            if (augmentNodeInfo.getAugmentIterator().hasNext()) {
                return augmentNodeInfo.getAugmentIterator().next();
            }
        }
        return null;
    }

    /**
     * Processes the current YANG node and if necessary adds it to the YDT
     * builder tree by extracting the information from the corresponding
     * class object.
     *
     * @param curNode      current YANG node
     * @param listNodeInfo previous node info for list
     * @return object of the schema node
     */
    private Object processCurSchemaNodeAndAddToYdt(YangNode curNode,
                                                   YtbNodeInfo listNodeInfo) {
        YtbNodeInfo curNodeInfo = new YtbNodeInfo();
        Object nodeObj = null;
        YtbNodeInfo parentNodeInfo = getParentYtbInfo();

        switch (curNode.getYangSchemaNodeType()) {
            case YANG_SINGLE_INSTANCE_NODE:
                nodeObj = processSingleInstanceNode(curNode, curNodeInfo,
                                                    parentNodeInfo);
                break;
            case YANG_MULTI_INSTANCE_NODE:
                nodeObj = processMultiInstanceNode(
                        curNode, curNodeInfo, listNodeInfo, parentNodeInfo);
                break;
            case YANG_CHOICE_NODE:
                nodeObj = processChoiceNode(curNode, parentNodeInfo);
                break;
            case YANG_NON_DATA_NODE:
                if (curNode instanceof YangCase) {
                    nodeObj = processCaseNode(curNode, parentNodeInfo);
                }
                break;
            case YANG_AUGMENT_NODE:
                nodeObj = processAugmentNode(curNode, parentNodeInfo);
                break;
            default:
                throw new YtbException(
                        "Non processable schema node has arrived for adding " +
                                "it in YDT tree");
        }
        // Processes leaf/leaf-list only when object has value, else it skips.
        if (nodeObj != null) {
            processLeaves(curNode);
            processLeavesList(curNode);
        }
        return nodeObj;
    }

    /**
     * Processes single instance node which is added to the YDT tree.
     *
     * @param curNode        current YANG node
     * @param curNodeInfo    current YDT node info
     * @param parentNodeInfo parent YDT node info
     * @return object of the current node
     */
    private Object processSingleInstanceNode(YangNode curNode,
                                             YtbNodeInfo curNodeInfo,
                                             YtbNodeInfo parentNodeInfo) {
        Object childObj = getChildObject(curNode, parentNodeInfo);
        if (childObj != null) {
            addChildNodeInYdt(childObj, curNode, curNodeInfo);
        }
        return childObj;
    }

    /**
     * Processes multi instance node which has to be added to the YDT tree.
     * For the first instance in the list, iterator is created and added to
     * the list. For second instance or more the iterator from first instance
     * is taken and iterated through to get the object of parent.
     *
     * @param curNode        current list node
     * @param curNodeInfo    current node info for list
     * @param listNodeInfo   previous instance node info of list
     * @param parentNodeInfo parent node info of list
     * @return object of the current instance
     */
    private Object processMultiInstanceNode(YangNode curNode,
                                            YtbNodeInfo curNodeInfo,
                                            YtbNodeInfo listNodeInfo,
                                            YtbNodeInfo parentNodeInfo) {
        Object childObj = null;
        /*
         * When YANG list comes to this flow for first time, its YTB node
         * will be null. When it comes for the second or more content, then
         * the list would have been already set for that node. According to
         * set or not set this flow will be proceeded.
         */
        if (listNodeInfo == null) {
            List<Object> childObjList = (List<Object>) getChildObject(
                    curNode, parentNodeInfo);
            if (nonEmpty(childObjList)) {
                Iterator<Object> listItr = childObjList.iterator();
                if (!listItr.hasNext()) {
                    return null;
                    //TODO: Handle the subtree filtering with no list entries.
                }
                childObj = listItr.next();
                /*
                 * For that node the iterator is set. So the next time for
                 * the list this iterator will be taken.
                 */
                curNodeInfo.setListIterator(listItr);
            }
        } else {
            /*
             * If the list value comes for second or more time, that list
             * node will be having YTB node info, where iterator can be
             * retrieved and check if any more contents are present. If
             * present those will be processed.
             */
            curNodeInfo.setListIterator(listNodeInfo.getListIterator());
            if (listNodeInfo.getListIterator().hasNext()) {
                childObj = listNodeInfo.getListIterator().next();
            }
        }
        if (childObj != null) {
            addChildNodeInYdt(childObj, curNode, curNodeInfo);
        }
        return childObj;
    }

    /**
     * Processes choice node which adds a map to the parent node info of
     * choice name and the case object. The object taken for choice node is
     * of case object with choice name. Also, this Skips the addition of choice
     * to YDT.
     *
     * @param curNode        current choice node
     * @param parentNodeInfo parent YTB node info
     * @return object of the choice node
     */
    private Object processChoiceNode(YangNode curNode,
                                     YtbNodeInfo parentNodeInfo) {
        /*
         * Retrieves the parent YTB info, to take the object of parent, so as
         * to check the child attribute from the object.
         */
        Object childObj = getChildObject(curNode, parentNodeInfo);
        if (childObj != null) {
            Map<String, Object> choiceCaseMap = parentNodeInfo
                    .getChoiceCaseMap();
            if (choiceCaseMap == null) {
                choiceCaseMap = new HashMap<>();
                parentNodeInfo.setChoiceCaseMap(choiceCaseMap);
            }
            choiceCaseMap.put(curNode.getName(), childObj);
        }
        return childObj;
    }

    /**
     * Processes case node from the map contents that is filled by choice
     * nodes. Object of choice is taken when choice name and case class name
     * matches. When the case node is not present in the map it returns null.
     *
     * @param curNode        current case node
     * @param parentNodeInfo choice parent node info
     * @return object of the case node
     */
    private Object processCaseNode(YangNode curNode,
                                   YtbNodeInfo parentNodeInfo) {
        Object childObj = null;
        if (parentNodeInfo.getChoiceCaseMap() != null) {
            childObj = getCaseObjectFromChoice(parentNodeInfo,
                                               curNode);
        }
        if (childObj != null) {
            /*
             * Sets the case object in parent info, so that rest of the case
             * children can use it as parent. Case is not added in YDT.
             */
            parentNodeInfo.setCaseObject(childObj);
        }
        return childObj;
    }

    /**
     * Processes augment node, which is not added in the YDT, but binds
     * itself to the parent YTB info, so rest of its child nodes can use for
     * adding themselves to the YDT tree. If there is no augment node added
     * in map or if the augment module is not registered, then it returns null.
     *
     * @param curNode        current augment node
     * @param parentNodeInfo augment parent node info
     * @return object of the augment node
     */
    private Object processAugmentNode(YangNode curNode,
                                      YtbNodeInfo parentNodeInfo) {
        String className = curNode.getJavaClassNameOrBuiltInType();
        String pkgName = curNode.getJavaPackage();
        Object parentObj = getParentObjectOfNode(parentNodeInfo,
                                                 curNode.getParent());
        Map augmentMap;
        try {
            augmentMap = (Map) getAttributeOfObject(parentObj,
                                                    YANG_AUGMENTED_INFO_MAP);
            /*
             * Gets the registered module class. Loads the class and gets the
             * augment class.
             */
            Class moduleClass = getClassLoaderForAugment(curNode, registry);
            if (moduleClass == null) {
                return null;
            }
            Class augmentClass = moduleClass.getClassLoader().loadClass(
                    pkgName + PERIOD + className);
            Object childObj = augmentMap.get(augmentClass);
            parentNodeInfo.setAugmentObject(childObj);
            return childObj;
        } catch (ClassNotFoundException | NoSuchMethodException e) {
            throw new YtbException(e);
        }
    }

    /**
     * Returns the YTB info from the parent node, so that its own bounded
     * object can be taken out.
     *
     * @return parent node YTB node info
     */
    private YtbNodeInfo getParentYtbInfo() {
        YdtExtendedContext parentExtContext = extBuilder.getCurNode();
        return (YtbNodeInfo) parentExtContext.getAppInfo(YTB);
    }

    /**
     * Returns the child object from the parent object. Uses java name of the
     * current node to search the attribute in the parent object.
     *
     * @param curNode        current YANG node
     * @param parentNodeInfo parent YTB node info
     * @return object of the child node
     */
    private Object getChildObject(YangNode curNode,
                                  YtbNodeInfo parentNodeInfo) {
        String nodeJavaName = curNode.getJavaAttributeName();
        Object parentObj = getParentObjectOfNode(parentNodeInfo,
                                                 curNode.getParent());
        try {
            return getAttributeOfObject(parentObj, nodeJavaName);
        } catch (NoSuchMethodException e) {
            throw new YtbException(e);
        }
    }

    /**
     * Adds the child node to the YDT by taking operation type from the
     * object. Also, binds the object to the YDT node through YTB node info.
     *
     * @param childObj    node object
     * @param curNode     current YANG node
     * @param curNodeInfo current YTB info
     */
    private void addChildNodeInYdt(Object childObj, YangNode curNode,
                                   YtbNodeInfo curNodeInfo) {
        YdtContextOperationType opType =
                getNodeOpType(childObj, getOpTypeName(curNode));
        extBuilder.addChild(opType, curNode);
        YdtExtendedContext curExtContext = extBuilder.getCurNode();
        curNodeInfo.setYangObject(childObj);
        curExtContext.addAppInfo(YTB, curNodeInfo);
    }

    /**
     * Processes every leaf in a YANG node. Iterates through the leaf, takes
     * value from the leaf and adds it to the YDT with value. If value is not
     * present, and select leaf is set, adds it to the YDT without value.
     *
     * @param yangNode leaves holder node
     */
    private void processLeaves(YangNode yangNode) {
        if (yangNode instanceof YangLeavesHolder) {
            List<YangLeaf> leavesList = ((YangLeavesHolder) yangNode)
                    .getListOfLeaf();
            if (leavesList != null) {
                for (YangLeaf yangLeaf : leavesList) {
                    YtbNodeInfo parentYtbInfo = getParentYtbInfo();
                    Object parentObj = getParentObjectOfNode(parentYtbInfo,
                                                             yangNode);
                    Object leafType;
                    try {
                        leafType = getAttributeOfObject(parentObj,
                                                        getJavaName(yangLeaf));
                    } catch (NoSuchMethodException e) {
                        throw new YtbException(e);
                    }

                    addLeafWithValue(yangNode, yangLeaf, parentObj, leafType);
                    addLeafWithoutValue(yangNode, yangLeaf, parentObj);
                }
            }
        }
    }

    /**
     * Processes every leaf-list in a YANG node for adding the value in YDT.
     *
     * @param yangNode list of leaf-list holder node
     */
    private void processLeavesList(YangNode yangNode) {
        if (yangNode instanceof YangLeavesHolder) {
            List<YangLeafList> listOfLeafList =
                    ((YangLeavesHolder) yangNode).getListOfLeafList();

            if (listOfLeafList != null) {
                for (YangLeafList yangLeafList : listOfLeafList) {
                    addToBuilder(yangNode, yangLeafList);
                }
            }
        }
    }

    /**
     * Processes the list of objects of the leaf list and adds the leaf list
     * value to the builder.
     *
     * @param yangNode YANG node
     * @param leafList YANG leaf list
     */
    private void addToBuilder(YangNode yangNode, YangLeafList leafList) {
        YtbNodeInfo ytbNodeInfo = getParentYtbInfo();
        Object parentObj = getParentObjectOfNode(ytbNodeInfo, yangNode);
        List<Object> obj;
        try {
            obj = (List<Object>) getAttributeOfObject(parentObj,
                                                      getJavaName(leafList));
        } catch (NoSuchMethodException e) {
            throw new YtbException(e);
        }
        if (obj != null) {
            addLeafListValue(yangNode, parentObj, leafList, obj);
        }
    }

    /**
     * Adds the leaf list value to the YDT builder by taking the string value
     * from the data type.
     *
     * @param yangNode  YANG node
     * @param parentObj parent object
     * @param leafList  YANG leaf list
     * @param obj       list of objects
     */
    private void addLeafListValue(YangNode yangNode, Object parentObj,
                                  YangLeafList leafList, List<Object> obj) {

        Set<String> leafListVal = new LinkedHashSet<>();
        boolean isEmpty = false;
        for (Object object : obj) {
            String val = getStringFromType(yangNode, parentObj,
                                           getJavaName(leafList), object,
                                           leafList.getDataType());
            isEmpty = isTypeEmpty(val, leafList.getDataType());
            if (isEmpty) {
                if (val.equals(TRUE)) {
                    addLeafList(leafListVal, leafList);
                }
                break;
            }
            if (!val.equals("")) {
                leafListVal.add(val);
            }
        }
        if (!isEmpty && !leafListVal.isEmpty()) {
            addLeafList(leafListVal, leafList);
        }
    }

    /**
     * Adds set of leaf list values in the builder and traverses back to the
     * holder.
     *
     * @param leafListVal set of values
     * @param leafList    YANG leaf list
     */
    private void addLeafList(Set<String> leafListVal, YangLeafList leafList) {
        extBuilder.addLeafList(leafListVal, leafList);
        extBuilder.traverseToParentWithoutValidation();
    }

    /**
     * Returns the schema node of notification from the root node. Gets the
     * enum value from event object and gives it to the root schema node for
     * getting back the notification schema node.
     *
     * @return YANG schema node of notification
     */
    private YangSchemaNode getSchemaNodeOfNotification() {

        Object eventObjType = getAttributeFromInheritance(rootObj, STR_TYPE);
        String opTypeValue = String.valueOf(eventObjType);

        if (opTypeValue.equals(STR_NULL) || opTypeValue.isEmpty()) {
            throw new YtbException(
                    "There is no notification present for the event. Invalid " +
                            "input for notification.");
        }
        try {
            return rootSchema.getNotificationSchemaNode(opTypeValue);
        } catch (DataModelException e) {
            throw new YtbException(e);
        }
    }

    /**
     * Returns the object of the notification by retrieving the attributes
     * from the event class object.
     *
     * @return notification YANG object
     */
    private Object getObjOfNotification() {

        Object eventSubjectObj =
                getAttributeFromInheritance(rootObj, STR_SUBJECT);
        String notificationName = rootSchema.getJavaAttributeName();
        try {
            return getAttributeOfObject(eventSubjectObj, notificationName);
        } catch (NoSuchMethodException e) {
            throw new YtbException(e);
        }
    }

    /**
     * Returns case object from the map that is bound to the parent node
     * info. For any case node, only when the key and value is matched the
     * object of the case is provided. If a match is not found, null is
     * returned.
     *
     * @param parentNodeInfo parent YTB node info
     * @param caseNode       case schema node
     * @return object of the case node
     */
    private Object getCaseObjectFromChoice(YtbNodeInfo parentNodeInfo,
                                           YangSchemaNode caseNode) {
        String javaName = getCapitalCase(
                caseNode.getJavaClassNameOrBuiltInType());
        String choiceName = ((YangNode) caseNode).getParent().getName();
        Map<String, Object> mapObj = parentNodeInfo.getChoiceCaseMap();
        Object caseObj = mapObj.get(choiceName);
        Class<?> interfaceClass = getInterfaceClassFromImplClass(caseObj);
        return interfaceClass.getSimpleName().equals(javaName) ? caseObj : null;
    }

    /**
     * Adds leaf to YDT when value is present. For primitive types, in order
     * to avoid default values, the value select is set or not is checked and
     * then added.
     *
     * @param holder    leaf holder
     * @param yangLeaf  YANG leaf node
     * @param parentObj leaf holder object
     * @param leafType  object of leaf type
     */
    private void addLeafWithValue(YangSchemaNode holder, YangLeaf yangLeaf,
                                  Object parentObj, Object leafType) {
        String fieldValue = null;
        if (isTypePrimitive(yangLeaf.getDataType())) {
            fieldValue = getLeafValueFromValueSetFlag(holder, parentObj,
                                                      yangLeaf, leafType);
            /*
             * Checks the object is present or not, when type is
             * non-primitive. And adds the value from the respective data type.
             */
        } else if (leafType != null) {
            fieldValue = getStringFromType(holder, parentObj,
                                           getJavaName(yangLeaf), leafType,
                                           yangLeaf.getDataType());
        }

        if (nonEmpty(fieldValue)) {
            boolean isEmpty = isTypeEmpty(fieldValue,
                                          yangLeaf.getDataType());
            if (isEmpty) {
                if (!fieldValue.equals(TRUE)) {
                    return;
                }
                fieldValue = null;
            }
            extBuilder.addLeaf(fieldValue, yangLeaf);
            extBuilder.traverseToParentWithoutValidation();
        }
    }

    /**
     * Returns the value as true if direct or referred type from leafref or
     * derived points to empty data type; false otherwise.
     *
     * @param fieldValue value of the leaf
     * @param dataType   type of the leaf
     * @return true if type is empty; false otherwise.
     */
    private boolean isTypeEmpty(String fieldValue, YangType<?> dataType) {
        if (fieldValue.equals(TRUE) || fieldValue.equals(FALSE)) {
            switch (dataType.getDataType()) {
                case EMPTY:
                    return true;

                case LEAFREF:
                    YangLeafRef leafRef =
                            (YangLeafRef) dataType.getDataTypeExtendedInfo();
                    return isTypeEmpty(fieldValue,
                                       leafRef.getEffectiveDataType());
                case DERIVED:
                    YangDerivedInfo info =
                            (YangDerivedInfo) dataType
                                    .getDataTypeExtendedInfo();
                    YangDataTypes type = info.getEffectiveBuiltInType();
                    return type == EMPTY;

                default:
                    return false;
            }
        }
        return false;
    }

    /**
     * Adds leaf without value, when the select leaf bit is set.
     *
     * @param holder    leaf holder
     * @param yangLeaf  YANG leaf node
     * @param parentObj leaf holder object
     */
    private void addLeafWithoutValue(YangSchemaNode holder, YangLeaf yangLeaf,
                                     Object parentObj) {

        String selectLeaf;
        try {
            selectLeaf = isValueOrSelectLeafSet(holder, parentObj,
                                                getJavaName(yangLeaf),
                                                IS_SELECT_LEAF_SET_METHOD);
        } catch (NoSuchMethodException e) {
            selectLeaf = FALSE;
        }
        if (selectLeaf.equals(TRUE)) {
            extBuilder.addLeaf(null, yangLeaf);
            extBuilder.traverseToParentWithoutValidation();
        }
    }

    /**
     * Returns the value of type, after checking the value leaf flag. If the
     * flag is set, then it takes the value else returns null.
     *
     * @param holder    leaf holder
     * @param parentObj parent object
     * @param yangLeaf  YANG leaf node
     * @param leafType  object of leaf type
     * @return value of type
     */
    private String getLeafValueFromValueSetFlag(YangSchemaNode holder, Object parentObj,
                                                YangLeaf yangLeaf, Object leafType) {

        String valueOfLeaf;
        try {
            valueOfLeaf = isValueOrSelectLeafSet(holder, parentObj,
                                                 getJavaName(yangLeaf),
                                                 IS_LEAF_VALUE_SET_METHOD);
        } catch (NoSuchMethodException e) {
            throw new YtbException(e);
        }
        if (valueOfLeaf.equals(TRUE)) {
            return getStringFromType(holder, parentObj,
                                     getJavaName(yangLeaf), leafType,
                                     yangLeaf.getDataType());
        }
        return null;
    }

    /**
     * Returns the node info which can be processed, by eliminating the nodes
     * which need not to be processed at normal conditions such as RPC,
     * notification and augment.
     *
     * @param curNode current node
     * @return info of node which needs processing
     */
    private YtbTraversalInfo getProcessableInfo(YangNode curNode) {
        if (curNode.getNextSibling() != null) {
            YangNode sibling = curNode.getNextSibling();
            while (isNonProcessableNode(sibling)) {
                sibling = sibling.getNextSibling();
            }
            if (sibling != null) {
                return new YtbTraversalInfo(sibling, SIBLING);
            }
        }
        return new YtbTraversalInfo(curNode.getParent(), PARENT);
    }

}
