| /* |
| * Copyright 2016-present Open Networking Foundation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.onosproject.yms.app.ytb; |
| |
| import org.onosproject.yangutils.datamodel.YangAugment; |
| import org.onosproject.yangutils.datamodel.YangAugmentableNode; |
| import org.onosproject.yangutils.datamodel.YangCase; |
| import org.onosproject.yangutils.datamodel.YangChoice; |
| import org.onosproject.yangutils.datamodel.YangDerivedInfo; |
| import org.onosproject.yangutils.datamodel.YangLeaf; |
| import org.onosproject.yangutils.datamodel.YangLeafList; |
| import org.onosproject.yangutils.datamodel.YangLeafRef; |
| import org.onosproject.yangutils.datamodel.YangLeavesHolder; |
| import org.onosproject.yangutils.datamodel.YangNode; |
| import org.onosproject.yangutils.datamodel.YangSchemaNode; |
| import org.onosproject.yangutils.datamodel.YangSchemaNodeIdentifier; |
| import org.onosproject.yangutils.datamodel.YangType; |
| import org.onosproject.yangutils.datamodel.exceptions.DataModelException; |
| import org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes; |
| import org.onosproject.yms.app.utils.TraversalType; |
| import org.onosproject.yms.app.ydt.YdtExtendedBuilder; |
| import org.onosproject.yms.app.ydt.YdtExtendedContext; |
| import org.onosproject.yms.app.ysr.YangSchemaRegistry; |
| import org.onosproject.yms.ydt.YdtContextOperationType; |
| |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.LinkedHashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.EMPTY; |
| import static org.onosproject.yangutils.utils.io.impl.YangIoUtils.getCapitalCase; |
| import static org.onosproject.yms.app.utils.TraversalType.CHILD; |
| import static org.onosproject.yms.app.utils.TraversalType.PARENT; |
| import static org.onosproject.yms.app.utils.TraversalType.ROOT; |
| import static org.onosproject.yms.app.utils.TraversalType.SIBLING; |
| import static org.onosproject.yms.app.ydt.AppType.YTB; |
| import static org.onosproject.yms.app.ytb.YtbUtil.PERIOD; |
| import static org.onosproject.yms.app.ytb.YtbUtil.STR_NULL; |
| import static org.onosproject.yms.app.ytb.YtbUtil.getAttributeFromInheritance; |
| import static org.onosproject.yms.app.ytb.YtbUtil.getAttributeOfObject; |
| import static org.onosproject.yms.app.ytb.YtbUtil.getClassLoaderForAugment; |
| import static org.onosproject.yms.app.ytb.YtbUtil.getInterfaceClassFromImplClass; |
| import static org.onosproject.yms.app.ytb.YtbUtil.getJavaName; |
| import static org.onosproject.yms.app.ytb.YtbUtil.getNodeOpType; |
| import static org.onosproject.yms.app.ytb.YtbUtil.getOpTypeName; |
| import static org.onosproject.yms.app.ytb.YtbUtil.getParentObjectOfNode; |
| import static org.onosproject.yms.app.ytb.YtbUtil.getStringFromType; |
| import static org.onosproject.yms.app.ytb.YtbUtil.isAugmentNode; |
| import static org.onosproject.yms.app.ytb.YtbUtil.isMultiInstanceNode; |
| import static org.onosproject.yms.app.ytb.YtbUtil.isNodeProcessCompleted; |
| import static org.onosproject.yms.app.ytb.YtbUtil.isNonProcessableNode; |
| import static org.onosproject.yms.app.ytb.YtbUtil.isTypePrimitive; |
| import static org.onosproject.yms.app.ytb.YtbUtil.isValueOrSelectLeafSet; |
| import static org.onosproject.yms.app.ytb.YtbUtil.nonEmpty; |
| import static org.onosproject.yms.ydt.YdtContextOperationType.NONE; |
| |
| /** |
| * Implements traversal of YANG node and its corresponding object, resulting |
| * in building of the YDT tree. |
| */ |
| public class YdtBuilderFromYo { |
| |
| private static final String STR_TYPE = "type"; |
| private static final String STR_SUBJECT = "subject"; |
| private static final String TRUE = "true"; |
| private static final String IS_LEAF_VALUE_SET_METHOD = "isLeafValueSet"; |
| private static final String IS_SELECT_LEAF_SET_METHOD = "isSelectLeaf"; |
| private static final String OUTPUT = "output"; |
| private static final String YANG_AUGMENTED_INFO_MAP = |
| "yangAugmentedInfoMap"; |
| private static final String FALSE = "false"; |
| |
| /** |
| * Application YANG schema registry. |
| */ |
| private final YangSchemaRegistry registry; |
| |
| /** |
| * Current instance of the YDT builder where the tree is built. |
| */ |
| private final YdtExtendedBuilder extBuilder; |
| |
| /** |
| * YANG root object that is required for walking along with the YANG node. |
| */ |
| private Object rootObj; |
| |
| /** |
| * YANG root node that is required for walking along with the YANG object. |
| */ |
| private YangSchemaNode rootSchema; |
| |
| /** |
| * Creates YDT builder from YANG object by assigning the mandatory values. |
| * |
| * @param rootBuilder root node builder |
| * @param rootObj root node object |
| * @param registry application schema registry |
| */ |
| public YdtBuilderFromYo(YdtExtendedBuilder rootBuilder, Object rootObj, |
| YangSchemaRegistry registry) { |
| extBuilder = rootBuilder; |
| this.rootObj = rootObj; |
| this.registry = registry; |
| } |
| |
| /** |
| * Returns schema root node, received from YSR, which searches based on |
| * the object received from YAB or YCH. |
| * |
| * @param object root node object |
| */ |
| public void getModuleNodeFromYsr(Object object) { |
| Class interfaceClass = getInterfaceClassFromImplClass(object); |
| rootSchema = registry |
| .getYangSchemaNodeUsingGeneratedRootNodeInterfaceFileName( |
| interfaceClass.getName()); |
| } |
| |
| /** |
| * Returns schema root node, received from YSR, which searches based on |
| * the object received from YNH. |
| * |
| * @param object notification event object |
| */ |
| public void getRootNodeWithNotificationFromYsr(Object object) { |
| rootSchema = registry.getRootYangSchemaNodeForNotification( |
| object.getClass().getName()); |
| } |
| |
| /** |
| * Creates the module node for in YDT before beginning with notification |
| * root node traversal. Collects sufficient information to fill YDT with |
| * notification root node in the traversal. |
| */ |
| public void createModuleInYdt() { |
| extBuilder.addChild(NONE, rootSchema); |
| rootSchema = getSchemaNodeOfNotification(); |
| rootObj = getObjOfNotification(); |
| } |
| |
| /** |
| * Creates the module and RPC node, in YDT tree, from the logical root |
| * node received from request workbench. The output schema node is taken |
| * from the child schema of RPC YANG node. |
| * |
| * @param rootNode logical root node |
| */ |
| public void createModuleAndRpcInYdt(YdtExtendedContext rootNode) { |
| |
| YdtExtendedContext moduleNode = |
| (YdtExtendedContext) rootNode.getFirstChild(); |
| extBuilder.addChild(NONE, moduleNode.getYangSchemaNode()); |
| |
| YdtExtendedContext rpcNode = |
| (YdtExtendedContext) moduleNode.getFirstChild(); |
| YangSchemaNode rpcSchemaNode = rpcNode.getYangSchemaNode(); |
| extBuilder.addChild(NONE, rpcSchemaNode); |
| |
| // Defines a schema identifier for output node. |
| YangSchemaNodeIdentifier schemaId = new YangSchemaNodeIdentifier(); |
| schemaId.setName(OUTPUT); |
| schemaId.setNameSpace(rpcSchemaNode.getNameSpace()); |
| try { |
| // Gets the output schema node from RPC child schema. |
| rootSchema = rpcSchemaNode.getChildSchema(schemaId).getSchemaNode(); |
| } catch (DataModelException e) { |
| throw new YtbException(e); |
| } |
| } |
| |
| /** |
| * Creates YDT tree from the root object, by traversing through YANG data |
| * model node, and simultaneously checking the object nodes presence and |
| * walking the object. |
| */ |
| public void createYdtFromRootObject() { |
| YangNode curNode = (YangNode) rootSchema; |
| TraversalType curTraversal = ROOT; |
| YtbNodeInfo listNodeInfo = null; |
| YtbNodeInfo augmentNodeInfo = null; |
| |
| while (curNode != null) { |
| /* |
| * Processes the node, if it is being visited for the first time in |
| * the schema, also if the schema node is being retraced in a multi |
| * instance node. |
| */ |
| if (curTraversal != PARENT || isMultiInstanceNode(curNode)) { |
| |
| if (curTraversal == PARENT && isMultiInstanceNode(curNode)) { |
| /* |
| * If the schema is being retraced for a multi-instance |
| * node, it has already entered for this multi-instance |
| * node. Now this re-processes the same schema node for |
| * any additional list object. |
| */ |
| listNodeInfo = getCurNodeInfoAndTraverseBack(); |
| } |
| |
| if (curTraversal == ROOT && !isAugmentNode(curNode)) { |
| /* |
| * In case of RPC output, the root node is augmentative, |
| * so when the root traversal is coming for augment this |
| * flow is skipped. This adds only the root node in the YDT. |
| */ |
| processApplicationRootNode(); |
| } else { |
| /* |
| * Gets the object corresponding to current schema node. |
| * If object exists, this adds the corresponding YDT node |
| * to the tree and returns the object. Else returns null. |
| */ |
| Object processedObject = processCurSchemaNodeAndAddToYdt( |
| curNode, listNodeInfo); |
| /* |
| * Clears the list info of processed node. The next time |
| * list info is taken newly and accordingly. |
| */ |
| listNodeInfo = null; |
| if (processedObject == null && !isAugmentNode(curNode)) { |
| /* |
| * Checks the presence of next sibling of the node, by |
| * breaking the complete chain of the current node, |
| * when the object value is not present, or when the |
| * list entries are completely retraced. The augment |
| * may have sibling, so this doesn't process for |
| * augment. |
| */ |
| YtbTraversalInfo traverseInfo = |
| getProcessableInfo(curNode); |
| curNode = traverseInfo.getYangNode(); |
| curTraversal = traverseInfo.getTraverseType(); |
| continue; |
| /* |
| * Irrespective of root or parent, sets the traversal |
| * type as parent, when augment node doesn't have any |
| * value. So, the other sibling augments can be |
| * processed, if present. |
| */ |
| } else if (processedObject == null && |
| isAugmentNode(curNode)) { |
| curTraversal = PARENT; |
| /* |
| * The second content in the list will be having |
| * parent traversal, in such case it cannot go to its |
| * child in the flow, so it is made as child |
| * traversal and proceeded to continue. |
| */ |
| } else if (curTraversal == PARENT && |
| isMultiInstanceNode(curNode)) { |
| curTraversal = CHILD; |
| } |
| } |
| } |
| /* |
| * Checks for the sibling augment when the first augment node is |
| * getting completed. From the current augment node the previous |
| * node info is taken for augment and the traversal is changed to |
| * child, so as to check for the presence of sibling augment. |
| */ |
| if (curTraversal == PARENT && isAugmentNode(curNode)) { |
| curNode = ((YangAugment) curNode).getAugmentedNode(); |
| augmentNodeInfo = getParentYtbInfo(); |
| curTraversal = CHILD; |
| } |
| /* |
| * Creates an augment iterator for the first time or takes the |
| * previous augment iterator for more than one time, whenever an |
| * augmentative node arrives. If augment is present it goes back |
| * for processing. If its null, the augmentative nodes process is |
| * continued. |
| */ |
| if (curTraversal != PARENT && |
| curNode instanceof YangAugmentableNode) { |
| YangNode augmentNode = getAugmentInsideSchemaNode( |
| curNode, augmentNodeInfo); |
| if (augmentNode != null) { |
| curNode = augmentNode; |
| continue; |
| } |
| } |
| /* |
| * Processes the child, after processing the node. If complete |
| * child depth is over, it takes up sibling and processes it. |
| * Once child and sibling is over, it is traversed back to the |
| * parent, without processing. In multi instance case, before |
| * going to parent or schema sibling, its own list sibling is |
| * processed. Skips the processing of RPC,notification and |
| * augment, as these nodes are dealt in a different flow. |
| */ |
| if (curTraversal != PARENT && curNode.getChild() != null) { |
| augmentNodeInfo = null; |
| listNodeInfo = null; |
| curTraversal = CHILD; |
| curNode = curNode.getChild(); |
| if (isNonProcessableNode(curNode)) { |
| YtbTraversalInfo traverseInfo = getProcessableInfo(curNode); |
| curNode = traverseInfo.getYangNode(); |
| curTraversal = traverseInfo.getTraverseType(); |
| } |
| } else if (curNode.getNextSibling() != null) { |
| if (isNodeProcessCompleted(curNode, curTraversal)) { |
| break; |
| } |
| if (isMultiInstanceNode(curNode)) { |
| listNodeInfo = getCurNodeInfoAndTraverseBack(); |
| augmentNodeInfo = null; |
| continue; |
| } |
| curTraversal = SIBLING; |
| augmentNodeInfo = null; |
| traverseToParent(curNode); |
| curNode = curNode.getNextSibling(); |
| if (isNonProcessableNode(curNode)) { |
| YtbTraversalInfo traverseInfo = getProcessableInfo(curNode); |
| curNode = traverseInfo.getYangNode(); |
| curTraversal = traverseInfo.getTraverseType(); |
| } |
| } else { |
| if (isNodeProcessCompleted(curNode, curTraversal)) { |
| break; |
| } |
| if (isMultiInstanceNode(curNode)) { |
| listNodeInfo = getCurNodeInfoAndTraverseBack(); |
| augmentNodeInfo = null; |
| continue; |
| } |
| curTraversal = PARENT; |
| traverseToParent(curNode); |
| curNode = getParentSchemaNode(curNode); |
| } |
| } |
| } |
| |
| /** |
| * Returns parent schema node of current node. |
| * |
| * @param curNode current schema node |
| * @return parent schema node |
| */ |
| private YangNode getParentSchemaNode(YangNode curNode) { |
| if (curNode instanceof YangAugment) { |
| /* |
| * If curNode is augment, either next augment or augmented node |
| * has to be processed. So traversal type is changed to parent, |
| * but node is not changed. |
| */ |
| return curNode; |
| } |
| return 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 |
| || curNode instanceof YangAugment) { |
| return; |
| } |
| extBuilder.traverseToParentWithoutValidation(); |
| } |
| |
| /** |
| * Returns the current YTB info of the YDT builder, and then traverses back |
| * to parent. In case of multi instance node the previous node info is |
| * used for iterating through the list. |
| * |
| * @return current YTB app info |
| */ |
| private YtbNodeInfo getCurNodeInfoAndTraverseBack() { |
| YtbNodeInfo appInfo = getParentYtbInfo(); |
| extBuilder.traverseToParentWithoutValidation(); |
| return appInfo; |
| } |
| |
| /** |
| * Returns augment node for an augmented node. From the list of augment |
| * nodes it has, one of the nodes is taken and provided linearly. If the |
| * node is not augmented or the all the augment nodes are processed, then |
| * it returns null. |
| * |
| * @param curNode current YANG node |
| * @param augmentNodeInfo previous augment node info |
| * @return YANG augment node |
| */ |
| private YangNode getAugmentInsideSchemaNode(YangNode curNode, |
| YtbNodeInfo augmentNodeInfo) { |
| if (augmentNodeInfo == null) { |
| List<YangAugment> augmentList = ((YangAugmentableNode) curNode) |
| .getAugmentedInfoList(); |
| if (nonEmpty(augmentList)) { |
| YtbNodeInfo parentNodeInfo = getParentYtbInfo(); |
| Iterator<YangAugment> augmentItr = augmentList.listIterator(); |
| parentNodeInfo.setAugmentIterator(augmentItr); |
| return augmentItr.next(); |
| } |
| } else if (augmentNodeInfo.getAugmentIterator() != null) { |
| if (augmentNodeInfo.getAugmentIterator().hasNext()) { |
| return augmentNodeInfo.getAugmentIterator().next(); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Processes the current YANG node and if necessary adds it to the YDT |
| * builder tree by extracting the information from the corresponding |
| * class object. |
| * |
| * @param curNode current YANG node |
| * @param listNodeInfo previous node info for list |
| * @return object of the schema node |
| */ |
| private Object processCurSchemaNodeAndAddToYdt(YangNode curNode, |
| YtbNodeInfo listNodeInfo) { |
| YtbNodeInfo curNodeInfo = new YtbNodeInfo(); |
| Object nodeObj = null; |
| YtbNodeInfo parentNodeInfo = getParentYtbInfo(); |
| |
| switch (curNode.getYangSchemaNodeType()) { |
| case YANG_SINGLE_INSTANCE_NODE: |
| nodeObj = processSingleInstanceNode(curNode, curNodeInfo, |
| parentNodeInfo); |
| break; |
| case YANG_MULTI_INSTANCE_NODE: |
| nodeObj = processMultiInstanceNode( |
| curNode, curNodeInfo, listNodeInfo, parentNodeInfo); |
| break; |
| case YANG_CHOICE_NODE: |
| nodeObj = processChoiceNode(curNode, parentNodeInfo); |
| break; |
| case YANG_NON_DATA_NODE: |
| if (curNode instanceof YangCase) { |
| nodeObj = processCaseNode(curNode, parentNodeInfo); |
| } |
| break; |
| case YANG_AUGMENT_NODE: |
| nodeObj = processAugmentNode(curNode, parentNodeInfo); |
| break; |
| default: |
| throw new YtbException( |
| "Non processable schema node has arrived for adding " + |
| "it in YDT tree"); |
| } |
| // Processes leaf/leaf-list only when object has value, else it skips. |
| if (nodeObj != null) { |
| processLeaves(curNode); |
| processLeavesList(curNode); |
| } |
| return nodeObj; |
| } |
| |
| /** |
| * Processes single instance node which is added to the YDT tree. |
| * |
| * @param curNode current YANG node |
| * @param curNodeInfo current YDT node info |
| * @param parentNodeInfo parent YDT node info |
| * @return object of the current node |
| */ |
| private Object processSingleInstanceNode(YangNode curNode, |
| YtbNodeInfo curNodeInfo, |
| YtbNodeInfo parentNodeInfo) { |
| Object childObj = getChildObject(curNode, parentNodeInfo); |
| if (childObj != null) { |
| addChildNodeInYdt(childObj, curNode, curNodeInfo); |
| } |
| return childObj; |
| } |
| |
| /** |
| * Processes multi instance node which has to be added to the YDT tree. |
| * For the first instance in the list, iterator is created and added to |
| * the list. For second instance or more the iterator from first instance |
| * is taken and iterated through to get the object of parent. |
| * |
| * @param curNode current list node |
| * @param curNodeInfo current node info for list |
| * @param listNodeInfo previous instance node info of list |
| * @param parentNodeInfo parent node info of list |
| * @return object of the current instance |
| */ |
| private Object processMultiInstanceNode(YangNode curNode, |
| YtbNodeInfo curNodeInfo, |
| YtbNodeInfo listNodeInfo, |
| YtbNodeInfo parentNodeInfo) { |
| Object childObj = null; |
| /* |
| * When YANG list comes to this flow for first time, its YTB node |
| * will be null. When it comes for the second or more content, then |
| * the list would have been already set for that node. According to |
| * set or not set this flow will be proceeded. |
| */ |
| if (listNodeInfo == null) { |
| List<Object> childObjList = (List<Object>) getChildObject( |
| curNode, parentNodeInfo); |
| if (nonEmpty(childObjList)) { |
| Iterator<Object> listItr = childObjList.iterator(); |
| if (!listItr.hasNext()) { |
| return null; |
| //TODO: Handle the subtree filtering with no list entries. |
| } |
| childObj = listItr.next(); |
| /* |
| * For that node the iterator is set. So the next time for |
| * the list this iterator will be taken. |
| */ |
| curNodeInfo.setListIterator(listItr); |
| } |
| } else { |
| /* |
| * If the list value comes for second or more time, that list |
| * node will be having YTB node info, where iterator can be |
| * retrieved and check if any more contents are present. If |
| * present those will be processed. |
| */ |
| curNodeInfo.setListIterator(listNodeInfo.getListIterator()); |
| if (listNodeInfo.getListIterator().hasNext()) { |
| childObj = listNodeInfo.getListIterator().next(); |
| } |
| } |
| if (childObj != null) { |
| addChildNodeInYdt(childObj, curNode, curNodeInfo); |
| } |
| return childObj; |
| } |
| |
| /** |
| * Processes choice node which adds a map to the parent node info of |
| * choice name and the case object. The object taken for choice node is |
| * of case object with choice name. Also, this Skips the addition of choice |
| * to YDT. |
| * |
| * @param curNode current choice node |
| * @param parentNodeInfo parent YTB node info |
| * @return object of the choice node |
| */ |
| private Object processChoiceNode(YangNode curNode, |
| YtbNodeInfo parentNodeInfo) { |
| /* |
| * Retrieves the parent YTB info, to take the object of parent, so as |
| * to check the child attribute from the object. |
| */ |
| Object childObj = getChildObject(curNode, parentNodeInfo); |
| if (childObj != null) { |
| Map<String, Object> choiceCaseMap = parentNodeInfo |
| .getChoiceCaseMap(); |
| if (choiceCaseMap == null) { |
| choiceCaseMap = new HashMap<>(); |
| parentNodeInfo.setChoiceCaseMap(choiceCaseMap); |
| } |
| choiceCaseMap.put(curNode.getName(), childObj); |
| } |
| return childObj; |
| } |
| |
| /** |
| * Processes case node from the map contents that is filled by choice |
| * nodes. Object of choice is taken when choice name and case class name |
| * matches. When the case node is not present in the map it returns null. |
| * |
| * @param curNode current case node |
| * @param parentNodeInfo choice parent node info |
| * @return object of the case node |
| */ |
| private Object processCaseNode(YangNode curNode, |
| YtbNodeInfo parentNodeInfo) { |
| Object childObj = null; |
| if (parentNodeInfo.getChoiceCaseMap() != null) { |
| childObj = getCaseObjectFromChoice(parentNodeInfo, |
| curNode); |
| } |
| if (childObj != null) { |
| /* |
| * Sets the case object in parent info, so that rest of the case |
| * children can use it as parent. Case is not added in YDT. |
| */ |
| parentNodeInfo.setCaseObject(childObj); |
| } |
| return childObj; |
| } |
| |
| /** |
| * Processes augment node, which is not added in the YDT, but binds |
| * itself to the parent YTB info, so rest of its child nodes can use for |
| * adding themselves to the YDT tree. If there is no augment node added |
| * in map or if the augment module is not registered, then it returns null. |
| * |
| * @param curNode current augment node |
| * @param parentNodeInfo augment parent node info |
| * @return object of the augment node |
| */ |
| private Object processAugmentNode(YangNode curNode, |
| YtbNodeInfo parentNodeInfo) { |
| String className = curNode.getJavaClassNameOrBuiltInType(); |
| String pkgName = curNode.getJavaPackage(); |
| Object parentObj = getParentObjectOfNode(parentNodeInfo, |
| curNode.getParent()); |
| Map augmentMap; |
| try { |
| augmentMap = (Map) getAttributeOfObject(parentObj, |
| YANG_AUGMENTED_INFO_MAP); |
| /* |
| * Gets the registered module class. Loads the class and gets the |
| * augment class. |
| */ |
| Class moduleClass = getClassLoaderForAugment(curNode, registry); |
| if (moduleClass == null) { |
| return null; |
| } |
| Class augmentClass = moduleClass.getClassLoader().loadClass( |
| pkgName + PERIOD + className); |
| Object childObj = augmentMap.get(augmentClass); |
| parentNodeInfo.setAugmentObject(childObj); |
| return childObj; |
| } catch (ClassNotFoundException | NoSuchMethodException e) { |
| throw new YtbException(e); |
| } |
| } |
| |
| /** |
| * Returns the YTB info from the parent node, so that its own bounded |
| * object can be taken out. |
| * |
| * @return parent node YTB node info |
| */ |
| private YtbNodeInfo getParentYtbInfo() { |
| YdtExtendedContext parentExtContext = extBuilder.getCurNode(); |
| return (YtbNodeInfo) parentExtContext.getAppInfo(YTB); |
| } |
| |
| /** |
| * Returns the child object from the parent object. Uses java name of the |
| * current node to search the attribute in the parent object. |
| * |
| * @param curNode current YANG node |
| * @param parentNodeInfo parent YTB node info |
| * @return object of the child node |
| */ |
| private Object getChildObject(YangNode curNode, |
| YtbNodeInfo parentNodeInfo) { |
| String nodeJavaName = curNode.getJavaAttributeName(); |
| Object parentObj = getParentObjectOfNode(parentNodeInfo, |
| curNode.getParent()); |
| try { |
| return getAttributeOfObject(parentObj, nodeJavaName); |
| } catch (NoSuchMethodException e) { |
| throw new YtbException(e); |
| } |
| } |
| |
| /** |
| * Adds the child node to the YDT by taking operation type from the |
| * object. Also, binds the object to the YDT node through YTB node info. |
| * |
| * @param childObj node object |
| * @param curNode current YANG node |
| * @param curNodeInfo current YTB info |
| */ |
| private void addChildNodeInYdt(Object childObj, YangNode curNode, |
| YtbNodeInfo curNodeInfo) { |
| YdtContextOperationType opType = |
| getNodeOpType(childObj, getOpTypeName(curNode)); |
| extBuilder.addChild(opType, curNode); |
| YdtExtendedContext curExtContext = extBuilder.getCurNode(); |
| curNodeInfo.setYangObject(childObj); |
| curExtContext.addAppInfo(YTB, curNodeInfo); |
| } |
| |
| /** |
| * Processes every leaf in a YANG node. Iterates through the leaf, takes |
| * value from the leaf and adds it to the YDT with value. If value is not |
| * present, and select leaf is set, adds it to the YDT without value. |
| * |
| * @param yangNode leaves holder node |
| */ |
| private void processLeaves(YangNode yangNode) { |
| if (yangNode instanceof YangLeavesHolder) { |
| List<YangLeaf> leavesList = ((YangLeavesHolder) yangNode) |
| .getListOfLeaf(); |
| if (leavesList != null) { |
| for (YangLeaf yangLeaf : leavesList) { |
| YtbNodeInfo parentYtbInfo = getParentYtbInfo(); |
| Object parentObj = getParentObjectOfNode(parentYtbInfo, |
| yangNode); |
| Object leafType; |
| try { |
| leafType = getAttributeOfObject(parentObj, |
| getJavaName(yangLeaf)); |
| } catch (NoSuchMethodException e) { |
| throw new YtbException(e); |
| } |
| |
| addLeafWithValue(yangNode, yangLeaf, parentObj, leafType); |
| addLeafWithoutValue(yangNode, yangLeaf, parentObj); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Processes every leaf-list in a YANG node for adding the value in YDT. |
| * |
| * @param yangNode list of leaf-list holder node |
| */ |
| private void processLeavesList(YangNode yangNode) { |
| if (yangNode instanceof YangLeavesHolder) { |
| List<YangLeafList> listOfLeafList = |
| ((YangLeavesHolder) yangNode).getListOfLeafList(); |
| |
| if (listOfLeafList != null) { |
| for (YangLeafList yangLeafList : listOfLeafList) { |
| addToBuilder(yangNode, yangLeafList); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Processes the list of objects of the leaf list and adds the leaf list |
| * value to the builder. |
| * |
| * @param yangNode YANG node |
| * @param leafList YANG leaf list |
| */ |
| private void addToBuilder(YangNode yangNode, YangLeafList leafList) { |
| YtbNodeInfo ytbNodeInfo = getParentYtbInfo(); |
| Object parentObj = getParentObjectOfNode(ytbNodeInfo, yangNode); |
| List<Object> obj; |
| try { |
| obj = (List<Object>) getAttributeOfObject(parentObj, |
| getJavaName(leafList)); |
| } catch (NoSuchMethodException e) { |
| throw new YtbException(e); |
| } |
| if (obj != null) { |
| addLeafListValue(yangNode, parentObj, leafList, obj); |
| } |
| } |
| |
| /** |
| * Adds the leaf list value to the YDT builder by taking the string value |
| * from the data type. |
| * |
| * @param yangNode YANG node |
| * @param parentObj parent object |
| * @param leafList YANG leaf list |
| * @param obj list of objects |
| */ |
| private void addLeafListValue(YangNode yangNode, Object parentObj, |
| YangLeafList leafList, List<Object> obj) { |
| |
| Set<String> leafListVal = new LinkedHashSet<>(); |
| boolean isEmpty = false; |
| for (Object object : obj) { |
| String val = getStringFromType(yangNode, parentObj, |
| getJavaName(leafList), object, |
| leafList.getDataType()); |
| isEmpty = isTypeEmpty(val, leafList.getDataType()); |
| if (isEmpty) { |
| if (val.equals(TRUE)) { |
| addLeafList(leafListVal, leafList); |
| } |
| break; |
| } |
| if (!"".equals(val)) { |
| leafListVal.add(val); |
| } |
| } |
| if (!isEmpty && !leafListVal.isEmpty()) { |
| addLeafList(leafListVal, leafList); |
| } |
| } |
| |
| /** |
| * Adds set of leaf list values in the builder and traverses back to the |
| * holder. |
| * |
| * @param leafListVal set of values |
| * @param leafList YANG leaf list |
| */ |
| private void addLeafList(Set<String> leafListVal, YangLeafList leafList) { |
| extBuilder.addLeafList(leafListVal, leafList); |
| extBuilder.traverseToParentWithoutValidation(); |
| } |
| |
| /** |
| * Returns the schema node of notification from the root node. Gets the |
| * enum value from event object and gives it to the root schema node for |
| * getting back the notification schema node. |
| * |
| * @return YANG schema node of notification |
| */ |
| private YangSchemaNode getSchemaNodeOfNotification() { |
| |
| Object eventObjType = getAttributeFromInheritance(rootObj, STR_TYPE); |
| String opTypeValue = String.valueOf(eventObjType); |
| |
| if (opTypeValue.equals(STR_NULL) || opTypeValue.isEmpty()) { |
| throw new YtbException( |
| "There is no notification present for the event. Invalid " + |
| "input for notification."); |
| } |
| try { |
| return rootSchema.getNotificationSchemaNode(opTypeValue); |
| } catch (DataModelException e) { |
| throw new YtbException(e); |
| } |
| } |
| |
| /** |
| * Returns the object of the notification by retrieving the attributes |
| * from the event class object. |
| * |
| * @return notification YANG object |
| */ |
| private Object getObjOfNotification() { |
| |
| Object eventSubjectObj = |
| getAttributeFromInheritance(rootObj, STR_SUBJECT); |
| String notificationName = rootSchema.getJavaAttributeName(); |
| try { |
| return getAttributeOfObject(eventSubjectObj, notificationName); |
| } catch (NoSuchMethodException e) { |
| throw new YtbException(e); |
| } |
| } |
| |
| /** |
| * Returns case object from the map that is bound to the parent node |
| * info. For any case node, only when the key and value is matched the |
| * object of the case is provided. If a match is not found, null is |
| * returned. |
| * |
| * @param parentNodeInfo parent YTB node info |
| * @param caseNode case schema node |
| * @return object of the case node |
| */ |
| private Object getCaseObjectFromChoice(YtbNodeInfo parentNodeInfo, |
| YangSchemaNode caseNode) { |
| String javaName = getCapitalCase( |
| caseNode.getJavaClassNameOrBuiltInType()); |
| String choiceName = ((YangNode) caseNode).getParent().getName(); |
| Map<String, Object> mapObj = parentNodeInfo.getChoiceCaseMap(); |
| Object caseObj = mapObj.get(choiceName); |
| Class<?> interfaceClass = getInterfaceClassFromImplClass(caseObj); |
| return interfaceClass.getSimpleName().equals(javaName) ? caseObj : null; |
| } |
| |
| /** |
| * Adds leaf to YDT when value is present. For primitive types, in order |
| * to avoid default values, the value select is set or not is checked and |
| * then added. |
| * |
| * @param holder leaf holder |
| * @param yangLeaf YANG leaf node |
| * @param parentObj leaf holder object |
| * @param leafType object of leaf type |
| */ |
| private void addLeafWithValue(YangSchemaNode holder, YangLeaf yangLeaf, |
| Object parentObj, Object leafType) { |
| String fieldValue = null; |
| if (isTypePrimitive(yangLeaf.getDataType())) { |
| fieldValue = getLeafValueFromValueSetFlag(holder, parentObj, |
| yangLeaf, leafType); |
| /* |
| * Checks the object is present or not, when type is |
| * non-primitive. And adds the value from the respective data type. |
| */ |
| } else if (leafType != null) { |
| fieldValue = getStringFromType(holder, parentObj, |
| getJavaName(yangLeaf), leafType, |
| yangLeaf.getDataType()); |
| } |
| |
| if (nonEmpty(fieldValue)) { |
| boolean isEmpty = isTypeEmpty(fieldValue, |
| yangLeaf.getDataType()); |
| if (isEmpty) { |
| if (!fieldValue.equals(TRUE)) { |
| return; |
| } |
| fieldValue = null; |
| } |
| extBuilder.addLeaf(fieldValue, yangLeaf); |
| extBuilder.traverseToParentWithoutValidation(); |
| } |
| } |
| |
| /** |
| * Returns the value as true if direct or referred type from leafref or |
| * derived points to empty data type; false otherwise. |
| * |
| * @param fieldValue value of the leaf |
| * @param dataType type of the leaf |
| * @return true if type is empty; false otherwise. |
| */ |
| private boolean isTypeEmpty(String fieldValue, YangType<?> dataType) { |
| if (fieldValue.equals(TRUE) || fieldValue.equals(FALSE)) { |
| switch (dataType.getDataType()) { |
| case EMPTY: |
| return true; |
| |
| case LEAFREF: |
| YangLeafRef leafRef = |
| (YangLeafRef) dataType.getDataTypeExtendedInfo(); |
| return isTypeEmpty(fieldValue, |
| leafRef.getEffectiveDataType()); |
| case DERIVED: |
| YangDerivedInfo info = |
| (YangDerivedInfo) dataType |
| .getDataTypeExtendedInfo(); |
| YangDataTypes type = info.getEffectiveBuiltInType(); |
| return type == EMPTY; |
| |
| default: |
| return false; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Adds leaf without value, when the select leaf bit is set. |
| * |
| * @param holder leaf holder |
| * @param yangLeaf YANG leaf node |
| * @param parentObj leaf holder object |
| */ |
| private void addLeafWithoutValue(YangSchemaNode holder, YangLeaf yangLeaf, |
| Object parentObj) { |
| |
| String selectLeaf; |
| try { |
| selectLeaf = isValueOrSelectLeafSet(holder, parentObj, |
| getJavaName(yangLeaf), |
| IS_SELECT_LEAF_SET_METHOD); |
| } catch (NoSuchMethodException e) { |
| selectLeaf = FALSE; |
| } |
| if (selectLeaf.equals(TRUE)) { |
| extBuilder.addLeaf(null, yangLeaf); |
| extBuilder.traverseToParentWithoutValidation(); |
| } |
| } |
| |
| /** |
| * Returns the value of type, after checking the value leaf flag. If the |
| * flag is set, then it takes the value else returns null. |
| * |
| * @param holder leaf holder |
| * @param parentObj parent object |
| * @param yangLeaf YANG leaf node |
| * @param leafType object of leaf type |
| * @return value of type |
| */ |
| private String getLeafValueFromValueSetFlag(YangSchemaNode holder, Object parentObj, |
| YangLeaf yangLeaf, Object leafType) { |
| |
| String valueOfLeaf; |
| try { |
| valueOfLeaf = isValueOrSelectLeafSet(holder, parentObj, |
| getJavaName(yangLeaf), |
| IS_LEAF_VALUE_SET_METHOD); |
| } catch (NoSuchMethodException e) { |
| throw new YtbException(e); |
| } |
| if (valueOfLeaf.equals(TRUE)) { |
| return getStringFromType(holder, parentObj, |
| getJavaName(yangLeaf), leafType, |
| yangLeaf.getDataType()); |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the node info which can be processed, by eliminating the nodes |
| * which need not to be processed at normal conditions such as RPC, |
| * notification and augment. |
| * |
| * @param curNode current node |
| * @return info of node which needs processing |
| */ |
| private YtbTraversalInfo getProcessableInfo(YangNode curNode) { |
| if (curNode.getNextSibling() != null) { |
| YangNode sibling = curNode.getNextSibling(); |
| while (isNonProcessableNode(sibling)) { |
| sibling = sibling.getNextSibling(); |
| } |
| if (sibling != null) { |
| return new YtbTraversalInfo(sibling, SIBLING); |
| } |
| } |
| return new YtbTraversalInfo(curNode.getParent(), PARENT); |
| } |
| |
| } |