blob: a82eea2ccd64ee5cb62272ef605985ab094c3bf9 [file] [log] [blame]
/*
* 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);
}
}