/*
 * 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.YangLeaf;
import org.onosproject.yangutils.datamodel.YangLeafList;
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.exceptions.DataModelException;
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.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

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.getCapitalCase;
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.getOperationTypeOfTheNode;
import static org.onosproject.yms.app.ytb.YtbUtil.getParentObjectOfNode;
import static org.onosproject.yms.app.ytb.YtbUtil.getStringFromDataType;
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.isNonEmpty;
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.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";

    /**
     * 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;
                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 (isNonEmpty(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 (isNonEmpty(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 =
                (YdtExtendedContext) 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 = getOperationTypeOfTheNode(childObj);
        extBuilder.addChild(opType, curNode);
        YdtExtendedContext curExtContext = (YdtExtendedContext) 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(yangLeaf, parentObj, leafType);
                    addLeafWithoutValue(yangLeaf, parentObj);
                }
            }
        }
    }

    /**
     * Processes every leaf-list in a YANG node. For each leaf-list, the list of
     * objects are iterated, value from each object is put in a set of string,
     * and is added to the 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) {

                    YtbNodeInfo ytbNodeInfo = getParentYtbInfo();
                    Object parentObj = getParentObjectOfNode(ytbNodeInfo,
                                                             yangNode);

                    //TODO: Let the received object list be generic collection.
                    List<Object> leafListObj;
                    try {
                        leafListObj = (List<Object>) getAttributeOfObject(
                                parentObj, getJavaName(yangLeafList));
                    } catch (NoSuchMethodException e) {
                        throw new YtbException(e);
                    }
                    Set<String> leafListValue = new HashSet<>();
                    /*
                     * If list is present, then adds each object value in set.
                     * Adds this set to the YDT, and traverse to parent.
                     */
                    if (leafListObj != null) {
                        for (Object object : leafListObj) {
                            String objValue = getStringFromDataType(
                                    object, yangLeafList.getDataType());
                            leafListValue.add(objValue);
                        }
                        extBuilder.addLeafList(leafListValue, yangLeafList);
                        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() {
        Class parentClass = rootObj.getClass().getSuperclass();
        Object eventObjType = getAttributeFromInheritance(
                parentClass, 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() {
        Class parentClass = rootObj.getClass().getSuperclass();
        Object eventSubjectObj = getAttributeFromInheritance(
                parentClass, 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 yangLeaf  YANG leaf node
     * @param parentObj leaf holder object
     * @param leafType  object of leaf type
     */
    private void addLeafWithValue(YangLeaf yangLeaf, Object parentObj,
                                  Object leafType) {
        String fieldValue = null;
        if (isTypePrimitive(yangLeaf.getDataType())) {
            fieldValue = getLeafValueFromValueSetFlag(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 = getStringFromDataType(leafType,
                                               yangLeaf.getDataType());
        }
        if (isNonEmpty(fieldValue)) {
            extBuilder.addLeaf(fieldValue, yangLeaf);
            extBuilder.traverseToParentWithoutValidation();
        }
    }

    /**
     * Adds leaf without value, when the select leaf bit is set.
     *
     * @param yangLeaf  YANG leaf node
     * @param parentObj leaf holder object
     */
    private void addLeafWithoutValue(YangLeaf yangLeaf, Object parentObj) {
        String selectLeaf = isValueOrSelectLeafSet(
                parentObj, getJavaName(yangLeaf), IS_SELECT_LEAF_SET_METHOD);
        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 or returns null.
     *
     * @param parentObj parent object
     * @param yangLeaf  YANG leaf node
     * @param leafType  object of leaf type
     * @return value of type
     */
    private String getLeafValueFromValueSetFlag(
            Object parentObj, YangLeaf yangLeaf, Object leafType) {
        String valueOfLeaf = isValueOrSelectLeafSet(
                parentObj, getJavaName(yangLeaf), IS_LEAF_VALUE_SET_METHOD);
        if (valueOfLeaf.equals(TRUE)) {
            return getStringFromDataType(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);
    }

}
