[ONOS-5081] YANG tree builder.
Change-Id: Id47015d0cec1a446efcae6c4f3e2ffe87a0f0e0e
diff --git a/apps/yms/app/src/main/java/org/onosproject/yms/app/ytb/YdtBuilderFromYo.java b/apps/yms/app/src/main/java/org/onosproject/yms/app/ytb/YdtBuilderFromYo.java
new file mode 100644
index 0000000..a82eea2
--- /dev/null
+++ b/apps/yms/app/src/main/java/org/onosproject/yms/app/ytb/YdtBuilderFromYo.java
@@ -0,0 +1,906 @@
+/*
+ * 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);
+    }
+
+}