[ONOS-6057] Model converter : Object to data node conversion.
Change-Id: Ib53474edec7a2abb5806f83f09505483ec6dd447
diff --git a/runtime/src/main/java/org/onosproject/yang/runtime/DefaultYangSerializerContext.java b/runtime/src/main/java/org/onosproject/yang/runtime/DefaultYangSerializerContext.java
index 1ee5b1f..cc9df84 100644
--- a/runtime/src/main/java/org/onosproject/yang/runtime/DefaultYangSerializerContext.java
+++ b/runtime/src/main/java/org/onosproject/yang/runtime/DefaultYangSerializerContext.java
@@ -41,7 +41,7 @@
@Override
public SchemaContext getContext() {
- return null;
+ return rootContext;
}
@Override
diff --git a/runtime/src/main/java/org/onosproject/yang/runtime/helperutils/RuntimeHelper.java b/runtime/src/main/java/org/onosproject/yang/runtime/helperutils/RuntimeHelper.java
index 1cd1dc4..79fe85d 100644
--- a/runtime/src/main/java/org/onosproject/yang/runtime/helperutils/RuntimeHelper.java
+++ b/runtime/src/main/java/org/onosproject/yang/runtime/helperutils/RuntimeHelper.java
@@ -40,6 +40,8 @@
public static final String OP_PARAM = "OpParam";
public static final String PERIOD = ".";
public static final String SERVICE = "Service";
+ public static final String DEFAULT_CAPS = "Default";
+ public static final String UNDER_SCORE = "_";
// Forbid construction.
private RuntimeHelper() {
diff --git a/runtime/src/main/java/org/onosproject/yang/runtime/impl/DataTreeBuilderHelper.java b/runtime/src/main/java/org/onosproject/yang/runtime/impl/DataTreeBuilderHelper.java
new file mode 100644
index 0000000..d9c3ce1
--- /dev/null
+++ b/runtime/src/main/java/org/onosproject/yang/runtime/impl/DataTreeBuilderHelper.java
@@ -0,0 +1,1075 @@
+/*
+ * Copyright 2017-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.yang.runtime.impl;
+
+import org.onosproject.yang.compiler.datamodel.RpcNotificationContainer;
+import org.onosproject.yang.compiler.datamodel.TraversalType;
+import org.onosproject.yang.compiler.datamodel.YangAugment;
+import org.onosproject.yang.compiler.datamodel.YangAugmentableNode;
+import org.onosproject.yang.compiler.datamodel.YangCase;
+import org.onosproject.yang.compiler.datamodel.YangChoice;
+import org.onosproject.yang.compiler.datamodel.YangDerivedInfo;
+import org.onosproject.yang.compiler.datamodel.YangLeaf;
+import org.onosproject.yang.compiler.datamodel.YangLeafList;
+import org.onosproject.yang.compiler.datamodel.YangLeafRef;
+import org.onosproject.yang.compiler.datamodel.YangLeavesHolder;
+import org.onosproject.yang.compiler.datamodel.YangList;
+import org.onosproject.yang.compiler.datamodel.YangNode;
+import org.onosproject.yang.compiler.datamodel.YangSchemaNode;
+import org.onosproject.yang.compiler.datamodel.YangType;
+import org.onosproject.yang.compiler.datamodel.utils.builtindatatype.YangDataTypes;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.InnerNode;
+import org.onosproject.yang.model.LeafNode;
+
+import java.util.ArrayList;
+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.yang.compiler.datamodel.TraversalType.CHILD;
+import static org.onosproject.yang.compiler.datamodel.TraversalType.PARENT;
+import static org.onosproject.yang.compiler.datamodel.TraversalType.ROOT;
+import static org.onosproject.yang.compiler.datamodel.TraversalType.SIBLING;
+import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.nonEmpty;
+import static org.onosproject.yang.compiler.datamodel.utils.builtindatatype.YangDataTypes.EMPTY;
+import static org.onosproject.yang.model.DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE;
+import static org.onosproject.yang.model.DataNode.Type.MULTI_INSTANCE_NODE;
+import static org.onosproject.yang.model.DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE;
+import static org.onosproject.yang.model.DataNode.Type.SINGLE_INSTANCE_NODE;
+import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.DEFAULT_CAPS;
+import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.PERIOD;
+import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.getCapitalCase;
+import static org.onosproject.yang.runtime.impl.ModelConverterUtil.getAttributeOfObject;
+import static org.onosproject.yang.runtime.impl.ModelConverterUtil.getAugmentObject;
+import static org.onosproject.yang.runtime.impl.ModelConverterUtil.getClassLoaderForAugment;
+import static org.onosproject.yang.runtime.impl.ModelConverterUtil.getInterfaceClassFromImplClass;
+import static org.onosproject.yang.runtime.impl.ModelConverterUtil.getJavaName;
+import static org.onosproject.yang.runtime.impl.ModelConverterUtil.getParentObjectOfNode;
+import static org.onosproject.yang.runtime.impl.ModelConverterUtil.getStringFromType;
+import static org.onosproject.yang.runtime.impl.ModelConverterUtil.isAugmentNode;
+import static org.onosproject.yang.runtime.impl.ModelConverterUtil.isMultiInstanceNode;
+import static org.onosproject.yang.runtime.impl.ModelConverterUtil.isNodeProcessCompleted;
+import static org.onosproject.yang.runtime.impl.ModelConverterUtil.isNonProcessableNode;
+import static org.onosproject.yang.runtime.impl.ModelConverterUtil.isTypePrimitive;
+import static org.onosproject.yang.runtime.impl.ModelConverterUtil.isValueOrSelectLeafSet;
+
+
+/**
+ * Implements traversal of YANG node and its corresponding object, resulting
+ * in building of the data tree.
+ */
+public class DataTreeBuilderHelper {
+
+ private static final String TRUE = "true";
+ private static final String IS_LEAF_VALUE_SET_METHOD = "isLeafValueSet";
+ private static final String AUGMENTATIONS = "augmentations";
+ private static final String FALSE = "false";
+
+ /**
+ * Default YANG model registry.
+ */
+ private final DefaultYangModelRegistry reg;
+
+ /**
+ * Current instance of the data node builder where the tree is built.
+ */
+ private DataNode.Builder 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;
+
+ /**
+ * Yang node for which exit builder is being processed.
+ */
+ private YangSchemaNode exitBuilderSchema;
+
+ /**
+ * Creates an instance of data tree builder helper.
+ *
+ * @param reg default model registry
+ */
+ public DataTreeBuilderHelper(DefaultYangModelRegistry reg) {
+ this.reg = reg;
+ }
+
+ /**
+ * Sets exit builder.
+ *
+ * @param extBuilder data node builder
+ */
+ public void setExtBuilder(DataNode.Builder extBuilder) {
+ this.extBuilder = extBuilder;
+ }
+
+ /**
+ * Creates data tree from the root object, by traversing through YANG data
+ * model node, and simultaneously checking the object nodes presence and
+ * walking the object.
+ *
+ * @param curSchema current root node schema
+ * @param builder data node builder
+ * @param obj current root object
+ */
+ DataNode.Builder getDataTree(YangSchemaNode curSchema, DataNode.Builder builder,
+ Object obj) {
+ extBuilder = builder;
+ rootObj = obj;
+ rootSchema = curSchema;
+ YangNode curNode = (YangNode) curSchema;
+ TraversalType curTraversal = ROOT;
+ DataTreeNodeInfo listNodeInfo = null;
+ DataTreeNodeInfo augmentNodeInfo = null;
+
+ do {
+ /*
+ * 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(curNode);
+ }
+
+ 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
+ * data tree.
+ */
+ processApplicationRootNode();
+ } else {
+ /*
+ * Gets the object corresponding to current schema node.
+ * If object exists, this adds the corresponding data node
+ * to the tree and returns the object. Else returns null.
+ */
+ Object processedObject = processCurSchemaNode(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.
+ */
+ ModelConverterTraversalInfo 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 = getParentInfo();
+ 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)) {
+ ModelConverterTraversalInfo traverseInfo = getProcessableInfo(curNode);
+ curNode = traverseInfo.getYangNode();
+ curTraversal = traverseInfo.getTraverseType();
+ }
+ } else if (curNode.getNextSibling() != null) {
+ if (isNodeProcessCompleted(curNode, curTraversal)) {
+ break;
+ }
+ if (isMultiInstanceNode(curNode)) {
+ listNodeInfo = getCurNodeInfoAndTraverseBack(curNode);
+ augmentNodeInfo = null;
+ continue;
+ }
+ curTraversal = SIBLING;
+ augmentNodeInfo = null;
+ traverseToParent(curNode);
+ //here if current node does have a sibling node but current
+ // node is equal to the root schema then it will fail because
+ // our current root object does not have info about its sibling.
+ if (!curNode.equals(rootSchema)) {
+ if (curNode instanceof YangAugment) {
+ curTraversal = PARENT;
+ continue;
+ }
+ if (isNonProcessableNode(curNode)) {
+ ModelConverterTraversalInfo traverseInfo = getProcessableInfo(curNode);
+ curNode = traverseInfo.getYangNode();
+ curTraversal = traverseInfo.getTraverseType();
+ } else {
+ curNode = curNode.getNextSibling();
+ }
+ }
+ } else {
+ if (isNodeProcessCompleted(curNode, curTraversal)) {
+ break;
+ }
+ if (isMultiInstanceNode(curNode)) {
+ listNodeInfo = getCurNodeInfoAndTraverseBack(curNode);
+ augmentNodeInfo = null;
+ continue;
+ }
+ curTraversal = PARENT;
+ traverseToParent(curNode);
+ curNode = getParentSchemaNode(curNode);
+ }
+ } while (curNode != null && !curNode.equals(curSchema));
+ return extBuilder;
+ }
+
+ /**
+ * 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;
+ }
+ if (!curNode.equals(rootSchema)) {
+ return curNode.getParent();
+ }
+ return curNode;
+ }
+
+ /**
+ * Processes root YANG node and adds it as a child to the data tree
+ * builder which is created earlier.
+ */
+ private void processApplicationRootNode() {
+ DataTreeNodeInfo nodeInfo = new DataTreeNodeInfo();
+ nodeInfo.setYangObject(rootObj);
+ if (rootSchema instanceof YangList) {
+ nodeInfo.type(MULTI_INSTANCE_NODE);
+ } else {
+ nodeInfo.type(SINGLE_INSTANCE_NODE);
+ }
+ extBuilder.appInfo(nodeInfo);
+ exitBuilderSchema = rootSchema;
+ processLeaves((YangNode) rootSchema, nodeInfo);
+ processLeavesList((YangNode) rootSchema, nodeInfo);
+ }
+
+ /**
+ * 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 data tree.
+ *
+ * @param curNode current YANG node
+ */
+ private void traverseToParent(YangNode curNode) {
+ if (curNode instanceof YangCase || curNode instanceof YangChoice
+ || curNode instanceof YangAugment) {
+ return;
+ }
+ if (!curNode.equals(rootSchema)) {
+ extBuilder = extBuilder.exitNode();
+ }
+ }
+
+ /**
+ * Returns the current data tree builder info of the data node builder, and
+ * then traverses back to parent. In case of multi instance node the
+ * previous node info is used for iterating through the list.
+ *
+ * @param curNode current YANG node
+ * @return current data tree builder info
+ */
+ private DataTreeNodeInfo getCurNodeInfoAndTraverseBack(YangNode curNode) {
+ DataTreeNodeInfo appInfo = getParentInfo();
+ if (!curNode.equals(rootSchema)) {
+ extBuilder = extBuilder.exitNode();
+ }
+ 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,
+ DataTreeNodeInfo augmentNodeInfo) {
+ if (augmentNodeInfo == null) {
+ List<YangAugment> augmentList = ((YangAugmentableNode) curNode)
+ .getAugmentedInfoList();
+ if (nonEmpty(augmentList)) {
+ DataTreeNodeInfo parentNodeInfo = getParentInfo();
+ 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 data tree
+ * builder 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 processCurSchemaNode(YangNode curNode,
+ DataTreeNodeInfo listNodeInfo) {
+ DataTreeNodeInfo curNodeInfo = new DataTreeNodeInfo();
+ Object nodeObj = null;
+ DataTreeNodeInfo parentNodeInfo = getParentInfo();
+ if (curNode instanceof YangAugment) {
+ YangNode augmented = ((YangAugment) curNode).getAugmentedNode();
+ String name;
+ if (augmented instanceof YangCase) {
+ name = augmented.getJavaAttributeName();
+ Object obj;
+ try {
+ obj = getAttributeOfObject(
+ parentNodeInfo.getYangObject(), name);
+ } catch (NoSuchMethodException e) {
+ throw new ModelConvertorException(
+ "Not processable case node with augment in " +
+ "data tree");
+ }
+ parentNodeInfo = new DataTreeNodeInfo();
+ parentNodeInfo.setYangObject(obj);
+ parentNodeInfo.type(SINGLE_INSTANCE_NODE);
+ }
+ }
+
+ switch (curNode.getYangSchemaNodeType()) {
+ case YANG_SINGLE_INSTANCE_NODE:
+ curNodeInfo.type(SINGLE_INSTANCE_NODE);
+ nodeObj = processSingleInstanceNode(curNode, curNodeInfo,
+ parentNodeInfo);
+ break;
+ case YANG_MULTI_INSTANCE_NODE:
+ curNodeInfo.type(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 ModelConvertorException(
+ "Non processable schema node has arrived for adding " +
+ "it in data tree");
+ }
+ // Processes leaf/leaf-list only when object has value, else it skips.
+ if (nodeObj != null) {
+ processLeaves(curNode, parentNodeInfo);
+ processLeavesList(curNode, parentNodeInfo);
+ }
+ return nodeObj;
+ }
+
+ /**
+ * Processes single instance node which is added to the data tree.
+ *
+ * @param curNode current YANG node
+ * @param curNodeInfo current data tree node info
+ * @param parentNodeInfo parent data tree node info
+ * @return object of the current node
+ */
+ private Object processSingleInstanceNode(YangNode curNode,
+ DataTreeNodeInfo curNodeInfo,
+ DataTreeNodeInfo parentNodeInfo) {
+ Object childObj = getChildObject(curNode, parentNodeInfo);
+ if (childObj != null) {
+ curNodeInfo.setYangObject(childObj);
+ curNodeInfo.type(SINGLE_INSTANCE_NODE);
+ processChildNode(curNode, curNodeInfo);
+ }
+ return childObj;
+ }
+
+ /**
+ * Processes multi instance node which has to be added to the data 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,
+ DataTreeNodeInfo curNodeInfo,
+ DataTreeNodeInfo listNodeInfo,
+ DataTreeNodeInfo parentNodeInfo) {
+ Object childObj = null;
+ /*
+ * When YANG list comes to this flow for first time, its data 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 data tree builder 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) {
+ curNodeInfo.setYangObject(childObj);
+ processChildNode(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 data tree.
+ *
+ * @param curNode current choice node
+ * @param parentNodeInfo parent data tree info
+ * @return object of the choice node
+ */
+ Object processChoiceNode(YangNode curNode,
+ DataTreeNodeInfo parentNodeInfo) {
+ /*
+ * Retrieves the parent data tree 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
+ */
+ Object processCaseNode(YangNode curNode,
+ DataTreeNodeInfo 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 data tree.
+ */
+ parentNodeInfo.setCaseObject(childObj);
+ }
+ return childObj;
+ }
+
+ /**
+ * Processes augment node, which is not added in the data tree, but binds
+ * itself to the parent data tree node info, so rest of its child nodes can
+ * use for adding themselves to the data 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
+ */
+ Object processAugmentNode(YangNode curNode,
+ DataTreeNodeInfo parentNodeInfo) {
+ String className = curNode.getJavaClassNameOrBuiltInType();
+ String pkgName = curNode.getJavaPackage();
+ Object parentObj = getParentObjectOfNode(parentNodeInfo,
+ curNode.getParent());
+
+ YangNode augmented = ((YangAugment) curNode).getAugmentedNode();
+ if (augmented instanceof YangChoice) {
+ String name = augmented.getJavaAttributeName();
+ try {
+ return getAttributeOfObject(
+ parentNodeInfo.getYangObject(), name);
+ } catch (NoSuchMethodException e) {
+ throw new ModelConvertorException(
+ "Not processable case node with augment in " +
+ "data tree");
+ }
+ }
+
+ Map augmentMap;
+ try {
+ augmentMap = (Map) getAugmentObject(parentObj,
+ AUGMENTATIONS);
+ if (augmentMap != null && !augmentMap.isEmpty()) {
+ /*
+ * Gets the registered module class. Loads the class and gets the
+ * augment class.
+ */
+ Class moduleClass = getClassLoaderForAugment(curNode, reg);
+ if (moduleClass == null) {
+ return null;
+ }
+ Class augmentClass = moduleClass.getClassLoader().loadClass(
+ pkgName + PERIOD + DEFAULT_CAPS + className);
+ Object childObj = augmentMap.get(augmentClass);
+ parentNodeInfo.setAugmentObject(childObj);
+ return childObj;
+ }
+ } catch (ClassNotFoundException | NoSuchMethodException e) {
+ throw new ModelConvertorException(e);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the data tree info from the parent node, so that its own bounded
+ * object can be taken out.
+ *
+ * @return parent node data tree node info
+ */
+ private DataTreeNodeInfo getParentInfo() {
+ return (DataTreeNodeInfo) extBuilder.appInfo();
+ }
+
+ /**
+ * 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 data tree node info
+ * @return object of the child node
+ */
+ Object getChildObject(YangNode curNode,
+ DataTreeNodeInfo parentNodeInfo) {
+ String nodeJavaName = curNode.getJavaAttributeName();
+ Object parentObj = getParentObjectOfNode(parentNodeInfo,
+ curNode.getParent());
+ try {
+ return getAttributeOfObject(parentObj, nodeJavaName);
+ } catch (NoSuchMethodException e) {
+ throw new ModelConvertorException(e);
+ }
+ }
+
+ /**
+ * Adds the child node to the data tree by taking operation type from the
+ * object. Also, binds the object to the data node through data tree node
+ * info.
+ *
+ * @param curNode current YANG node
+ * @param curNodeInfo current data tree info
+ */
+ private void processChildNode(YangNode curNode, DataTreeNodeInfo curNodeInfo) {
+ if (extBuilder == null) {
+ InnerNode.Builder builder = InnerNode.builder(
+ curNode.getName(), curNode.getNameSpace().getModuleNamespace());
+ if (curNode instanceof YangList) {
+ builder.type(MULTI_INSTANCE_NODE);
+ } else {
+ builder.type(SINGLE_INSTANCE_NODE);
+ }
+ extBuilder = builder;
+ } else {
+ extBuilder = extBuilder.createChildBuilder(
+ curNode.getName(), curNode.getNameSpace()
+ .getModuleNamespace()).type(curNodeInfo.type());
+ }
+ exitBuilderSchema = curNode;
+ extBuilder.appInfo(curNodeInfo);
+ }
+
+ /**
+ * Processes every leaf in a YANG node. Iterates through the leaf, takes
+ * value from the leaf and adds it to the data tree with value. If value is
+ * not present, and select leaf is set, adds it to the data tree without
+ * value.
+ *
+ * @param yangNode leaves holder node
+ * @param info data node info
+ */
+ private void processLeaves(YangNode yangNode, DataTreeNodeInfo info) {
+ if (yangNode instanceof YangLeavesHolder) {
+ List<YangLeaf> leavesList = ((YangLeavesHolder) yangNode)
+ .getListOfLeaf();
+ if (leavesList != null) {
+ for (YangLeaf yangLeaf : leavesList) {
+ DataTreeNodeInfo parentInfo = getParentInfo();
+ if (yangNode instanceof YangAugment) {
+ if (info != null) {
+ parentInfo = info;
+ }
+ }
+ if (parentInfo == null) {
+ parentInfo = info;
+ }
+ Object parentObj = getParentObjectOfNode(parentInfo,
+ yangNode);
+ Object leafType;
+ try {
+ leafType = getAttributeOfObject(parentObj,
+ getJavaName(yangLeaf));
+ } catch (NoSuchMethodException e) {
+ throw new ModelConvertorException(e);
+ }
+
+ addLeafWithValue(yangNode, yangLeaf, parentObj, leafType);
+ }
+ }
+ }
+ }
+
+ /**
+ * Processes every leaf-list in a YANG node for adding the value in data
+ * tree.
+ *
+ * @param yangNode list of leaf-list holder node
+ * @param info data node info
+ */
+ private void processLeavesList(YangNode yangNode, DataTreeNodeInfo info) {
+ if (yangNode instanceof YangLeavesHolder) {
+ List<YangLeafList> listOfLeafList =
+ ((YangLeavesHolder) yangNode).getListOfLeafList();
+
+ if (listOfLeafList != null) {
+ for (YangLeafList yangLeafList : listOfLeafList) {
+ addToBuilder(yangNode, yangLeafList, info);
+ }
+ }
+ }
+ }
+
+ /**
+ * 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
+ * @param info data node info
+ */
+ private List<DataNode.Builder> addToBuilder(
+ YangNode yangNode, YangLeafList leafList,
+ DataTreeNodeInfo info) {
+ DataTreeNodeInfo dnbNodeInfo = getParentInfo();
+ if (yangNode instanceof YangAugment) {
+ if (info != null) {
+ dnbNodeInfo = info;
+ }
+ }
+ if (dnbNodeInfo == null) {
+ dnbNodeInfo = info;
+ }
+ Object parentObj = getParentObjectOfNode(dnbNodeInfo, yangNode);
+ List<Object> obj;
+ try {
+ obj = (List<Object>) getAttributeOfObject(parentObj,
+ getJavaName(leafList));
+ } catch (NoSuchMethodException e) {
+ throw new ModelConvertorException(e);
+ }
+ if (obj != null) {
+ return addLeafListValue(yangNode, parentObj, leafList, obj);
+ }
+ return null;
+ }
+
+ /**
+ * Adds the leaf list value to the data tree 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
+ */
+ List<DataNode.Builder> addLeafListValue(
+ YangSchemaNode yangNode, Object parentObj,
+ YangLeafList leafList, List<Object> obj) {
+
+ Set<String> leafListVal = new LinkedHashSet<>();
+ boolean isEmpty = false;
+ for (Object object : obj) {
+ String val = getStringFromType(yangNode, parentObj,
+ getJavaName(leafList), object,
+ leafList.getDataType());
+ isEmpty = isTypeEmpty(val, leafList.getDataType());
+ if (isEmpty) {
+ if (val.equals(TRUE)) {
+ addLeafList(leafListVal, leafList);
+ }
+ break;
+ }
+ if (!val.equals("")) {
+ leafListVal.add(val);
+ }
+ }
+ if (!isEmpty && !leafListVal.isEmpty()) {
+ return addLeafList(leafListVal, leafList);
+ }
+ return null;
+ }
+
+ /**
+ * 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 List<DataNode.Builder> addLeafList(Set<String> leafListVal, YangLeafList
+ leafList) {
+ if (extBuilder != null) {
+ for (String val : leafListVal) {
+ DataNode.Builder leaf = extBuilder.createChildBuilder(
+ leafList.getName(), leafList.getNameSpace().getModuleNamespace(),
+ val);
+ leaf.type(MULTI_INSTANCE_LEAF_VALUE_NODE);
+ leaf.addLeafListValue(val);
+ extBuilder = leaf.exitNode();
+ }
+ return null;
+ }
+ //In case of root node leaf lists.
+ List<DataNode.Builder> builders = new ArrayList<>();
+ for (String val : leafListVal) {
+ DataNode.Builder leaf = LeafNode.builder(
+ leafList.getName(), leafList.getNameSpace().getModuleNamespace())
+ .value(val);
+ leaf.type(MULTI_INSTANCE_LEAF_VALUE_NODE);
+ leaf.addLeafListValue(val);
+ builders.add(leaf);
+ }
+ return builders;
+ }
+
+ /**
+ * 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 data tree node info
+ * @param caseNode case schema node
+ * @return object of the case node
+ */
+ private Object getCaseObjectFromChoice(DataTreeNodeInfo parentNodeInfo,
+ YangSchemaNode caseNode) {
+ String javaName = getCapitalCase(
+ caseNode.getJavaClassNameOrBuiltInType());
+ YangNode parent = ((YangNode) caseNode).getParent();
+ String choiceName;
+ if (parent instanceof YangAugment) {
+ choiceName = ((YangAugment) parent).getAugmentedNode().getName();
+ } else {
+ 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 data tree 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
+ */
+ DataNode.Builder 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 (ModelConverterUtil.nonEmpty(fieldValue)) {
+ boolean isEmpty = isTypeEmpty(fieldValue,
+ yangLeaf.getDataType());
+ if (isEmpty) {
+ if (!fieldValue.equals(TRUE)) {
+ return null;
+ }
+ fieldValue = null;
+ }
+
+ //Create leaf node.
+ return createLeafNode(yangLeaf, fieldValue);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the value as true if direct or referred type from leaf-ref 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;
+ }
+
+ /**
+ * Creates data leaf node.
+ *
+ * @param yangLeaf YANG leaf
+ * @param val value for the leaf
+ */
+ private DataNode.Builder createLeafNode(YangLeaf yangLeaf, Object val) {
+ if (extBuilder != null) {
+ //Add leaf to key leaves.
+ if (yangLeaf.isKeyLeaf()) {
+ extBuilder.addKeyLeaf(yangLeaf.getName(), yangLeaf.getNameSpace()
+ .getModuleNamespace(), val);
+ }
+ //build leaf node and add to parent node.
+ DataNode.Builder leaf = extBuilder.createChildBuilder(
+ yangLeaf.getName(), yangLeaf.getNameSpace()
+ .getModuleNamespace(), val);
+ leaf.type(SINGLE_INSTANCE_LEAF_VALUE_NODE);
+
+ extBuilder = leaf.exitNode();
+ return leaf;
+ }
+ return LeafNode.builder(yangLeaf.getName(), yangLeaf.getNameSpace()
+ .getModuleNamespace())
+ .type(SINGLE_INSTANCE_LEAF_VALUE_NODE)
+ .value(val);
+ }
+
+ /**
+ * 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 ModelConvertorException(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 ModelConverterTraversalInfo getProcessableInfo(YangNode curNode) {
+ if (curNode.getNextSibling() != null) {
+ YangNode sibling = curNode.getNextSibling();
+ while (isNonProcessableNode(sibling)) {
+ sibling = sibling.getNextSibling();
+ }
+ if (sibling != null) {
+ return new ModelConverterTraversalInfo(sibling, SIBLING);
+ }
+ }
+ YangNode parent = curNode.getParent();
+ if (!(parent instanceof RpcNotificationContainer)) {
+ return new ModelConverterTraversalInfo(curNode.getParent(), PARENT);
+ }
+ return new ModelConverterTraversalInfo((YangNode) exitBuilderSchema, PARENT);
+ }
+}
diff --git a/runtime/src/main/java/org/onosproject/yang/runtime/impl/DataTreeNodeInfo.java b/runtime/src/main/java/org/onosproject/yang/runtime/impl/DataTreeNodeInfo.java
new file mode 100644
index 0000000..b3893d5
--- /dev/null
+++ b/runtime/src/main/java/org/onosproject/yang/runtime/impl/DataTreeNodeInfo.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2017-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.yang.runtime.impl;
+
+import org.onosproject.yang.compiler.datamodel.YangAugment;
+import org.onosproject.yang.model.DataNode;
+
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Represents data tree info for all the nodes that are added to the
+ * data tree.Contains the information which can be attached and retrieved
+ * back from data tree while walking.
+ */
+class DataTreeNodeInfo {
+
+ /**
+ * Data node type info.
+ */
+ private DataNode.Type type;
+
+ /**
+ * Object of the corresponding YANG construct. This object is bound to
+ * each and every data node. So, whenever walk of parent and sibling
+ * happens, object can be retrieved from its data node.
+ */
+ private Object yangObject;
+
+ /**
+ * The list iterator since first content of the multi instance node is
+ * faced. With this iterator the node can be walked multiple times till
+ * it becomes empty.
+ */
+ private Iterator<Object> listIterator;
+
+ /**
+ * The current data node's, list of augments are iterated through this
+ * iterator. Every time an augment is built completely, this iterator
+ * gives the next augment node until it becomes empty.
+ */
+ private Iterator<YangAugment> augmentNodeItr;
+
+ /**
+ * The map with case object as value and choice node name as key is added
+ * for the current data tree builder info. Every time a case schema node
+ * comes, it takes this map and checks if it is present.
+ */
+ private Map<String, Object> choiceCaseMap;
+
+ /**
+ * When the case finds its object in map, it assigns it to case object of
+ * the data tree builder info, so when its child wants to take the parent
+ * object, they can take from the data tree builder info's case object.
+ */
+ private Object caseObject;
+
+ /**
+ * When the augment object is present, it assigns it to augment object of
+ * the data tree builder info, so when its child wants to take the parent
+ * object, they can take from the data tree info's augment object.
+ */
+ private Object augmentObject;
+
+ /**
+ * Constructs a default data tree node info.
+ */
+ DataTreeNodeInfo() {
+ }
+
+ /**
+ * Returns the object of the YANG schema node.
+ *
+ * @return YANG node object
+ */
+ Object getYangObject() {
+ return yangObject;
+ }
+
+ /**
+ * Sets the object of the YANG schema node.
+ *
+ * @param yangObject YANG node object
+ */
+ void setYangObject(Object yangObject) {
+ this.yangObject = yangObject;
+ }
+
+ /**
+ * Returns the current list iterator of the YANG schema node.
+ *
+ * @return current list iterator for the schema node
+ */
+ Iterator<Object> getListIterator() {
+ return listIterator;
+ }
+
+ /**
+ * Sets the current list iterator of the YANG schema node.
+ *
+ * @param listIterator current list iterator for the schema node
+ */
+ void setListIterator(Iterator<Object> listIterator) {
+ this.listIterator = listIterator;
+ }
+
+ /**
+ * Returns the map of choice schema name and case object.
+ *
+ * @return choice name and case object map
+ */
+ Map<String, Object> getChoiceCaseMap() {
+ return choiceCaseMap;
+ }
+
+ /**
+ * Sets the map of choice schema name and case object.
+ *
+ * @param choiceCaseMap choice name and case object map
+ */
+ void setChoiceCaseMap(Map<String, Object> choiceCaseMap) {
+ this.choiceCaseMap = choiceCaseMap;
+ }
+
+ /**
+ * Returns the case object.
+ *
+ * @return case object
+ */
+ Object getCaseObject() {
+ return caseObject;
+ }
+
+ /**
+ * Sets the case node object.
+ *
+ * @param caseObject case node object
+ */
+ void setCaseObject(Object caseObject) {
+ this.caseObject = caseObject;
+ }
+
+ /**
+ * Returns the augment node object.
+ *
+ * @return augment node object
+ */
+ Object getAugmentObject() {
+ return augmentObject;
+ }
+
+ /**
+ * Sets the augment node object.
+ *
+ * @param augmentObject augment node object
+ */
+ void setAugmentObject(Object augmentObject) {
+ this.augmentObject = augmentObject;
+ }
+
+ /**
+ * Returns the current list iterator of the YANG augment node.
+ *
+ * @return augment node iterator
+ */
+ Iterator<YangAugment> getAugmentIterator() {
+ return augmentNodeItr;
+ }
+
+ /**
+ * Sets the current list iterator of the YANG augment node.
+ *
+ * @param augmentNodeItr augment node iterator
+ */
+ void setAugmentIterator(Iterator<YangAugment> augmentNodeItr) {
+ this.augmentNodeItr = augmentNodeItr;
+ }
+
+ /**
+ * Returns data node type info.
+ *
+ * @return data node type info
+ */
+ public DataNode.Type type() {
+ return type;
+ }
+
+ /**
+ * Sets data node type info.
+ *
+ * @param type data node type info
+ */
+ public void type(DataNode.Type type) {
+ this.type = type;
+ }
+}
diff --git a/runtime/src/main/java/org/onosproject/yang/runtime/impl/DefaultDataTreeBuilder.java b/runtime/src/main/java/org/onosproject/yang/runtime/impl/DefaultDataTreeBuilder.java
new file mode 100644
index 0000000..7be4b60
--- /dev/null
+++ b/runtime/src/main/java/org/onosproject/yang/runtime/impl/DefaultDataTreeBuilder.java
@@ -0,0 +1,808 @@
+/*
+ * Copyright 2017-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.yang.runtime.impl;
+
+import org.onosproject.yang.compiler.datamodel.RpcNotificationContainer;
+import org.onosproject.yang.compiler.datamodel.YangAugment;
+import org.onosproject.yang.compiler.datamodel.YangAugmentableNode;
+import org.onosproject.yang.compiler.datamodel.YangCase;
+import org.onosproject.yang.compiler.datamodel.YangChoice;
+import org.onosproject.yang.compiler.datamodel.YangLeaf;
+import org.onosproject.yang.compiler.datamodel.YangLeafList;
+import org.onosproject.yang.compiler.datamodel.YangLeavesHolder;
+import org.onosproject.yang.compiler.datamodel.YangList;
+import org.onosproject.yang.compiler.datamodel.YangNode;
+import org.onosproject.yang.compiler.datamodel.YangSchemaNode;
+import org.onosproject.yang.compiler.utils.io.YangPluginConfig;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.InnerNode;
+import org.onosproject.yang.model.LeafModelObject;
+import org.onosproject.yang.model.LeafNode;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ModelObjectId;
+import org.onosproject.yang.model.ResourceData;
+import org.onosproject.yang.runtime.DefaultResourceData;
+
+import java.util.Iterator;
+import java.util.List;
+
+import static org.onosproject.yang.compiler.datamodel.YangSchemaNodeType.YANG_NON_DATA_NODE;
+import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.nonEmpty;
+import static org.onosproject.yang.compiler.translator.tojava.YangJavaModelUtils.getAugmentClassName;
+import static org.onosproject.yang.compiler.utils.io.impl.YangIoUtils.getCamelCase;
+import static org.onosproject.yang.model.DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE;
+import static org.onosproject.yang.model.DataNode.Type.MULTI_INSTANCE_NODE;
+import static org.onosproject.yang.model.DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE;
+import static org.onosproject.yang.model.DataNode.Type.SINGLE_INSTANCE_NODE;
+import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.DEFAULT_CAPS;
+import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.PERIOD;
+import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.getCapitalCase;
+import static org.onosproject.yang.runtime.impl.ModelConverterUtil.getAttributeOfObject;
+import static org.onosproject.yang.runtime.impl.ModelConverterUtil.getJavaName;
+
+/**
+ * Representation of data tree builder which generates YANG data tree from the
+ * class objects which are provided from the applications and return it to the
+ * protocol(s).
+ */
+class DefaultDataTreeBuilder {
+ /*
+ *
+ * ModelObjectId | List<ModelObject> | ResourceId | List<DN>
+ * ---------------|-------------------|----------------------|---------
+ * Null | Null | Form module | null
+ * Class | Null | Form module to node | null
+ * Class +Leaf | Null | From module to leaf | null
+ * Leaf | Null | From module to leaf | null
+ * Null | Class | Form module | class
+ * Class | Class | From module to node | class
+ * Class+leaf | Object | INVALID case | -----
+ */
+
+ /**
+ * Default YANG Model registry for getting the schema node with respect
+ * to class packages.
+ */
+ private final DefaultYangModelRegistry reg;
+
+ /**
+ * Creates and instance of data tree builder.
+ *
+ * @param registry model registry
+ */
+ DefaultDataTreeBuilder(DefaultYangModelRegistry registry) {
+ reg = registry;
+ }
+
+ /**
+ * Returns resource data for given model object data. resource data
+ * contains resource identifier for given model object identifier and
+ * list of data nodes for given model objects.
+ *
+ * @param modelData model object data
+ * @return resource data
+ */
+ ResourceData getResourceData(ModelObjectData modelData) {
+
+ List<ModelObject> modelObjects = modelData.modelObjects();
+ ModelObjectId id = modelData.identifier();
+
+ DefaultResourceData.Builder rscData = DefaultResourceData.builder();
+
+ //Create resource identifier.
+ ModIdToRscIdConverter converter = new ModIdToRscIdConverter(reg);
+ rscData.resourceId(converter.fetchResourceId(id));
+ YangSchemaNode lastIndexNode = converter.getLastIndexNode();
+
+ //If module object list is empty or null then we just need to
+ // create resource identifier.
+ if (!nonEmpty(modelObjects)) {
+ return rscData.build();
+ }
+
+ if (converter.isMoIdWithLeaf() && nonEmpty(modelObjects)) {
+ throw new ModelConvertorException(
+ "invalid module object data when model object identifier" +
+ " contains leaf node, no object should be added to" +
+ " model object list." + modelData);
+ }
+
+ if (id == null || !nonEmpty(id.atomicPaths())) {
+ lastIndexNode = fetchModNode(modelObjects.get(0), converter);
+ }
+
+ //Create data nodes.
+ DataTreeBuilderHelper helper = new DataTreeBuilderHelper(reg);
+ YangSchemaNode curNode;
+ for (Object modObj : modelObjects) {
+ //Do processing of data node conversion from model objects.
+ if (modObj instanceof LeafModelObject) {
+ //Process leaf object.
+ processLeafObj(lastIndexNode, rscData, (LeafModelObject) modObj);
+ } else {
+ curNode = fetchCurNode(modObj, (YangNode) lastIndexNode);
+ if (curNode != null) {
+ processDataNodeConversion((YangNode) curNode, helper,
+ rscData, modObj);
+ } else {
+ throw new ModelConvertorException(
+ "failed to convert model object in data node" +
+ modObj.toString());
+ }
+ }
+ }
+
+ return rscData.build();
+ }
+
+ /**
+ * Process model object to data node conversion.
+ *
+ * @param curNode current root node
+ * @param helper data tree builder helper
+ * @param rscData resource data builder
+ * @param curObj current root object
+ */
+ private void processDataNodeConversion(
+ YangNode curNode, DataTreeBuilderHelper helper,
+ DefaultResourceData.Builder rscData, Object curObj) {
+ if (curNode == null) {
+ return;
+ }
+ DataTreeNodeInfo info = new DataTreeNodeInfo();
+ //Set object in parent node info.
+ setObjInParent(curNode, curObj, info);
+ info.type(SINGLE_INSTANCE_NODE);
+ switch (curNode.getYangSchemaNodeType()) {
+ case YANG_SINGLE_INSTANCE_NODE:
+ case YANG_MULTI_INSTANCE_NODE:
+ processNodeObj(helper, curObj, rscData, curNode);
+ break;
+ case YANG_AUGMENT_NODE:
+ processModelObjects(helper, curNode, rscData, curObj);
+ break;
+ case YANG_CHOICE_NODE:
+ handleChoiceNode(curNode, info, helper, rscData);
+ break;
+ case YANG_NON_DATA_NODE:
+ if (curNode instanceof YangCase) {
+ handleCaseNode(curNode, info, helper, rscData);
+ }
+ break;
+ default:
+ throw new ModelConvertorException(
+ "Non processable schema node has arrived for adding " +
+ "it in data tree");
+ }
+ }
+
+ /**
+ * In last index node we will be having parent node of the current object
+ * so we need to get the current node and start processing it for
+ * conversion.
+ *
+ * @param obj current object
+ * @param parent parent node
+ * @return current node
+ */
+ private YangSchemaNode fetchCurNode(Object obj, YangNode parent) {
+ YangSchemaNode output;
+ if (obj != null && parent != null) {
+ //process all the node which are in data model tree.
+ String name = obj.getClass().getName();
+ YangNode child = parent.getChild();
+ while (child != null) {
+ //search if parent node has choice as child node.
+ if (child instanceof YangChoice) {
+ output = findFromChoiceNode(name, parent);
+ //search if parent node has a case child node
+ } else if (child instanceof YangCase) {
+ output = findFromCaseNode(name, parent);
+ //no need to process non data nodes.
+ } else if (child.getYangSchemaNodeType() == YANG_NON_DATA_NODE) {
+ continue;
+ } else {
+ //search for normal nodes.
+ output = getNode(child, name);
+ }
+ if (output != null) {
+ return output;
+ }
+ child = child.getNextSibling();
+ }
+ return findIfAugmentable(name, parent);
+ }
+ return null;
+ }
+
+
+ /**
+ * Find the node in augment. if current object is a object of augment
+ * node or if object is a object of child node of augment node.
+ *
+ * @param name class qualified name
+ * @param parent parent node
+ * @return current node for object
+ */
+ private YangSchemaNode findIfAugmentable(String name, YangNode parent) {
+ List<YangAugment> augments = ((YangAugmentableNode) parent)
+ .getAugmentedInfoList();
+ YangNode child;
+ YangSchemaNode output;
+ if (nonEmpty(augments)) {
+ //this is if we are having an augment class object.
+ for (YangAugment augment : augments) {
+ output = getNode(augment, name);
+ if (output != null) {
+ return output;
+ }
+ }
+ //this is if we have a child class object which is a
+ // child node of augment node.
+ for (YangAugment augment : augments) {
+ child = augment.getChild();
+ output = getNode(child, name);
+ if (output != null) {
+ return output;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find in choice node if current object is an object of choice/case node.
+ *
+ * @param qName qualified name
+ * @param parent choice's paren node
+ * @return choice node
+ */
+ private YangSchemaNode findFromChoiceNode(String qName, YangSchemaNode parent) {
+ YangNode child = ((YangNode) parent).getChild();
+ YangSchemaNode output;
+ while (child != null) {
+ if (child instanceof YangChoice) {
+ output = findFromCaseNode(qName, child);
+ if (output != null) {
+ return output;
+ }
+ }
+ child = child.getNextSibling();
+ }
+ return null;
+ }
+
+ /**
+ * Find in case if given object is an object of case node.
+ *
+ * @param qName qualified name
+ * @param parent case's parent node
+ * @return case node
+ */
+ private YangSchemaNode findFromCaseNode(String qName, YangSchemaNode parent) {
+ YangNode caseNode = ((YangNode) parent).getChild();
+ String javaName;
+ while (caseNode != null) {
+ javaName = caseNode.getJavaPackage() + PERIOD +
+ DEFAULT_CAPS + getCapitalCase(getCamelCase(
+ caseNode.getName(), null));
+ if (javaName.equals(qName)) {
+ return caseNode;
+ }
+ caseNode = caseNode.getNextSibling();
+ }
+ return findIfAugmentable(qName, (YangNode) parent);
+ }
+
+ /**
+ * Returns the node which has the same java package as the object's package.
+ *
+ * @param child child node
+ * @param pkg java package
+ * @return child node
+ */
+ private YangSchemaNode getNode(YangNode child, String pkg) {
+ String javaName;
+ while (child != null) {
+ if (child instanceof YangAugment) {
+ javaName = child.getJavaPackage() + PERIOD + DEFAULT_CAPS +
+ getAugmentClassName((YangAugment) child,
+ new YangPluginConfig());
+ } else {
+ javaName = child.getJavaPackage() + PERIOD + DEFAULT_CAPS +
+ getCapitalCase(getCamelCase(child.getName(), null));
+ }
+ if (javaName.equals(pkg)) {
+ return child;
+ }
+ child = child.getNextSibling();
+ }
+ return null;
+ }
+
+ /**
+ * Returns module node when model object identifier is null. model object
+ * will be used here to get the module node.
+ *
+ * @param object module object
+ * @param converter identifier converter
+ * @return module node
+ */
+ private YangSchemaNode fetchModNode(ModelObject object,
+ ModIdToRscIdConverter converter) {
+ if (object instanceof LeafModelObject) {
+ LeafModelObject obj = (LeafModelObject) object;
+ return converter.fetchModNodeFromLeaf(obj.leafIdentifier()
+ .getClass().getName());
+ }
+ return converter.fetchModuleNode(object.getClass().getName());
+ }
+
+ /**
+ * Process leaf and leaf list information.
+ *
+ * @param rootNode root node
+ * @param rscData resource data
+ */
+ private void processLeafObj(YangSchemaNode rootNode,
+ DefaultResourceData.Builder rscData,
+ LeafModelObject rootObj) {
+ //handle leaf nodes.
+ YangLeavesHolder holder = (YangLeavesHolder) rootNode;
+ if (rootObj.leafIdentifier() != null) {
+ String name = rootObj.leafIdentifier().toString().toLowerCase();
+ List<Object> values = rootObj.values();
+ // handle all leaf nodes and add their data nodes to resource data.
+ List<YangLeaf> leaves = holder.getListOfLeaf();
+ if (nonEmpty(leaves)) {
+ for (YangLeaf leaf : leaves) {
+ //Add node for leaf with value.
+ if (name.equals(leaf.getJavaAttributeName().toLowerCase())) {
+ DataNode node = LeafNode.builder(leaf.getName(), leaf
+ .getNameSpace().getModuleNamespace())
+ .value(values.get(0))
+ .type(SINGLE_INSTANCE_LEAF_VALUE_NODE).build();
+ rscData.addDataNode(node);
+ break;
+ }
+ }
+ }
+ // handle all leaf list nodes and add their data nodes to resource data.
+ List<YangLeafList> leafLists = holder.getListOfLeafList();
+ if (nonEmpty(leafLists)) {
+ for (YangLeafList leafList : leafLists) {
+ if (name.equals(leafList.getJavaAttributeName().toLowerCase())) {
+ //for leaf list we need to add multi instance of leaf
+ // node.
+ for (Object o : values) {
+ DataNode node = LeafNode
+ .builder(leafList.getName(),
+ leafList.getNameSpace().getModuleNamespace())
+ .value(o)
+ .type(MULTI_INSTANCE_LEAF_VALUE_NODE).build();
+ rscData.addDataNode(node);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Process single instance/multi instance nodes and build there data nodes.
+ *
+ * @param helper data tree builder helper
+ * @param modObj model object
+ * @param rscData resource data
+ * @param curRoot current root node
+ */
+ private void processNodeObj(DataTreeBuilderHelper helper, Object modObj,
+ ResourceData.Builder rscData, YangSchemaNode curRoot) {
+ DataNode.Builder builder = InnerNode.builder(
+ curRoot.getName(), curRoot.getNameSpace()
+ .getModuleNamespace());
+ //assign the type of the node.
+ if (curRoot instanceof YangList) {
+ builder.type(MULTI_INSTANCE_NODE);
+ } else {
+ builder.type(SINGLE_INSTANCE_NODE);
+ }
+ //process current node and get data tree.
+ builder = helper.getDataTree(curRoot, builder, modObj);
+ if (builder != null) {
+ rscData.addDataNode(builder.build());
+ }
+ }
+
+ /**
+ * Does the processing to convert objects to data nodes.
+ *
+ * @param modYo data node builder
+ * @param lastIndexNode last index schema node
+ * @param rscData resource data
+ * @param yangObj object for node
+ */
+ private void processModelObjects(DataTreeBuilderHelper modYo, YangSchemaNode lastIndexNode,
+ DefaultResourceData.Builder rscData, Object
+ yangObj) {
+ //Process all the leaf nodes of root node.
+ processRootLeafInfo(modYo, lastIndexNode, rscData, yangObj);
+
+ //Process all the list nodes of root node.
+ processRootLevelListNode(modYo, lastIndexNode, rscData,
+ yangObj);
+ //process all the single instance node of root nodes.
+ processRootLevelSingleInNode(modYo, lastIndexNode, rscData,
+ yangObj);
+ }
+
+ /**
+ * Process leaf and leaf list information.
+ *
+ * @param modYo module builder
+ * @param rootNode root node
+ * @param rscData resource data
+ */
+ private void processRootLeafInfo(
+ DataTreeBuilderHelper modYo, YangSchemaNode rootNode,
+ DefaultResourceData.Builder rscData, Object rootObj) {
+ //handle leaf nodes.
+ YangLeavesHolder holder = (YangLeavesHolder) rootNode;
+ if (rootNode instanceof YangCase) {
+ if (((YangCase) rootNode).getParent().getParent() instanceof
+ RpcNotificationContainer) {
+ modYo.setExtBuilder(null);
+ }
+ }
+ // handle all leaf nodes and add their data nodes to resource data.
+ List<YangLeaf> leaves = holder.getListOfLeaf();
+ DataNode.Builder builder;
+ if (nonEmpty(leaves)) {
+ for (YangLeaf leaf : leaves) {
+ try {
+ //Add node for leaf with value.
+ builder = modYo.addLeafWithValue(
+ rootNode, leaf, rootObj, getAttributeOfObject(
+ rootObj, leaf.getJavaAttributeName()));
+ addDataNode(builder, rscData);
+ } catch (NoSuchMethodException e) {
+ throw new ModelConvertorException("failed to create data node for " +
+ "leaf " + leaf.getName());
+ }
+ }
+ }
+ // handle all leaf list nodes and add their data nodes to resource data.
+ List<YangLeafList> leafLists = holder.getListOfLeafList();
+ List<DataNode.Builder> nodes;
+ if (nonEmpty(leafLists)) {
+ List<Object> obj;
+ for (YangLeafList leafList : leafLists) {
+ try {
+ obj = (List<Object>) getAttributeOfObject(
+ rootObj, getJavaName(leafList));
+ if (obj != null) {
+ nodes = modYo.addLeafListValue(rootNode, rootObj,
+ leafList, obj);
+ if (nodes != null) {
+ for (DataNode.Builder node : nodes) {
+ rscData.addDataNode(node.build());
+ }
+ }
+ }
+ } catch (NoSuchMethodException e) {
+ throw new ModelConvertorException(e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Process all current root level list nodes. list node instances should be
+ * added as a new instance in resource data.
+ *
+ * @param helper data tree builder helper
+ * @param curRootNode current root schema node
+ * @param rscData resource data
+ * @param curRootObj current root object
+ */
+ private void processRootLevelListNode(
+ DataTreeBuilderHelper helper, YangSchemaNode curRootNode,
+ DefaultResourceData.Builder rscData, Object curRootObj) {
+
+ YangNode curNode = ((YangNode) curRootNode).getChild();
+ DataTreeNodeInfo parentInfo = new DataTreeNodeInfo();
+ //Set object in parent node info.
+ setObjInParent(curRootNode, curRootObj, parentInfo);
+ parentInfo.type(SINGLE_INSTANCE_NODE);
+ DataNode.Builder builder;
+
+ Object childObj;
+ while (curNode != null) {
+ curNode = verifyAndGetList(curNode);
+ if (curNode == null) {
+ break;
+ }
+ //Get all the instance object for list node.
+ List<Object> childObjList = (List<Object>) helper.getChildObject(
+ curNode, parentInfo);
+ if (nonEmpty(childObjList)) {
+ Iterator<Object> listItr = childObjList.iterator();
+ while (listItr.hasNext()) {
+ childObj = listItr.next();
+ builder = InnerNode.builder(curNode.getName(), curNode
+ .getNameSpace().getModuleNamespace())
+ .type(MULTI_INSTANCE_NODE);
+ if (childObj != null) {
+ DataNode.Builder output = helper
+ .getDataTree(curNode, builder, childObj);
+ if (output != null) {
+ rscData.addDataNode(output.build());
+ }
+ }
+ }
+ }
+ curNode = curNode.getNextSibling();
+ }
+ }
+
+ /**
+ * Sets parent object on parent data tree info.
+ *
+ * @param rootNode current root node
+ * @param rootObj current root object
+ * @param parentInfo parent data tree info
+ */
+ private void setObjInParent(YangSchemaNode rootNode, Object rootObj,
+ DataTreeNodeInfo parentInfo) {
+ if (rootNode instanceof YangCase) {
+ parentInfo.setCaseObject(rootObj);
+ }
+ if (rootNode instanceof YangAugment) {
+ parentInfo.setAugmentObject(rootObj);
+ parentInfo.setYangObject(rootObj);
+ } else {
+ parentInfo.setYangObject(rootObj);
+ }
+ }
+
+ /**
+ * Process root level single instance nodes.
+ *
+ * @param helper data tree builder helper
+ * @param rootNode current root node
+ * @param rscData resource data
+ * @param rootObj current root object
+ */
+ private void processRootLevelSingleInNode(
+ DataTreeBuilderHelper helper, YangSchemaNode rootNode,
+ DefaultResourceData.Builder rscData, Object rootObj) {
+
+ YangNode curNode = ((YangNode) rootNode).getChild();
+
+ DataTreeNodeInfo parentInfo = new DataTreeNodeInfo();
+ parentInfo.type(SINGLE_INSTANCE_NODE);
+ setObjInParent(rootNode, rootObj, parentInfo);
+
+ Object childObj = null;
+ DataNode.Builder builder;
+ while (curNode != null) {
+ // we need to get current data node.
+ curNode = verifyAndDoNotGetList(curNode, helper, parentInfo, rscData);
+ if (curNode == null) {
+ break;
+ }
+ if (curNode.getYangSchemaNodeType() != YANG_NON_DATA_NODE) {
+ childObj = helper.getChildObject(
+ curNode, parentInfo);
+ }
+
+ if (childObj != null) {
+ builder = InnerNode.builder(curNode.getName(), curNode
+ .getNameSpace().getModuleNamespace())
+ .type(SINGLE_INSTANCE_NODE);
+ DataNode.Builder output = helper
+ .getDataTree(curNode, builder, childObj);
+ if (output != null) {
+ rscData.addDataNode(output.build());
+ }
+ }
+ curNode = curNode.getNextSibling();
+ }
+ // check for augments in current node.
+ if (rootNode instanceof YangAugmentableNode) {
+ List<YangAugment> augments = ((YangAugmentableNode) rootNode)
+ .getAugmentedInfoList();
+ if (nonEmpty(augments)) {
+ for (YangAugment augment : augments) {
+ childObj = helper.processAugmentNode(augment, parentInfo);
+ if (childObj != null) {
+ processModelObjects(helper, augment, rscData, childObj);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Check for the list node and its siblings. if found list then return
+ * node else null.
+ *
+ * @param curNode current node
+ * @return list node
+ */
+ private YangNode verifyAndGetList(YangNode curNode) {
+ if (curNode == null) {
+ return null;
+ }
+ if (!(curNode instanceof YangList)) {
+ curNode = curNode.getNextSibling();
+ curNode = verifyAndGetList(curNode);
+ }
+ return curNode;
+ }
+
+ /**
+ * Verify if current node is a data node. handles choice ,case and
+ * augment node itself and returns only when node is a data node.
+ *
+ * @param curNode current node
+ * @param helper data tree builder helper
+ * @param info parent info
+ * @param rscData resource data
+ * @return single instance node
+ */
+ private YangNode verifyAndDoNotGetList(YangNode curNode, DataTreeBuilderHelper
+ helper, DataTreeNodeInfo info, DefaultResourceData.Builder rscData) {
+ if (curNode == null) {
+ return null;
+ }
+ switch (curNode.getYangSchemaNodeType()) {
+ case YANG_SINGLE_INSTANCE_NODE:
+ return curNode;
+ case YANG_MULTI_INSTANCE_NODE:
+ case YANG_AUGMENT_NODE:
+ break;
+ case YANG_CHOICE_NODE:
+ handleChoiceNode(curNode, info, helper, rscData);
+ break;
+ case YANG_NON_DATA_NODE:
+ if (curNode instanceof YangCase) {
+ handleCaseNode(curNode, info, helper, rscData);
+ }
+ break;
+ default:
+ throw new ModelConvertorException(
+ "Non processable schema node has arrived for adding " +
+ "it in data tree");
+ }
+ return processReCheckSibling(curNode, helper, info, rscData);
+ }
+
+ /**
+ * In case of case , choice and augment we need to process then and then
+ * need to check for their siblings so we can get a single instance node
+ * to process and add in resource data.
+ *
+ * @param curNode current node
+ * @param helper data tree helper
+ * @param info data tree node info
+ * @param rscData resource data
+ * @return single instance node
+ */
+ private YangNode processReCheckSibling(
+ YangNode curNode, DataTreeBuilderHelper helper, DataTreeNodeInfo info,
+ DefaultResourceData.Builder rscData) {
+ curNode = curNode.getNextSibling();
+ curNode = verifyAndDoNotGetList(curNode, helper, info, rscData);
+ return curNode;
+ }
+
+ /**
+ * Handles root level choice node.
+ *
+ * @param curNode current schema node
+ * @param info data node info
+ * @param helper data node builder
+ * @param rscData resource data
+ */
+ private void handleChoiceNode(
+ YangNode curNode, DataTreeNodeInfo info, DataTreeBuilderHelper helper,
+ DefaultResourceData.Builder rscData) {
+ // get the choice object.
+ Object childObj = helper.processChoiceNode(curNode, info);
+ YangNode tempNode = curNode;
+ YangNode caseNode;
+ curNode = curNode.getChild();
+ if (childObj != null) {
+ while (curNode != null) {
+ // process child case nodes.
+ processCaseNode(curNode, info, helper, rscData);
+ curNode = curNode.getNextSibling();
+ }
+ //process augment nodes because choice can have a augmented case
+ // in it.
+ List<YangAugment> augments = ((YangChoice) tempNode)
+ .getAugmentedInfoList();
+ if (nonEmpty(augments)) {
+ for (YangAugment augment : augments) {
+ caseNode = augment.getChild();
+ while (caseNode != null && caseNode instanceof YangCase) {
+ processCaseNode(caseNode, info, helper, rscData);
+ caseNode = caseNode.getNextSibling();
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Process case node.
+ * case node is non data node so contents of a case
+ * node should be added to its choice's parent node. if there is current
+ * root node is parent for choice node then data node for case child
+ * schema's will be added to resource data.
+ *
+ * @param curNode current case node
+ * @param info parent tree info
+ * @param helper data tree helper
+ * @param rscData resource data
+ */
+ private void processCaseNode(
+ YangNode curNode, DataTreeNodeInfo info, DataTreeBuilderHelper helper,
+ DefaultResourceData.Builder rscData) {
+ Object childObj = helper.processCaseNode(curNode, info);
+ if (childObj != null) {
+ processModelObjects(helper, curNode, rscData, childObj);
+ }
+ }
+
+ /**
+ * Handles case node when model object contains choice class. we need to
+ * add all the content of case node as new data node in resource data
+ * node list.
+ *
+ * @param curNode current node
+ * @param info data node builder info
+ * @param yo data node builder
+ * @param rscData resource data
+ */
+ private void handleCaseNode(
+ YangNode curNode, DataTreeNodeInfo info, DataTreeBuilderHelper yo,
+ DefaultResourceData.Builder rscData) {
+
+ Object obj = info.getYangObject();
+ if (obj != null) {
+ processModelObjects(yo, curNode, rscData, obj);
+ }
+ }
+
+ /**
+ * Adds data node to resource data.
+ *
+ * @param node data node
+ * @param builder resource data builder
+ */
+ private void addDataNode(DataNode.Builder node,
+ DefaultResourceData.Builder builder) {
+ if (node != null) {
+ builder.addDataNode(node.build());
+ }
+ }
+}
diff --git a/runtime/src/main/java/org/onosproject/yang/runtime/impl/DefaultModelConverter.java b/runtime/src/main/java/org/onosproject/yang/runtime/impl/DefaultModelConverter.java
index 7c2faf8..241304c 100644
--- a/runtime/src/main/java/org/onosproject/yang/runtime/impl/DefaultModelConverter.java
+++ b/runtime/src/main/java/org/onosproject/yang/runtime/impl/DefaultModelConverter.java
@@ -38,13 +38,12 @@
@Override
public ModelObjectData createModel(ResourceData data) {
- //TODO: add implementation.
return null;
}
@Override
- public ResourceData createDataNode(ModelObjectData modelData) {
- //TODO: add implementation.
- return null;
+ public synchronized ResourceData createDataNode(ModelObjectData modelData) {
+ DefaultDataTreeBuilder builder = new DefaultDataTreeBuilder(reg);
+ return builder.getResourceData(modelData);
}
}
diff --git a/runtime/src/main/java/org/onosproject/yang/runtime/impl/DefaultYangModelRegistry.java b/runtime/src/main/java/org/onosproject/yang/runtime/impl/DefaultYangModelRegistry.java
index 09401aa..9756603 100644
--- a/runtime/src/main/java/org/onosproject/yang/runtime/impl/DefaultYangModelRegistry.java
+++ b/runtime/src/main/java/org/onosproject/yang/runtime/impl/DefaultYangModelRegistry.java
@@ -43,6 +43,7 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.Collections.sort;
+import static java.util.Collections.unmodifiableSet;
import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.getNodeIdFromSchemaId;
import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.getDateInStringFormat;
import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.getInterfaceClassName;
@@ -57,8 +58,9 @@
public class DefaultYangModelRegistry implements YangModelRegistry,
SingleInstanceNodeContext {
- private static final String AT = "@";
private final Logger log = getLogger(getClass());
+ private static final String AT = "@";
+
/*
* Map for storing YANG schema nodes. Key will be the schema name of
* module node defined in YANG file.
@@ -73,6 +75,12 @@
private final ConcurrentMap<String, YangSchemaNode> interfaceNameKeyStore;
/*
+ * Map for storing YANG schema nodes with respect to root's generated
+ * interface file name.
+ */
+ private final ConcurrentMap<String, YangSchemaNode> pkgKeyStore;
+
+ /*
* Map for storing YANG schema nodes root's generated op param file name.
*/
private final ConcurrentMap<String, YangSchemaNode> opParamNameKeyStore;
@@ -117,6 +125,7 @@
registerClassStore = new ConcurrentHashMap<>();
appNameKeyStore = new ConcurrentHashMap<>();
nameSpaceSchemaStore = new ConcurrentHashMap<>();
+ pkgKeyStore = new ConcurrentHashMap<>();
schemaId = new SchemaId("/", null);
}
@@ -172,6 +181,8 @@
removeSchemaNode(curNode);
interfaceNameKeyStore.remove(
getInterfaceClassName(curNode));
+ pkgKeyStore.remove(getInterfaceClassName(curNode)
+ .toLowerCase());
opParamNameKeyStore.remove(
getOpParamClassName(curNode));
appNameKeyStore.remove(serviceName);
@@ -194,7 +205,7 @@
@Override
public Set<YangModel> getModels() {
- return models;
+ return unmodifiableSet(models);
}
/**
@@ -239,6 +250,23 @@
}
/**
+ * Returns schema node for the given package. pkg should be generated class
+ * pkg. the pkg provided here should be for registered interface class.
+ * pkg string contains the java package and java name of the module
+ * generated class in lower case.
+ *
+ * @param pkg interface class pkg
+ * @return YANG schema node
+ */
+ public YangSchemaNode getForInterfaceFilePkg(String pkg) {
+ YangSchemaNode node = pkgKeyStore.get(pkg);
+ if (node == null) {
+ log.error("{} not found.", pkg);
+ }
+ return node;
+ }
+
+ /**
* Returns schema node for the given name. Name should be generated class
* name. the name provided here should be for registered op param class.
*
@@ -343,17 +371,16 @@
* @param appNode application YANG schema nodes
* @param name class name
*/
- private void processApplicationContext(YangSchemaNode appNode,
- String name) {
+ public void processApplicationContext(YangSchemaNode appNode,
+ String name) {
//Update map for which registrations is being called.
try {
- if (appNode.isNotificationPresent()) {
- //TODO: add logic for getting wrt RPC.
+ if (appNode.isNotificationPresent() || appNode.isRpcPresent()) {
appNameKeyStore.put(name, appNode);
}
} catch (DataModelException e) {
- e.printStackTrace();
+ log.error("error occurred due to {}", e.getLocalizedMessage());
}
// Updates schema store.
@@ -361,6 +388,8 @@
// update interface store.
interfaceNameKeyStore.put(getInterfaceClassName(appNode), appNode);
+ pkgKeyStore.put(getInterfaceClassName(appNode).toLowerCase(), appNode);
+
//update op param store.
opParamNameKeyStore.put(getOpParamClassName(appNode), appNode);
diff --git a/runtime/src/main/java/org/onosproject/yang/runtime/impl/ModIdToRscIdConverter.java b/runtime/src/main/java/org/onosproject/yang/runtime/impl/ModIdToRscIdConverter.java
new file mode 100644
index 0000000..837795e
--- /dev/null
+++ b/runtime/src/main/java/org/onosproject/yang/runtime/impl/ModIdToRscIdConverter.java
@@ -0,0 +1,408 @@
+/*
+ * Copyright 2017-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.yang.runtime.impl;
+
+import org.onosproject.yang.compiler.datamodel.YangAugment;
+import org.onosproject.yang.compiler.datamodel.YangAugmentableNode;
+import org.onosproject.yang.compiler.datamodel.YangLeaf;
+import org.onosproject.yang.compiler.datamodel.YangLeafList;
+import org.onosproject.yang.compiler.datamodel.YangLeavesHolder;
+import org.onosproject.yang.compiler.datamodel.YangList;
+import org.onosproject.yang.compiler.datamodel.YangNode;
+import org.onosproject.yang.compiler.datamodel.YangRpc;
+import org.onosproject.yang.compiler.datamodel.YangSchemaNode;
+import org.onosproject.yang.model.AtomicPath;
+import org.onosproject.yang.model.ModelObjectId;
+import org.onosproject.yang.model.MultiInstanceLeaf;
+import org.onosproject.yang.model.MultiInstanceNode;
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.model.SingleInstanceLeaf;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import static org.onosproject.yang.compiler.datamodel.YangSchemaNodeType.YANG_NON_DATA_NODE;
+import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.nonEmpty;
+import static org.onosproject.yang.compiler.utils.io.impl.YangIoUtils.getCamelCase;
+import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.DEFAULT_CAPS;
+import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.PERIOD;
+import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.getCapitalCase;
+import static org.onosproject.yang.runtime.impl.ModelConverterUtil.fetchPackage;
+import static org.onosproject.yang.runtime.impl.ModelConverterUtil.getAttributeOfObject;
+
+/**
+ * Converts model object identifier to resource identifier.
+ */
+class ModIdToRscIdConverter {
+
+ /**
+ * Schema node with respect to the last atomic path in model object
+ * identifier. in case of leaf node as last atomic path last index node
+ * will be leaf's parent node.
+ */
+ private YangSchemaNode lastIndexNode;
+
+ /**
+ * Flag to know if model object identifier contains leaf identifier.
+ */
+ private boolean isMoIdWithLeaf;
+
+ /**
+ * Flag is true if rpc is added in branch point schema of resource
+ * identifier.
+ */
+ private boolean isRpcAdded = true;
+
+ /**
+ * Model registry.
+ */
+ private final DefaultYangModelRegistry reg;
+
+ /**
+ * Creates an instance of converter.
+ *
+ * @param registry model registry
+ */
+ ModIdToRscIdConverter(DefaultYangModelRegistry registry) {
+ reg = registry;
+ }
+
+
+ /**
+ * Fetch resource identifier from model object identifier.
+ *
+ * @param id model object identifier
+ * @return resource identifier from model object identifier
+ */
+ ResourceId fetchResourceId(ModelObjectId id) {
+
+ ResourceId.Builder rid = ResourceId.builder().addBranchPointSchema("/", null);
+ if (id == null || id.atomicPaths().isEmpty()) {
+ return rid.build();
+ }
+
+ List<AtomicPath> paths = id.atomicPaths();
+ AtomicPath path = paths.get(0);
+
+ //If first element in model id contains only leaf/leaf-list then it
+ // will be for module so in that case resource identifier will be
+ // till module's leaf only.
+ if (path instanceof SingleInstanceLeaf ||
+ path instanceof MultiInstanceLeaf) {
+ isMoIdWithLeaf = true;
+ Object identifier;
+ if (path instanceof SingleInstanceLeaf) {
+ identifier = ((SingleInstanceLeaf) path).leafIdentifier();
+ } else {
+ identifier = ((MultiInstanceLeaf) path).leafIdentifier();
+ }
+ lastIndexNode = fetchModNodeFromLeaf(identifier.getClass().getName());
+ if (lastIndexNode != null) {
+ handleLeafInRid(lastIndexNode, id, rid, path);
+ return rid.build();
+ }
+ }
+
+ return convertToResourceId(id, fetchModuleNode(fetchPackage(path)),
+ rid);
+ }
+
+ /**
+ * Returns module node from leaf package.
+ *
+ * @param pkg leaf identifier package
+ * @return module node from leaf package
+ */
+ YangSchemaNode fetchModNodeFromLeaf(String pkg) {
+ String[] array = pkg.split(Pattern.quote("$"));
+ return reg.getForInterfaceFileName(array[0]);
+ }
+
+ /**
+ * Takes the first element in model object id and then uses it to fetch
+ * the module schema fetchNode from model registry.
+ *
+ * @param pkg package for child node
+ */
+ YangSchemaNode fetchModuleNode(String pkg) {
+ YangSchemaNode modNode;
+ StringBuilder modPkg = new StringBuilder();
+
+ //In other case we need to find the package
+ // of module fetchNode from the given fetchNode's package.
+ String[] strArray = pkg.split(Pattern.quote(PERIOD));
+ int i = 0;
+ while (i <= strArray.length - 3) {
+ modPkg.append(strArray[i]).append(PERIOD);
+ i++;
+ }
+
+ //If path contains input fetchNode class then in that case if we add
+ // current modePkg will be the correct package for module fetchNode
+ // because the next string will be rpc name in received from fetch
+ // package method.
+ modPkg.deleteCharAt(modPkg.lastIndexOf(PERIOD));
+ YangNode node = (YangNode) reg.getForInterfaceFilePkg(modPkg.toString());
+ if (node != null) {
+ modNode = node;
+ //in this case we should update the lastIndexNode for object to
+ // data fetchNode conversion. because we need to create the data fetchNode
+ // with the input fetchNode's data
+ node = node.getChild();
+ while (node != null) {
+ if (node.getJavaAttributeName().toLowerCase()
+ .equals(strArray[i])) {
+ //last index fetchNode will be input fetchNode.
+ lastIndexNode = node.getChild();
+ break;
+ }
+ node = node.getNextSibling();
+ }
+ } else {
+ modPkg.append(PERIOD);
+ //In this case this package will be of module fetchNode.
+ modPkg.append(strArray[i]);
+ modNode = reg.getForInterfaceFilePkg(modPkg.toString());
+ }
+ return modNode;
+ }
+
+ /**
+ * Converts model object identifier to resource identifier.
+ *
+ * @param id model object identifier
+ * @param builder resource id builder
+ * @return resource identifier
+ */
+ private ResourceId convertToResourceId(ModelObjectId id, YangSchemaNode
+ modNode, ResourceId.Builder builder) {
+ List<AtomicPath> paths = id.atomicPaths();
+ Iterator<AtomicPath> it = paths.iterator();
+ AtomicPath path;
+ String pkg;
+ YangSchemaNode curNode = modNode;
+ YangSchemaNode preNode = null;
+ YangNode tempNode;
+ while (it.hasNext()) {
+ path = it.next();
+ //Get the java package for given atomic path. this package will
+ // be java package for schema node
+ pkg = fetchPackage(path);
+ if (curNode instanceof YangAugmentableNode) {
+ tempNode = fetchFromAugment((YangNode) curNode, pkg, builder);
+ if (tempNode != null) {
+ curNode = tempNode;
+ } else {
+ //fetch the node for which model object identifier
+ // contains the atomic path.
+ curNode = fetchNode(((YangNode) curNode).getChild(), pkg, builder);
+ }
+ } else {
+ curNode = fetchNode(((YangNode) curNode).getChild(), pkg, builder);
+ }
+ //if the current node is null and atomic path list contains
+ // another node, then there is possibility that its a leaf node.
+ if (curNode == null && paths.indexOf(path) == paths.size() - 1) {
+ //check leaf nodes in previous nodes.
+ handleLeafInRid(preNode, id, builder, path);
+ } else if (curNode != null) {
+
+ builder.addBranchPointSchema(curNode.getName(), curNode
+ .getNameSpace().getModuleNamespace());
+ //list node can have key leaf in it. so resource identifier
+ // should have key leaves also.
+ if (curNode instanceof YangList) {
+ YangList list = (YangList) curNode;
+ MultiInstanceNode mil = (MultiInstanceNode) path;
+ Object keyObj = mil.key();
+ Set<String> keys = list.getKeyLeaf();
+ for (String key : keys) {
+ builder.addKeyLeaf(key, list.getNameSpace()
+ .getModuleNamespace(), getKeyValue(keyObj, key));
+ }
+ }
+ } else {
+ throw new ModelConvertorException("invalid model object id." + id);
+ }
+ preNode = curNode;
+ }
+ if (!isMoIdWithLeaf) {
+ // last node with respect to the last class in model object
+ // identifier. model object will be an object for last index node.
+ lastIndexNode = curNode;
+ }
+ return builder.build();
+ }
+
+ private void handleLeafInRid(YangSchemaNode preNode, ModelObjectId id,
+ ResourceId.Builder builder, AtomicPath path) {
+ //check leaf nodes in previous nodes.
+ YangSchemaNode curNode = fetchLeaf(preNode, fetchPackage(path));
+ if (curNode == null) {
+ throw new ModelConvertorException("invalid model object id." + id);
+ }
+ isMoIdWithLeaf = true;
+ if (curNode instanceof YangLeaf) {
+ //leaf should be added as a branch point schema
+ builder.addBranchPointSchema(curNode.getName(), curNode
+ .getNameSpace().getModuleNamespace());
+ } else {
+ // leaf list should be added as leaf list branch point
+ // schema with its value added to it.
+ Object val = ((MultiInstanceLeaf) path).value();
+ builder.addLeafListBranchPoint(curNode.getName(), curNode
+ .getNameSpace().getModuleNamespace(), val);
+ }
+ }
+
+ private String getJavaPkg(YangNode node) {
+ return node.getJavaPackage() + PERIOD + DEFAULT_CAPS +
+ getCapitalCase(node.getJavaClassNameOrBuiltInType());
+ }
+
+ /**
+ * Returns augment node in case node is augmented.
+ *
+ * @param curNode current node
+ * @param pkg java package
+ * @return augment node
+ */
+ private YangNode fetchFromAugment(YangNode curNode, String pkg,
+ ResourceId.Builder builder) {
+ YangNode tempNode;
+ if (curNode != null) {
+ if (curNode instanceof YangAugmentableNode) {
+ List<YangAugment> augments = ((YangAugmentableNode) curNode)
+ .getAugmentedInfoList();
+ if (nonEmpty(augments)) {
+ //fetch augment node from augment list and returns it.
+ for (YangAugment augment : augments) {
+ //process augment's child nodes.
+ tempNode = fetchNode(augment.getChild(), pkg, builder);
+ if (tempNode != null) {
+ return tempNode;
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns key value from the key class object.
+ *
+ * @param keys key class object
+ * @param keyName key name
+ * @return key value
+ */
+ private Object getKeyValue(Object keys, String keyName) {
+ try {
+ return getAttributeOfObject(keys, getCamelCase(keyName, null));
+ } catch (NoSuchMethodException e) {
+ throw new ModelConvertorException("invalid key value in model id for list" +
+ "." + keys.getClass().getName());
+ }
+ }
+
+ /**
+ * Returns YANG fetchNode for given package.
+ *
+ * @param node YANG fetchNode
+ * @param pkg package
+ * @param builder resource identifier builder
+ * @return YANG fetchNode
+ */
+ private YangNode fetchNode(YangNode node, String pkg,
+ ResourceId.Builder builder) {
+ String java;
+ while (node != null) {
+ //compare the java package with the package found in model object
+ // identifier.
+ if (node.getYangSchemaNodeType() == YANG_NON_DATA_NODE) {
+ while (node != null &&
+ node.getYangSchemaNodeType() == YANG_NON_DATA_NODE) {
+ node = node.getNextSibling();
+ }
+ }
+ if (node != null) {
+ java = getJavaPkg(node);
+ if (java.equals(pkg)) {
+ return node;
+ } else if (node instanceof YangRpc) {
+ // in case of a input node rpc also needs to be added to
+ // resource identifier
+ if (isRpcAdded) {
+ isRpcAdded = false;
+ builder.addBranchPointSchema(node.getName(), node.getNameSpace()
+ .getModuleNamespace());
+ }
+ // node will become input node
+ node = node.getChild();
+ } else {
+ // check in next sibling node
+ node = node.getNextSibling();
+ }
+ }
+ }
+ return null;
+ }
+
+ private YangSchemaNode fetchLeaf(YangSchemaNode node, String name) {
+ YangLeavesHolder holder = (YangLeavesHolder) node;
+ List<YangLeaf> leaves = holder.getListOfLeaf();
+ // check if the names is equal to any of the leaf/leaf-list nodes.
+ if (nonEmpty(leaves)) {
+ for (YangLeaf leaf : leaves) {
+ if (leaf.getJavaAttributeName().toLowerCase()
+ .equals(name)) {
+ return leaf;
+ }
+ }
+ }
+ List<YangLeafList> leafLists = holder.getListOfLeafList();
+ if (nonEmpty(leafLists)) {
+ for (YangLeafList leaf : leafLists) {
+ if (leaf.getJavaAttributeName().toLowerCase()
+ .equals(name)) {
+ return leaf;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns last index node for the last index atomic path of model object
+ * identifier.
+ *
+ * @return schema node
+ */
+ YangSchemaNode getLastIndexNode() {
+ return lastIndexNode;
+ }
+
+ /**
+ * Returns true if model object identifier contains leaf.
+ *
+ * @return true if model object identifier contains leaf
+ */
+ boolean isMoIdWithLeaf() {
+ return isMoIdWithLeaf;
+ }
+}
diff --git a/runtime/src/main/java/org/onosproject/yang/runtime/impl/ModelConverterTraversalInfo.java b/runtime/src/main/java/org/onosproject/yang/runtime/impl/ModelConverterTraversalInfo.java
new file mode 100644
index 0000000..2978fdb
--- /dev/null
+++ b/runtime/src/main/java/org/onosproject/yang/runtime/impl/ModelConverterTraversalInfo.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2017-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.yang.runtime.impl;
+
+import org.onosproject.yang.compiler.datamodel.TraversalType;
+import org.onosproject.yang.compiler.datamodel.YangNode;
+
+/**
+ * Represents model converter Traversal info which is needed every time the traversal of
+ * a YANG node happens. This contains YANG node and its corresponding traversal
+ * type information.
+ */
+class ModelConverterTraversalInfo {
+
+ /**
+ * YANG node of the current traversal.
+ */
+ private final YangNode yangNode;
+
+ /**
+ * Traverse type of the current traversal.
+ */
+ private final TraversalType traverseType;
+
+ /**
+ * Creates model converter traversal info by taking the traversal type and the YANG
+ * node.
+ *
+ * @param yangNode YANG node
+ * @param traverseType traversal type
+ */
+ ModelConverterTraversalInfo(YangNode yangNode, TraversalType traverseType) {
+ this.yangNode = yangNode;
+ this.traverseType = traverseType;
+ }
+
+ /**
+ * Returns the YANG node of the current traversal.
+ *
+ * @return YANG node
+ */
+ YangNode getYangNode() {
+ return yangNode;
+ }
+
+ /**
+ * Returns the traversal type of the current traversal.
+ *
+ * @return traversal type
+ */
+ TraversalType getTraverseType() {
+ return traverseType;
+ }
+}
diff --git a/runtime/src/main/java/org/onosproject/yang/runtime/impl/ModelConverterUtil.java b/runtime/src/main/java/org/onosproject/yang/runtime/impl/ModelConverterUtil.java
new file mode 100644
index 0000000..11e50d7
--- /dev/null
+++ b/runtime/src/main/java/org/onosproject/yang/runtime/impl/ModelConverterUtil.java
@@ -0,0 +1,509 @@
+/*
+ * Copyright 2017-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.yang.runtime.impl;
+
+
+import org.onosproject.yang.compiler.datamodel.TraversalType;
+import org.onosproject.yang.compiler.datamodel.YangAugment;
+import org.onosproject.yang.compiler.datamodel.YangCase;
+import org.onosproject.yang.compiler.datamodel.YangIdentity;
+import org.onosproject.yang.compiler.datamodel.YangIdentityRef;
+import org.onosproject.yang.compiler.datamodel.YangLeafRef;
+import org.onosproject.yang.compiler.datamodel.YangNode;
+import org.onosproject.yang.compiler.datamodel.YangNotification;
+import org.onosproject.yang.compiler.datamodel.YangOutput;
+import org.onosproject.yang.compiler.datamodel.YangRpc;
+import org.onosproject.yang.compiler.datamodel.YangSchemaNode;
+import org.onosproject.yang.compiler.datamodel.YangType;
+import org.onosproject.yang.compiler.datamodel.utils.builtindatatype.YangDataTypes;
+import org.onosproject.yang.model.AtomicPath;
+import org.onosproject.yang.model.MultiInstanceLeaf;
+import org.onosproject.yang.model.MultiInstanceNode;
+import org.onosproject.yang.model.SingleInstanceLeaf;
+import org.onosproject.yang.model.SingleInstanceNode;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.onosproject.yang.compiler.datamodel.TraversalType.PARENT;
+import static org.onosproject.yang.compiler.datamodel.YangSchemaNodeType.YANG_AUGMENT_NODE;
+import static org.onosproject.yang.compiler.datamodel.YangSchemaNodeType.YANG_MULTI_INSTANCE_NODE;
+import static org.onosproject.yang.compiler.datamodel.utils.builtindatatype.YangDataTypes.BOOLEAN;
+import static org.onosproject.yang.compiler.datamodel.utils.builtindatatype.YangDataTypes.EMPTY;
+import static org.onosproject.yang.compiler.datamodel.utils.builtindatatype.YangDataTypes.INT16;
+import static org.onosproject.yang.compiler.datamodel.utils.builtindatatype.YangDataTypes.INT32;
+import static org.onosproject.yang.compiler.datamodel.utils.builtindatatype.YangDataTypes.INT64;
+import static org.onosproject.yang.compiler.datamodel.utils.builtindatatype.YangDataTypes.INT8;
+import static org.onosproject.yang.compiler.datamodel.utils.builtindatatype.YangDataTypes.LEAFREF;
+import static org.onosproject.yang.compiler.datamodel.utils.builtindatatype.YangDataTypes.UINT16;
+import static org.onosproject.yang.compiler.datamodel.utils.builtindatatype.YangDataTypes.UINT32;
+import static org.onosproject.yang.compiler.datamodel.utils.builtindatatype.YangDataTypes.UINT8;
+import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.PERIOD;
+import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.UNDER_SCORE;
+import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.getCapitalCase;
+
+
+/**
+ * Representation of utility for YANG tree builder.
+ */
+final class ModelConverterUtil {
+
+ /**
+ * Static attribute for string value having null.
+ */
+ static final String STR_NULL = "null";
+
+ private static final int ONE = 1;
+ private static final String ENUM_LEAF_IDENTIFIER = "$LeafIdentifier";
+ private static final Set<YangDataTypes> PRIMITIVE_TYPES =
+ new HashSet<>(Arrays.asList(INT8, INT16, INT32, INT64, UINT8,
+ UINT16, UINT32, BOOLEAN, EMPTY));
+ private static final String TO_STRING = "toString";
+
+ // No instantiation.
+ private ModelConverterUtil() {
+ }
+
+ /**
+ * Returns the object of the node from the node info. Getting object for
+ * augment and case differs from other node.
+ *
+ * @param nodeInfo node info of the holder
+ * @param yangNode YANG node of the holder
+ * @return object of the parent
+ */
+ static Object getParentObjectOfNode(DataTreeNodeInfo nodeInfo,
+ YangNode yangNode) {
+ Object object;
+ if (yangNode instanceof YangCase) {
+ object = nodeInfo.getCaseObject();
+ } else if (yangNode instanceof YangAugment) {
+ object = nodeInfo.getAugmentObject();
+ } else {
+ object = nodeInfo.getYangObject();
+ }
+ return object;
+ }
+
+ /**
+ * Returns the value of an attribute, in a class object. The attribute
+ * name is taken from the YANG node java name.
+ *
+ * @param nodeObj object of the node
+ * @param fieldName name of the attribute
+ * @return object of the attribute
+ * @throws NoSuchMethodException method not found exception
+ */
+ static Object getAttributeOfObject(Object nodeObj, String fieldName)
+ throws NoSuchMethodException {
+ Class<?> nodeClass = nodeObj.getClass();
+ Method getterMethod;
+ try {
+ getterMethod = nodeClass.getDeclaredMethod(fieldName);
+ return getterMethod.invoke(nodeObj);
+ } catch (InvocationTargetException | IllegalAccessException e) {
+ throw new ModelConvertorException(e);
+ }
+ }
+
+ /**
+ * Returns the value of an attribute, in a class object. The attribute
+ * name is taken from the YANG node java name.
+ *
+ * @param nodeObj object of the node
+ * @param fieldName name of the attribute
+ * @return object of the attribute
+ * @throws NoSuchMethodException method not found exception
+ */
+ static Object getAugmentObject(Object nodeObj, String fieldName)
+ throws NoSuchMethodException {
+ Class<?> nodeClass = nodeObj.getClass().getSuperclass();
+ Method getterMethod;
+ try {
+ getterMethod = nodeClass.getDeclaredMethod(fieldName);
+ return getterMethod.invoke(nodeObj);
+ } catch (InvocationTargetException | IllegalAccessException e) {
+ throw new ModelConvertorException(e);
+ }
+ }
+
+ /**
+ * Returns the object of the declared method in parent class by invoking
+ * through the child class object.
+ *
+ * @param childClass child class which inherits the parent class
+ * @param methodName name of the declared method
+ * @return value of the method
+ */
+ static Object getAttributeFromInheritance(Object childClass,
+ String methodName) {
+ Class<?> parentClass = childClass.getClass().getSuperclass();
+ Method getterMethod;
+ try {
+ getterMethod = parentClass.getDeclaredMethod(methodName);
+ return getterMethod.invoke(childClass);
+ } catch (InvocationTargetException | NoSuchMethodException |
+ IllegalAccessException e) {
+ throw new ModelConvertorException(e);
+ }
+ }
+
+ /**
+ * Returns interface class from an implementation class object.
+ *
+ * @param obj implementation class object
+ * @return interface class
+ */
+ static Class<?> getInterfaceClassFromImplClass(Object obj) {
+ Class<?>[] interfaces = obj.getClass().getInterfaces();
+ if (interfaces.length > ONE) {
+ // TODO: Need to handle when impl class has more than one interface.
+ throw new ModelConvertorException("Implementation class having more than one" +
+ " interface is not handled");
+ }
+ return interfaces[0];
+ }
+
+ /**
+ * Returns true, if data type of leaf is primitive data type; false
+ * otherwise.
+ *
+ * @param yangType leaf type
+ * @return true if data type is primitive; false otherwise
+ */
+ static boolean isTypePrimitive(YangType yangType) {
+ if (yangType.getDataType() == LEAFREF) {
+ YangLeafRef leafRef =
+ (YangLeafRef) yangType.getDataTypeExtendedInfo();
+ return isPrimitiveDataType(leafRef.getEffectiveDataType()
+ .getDataType());
+ }
+ return isPrimitiveDataType(yangType.getDataType());
+ }
+
+ /**
+ * Returns the registered class from the YSR of the module node where
+ * augment is present.
+ *
+ * @param curNode current augment node
+ * @param registry schema registry
+ * @return class loader of module
+ */
+ static Class<?> getClassLoaderForAugment(
+ YangNode curNode, DefaultYangModelRegistry registry) {
+ return registry.getRegisteredClass(curNode.getParent());
+ }
+
+ /**
+ * Returns the string true, if the leaf data is actually set; false
+ * otherwise.
+ *
+ * @param holder leaf holder
+ * @param nodeObj object if the node
+ * @param javaName java name of the leaf
+ * @param methodName getter method name
+ * @return string value of the boolean method
+ * @throws NoSuchMethodException if the method is not present
+ */
+ static String isValueOrSelectLeafSet(YangSchemaNode holder, Object nodeObj,
+ String javaName, String methodName)
+ throws NoSuchMethodException {
+
+ Class<?> nodeClass = nodeObj.getClass();
+
+ // Appends the enum inner package to the interface class package.
+ String enumPackage = holder.getJavaPackage() + PERIOD +
+ getCapitalCase(holder.getJavaClassNameOrBuiltInType()) +
+ ENUM_LEAF_IDENTIFIER;
+
+ ClassLoader classLoader = nodeClass.getClassLoader();
+ Class leafEnum;
+ try {
+ leafEnum = classLoader.loadClass(enumPackage);
+ Method getterMethod = nodeClass.getMethod(methodName, leafEnum);
+ // Gets the value of the enum.
+ Enum<?> value = Enum.valueOf(leafEnum, javaName.toUpperCase());
+ // Invokes the method with the value of enum as param.
+ return String.valueOf(getterMethod.invoke(nodeObj, value));
+ } catch (IllegalAccessException | InvocationTargetException |
+ ClassNotFoundException e) {
+ throw new ModelConvertorException(e);
+ }
+ }
+
+ /**
+ * Returns the string value from the respective data types of the
+ * leaf/leaf-list.
+ *
+ * @param holder leaf/leaf-list holder
+ * @param holderObj leaf/leaf-list holder object
+ * @param name leaf/leaf-list name
+ * @param fieldObj object of the leaf/leaf-list field
+ * @param dataType type of the leaf/leaf-list
+ * @return string value from the type
+ */
+ static String getStringFromType(YangSchemaNode holder, Object holderObj,
+ String name, Object fieldObj, YangType dataType) {
+
+ if (fieldObj == null) {
+ throw new ModelConvertorException("Value of " + holder.getName() + " is null");
+ }
+
+ YangDataTypes type = dataType.getDataType();
+ switch (type) {
+ case INT8:
+ case INT16:
+ case INT32:
+ case INT64:
+ case UINT8:
+ case UINT16:
+ case UINT32:
+ case UINT64:
+ case EMPTY:
+ case STRING:
+ case DECIMAL64:
+ case INSTANCE_IDENTIFIER:
+ case DERIVED:
+ case UNION:
+ case ENUMERATION:
+ case BOOLEAN:
+ return String.valueOf(fieldObj).trim();
+
+ case BITS:
+ return getBitsValue(holder, holderObj, name, fieldObj).trim();
+
+ case BINARY:
+ return Base64.getEncoder().encodeToString((byte[]) fieldObj);
+
+ case IDENTITYREF:
+ YangIdentityRef ir =
+ (YangIdentityRef) dataType.getDataTypeExtendedInfo();
+ if (ir.isInGrouping()) {
+ return String.valueOf(fieldObj).trim();
+ }
+ return getIdentityRefValue(fieldObj, ir, holderObj);
+
+ case LEAFREF:
+ YangLeafRef leafRef =
+ (YangLeafRef) dataType.getDataTypeExtendedInfo();
+ return getStringFromType(holder, holderObj, name, fieldObj,
+ leafRef.getEffectiveDataType());
+
+ default:
+ throw new ModelConvertorException("Unsupported data type. Cannot be " +
+ "processed.");
+ }
+ }
+
+ /**
+ * Returns the string values for the data type bits.
+ *
+ * @param holder leaf/leaf-list holder
+ * @param holderObj leaf/leaf-list holder object
+ * @param name leaf/leaf-list name
+ * @param fieldObj object of the leaf/leaf-list field
+ * @return string value for bits type
+ */
+ private static String getBitsValue(YangSchemaNode holder, Object holderObj,
+ String name, Object fieldObj) {
+
+ Class<?> holderClass = holderObj.getClass();
+ String interfaceName = holder.getJavaClassNameOrBuiltInType();
+ String className = interfaceName.toLowerCase() + PERIOD +
+ getCapitalCase(name);
+ String pkgName = holder.getJavaPackage() + PERIOD + className;
+ ClassLoader classLoader = holderClass.getClassLoader();
+
+ Class<?> bitClass;
+ try {
+ bitClass = classLoader.loadClass(pkgName);
+ Method getterMethod = bitClass.getDeclaredMethod(
+ TO_STRING, fieldObj.getClass());
+ return String.valueOf(getterMethod.invoke(null, fieldObj));
+ } catch (ClassNotFoundException | NoSuchMethodException |
+ InvocationTargetException | IllegalAccessException e) {
+ throw new ModelConvertorException(e);
+ }
+ }
+
+ /**
+ * Returns the string value of the type identity-ref.
+ *
+ * @param fieldObj object of the leaf/leaf-list field
+ * @param ir YANG identity ref
+ * @param holderObj leaf/leaf-list holder object
+ * @return string value for identity ref type
+ */
+ private static String getIdentityRefValue(Object fieldObj, YangIdentityRef ir,
+ Object holderObj) {
+
+ YangIdentity id = ir.getReferredIdentity();
+ String idName = id.getJavaClassNameOrBuiltInType();
+ String idPkg = id.getJavaPackage() + PERIOD + getCapitalCase(idName);
+ String methodName = idName + getCapitalCase(TO_STRING);
+
+ Class<?> holderClass = holderObj.getClass();
+ ClassLoader classLoader = holderClass.getClassLoader();
+ Class<?> idClass;
+ try {
+ idClass = classLoader.loadClass(idPkg);
+ Method method = idClass.getDeclaredMethod(methodName, (Class<?>) null);
+ return String.valueOf(method.invoke(fieldObj, (Object) null)).trim();
+ } catch (ClassNotFoundException | NoSuchMethodException |
+ InvocationTargetException | IllegalAccessException e) {
+ throw new ModelConvertorException(e);
+ }
+ }
+
+ /**
+ * Returns true, if the data type is primitive; false otherwise.
+ *
+ * @param dataType data type
+ * @return true if the data type is primitive; false otherwise
+ */
+ private static boolean isPrimitiveDataType(YangDataTypes dataType) {
+ return PRIMITIVE_TYPES.contains(dataType);
+ }
+
+ /**
+ * Returns true, if processing of the node is not required; false otherwise.
+ * For the nodes such as notification, RPC, augment there is a different
+ * flow, so these nodes are skipped in normal conditions.
+ *
+ * @param yangNode node to be checked
+ * @return true if node processing is not required; false otherwise.
+ */
+ static boolean isNonProcessableNode(YangNode yangNode) {
+ return yangNode != null &&
+ yangNode instanceof YangNotification ||
+ yangNode instanceof YangRpc ||
+ yangNode instanceof YangAugment;
+ }
+
+ /**
+ * Returns true, if multi instance node; false otherwise.
+ *
+ * @param yangNode YANG node
+ * @return true, if multi instance node; false otherwise.
+ */
+ static boolean isMultiInstanceNode(YangNode yangNode) {
+ return yangNode.getYangSchemaNodeType() == YANG_MULTI_INSTANCE_NODE;
+ }
+
+ /**
+ * Returns true, if augment node; false otherwise.
+ *
+ * @param yangNode YANG node
+ * @return true, if augment node; false otherwise.
+ */
+ static boolean isAugmentNode(YangNode yangNode) {
+ return yangNode.getYangSchemaNodeType() == YANG_AUGMENT_NODE;
+ }
+
+ /**
+ * Returns string for throwing error when empty object is given as input
+ * to YTB.
+ *
+ * @param objName name of the object
+ * @return error message
+ */
+ static String emptyObjErrMsg(String objName) {
+ return "The " + objName + " given for tree creation cannot be null";
+ }
+
+ /**
+ * Returns the java name for the nodes, leaf/leaf-list.
+ *
+ * @param node YANG node
+ * @return node java name
+ */
+ static String getJavaName(Object node) {
+ return ((YangSchemaNode) node).getJavaAttributeName();
+ }
+
+ /**
+ * Returns true, if the string is not null and non-empty; false otherwise.
+ *
+ * @param str string value
+ * @return true, if the string is not null and non-empty; false otherwise.
+ */
+ static boolean nonEmpty(String str) {
+ return str != null && !str.isEmpty();
+ }
+
+ /**
+ * Returns true when the node processing of RPC and notification is
+ * completed; false otherwise. For RPC and notification, processing of
+ * other nodes are invalid, so once node gets completed, it must be stopped.
+ *
+ * @param curNode current node
+ * @param type current traversal of the node
+ * @return true, if the node processing is completed; false otherwise.
+ */
+ static boolean isNodeProcessCompleted(YangNode curNode, TraversalType type) {
+ return type == PARENT &&
+ curNode instanceof YangNotification ||
+ curNode instanceof YangOutput;
+ }
+
+ /**
+ * Returns package for the given atomic path.
+ *
+ * @param path atomic path
+ * @return package for the given path
+ */
+ static String fetchPackage(AtomicPath path) {
+ switch (path.type()) {
+ case SINGLE_INSTANCE_NODE:
+ SingleInstanceNode sin = (SingleInstanceNode) path;
+ return sin.container().getName();
+ case MULTI_INSTANCE_NODE:
+ MultiInstanceNode min = (MultiInstanceNode) path;
+ return min.listClass().getName();
+ case SINGLE_INSTANCE_LEAF_VALUE_NODE:
+ SingleInstanceLeaf sil = (SingleInstanceLeaf) path;
+ return getNameWithOutSpecialChar(
+ sil.leafIdentifier().toString().toLowerCase());
+ case MULTI_INSTANCE_LEAF_VALUE_NODE:
+ MultiInstanceLeaf mil = (MultiInstanceLeaf) path;
+ return getNameWithOutSpecialChar(
+ mil.leafIdentifier().toString().toLowerCase());
+ default:
+ throw new ModelConvertorException("leaf/leaf-list can't be at this " +
+ "position");
+ }
+ }
+
+ /**
+ * Removes underscore from the given name.
+ *
+ * @param name name of instance
+ * @return name
+ */
+ private static String getNameWithOutSpecialChar(String name) {
+ String[] str = name.split(UNDER_SCORE);
+ StringBuilder builder = new StringBuilder();
+ for (String s : str) {
+ builder.append(s);
+ }
+ return builder.toString();
+ }
+}
diff --git a/runtime/src/main/java/org/onosproject/yang/runtime/impl/ModelConvertorException.java b/runtime/src/main/java/org/onosproject/yang/runtime/impl/ModelConvertorException.java
new file mode 100644
index 0000000..534ed13
--- /dev/null
+++ b/runtime/src/main/java/org/onosproject/yang/runtime/impl/ModelConvertorException.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2017-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.yang.runtime.impl;
+
+/**
+ * Represents exception that needs to be handled by model converter.
+ */
+class ModelConvertorException extends RuntimeException {
+
+ /**
+ * Creates model converter exception with an exception message.
+ *
+ * @param exceptionMessage message with which exception must be thrown
+ */
+ ModelConvertorException(String exceptionMessage) {
+ super(exceptionMessage);
+ }
+
+ /**
+ * Creates model converter exception with the cause for it.
+ *
+ * @param cause cause of the exception
+ */
+ ModelConvertorException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/runtime/src/test/java/org/onosproject/yang/runtime/impl/DataTreeContextSwitchTest.java b/runtime/src/test/java/org/onosproject/yang/runtime/impl/DataTreeContextSwitchTest.java
new file mode 100644
index 0000000..0e6a5ba
--- /dev/null
+++ b/runtime/src/test/java/org/onosproject/yang/runtime/impl/DataTreeContextSwitchTest.java
@@ -0,0 +1,1665 @@
+/*
+ * Copyright 2017-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.yang.runtime.impl;
+
+
+import org.junit.Test;
+import org.onosproject.yang.gen.v1.yms.test.ytb.choice.with.container.and.leaf.yangautoprefixlist.rev20160826.ytbchoicewithcontainerandleaflist.contenttest.choicecontainer.ChoiceContainer;
+import org.onosproject.yang.gen.v1.yms.test.ytb.choice.with.container.and.leaf.yangautoprefixlist.rev20160826.ytbchoicewithcontainerandleaflist.contenttest.choicecontainer.DefaultChoiceContainer;
+import org.onosproject.yang.gen.v1.yms.test.ytb.choice.with.container.and.leaf.yangautoprefixlist.rev20160826.ytbchoicewithcontainerandleaflist.contenttest.choicecontainer.choicecontainer.DefaultPredict;
+import org.onosproject.yang.gen.v1.yms.test.ytb.choice.with.container.and.leaf.yangautoprefixlist.rev20160826.ytbchoicewithcontainerandleaflist.contenttest.choicecontainer.choicecontainer.Predict;
+import org.onosproject.yang.gen.v1.yms.test.ytb.choice.with.container.and.leaf.yangautoprefixlist.rev20160826.ytbchoicewithcontainerandleaflist.contenttest.choicecontainer.choicecontainer.predict.DefaultReproduce;
+import org.onosproject.yang.gen.v1.yms.test.ytb.choice.with.container.and.leaf.yangautoprefixlist.rev20160826.ytbchoicewithcontainerandleaflist.contenttest.choicecontainer.choicecontainer.predict.Reproduce;
+import org.onosproject.yang.gen.v1.yms.test.ytb.choice.with.container.and.leaf.yangautoprefixlist.rev20160826.ytbchoicewithcontainerandleaflist.currentvalue.DefaultYtbAbsent;
+import org.onosproject.yang.gen.v1.yms.test.ytb.simple.augment.rev20160826.ytbsimpleaugment.DefaultCont1;
+import org.onosproject.yang.gen.v1.yms.test.ytb.simple.augment.rev20160826.ytbsimpleaugment.cont1.DefaultCont2;
+import org.onosproject.yang.gen.v1.yms.test.ytb.simple.augment.rev20160826.ytbsimpleaugment.cont1.cont2.DefaultAugmentedCont2;
+import org.onosproject.yang.gen.v1.yms.test.ytb.simple.augment.rev20160826.ytbsimpleaugment.cont1.cont2.augmentedcont2.Cont1s;
+import org.onosproject.yang.gen.v1.yms.test.ytb.simple.augment.rev20160826.ytbsimpleaugment.cont1.cont2.augmentedcont2.DefaultCont1s;
+import org.onosproject.yang.gen.v1.yms.test.ytb.simple.choice.yangautoprefixcase.rev20160826.ytbsimplechoicecase.DefaultYtbFood;
+import org.onosproject.yang.gen.v1.yms.test.ytb.simple.choice.yangautoprefixcase.rev20160826.ytbsimplechoicecase.ytbfood.ytbsnack.DefaultYtbLateNight;
+import org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.modulelistandkey.DefaultModKey;
+import org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.modulelistandkeyaugment.modkey.DefaultAugmentedSchModKey;
+import org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.modulelistandkeyaugment.modkey.augmentedschmodkey.AugListModKey;
+import org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.modulelistandkeyaugment.modkey.augmentedschmodkey.DefaultAugListModKey;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.BinaryTypedef;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.DefaultFirstLevel;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.UnionTypedef;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.Uri;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.firstlevel.DefaultContainerChoice;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.firstlevel.DefaultContainerGrouping;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.firstlevel.DefaultContainerLeaf;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.firstlevel.DefaultContainerLeafList;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.firstlevel.DefaultContainerList;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.firstlevel.DefaultOnlyContainer;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.firstlevel.containerchoice.choicecase.DefaultLeafCase;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.firstlevel.containerchoice.choicecase.leafcase.DefaultAugmentedLeafCase;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.firstlevel.containerleaf.DefaultAugmentedContainerLeaf;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.firstlevel.containerleaflist.LeafList2Enum;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.firstlevel.containerlist.DefaultListLeaf;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.firstlevel.containerlist.ListLeaf;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.firstlevel.containerlist.ListLeafKeys;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.firstlevel.containerlist.listleaf.DefaultAugmentedListLeaf;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedata.group1.DefaultGroupContainer;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedatainterfile.firstlevel.containerchoice.choicecase.augmentedschchoicecase.DefaultLeafInterAug;
+import org.onosproject.yang.gen.v1.yrt.model.converter.model.data.to.resource.data.rev20160826.modeldatatoresourcedatainterfile.firstlevel.containerchoice.choicecase.leafcase.DefaultAugmentedSchLeafCase;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.DefaultModelObjectData;
+import org.onosproject.yang.model.InnerNode;
+import org.onosproject.yang.model.KeyLeaf;
+import org.onosproject.yang.model.ListKey;
+import org.onosproject.yang.model.ModelObjectId;
+import org.onosproject.yang.model.NodeKey;
+import org.onosproject.yang.model.ResourceData;
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.model.SchemaId;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.onosproject.yang.model.DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE;
+import static org.onosproject.yang.model.DataNode.Type.MULTI_INSTANCE_NODE;
+import static org.onosproject.yang.model.DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE;
+import static org.onosproject.yang.model.DataNode.Type.SINGLE_INSTANCE_NODE;
+import static org.onosproject.yang.runtime.impl.TestUtils.validateDataNode;
+
+/**
+ * Unit test cases for YANG tree builder for context switch for augment, RPC
+ * and case.
+ */
+public class DataTreeContextSwitchTest {
+
+ private static final String CHOC = "choc";
+ private static final String VAL = "val";
+ private static final String IND = "ind";
+ private ResourceData rscData;
+ private DefaultDataTreeBuilder treeBuilder;
+ private ResourceId id;
+ private List<NodeKey> keys;
+ private String nameSpace;
+ private SchemaId sid;
+ private List<DataNode> dataNodes;
+ private DataNode node;
+ private ModelObjectId mid;
+ private DefaultModelObjectData.Builder data;
+ private final TestYangSchemaNodeProvider schemaProvider = new
+ TestYangSchemaNodeProvider();
+
+ /**
+ * Do the prior setup for each UT.
+ */
+ private void setUp() {
+ schemaProvider.processSchemaRegistry();
+ DefaultYangModelRegistry registry = schemaProvider.registry();
+ treeBuilder = new DefaultDataTreeBuilder(registry);
+ }
+
+ /**
+ * Unit test case to process a simple choice inside module. Here model
+ * object id is null so resource identifier will have "/". Data node list
+ * will contain container node which will have nodes for once of the case.
+ */
+ @Test
+ public void processSimpleChoiceCase() {
+
+ setUp();
+
+ // As an application, creates the object.
+
+ // Creates a choice snack with the case late night.
+ DefaultYtbLateNight lateNight = new DefaultYtbLateNight();
+ lateNight.chocolate(CHOC);
+
+ // Creates container food with the created case.
+ DefaultYtbFood food = new DefaultYtbFood();
+ food.ytbSnack(lateNight);
+
+ // Builds YANG tree in YTB.
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(food);
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yms:test:ytb:simple:choice:case";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(1, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "YtbFood", nameSpace, SINGLE_INSTANCE_NODE,
+ true, null);
+
+ Map<NodeKey, DataNode> child = ((InnerNode) node).childNodes();
+ assertThat(1, is(child.size()));
+
+ Iterator<Map.Entry<NodeKey, DataNode>> it = child.entrySet().iterator();
+ Map.Entry<NodeKey, DataNode> n = it.next();
+
+ validateDataNode(n.getValue(), "chocolate", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, CHOC);
+ }
+
+ /**
+ * Unit test case to process a simple choice inside module. Here model
+ * object id is having container class so resource identifier will have
+ * "/" and container in it. data node list will have content of case node.
+ */
+ @Test
+ public void processSimpleChoiceCaseModIdOne() {
+
+ setUp();
+
+ // As an application, creates the object.
+
+ // Creates a choice snack with the case late night.
+ DefaultYtbLateNight lateNight = new DefaultYtbLateNight();
+ lateNight.chocolate(CHOC);
+
+ // Builds YANG tree in YTB.
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(lateNight);
+ mid = ModelObjectId.builder().addChild(DefaultYtbFood.class).build();
+ data.identifer(mid);
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yms:test:ytb:simple:choice:case";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(2, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("YtbFood", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "chocolate", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, CHOC);
+ }
+
+ /**
+ * Unit test case for a module containing 2 choice nodes. model object id
+ * is null so resource identifier will be "/". model object will contain
+ * data for case1 and case 2. container has list which does not have a
+ * key. in that case while adding it to parent data node it will
+ * overwrite the data for previous instance of list. resource data will
+ * have 3 model objects in list. 1 for container and other 2 for leaf
+ * list of second choice node.
+ */
+ @Test
+ public void processChoiceWithNodeAndLeafList() {
+ setUp();
+
+ // As an application, creates the object.
+
+ // Creates reproduce container for list predict-1.
+ Reproduce reproduce1 = new DefaultReproduce();
+ reproduce1.yangAutoPrefixCatch((short) 90);
+
+ // Assigns predict-1 with the container.
+ Predict predict1 = new DefaultPredict();
+ predict1.reproduce(reproduce1);
+
+ // Creates reproduce container for list predict-2.
+ Reproduce reproduce2 = new DefaultReproduce();
+ reproduce2.yangAutoPrefixCatch((short) 100);
+
+ // Assigns predict-2 with the container.
+ Predict predict2 = new DefaultPredict();
+ predict2.reproduce(reproduce2);
+
+ List<Predict> predictList = new ArrayList<>();
+ predictList.add(predict1);
+ predictList.add(predict2);
+
+ // Case container is added to the choice content-test.
+ ChoiceContainer containerCase = new DefaultChoiceContainer();
+ containerCase.predict(predictList);
+ // Case container is added to the choice content-test.
+ org.onosproject.yang.gen.v1.yms.test.ytb.choice.with
+ .container.and.leaf.yangautoprefixlist.rev20160826
+ .ytbchoicewithcontainerandleaflist.contenttest
+ .DefaultChoiceContainer contentTest =
+ new org.onosproject.yang.gen.v1.yms.test.ytb.choice.with
+ .container.and.leaf.yangautoprefixlist.rev20160826
+ .ytbchoicewithcontainerandleaflist.contenttest
+ .DefaultChoiceContainer();
+ contentTest.choiceContainer(containerCase);
+
+ // Creates string list for leaf-list final.
+ List<String> stringList = new ArrayList<>();
+ stringList.add(VAL);
+ stringList.add(IND);
+
+ // For choice current value, the leaf list gets added as case.
+ DefaultYtbAbsent currentValue = new DefaultYtbAbsent();
+ currentValue.yangAutoPrefixFinal(stringList);
+
+ // Builds YANG tree in YTB.
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(contentTest).addModelObject(currentValue);
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yms:test:ytb:choice:with:container:and:leaf:list";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(1, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(3, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "choice-container", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+ //Here only one instance of list will be added because config is
+ // false. so there will be no difference in 2 instance of list node.
+ Map<NodeKey, DataNode> child = ((InnerNode) node).childNodes();
+ assertThat(1, is(child.size()));
+ Iterator<Map.Entry<NodeKey, DataNode>> it = child.entrySet().iterator();
+
+ Map.Entry<NodeKey, DataNode> n = it.next();
+ validateDataNode(n.getValue(), "predict", nameSpace,
+ MULTI_INSTANCE_NODE,
+ true, null);
+ child = ((InnerNode) n.getValue()).childNodes();
+ assertThat(1, is(child.size()));
+
+ it = child.entrySet().iterator();
+ n = it.next();
+ validateDataNode(n.getValue(), "reproduce", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+
+ child = ((InnerNode) n.getValue()).childNodes();
+ assertThat(1, is(child.size()));
+
+ it = child.entrySet().iterator();
+ n = it.next();
+ validateDataNode(n.getValue(), "catch", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "100");
+
+ node = dataNodes.get(1);
+ validateDataNode(node, "final", nameSpace,
+ MULTI_INSTANCE_LEAF_VALUE_NODE,
+ true, VAL);
+
+ node = dataNodes.get(2);
+ validateDataNode(node, "final", nameSpace,
+ MULTI_INSTANCE_LEAF_VALUE_NODE,
+ true, IND);
+ }
+
+ /**
+ * Unit test for a module containing a container and augment. Model
+ * object id is null so resource identifier will have only "/". and as we
+ * are augmenting one of the container. data node for container will have
+ * augment data as child nodes.
+ */
+ @Test
+ public void processSimpleAugment() {
+ setUp();
+ // As an application, creates the object.
+
+ // Creates container cont1s with the leaf.
+ org.onosproject.yang.gen.v1.yms.test.ytb.simple.augment.rev20160826
+ .ytbsimpleaugment.cont1.cont2.augmentedcont2.cont1s
+ .Cont1s cont1s1 = new org.onosproject.yang.gen.v1.yms.test
+ .ytb.simple.augment.rev20160826.ytbsimpleaugment.cont1.cont2
+ .augmentedcont2.cont1s.DefaultCont1s();
+
+ // Appends the created container into another container.
+ Cont1s cont1s = new DefaultCont1s();
+ cont1s.cont1s(cont1s1);
+
+ // Creates augment with the container and leaf.
+ DefaultAugmentedCont2 augment = new DefaultAugmentedCont2();
+ augment.cont1s(cont1s);
+ augment.leaf4(500);
+
+ // Creates for the node which will be getting augmented.
+ // Creates cont2 where content will be augmented into.
+ DefaultCont2 augCont2 = new DefaultCont2();
+ augCont2.addAugmentation(augment);
+
+ // Creates cont1 where cont2 is added.
+ DefaultCont1 cont1 = new DefaultCont1();
+ cont1.cont2(augCont2);
+
+ // Builds YANG tree in YTB.
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(cont1);
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yms:test:ytb:simple:augment";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(1, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "cont1", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+ //Here only one instance of list will be added because config is
+ // false. so there will be no difference in 2 instance of list node.
+ Map<NodeKey, DataNode> child = ((InnerNode) node).childNodes();
+ assertThat(1, is(child.size()));
+ Iterator<Map.Entry<NodeKey, DataNode>> it = child.entrySet().iterator();
+
+ Map.Entry<NodeKey, DataNode> n = it.next();
+ validateDataNode(n.getValue(), "cont2", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+ child = ((InnerNode) n.getValue()).childNodes();
+ assertThat(2, is(child.size()));
+
+ it = child.entrySet().iterator();
+ n = it.next();
+ validateDataNode(n.getValue(), "leaf4", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "500");
+
+ n = it.next();
+ validateDataNode(n.getValue(), "cont1s", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+
+ child = ((InnerNode) n.getValue()).childNodes();
+ assertThat(1, is(child.size()));
+
+ it = child.entrySet().iterator();
+ n = it.next();
+ validateDataNode(n.getValue(), "cont1s", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+ }
+
+ /**
+ * Unit test for a module containing a container and augment. Model
+ * object id is having container so resource identifier will have "/".
+ * and container node. as we are augmenting one of the container. data node
+ * for container will have augment data as child nodes.
+ */
+ @Test
+ public void processSimpleAugmentModIdC1() {
+ setUp();
+ // As an application, creates the object.
+
+ // Creates container cont1s with the leaf.
+ org.onosproject.yang.gen.v1.yms.test.ytb.simple.augment.rev20160826
+ .ytbsimpleaugment.cont1.cont2.augmentedcont2.cont1s
+ .Cont1s cont1s1 = new org.onosproject.yang.gen.v1.yms.test
+ .ytb.simple.augment.rev20160826.ytbsimpleaugment.cont1.cont2
+ .augmentedcont2.cont1s.DefaultCont1s();
+
+ // Appends the created container into another container.
+ Cont1s cont1s = new DefaultCont1s();
+ cont1s.cont1s(cont1s1);
+
+ // Creates augment with the container and leaf.
+ DefaultAugmentedCont2 augment = new DefaultAugmentedCont2();
+ augment.cont1s(cont1s);
+ augment.leaf4(500);
+
+ // Creates for the node which will be getting augmented.
+ // Creates cont2 where content will be augmented into.
+ DefaultCont2 augCont2 = new DefaultCont2();
+ augCont2.addAugmentation(augment);
+
+ // Builds YANG tree in YTB.
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(augCont2);
+ mid = ModelObjectId.builder().addChild(DefaultCont1.class).build();
+ data.identifer(mid);
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yms:test:ytb:simple:augment";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(2, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("cont1", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "cont2", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+ //Here only one instance of list will be added because config is
+ // false. so there will be no difference in 2 instance of list node.
+ Map<NodeKey, DataNode> child = ((InnerNode) node).childNodes();
+ assertThat(2, is(child.size()));
+ Iterator<Map.Entry<NodeKey, DataNode>> it = child.entrySet().iterator();
+
+ Map.Entry<NodeKey, DataNode> n = it.next();
+ validateDataNode(n.getValue(), "leaf4", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "500");
+
+ n = it.next();
+ validateDataNode(n.getValue(), "cont1s", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+
+ child = ((InnerNode) n.getValue()).childNodes();
+ assertThat(1, is(child.size()));
+
+ it = child.entrySet().iterator();
+ n = it.next();
+ validateDataNode(n.getValue(), "cont1s", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+ }
+
+ /**
+ * Unit test for a module containing a container and augment. Model
+ * object id is having container so resource identifier will have "/".
+ * and container node. as we are augmenting one of the container. data node
+ * for container will have augment data as child nodes.
+ */
+ @Test
+ public void processSimpleAugmentModIdC2() {
+ setUp();
+ // As an application, creates the object.
+
+ // Creates container cont1s with the leaf.
+ org.onosproject.yang.gen.v1.yms.test.ytb.simple.augment.rev20160826
+ .ytbsimpleaugment.cont1.cont2.augmentedcont2.cont1s
+ .Cont1s cont1s1 = new org.onosproject.yang.gen.v1.yms.test
+ .ytb.simple.augment.rev20160826.ytbsimpleaugment.cont1.cont2
+ .augmentedcont2.cont1s.DefaultCont1s();
+
+ // Appends the created container into another container.
+ Cont1s cont1s = new DefaultCont1s();
+ cont1s.cont1s(cont1s1);
+
+ // Creates augment with the container and leaf.
+ DefaultAugmentedCont2 augment = new DefaultAugmentedCont2();
+ augment.cont1s(cont1s);
+ augment.leaf4(500);
+
+ // Builds YANG tree in YTB.
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(augment);
+ mid = ModelObjectId.builder().addChild(DefaultCont1.class)
+ .addChild(DefaultCont2.class).build();
+
+ data.identifer(mid);
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yms:test:ytb:simple:augment";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(3, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("cont1", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = keys.get(2).schemaId();
+ assertThat("cont2", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(2, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "leaf4", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "500");
+
+ node = dataNodes.get(1);
+ validateDataNode(node, "cont1s", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+ }
+
+ /**
+ * Unit test for a module containing a container and augment. Model
+ * object id is having container which added by augment so resource
+ * identifier will have "/".
+ * and container node. list of data nodes will contain the augmented
+ * container's child node.
+ */
+ @Test
+ public void processSimpleAugmentModIdAug() {
+ setUp();
+ // As an application, creates the object.
+
+ // Creates container cont1s with the leaf.
+ org.onosproject.yang.gen.v1.yms.test.ytb.simple.augment.rev20160826
+ .ytbsimpleaugment.cont1.cont2.augmentedcont2.cont1s
+ .DefaultCont1s cont1s1 = new org.onosproject.yang.gen.v1.yms.test
+ .ytb.simple.augment.rev20160826.ytbsimpleaugment.cont1.cont2
+ .augmentedcont2.cont1s.DefaultCont1s();
+
+ // Builds YANG tree in YTB.
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(cont1s1);
+ mid = ModelObjectId.builder().addChild(DefaultCont1.class)
+ .addChild(DefaultCont2.class)
+ .addChild(DefaultCont1s.class).build();
+
+ data.identifer(mid);
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yms:test:ytb:simple:augment";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(4, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("cont1", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = keys.get(2).schemaId();
+ assertThat("cont2", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = keys.get(3).schemaId();
+ assertThat("cont1s", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "cont1s", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+ }
+
+
+ /**
+ * Unit test for inter file augment. Model object is null so resource id
+ * will have "/" and data nodes will contain augment data as well.
+ */
+ @Test
+ public void processInterFileAugmentList() {
+ setUp();
+
+ // As an application, creates the object.
+
+ DefaultModKey modKey = new DefaultModKey();
+ modKey.types(20);
+
+ //add augment.
+ DefaultAugmentedSchModKey aug = new DefaultAugmentedSchModKey();
+ DefaultAugListModKey modAug = new DefaultAugListModKey();
+ modAug.types(10);
+ List<AugListModKey> modKeys = new ArrayList<>();
+ modKeys.add(modAug);
+ aug.augListModKey(modKeys);
+
+ modKey.addAugmentation(aug);
+
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(modKey);
+
+ // Builds YANG tree in YTB.
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yms:test:ytb:tree:builder:for:list:having:list";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(1, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "modKey", nameSpace,
+ MULTI_INSTANCE_NODE,
+ true, null);
+
+ Map<NodeKey, DataNode> child = ((InnerNode) node).childNodes();
+ assertThat(2, is(child.size()));
+
+ Iterator<Map.Entry<NodeKey, DataNode>> it = child.entrySet().iterator();
+
+ Map.Entry<NodeKey, DataNode> n = it.next();
+ validateDataNode(n.getValue(), "types", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "20");
+ n = it.next();
+ validateDataNode(n.getValue(), "aug-list-modKey", nameSpace,
+ MULTI_INSTANCE_NODE,
+ true, null);
+ }
+
+ /**
+ * Basic unit test for second level nodes. in this ut we are testing for
+ * a normal container in container case. model object id contain the
+ * first level container class so resource id will contain it and
+ * resource data will contain object of the second container.
+ */
+ @Test
+ public void moduleWithModIdFirstLvlOne() {
+ setUp();
+
+ DefaultOnlyContainer con = new DefaultOnlyContainer();
+
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(con);
+ data.identifer(ModelObjectId.builder()
+ .addChild(DefaultFirstLevel.class).build());
+
+ // Builds YANG tree in YTB.
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yrt:model:converter:model:data:to:resource:data";
+
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(2, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("first-level", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "only-container", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+
+ Map<NodeKey, DataNode> child = ((InnerNode) node).childNodes();
+ assertThat(0, is(child.size()));
+ }
+
+ /**
+ * Basic unit test for second level nodes. in this ut we are testing for
+ * a normal container in container case. model object id contain the
+ * first level and container class so resource id will contain it and
+ * resource data will empty list
+ */
+ @Test
+ public void moduleWithModIdFirstLvlOneL2() {
+ setUp();
+
+ data = new DefaultModelObjectData.Builder();
+ data.identifer(ModelObjectId.builder()
+ .addChild(DefaultFirstLevel.class)
+ .addChild(DefaultOnlyContainer.class).build());
+
+ // Builds YANG tree in YTB.
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yrt:model:converter:model:data:to:resource:data";
+
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(3, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("first-level", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = keys.get(2).schemaId();
+ assertThat("only-container", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(0, is(dataNodes.size()));
+ }
+
+
+ /**
+ * Basic unit test for second level nodes. in this ut we are testing for
+ * a normal container in container case. model object id contain the
+ * first level container class so resource id will contain it and
+ * resource data will contain object of the second container. we have
+ * augmented leaf added to it so those should also be part of data nodes.
+ */
+ @Test
+ public void moduleWithModIdFirstLvlTwo() {
+ setUp();
+
+ DefaultContainerLeaf con = new DefaultContainerLeaf();
+ con.leaf2("leaf2");
+
+ DefaultAugmentedContainerLeaf aug = new DefaultAugmentedContainerLeaf();
+ aug.leafAug(true);
+ con.addAugmentation(aug);
+
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(con);
+ data.identifer(ModelObjectId.builder()
+ .addChild(DefaultFirstLevel.class).build());
+
+ // Builds YANG tree in YTB.
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yrt:model:converter:model:data:to:resource:data";
+
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(2, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("first-level", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "container-leaf", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+
+ Map<NodeKey, DataNode> child = ((InnerNode) node).childNodes();
+ assertThat(2, is(child.size()));
+
+ Iterator<Map.Entry<NodeKey, DataNode>> it = child.entrySet().iterator();
+
+ Map.Entry<NodeKey, DataNode> n = it.next();
+ validateDataNode(n.getValue(), "leaf2", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "leaf2");
+ n = it.next();
+ validateDataNode(n.getValue(), "leaf-aug", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, null);
+ }
+
+ /**
+ * Basic unit test for second level nodes. in this ut we are testing for
+ * a normal container in container case. model object id contain the
+ * first level container class so resource id will contain it and
+ * resource data will contain object of the second container. each leaf
+ * list instance should have its data node.
+ */
+ @Test
+ public void moduleWithModIdFirstLvlThree() {
+ setUp();
+
+ List<LeafList2Enum> list = new ArrayList<>();
+ list.add(LeafList2Enum.HUNDRED);
+ list.add(LeafList2Enum.TEN);
+ list.add(LeafList2Enum.THOUSAND);
+
+ DefaultContainerLeafList con = new DefaultContainerLeafList();
+ con.leafList2(list);
+
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(con);
+ data.identifer(ModelObjectId.builder()
+ .addChild(DefaultFirstLevel.class).build());
+
+ // Builds YANG tree in YTB.
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yrt:model:converter:model:data:to:resource:data";
+
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(2, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("first-level", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "container-leaf-list", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+
+ Map<NodeKey, DataNode> child = ((InnerNode) node).childNodes();
+ assertThat(3, is(child.size()));
+
+ Iterator<Map.Entry<NodeKey, DataNode>> it = child.entrySet().iterator();
+
+ Map.Entry<NodeKey, DataNode> n = it.next();
+ validateDataNode(n.getValue(), "leaf-list2", nameSpace,
+ MULTI_INSTANCE_LEAF_VALUE_NODE,
+ true, "hundred");
+ n = it.next();
+ validateDataNode(n.getValue(), "leaf-list2", nameSpace,
+ MULTI_INSTANCE_LEAF_VALUE_NODE,
+ true, "ten");
+ n = it.next();
+ validateDataNode(n.getValue(), "leaf-list2", nameSpace,
+ MULTI_INSTANCE_LEAF_VALUE_NODE,
+ true, "thousand");
+ }
+
+ /**
+ * Basic unit test for second level nodes. in this ut we are testing for
+ * a normal container in container case. model object id contain the
+ * first level container class so resource id will contain it and
+ * resource data will contain object of the second list. each
+ * list instance should have its data node.
+ */
+ @Test
+ public void moduleWithModIdFirstLvlFour() {
+ setUp();
+
+ List<ListLeaf> list = new ArrayList<>();
+ DefaultListLeaf listLeaf = new DefaultListLeaf();
+ DefaultAugmentedListLeaf aug = new DefaultAugmentedListLeaf();
+ aug.leafAug(UnionTypedef.fromString("12"));
+ listLeaf.addAugmentation(aug);
+
+ listLeaf.name("first");
+ list.add(listLeaf);
+
+ listLeaf = new DefaultListLeaf();
+ aug = new DefaultAugmentedListLeaf();
+ aug.leafAug(UnionTypedef.fromString("14"));
+ listLeaf.addAugmentation(aug);
+
+ listLeaf.name("second");
+ list.add(listLeaf);
+
+ DefaultContainerList con = new DefaultContainerList();
+ con.listLeaf(list);
+
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(con);
+ data.identifer(ModelObjectId.builder()
+ .addChild(DefaultFirstLevel.class).build());
+
+ // Builds YANG tree in YTB.
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yrt:model:converter:model:data:to:resource:data";
+
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(2, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("first-level", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "container-list", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+
+ Map<NodeKey, DataNode> child = ((InnerNode) node).childNodes();
+ assertThat(2, is(child.size()));
+
+ Iterator<Map.Entry<NodeKey, DataNode>> it = child.entrySet().iterator();
+
+ Map.Entry<NodeKey, DataNode> n = it.next();
+ validateDataNode(n.getValue(), "list-leaf", nameSpace,
+ MULTI_INSTANCE_NODE,
+ true, null);
+ child = ((InnerNode) n.getValue()).childNodes();
+ assertThat(2, is(child.size()));
+
+ it = child.entrySet().iterator();
+ n = it.next();
+ validateDataNode(n.getValue(), "name", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "first");
+ n = it.next();
+ validateDataNode(n.getValue(), "leaf-aug", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "12");
+
+ child = ((InnerNode) node).childNodes();
+ assertThat(2, is(child.size()));
+
+ it = child.entrySet().iterator();
+
+ n = it.next();
+ //second child
+ n = it.next();
+ validateDataNode(n.getValue(), "list-leaf", nameSpace,
+ MULTI_INSTANCE_NODE,
+ true, null);
+ child = ((InnerNode) n.getValue()).childNodes();
+ assertThat(2, is(child.size()));
+
+ it = child.entrySet().iterator();
+ n = it.next();
+ validateDataNode(n.getValue(), "name", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "second");
+ n = it.next();
+ validateDataNode(n.getValue(), "leaf-aug", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "14");
+ }
+
+ /**
+ * Basic unit test for second level nodes. in this ut we are testing for
+ * a normal container in container case. model object id contain the
+ * first level and container ,list class so resource id will contain it
+ * and resource data will contain leafs.
+ */
+ @Test
+ public void moduleWithModIdFirstLvlFourL2() {
+ setUp();
+
+ data = new DefaultModelObjectData.Builder();
+ List<ListLeaf> list = new ArrayList<>();
+ DefaultListLeaf listLeaf = new DefaultListLeaf();
+ DefaultAugmentedListLeaf aug = new DefaultAugmentedListLeaf();
+ aug.leafAug(UnionTypedef.fromString("12"));
+ listLeaf.addAugmentation(aug);
+
+ listLeaf.name("first");
+ list.add(listLeaf);
+
+ data.addModelObject(listLeaf);
+ listLeaf = new DefaultListLeaf();
+ aug = new DefaultAugmentedListLeaf();
+ aug.leafAug(UnionTypedef.fromString("14"));
+ listLeaf.addAugmentation(aug);
+
+ listLeaf.name("second");
+ list.add(listLeaf);
+
+ data.addModelObject(listLeaf);
+ DefaultContainerList con = new DefaultContainerList();
+ con.listLeaf(list);
+
+ data.identifer(ModelObjectId.builder()
+ .addChild(DefaultFirstLevel.class)
+ .addChild(DefaultContainerList.class).build());
+
+ // Builds YANG tree in YTB.
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yrt:model:converter:model:data:to:resource:data";
+
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(3, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("first-level", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = keys.get(2).schemaId();
+ assertThat("container-list", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(2, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "list-leaf", nameSpace,
+ MULTI_INSTANCE_NODE,
+ true, null);
+
+ Map<NodeKey, DataNode> child = ((InnerNode) node).childNodes();
+ assertThat(2, is(child.size()));
+
+ Iterator<Map.Entry<NodeKey, DataNode>> it = child.entrySet().iterator();
+
+ Map.Entry<NodeKey, DataNode> n = it.next();
+ validateDataNode(n.getValue(), "name", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "first");
+ n = it.next();
+ validateDataNode(n.getValue(), "leaf-aug", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "12");
+
+ node = dataNodes.get(1);
+ validateDataNode(node, "list-leaf", nameSpace,
+ MULTI_INSTANCE_NODE,
+ true, null);
+ child = ((InnerNode) node).childNodes();
+ assertThat(2, is(child.size()));
+
+ it = child.entrySet().iterator();
+ n = it.next();
+ validateDataNode(n.getValue(), "name", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "second");
+ n = it.next();
+ validateDataNode(n.getValue(), "leaf-aug", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "14");
+ }
+
+ /**
+ * Basic unit test for second level nodes. in this ut we are testing for
+ * a normal container in container case. model object id contain the
+ * first level and container ,list class so resource id will contain it
+ * and resource data will contain leafs.
+ */
+ @Test
+ public void moduleWithModIdFirstLvlFourL3() {
+ setUp();
+
+ data = new DefaultModelObjectData.Builder();
+ ListLeafKeys key = new ListLeafKeys();
+ key.name("key leaf");
+ data.identifer(ModelObjectId.builder()
+ .addChild(DefaultFirstLevel.class)
+ .addChild(DefaultContainerList.class)
+ .addChild(DefaultListLeaf.class, key).build());
+
+ // Builds YANG tree in YTB.
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yrt:model:converter:model:data:to:resource:data";
+
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(4, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("first-level", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = keys.get(2).schemaId();
+ assertThat("container-list", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = keys.get(3).schemaId();
+ assertThat("list-leaf", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+ NodeKey nodeKey = keys.get(3);
+ assertThat(true, is(nodeKey instanceof ListKey));
+
+ ListKey listKey = (ListKey) nodeKey;
+ List<KeyLeaf> keyLeaves = listKey.keyLeafs();
+
+ assertThat(1, is(keyLeaves.size()));
+
+ KeyLeaf leaf = keyLeaves.get(0);
+ sid = leaf.leafSchema();
+ assertThat("name", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ Object val = leaf.leafValAsString();
+ assertThat(true, is(val.equals("key leaf")));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(0, is(dataNodes.size()));
+ }
+
+ /**
+ * Basic unit test for second level nodes. in this ut we are testing for
+ * a normal container in container case. model object id contain the
+ * first level container class so resource id will contain it and
+ * resource data will contain object of the case's nodes contains as data
+ * nodes. augmented info also should be present.
+ */
+ @Test
+ public void moduleWithModIdFirstLvlFive() {
+ setUp();
+
+ DefaultLeafCase c1 = new DefaultLeafCase();
+ c1.leaf3(120);
+
+ DefaultAugmentedLeafCase aug1 = new DefaultAugmentedLeafCase();
+ aug1.leafAug(BinaryTypedef.fromString("1011"));
+
+ c1.addAugmentation(aug1);
+
+ DefaultAugmentedSchLeafCase aug2 = new DefaultAugmentedSchLeafCase();
+ aug2.leafInterAug(BigDecimal.valueOf(21102));
+
+ c1.addAugmentation(aug2);
+
+ DefaultContainerChoice con = new DefaultContainerChoice();
+ con.choiceCase(c1);
+
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(con);
+ data.identifer(ModelObjectId.builder()
+ .addChild(DefaultFirstLevel.class).build());
+
+ // Builds YANG tree in YTB.
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yrt:model:converter:model:data:to:resource:data";
+
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(2, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("first-level", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "container-choice", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+
+ Map<NodeKey, DataNode> child = ((InnerNode) node).childNodes();
+ assertThat(3, is(child.size()));
+
+ Iterator<Map.Entry<NodeKey, DataNode>> it = child.entrySet().iterator();
+
+ Map.Entry<NodeKey, DataNode> n = it.next();
+ validateDataNode(n.getValue(), "leaf3", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "120");
+ n = it.next();
+ validateDataNode(n.getValue(), "leaf-aug", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "1011");
+ n = it.next();
+ validateDataNode(n.getValue(), "leaf-inter-aug", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "21102");
+ }
+
+ /**
+ * Basic unit test for second level nodes. in this ut we are testing for
+ * a normal container in container case. model object id contain the
+ * first level container class so resource id will contain it and
+ * resource data will contain object of the augmented case's nodes.
+ * augmented case will be added as child object to the parent class of
+ * choice node.
+ */
+ @Test
+ public void moduleWithModIdFirstLvlSix() {
+ setUp();
+
+ DefaultLeafInterAug c1 = new DefaultLeafInterAug();
+ c1.leafInterAug(Uri.fromString("namespace"));
+
+ DefaultContainerChoice con = new DefaultContainerChoice();
+ con.choiceCase(c1);
+
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(con);
+ data.identifer(ModelObjectId.builder()
+ .addChild(DefaultFirstLevel.class).build());
+
+ // Builds YANG tree in YTB.
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yrt:model:converter:model:data:to:resource:data";
+
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(2, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("first-level", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "container-choice", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+
+ Map<NodeKey, DataNode> child = ((InnerNode) node).childNodes();
+ assertThat(1, is(child.size()));
+
+ Iterator<Map.Entry<NodeKey, DataNode>> it = child.entrySet().iterator();
+
+ Map.Entry<NodeKey, DataNode> n = it.next();
+ validateDataNode(n.getValue(), "leaf-inter-aug", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "namespace");
+ }
+
+
+ /**
+ * Basic unit test for second level nodes. in this ut we are testing for
+ * a normal container in container case. model object id contain the
+ * first level container class so resource id will contain it and
+ * resource data will contain object of the cloned container node.
+ */
+ @Test
+ public void moduleWithModIdFirstLvlSeven() {
+ setUp();
+
+ DefaultGroupContainer gp = new DefaultGroupContainer();
+ gp.groupLeaf(Uri.fromString("namespace"));
+
+ DefaultContainerGrouping con = new DefaultContainerGrouping();
+ con.groupContainer(gp);
+
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(con);
+ data.identifer(ModelObjectId.builder()
+ .addChild(DefaultFirstLevel.class).build());
+
+ // Builds YANG tree in YTB.
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yrt:model:converter:model:data:to:resource:data";
+
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(2, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("first-level", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "container-grouping", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+
+ Map<NodeKey, DataNode> child = ((InnerNode) node).childNodes();
+ assertThat(1, is(child.size()));
+
+ Iterator<Map.Entry<NodeKey, DataNode>> it = child.entrySet().iterator();
+
+ Map.Entry<NodeKey, DataNode> n = it.next();
+ validateDataNode(n.getValue(), "group-container", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+
+ child = ((InnerNode) n.getValue()).childNodes();
+ assertThat(1, is(child.size()));
+
+ it = child.entrySet().iterator();
+
+ n = it.next();
+ validateDataNode(n.getValue(), "group-leaf", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "namespace");
+ }
+
+
+ /**
+ * Unit test for inter file augment. Model object is null so resource id
+ * will have "/" and data nodes will contain augment data as well.
+ */
+ @Test
+ public void processInterFileAugmentChoice() {
+
+ //FIXME: when get filters are done
+// setUp();
+//
+// AugChoiceModKey augChoiceModKey =
+// new org.onosproject.yang.gen.v1.yms.test.ytb.choice.with
+// .container.and.leaf.yangautoprefixlist
+// .rev20160826.augmentchoice.contenttest
+// .augmentedschcontenttest.augchoicemodkey
+// .DefaultAugChoiceModKey();
+// augChoiceModKey.types(30);
+// List<AugChoiceModKey> list = new ArrayList<>();
+// list.add(augChoiceModKey);
+//
+// DefaultAugChoiceModKey aug1 = new DefaultAugChoiceModKey();
+// aug1.augChoiceModKey(list);
+//
+// data = new DefaultModelObjectData.Builder();
+// data.addModelObject(aug1);
+//
+// // Builds YANG tree in YTB.
+// rscData = treeBuilder.getResourceData(data.build());
+//
+// nameSpace = "yms:test:ytb:choice:with:container:and:leaf:list";
+//
+// id = rscData.resourceId();
+// keys = id.nodeKeys();
+// assertThat(1, is(keys.size()));
+//
+// sid = keys.get(0).schemaId();
+// assertThat("/", is(sid.name()));
+// assertThat(null, is(sid.namespace()));
+//
+// dataNodes = rscData.dataNodes();
+// assertThat(1, is(dataNodes.size()));
+//
+// node = dataNodes.get(0);
+// validateDataNode(node, "aug-choice-modKey", nameSpace,
+// MULTI_INSTANCE_NODE,
+// true, null);
+//
+// Map<NodeKey, DataNode> child = ((InnerNode) node).childNodes();
+// assertThat(1, is(child.size()));
+//
+// Iterator<Map.Entry<NodeKey, DataNode>> it = child.entrySet().iterator();
+//
+// Map.Entry<NodeKey, DataNode> n = it.next();
+// validateDataNode(n.getValue(), "types", nameSpace,
+// SINGLE_INSTANCE_LEAF_VALUE_NODE,
+// true, "30");
+ }
+
+//TODO: check this in St test case.
+// /**
+// * Processes inter file augment with augmented node as list and the
+// * augment having list.
+// */
+// // @Test
+// public void processInterFileAugment() {
+// setUp();
+//
+// // As an application, creates the object.
+// YrtIetfNetworkOpParam opParam = createObjectForInterFileAugment();
+// data = new DefaultModelObjectData.Builder();
+// data.addModelObject(opParam);
+//
+// // Builds YANG tree in YTB.
+// rscData = treeBuilder.getResourceData(data.build());
+//
+// nameSpace = "yms:test:ytb:simple:augment";
+// id = rscData.resourceId();
+// keys = id.nodeKeys();
+// assertThat(1, is(keys.size()));
+//
+// sid = keys.get(0).schemaId();
+// assertThat("/", is(sid.name()));
+// assertThat(null, is(sid.namespace()));
+//
+// dataNodes = rscData.dataNodes();
+// assertThat(1, is(dataNodes.size()));
+//
+// node = dataNodes.get(0);
+// validateDataNode(node, "networks", nameSpace,
+// SINGLE_INSTANCE_NODE,
+// true, null);
+// }
+//
+// /**
+// * Creates an application object for inter file augment.
+// *
+// * @return application object
+// */
+// private YrtIetfNetworkOpParam createObjectForInterFileAugment() {
+//
+// // Creates leaf value for network-ref.
+// Uri nwkRef = new Uri(AUG_NW_REF_1);
+// NetworkId nwIdUri = new NetworkId(nwkRef);
+// Uri nwkRef2 = new Uri("network-ref-aug2");
+// NetworkId nwIdUri2 = new NetworkId(nwkRef2);
+//
+// // Creates leaf value for node-ref
+// Uri nodeRef = new Uri(AUG_NODE_REF_1);
+// NodeId nodeId = new NodeId(nodeRef);
+//
+// Uri nodeRef2 = new Uri("node-ref-aug2");
+// NodeId nodeId2 = new NodeId(nodeRef2);
+//
+// // Creates support termination list with the above two contents.
+// SupportingTerminationPoint point1 =
+// new DefaultSupportingTerminationPoint();
+// point1.networkRef(nwIdUri);
+// point1.nodeRef(nodeId);
+// point1.tpRef(AUG_TP_REF_1);
+//
+// SupportingTerminationPoint point2 =
+// new DefaultSupportingTerminationPoint();
+// point2.networkRef(nwIdUri2);
+// point2.nodeRef(nodeId2);
+// point2.tpRef("tp-ref-aug-2");
+//
+// List<SupportingTerminationPoint> pointList = new ArrayList<>();
+// pointList.add(point1);
+// pointList.add(point2);
+//
+// // Adds the list created to the termination point content1.
+// TerminationPoint tPoint1 = new DefaultTerminationPoint();
+// tPoint1.supportingTerminationPoint(pointList);
+// tPoint1.tpId(AUG_TP_ID_1);
+//
+// // Creates leaf value for network-ref.
+// Uri nwkRef3 = new Uri(AUG_NW_REF_B1);
+// NetworkId nwIdUri3 = new NetworkId(nwkRef3);
+// Uri nwkRef4 = new Uri("network-ref-augb2");
+// NetworkId nwIdUri4 = new NetworkId(nwkRef4);
+//
+// // Creates leaf value for node-ref
+// Uri nodeRef3 = new Uri(AUG_NODE_REF_B1);
+// NodeId nodeId3 = new NodeId(nodeRef3);
+//
+// Uri nodeRef4 = new Uri("node-ref-augb2");
+// NodeId nodeId4 = new NodeId(nodeRef4);
+//
+// // Creates support termination list with the above two contents.
+// SupportingTerminationPoint point3 =
+// new DefaultSupportingTerminationPoint();
+// point3.networkRef(nwIdUri3);
+// point3.nodeRef(nodeId3);
+// point3.tpRef(AUG_TP_REF_B1);
+// SupportingTerminationPoint point4 =
+// new DefaultSupportingTerminationPoint();
+// point4.networkRef(nwIdUri4);
+// point4.nodeRef(nodeId4);
+// point4.tpRef("tp-ref-aug-b2");
+//
+// List<SupportingTerminationPoint> pointList2 = new ArrayList<>();
+// pointList2.add(point3);
+// pointList2.add(point4);
+//
+// // Adds the list created to the termination point content2.
+// TerminationPoint tPoint2 = new DefaultTerminationPoint();
+// tPoint2.supportingTerminationPoint(pointList2);
+// tPoint2.tpId(AUG_TP_ID_B1);
+//
+// List<TerminationPoint> terminationPointList = new ArrayList<>();
+// terminationPointList.add(tPoint1);
+// terminationPointList.add(tPoint2);
+//
+// // Adds all the above contents to the augment.
+// DefaultAugmentedNdNode augment = new DefaultAugmentedNdNode();
+// augment.terminationPoint(terminationPointList);
+//
+// // Creates leaf value for network-ref in augmented node(ietf-network).
+// Uri nwRef5 = new Uri(NW_REF);
+// NetworkId nwIdUri5 = new NetworkId(nwRef5);
+//
+// //Creates leaf value for node-ref in augmented node(ietf-network).
+// Uri nodeRef5 = new Uri(NODE_REF);
+// NodeId nodeId5 = new NodeId(nodeRef5);
+//
+// // Creates supporting node list content 1 with above contents.
+// SupportingNode supNode1 = new DefaultSupportingNode();
+// supNode1.nodeRef(nodeId5);
+// supNode1.networkRef(nwIdUri5);
+//
+// // Creates leaf value for network-ref in augmented node(ietf-network).
+// Uri nwRef6 = new Uri(NW_REF_2);
+// NetworkId nwIdUri6 = new NetworkId(nwRef6);
+//
+// //Creates leaf value for node-ref in augmented node(ietf-network).
+// Uri nodeRef6 = new Uri("node-ref2");
+// NodeId nodeId6 = new NodeId(nodeRef6);
+//
+// // Creates supporting node list content 2 with above contents.
+// SupportingNode supNode2 = new DefaultSupportingNode();
+// supNode1.nodeRef(nodeId6);
+// supNode1.networkRef(nwIdUri6);
+//
+// List<SupportingNode> supNodeList = new ArrayList<>();
+// supNodeList.add(supNode1);
+// supNodeList.add(supNode2);
+//
+// // Creates leaf value for node-id in augmented node(ietf-network).
+// Uri nodeId1 = new Uri(NODE_REF_3);
+// NodeId nodeIdForId = new NodeId(nodeId1);
+//
+// // Creates node list with content 1 by adding augment also.
+// DefaultNode node1 = new DefaultNode();
+// node1.addAugmentation(augment);
+// node1.supportingNode(supNodeList);
+// node1.nodeId(nodeIdForId);
+//
+// // Creates an augment node without any values set to it.
+// DefaultAugmentedNdNode augmentedNdNode2 = new DefaultAugmentedNdNode();
+//
+// // Creates leaf value for network-ref in augmented node(ietf-network).
+// Uri nwRef7 = new Uri(NW_REF_B);
+// NetworkId nwIdUri7 = new NetworkId(nwRef7);
+// //Creates leaf value for node-ref in augmented node(ietf-network).
+// Uri nodeRef7 = new Uri(NODE_REF_B);
+// NodeId nodeId7 = new NodeId(nodeRef7);
+//
+// // Creates supporting node list content 1 with above contents.
+// SupportingNode supNode3 = new DefaultSupportingNode();
+// supNode3.nodeRef(nodeId7);
+// supNode3.networkRef(nwIdUri7);
+//
+// // Creates leaf value for network-ref in augmented node(ietf-network).
+// Uri nwRef8 = new Uri(NW_REF_2B);
+// NetworkId nwIdUri8 = new NetworkId(nwRef8);
+//
+// //Creates leaf value for node-ref in augmented node(ietf-network).
+// Uri nodeRef8 = new Uri(NODE_REF_2B);
+// NodeId nodeId8 = new NodeId(nodeRef8);
+//
+// // Creates supporting node list content 1 with above contents.
+// SupportingNode supNode4 = new DefaultSupportingNode();
+// supNode3.nodeRef(nodeId8);
+// supNode3.networkRef(nwIdUri8);
+//
+// List<SupportingNode> supNodeList2 = new ArrayList<>();
+// supNodeList2.add(supNode3);
+// supNodeList2.add(supNode4);
+//
+// // Creates leaf value for node-id in augmented node(ietf-network).
+// Uri nodeIdLeaf = new Uri(NODE_REF_3B);
+// NodeId nodeIdForId2 = new NodeId(nodeIdLeaf);
+//
+// // Creates node list with content 2 by adding empty augment also.
+// DefaultNode node2 = new DefaultNode();
+// node2.addAugmentation(augmentedNdNode2);
+// node2.supportingNode(supNodeList2);
+// node2.nodeId(nodeIdForId2);
+//
+// // Adds both nodes into the list.
+// List<Node> nodeList = new LinkedList<>();
+// nodeList.add(node1);
+// nodeList.add(node2);
+//
+// // Adds the list into the network list.
+// DefaultNetwork nwkList = new DefaultNetwork();
+// nwkList.node(nodeList);
+//
+// List<Network> networkList = new ArrayList<>();
+// networkList.add(nwkList);
+//
+// // Adds the network list into networks container.
+// Networks contNetworks = new DefaultNetworks();
+// contNetworks.network(networkList);
+//
+// // Adds the container into the module.
+// YrtIetfNetworkOpParam opParam = new YrtIetfNetworkOpParam();
+// opParam.networks(contNetworks);
+// return opParam;
+// }
+}
diff --git a/runtime/src/test/java/org/onosproject/yang/runtime/impl/DefaultDataTreeBuilderTest.java b/runtime/src/test/java/org/onosproject/yang/runtime/impl/DefaultDataTreeBuilderTest.java
new file mode 100644
index 0000000..24a217e
--- /dev/null
+++ b/runtime/src/test/java/org/onosproject/yang/runtime/impl/DefaultDataTreeBuilderTest.java
@@ -0,0 +1,1023 @@
+/*
+ * Copyright 2017-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.yang.runtime.impl;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.onosproject.yang.gen.v1.yms.test.ytb.module.with.container.rev20160826.ytbmodulewithcontainer.DefaultSched;
+import org.onosproject.yang.gen.v1.yms.test.ytb.module.with.leaf.ietfschedule.rev20160826.YtbIetfSchedule;
+import org.onosproject.yang.gen.v1.yms.test.ytb.module.with.leaf.ietfschedule.rev20160826.ytbietfschedule.Enum1Enum;
+import org.onosproject.yang.gen.v1.yms.test.ytb.module.with.leaf.ietfschedule.rev20160826.ytbietfschedule.Enum2Enum;
+import org.onosproject.yang.gen.v1.yms.test.ytb.module.with.leaflist.rev20160826.YtbModuleWithLeafList;
+import org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.modulelistandkey.DefaultModKey;
+import org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.modulelistandkey.ModKey;
+import org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.modulelistandkey.ModKeyKeys;
+import org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.ytbtreebuilderforlisthavinglist.DefaultCarrier;
+import org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.ytbtreebuilderforlisthavinglist.carrier.DefaultMultiplexes;
+import org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.ytbtreebuilderforlisthavinglist.carrier.Multiplexes;
+import org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.ytbtreebuilderforlisthavinglist.carrier.multiplexes.ApplicationAreas;
+import org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.ytbtreebuilderforlisthavinglist.carrier.multiplexes.DefaultApplicationAreas;
+import org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.ytbtreebuilderforlisthavinglist.carrier.multiplexes.TypesEnum;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.DefaultModelObjectData;
+import org.onosproject.yang.model.InnerNode;
+import org.onosproject.yang.model.KeyLeaf;
+import org.onosproject.yang.model.LeafListKey;
+import org.onosproject.yang.model.LeafModelObject;
+import org.onosproject.yang.model.ListKey;
+import org.onosproject.yang.model.ModelObjectId;
+import org.onosproject.yang.model.NodeKey;
+import org.onosproject.yang.model.ResourceData;
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.model.SchemaId;
+import org.onosproject.yang.runtime.mockclass.testmodule.DefaultTestNotification;
+import org.onosproject.yang.runtime.mockclass.testmodule.testnotification.DefaultTestContainer;
+import org.onosproject.yang.runtime.mockclass.testmodule.testrpc.DefaultTestInput;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.onosproject.yang.model.DataNode.Type.MULTI_INSTANCE_LEAF_VALUE_NODE;
+import static org.onosproject.yang.model.DataNode.Type.MULTI_INSTANCE_NODE;
+import static org.onosproject.yang.model.DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE;
+import static org.onosproject.yang.model.DataNode.Type.SINGLE_INSTANCE_NODE;
+import static org.onosproject.yang.runtime.impl.TestUtils.validateDataNode;
+import static org.onosproject.yang.runtime.impl.TestUtils.validateLeafDataNode;
+
+/*
+ *
+ * ModelObjectId | List<ModelObject> | ResourceId | List<DN>
+ * Null | Null | For module | null
+ * Class | Null | Form module to node | null
+ * Class +Leaf | Null | From module to leaf | null
+ * Class | Class | From module to node | class
+ * Leaf | Null | From module to leaf | null
+ * Class+leaf | Object | INVALID case | -----
+ */
+
+/**
+ * Unit test cases for YANG tree builder with different YANG object
+ * configuration.
+ */
+public class DefaultDataTreeBuilderTest {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ private ResourceData rscData;
+ private DefaultDataTreeBuilder treeBuilder;
+ private DefaultYangModelRegistry registry;
+ private ResourceId id;
+ private List<NodeKey> keys;
+ private String nameSpace;
+ private SchemaId sid;
+ private List<DataNode> dataNodes;
+ private DataNode node;
+ private ModelObjectId mid;
+ private DefaultModelObjectData.Builder data;
+ private final TestYangSchemaNodeProvider schemaProvider = new
+ TestYangSchemaNodeProvider();
+
+ /**
+ * Do the prior setup for each UT.
+ */
+ private void setUp() {
+ schemaProvider.processSchemaRegistry();
+ registry = schemaProvider.registry();
+ treeBuilder = new DefaultDataTreeBuilder(registry);
+ }
+
+ /**
+ * Unit test to test resource data generation of a module with leaf
+ * .resource id should start form "/" and should not contain info about the
+ * leaf node . the list of data node should only have one entry and that
+ * should be for leaf.
+ */
+ @Test
+ public void processModuleAndLeaf() {
+ setUp();
+
+ // As an application, creates the object.
+
+ LeafModelObject modelObject = new LeafModelObject();
+ modelObject.leafIdentifier(YtbIetfSchedule.LeafIdentifier.TIME);
+ List<Object> objects = new ArrayList<>();
+ objects.add(9);
+ modelObject.values(objects);
+ // Builds YANG tree in YTB.
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(modelObject);
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yms:test:ytb:module:with:leaf:ietfschedule";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(1, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+
+ validateDataNode(node, "time", nameSpace, SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "9");
+ }
+
+ /**
+ * Unit test to test resource data generation of a module with leaf-list
+ * .resource id should start form "/" and should not contain info about the
+ * leaf list node . the list of data node should only have 3 entry and
+ * that should be for leaf-list and its value.
+ */
+ @Test
+ public void processModuleAndLeafList() {
+
+ setUp();
+ //As an application, creates the object.
+
+ LeafModelObject modelObject = new LeafModelObject();
+ modelObject.leafIdentifier(YtbModuleWithLeafList.LeafIdentifier.TIME);
+ List<Object> objects = new ArrayList<>();
+ objects.add(1);
+ objects.add(2);
+ objects.add(3);
+ modelObject.values(objects);
+
+ //Builds YANG tree in YTB.
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(modelObject);
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yms:test:ytb:module:with:leaflist";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(1, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(3, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "time", nameSpace, MULTI_INSTANCE_LEAF_VALUE_NODE,
+ true, "1");
+
+ node = dataNodes.get(1);
+ validateDataNode(node, "time", nameSpace, MULTI_INSTANCE_LEAF_VALUE_NODE,
+ true, "2");
+
+ node = dataNodes.get(2);
+ validateDataNode(node, "time", nameSpace, MULTI_INSTANCE_LEAF_VALUE_NODE,
+ true, "3");
+ }
+
+ /**
+ * Unit test to test resource data generation of a module with one
+ * instance of list with one leaf.resource id should start form "/" and
+ * should not contain info about the list node. list of data node will
+ * only contain node of list.
+ */
+ @Test
+ public void processModuleListAndKeyOneIn() {
+ setUp();
+
+ //As an application, creates the object.
+ DefaultModKey m1 = new DefaultModKey();
+ m1.types(1);
+
+ data = new DefaultModelObjectData.Builder();
+
+ data.addModelObject(m1);
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yms:test:ytb:tree:builder:for:list:having:list";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(1, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "modKey", nameSpace, MULTI_INSTANCE_NODE,
+ true, null);
+
+ DataNode dataNode = node;
+
+ Map<NodeKey, DataNode> childMap = ((InnerNode) dataNode).childNodes();
+ Iterator<Map.Entry<NodeKey, DataNode>> it = childMap.entrySet().iterator();
+ Map.Entry<NodeKey, DataNode> n = it.next();
+ validateDataNode(n.getValue(), "types", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE, true, "1");
+
+ Iterator<KeyLeaf> keyIt = ((ListKey) node.key()).keyLeafs().iterator();
+
+ validateLeafDataNode(keyIt.next(), "types", nameSpace, "1");
+ }
+
+ /**
+ * Unit test to test resource data generation of a module with multi
+ * instance of list with one leaf.resource id should start form "/" and
+ * should not contain info about the list node. list of data node will
+ * only contain list nodes
+ */
+ @Test
+ public void processModuleListAndKey() {
+ setUp();
+
+ //As an application, creates the object.
+ DefaultModKey m1 = new DefaultModKey();
+ m1.types(1);
+
+ DefaultModKey m2 = new DefaultModKey();
+ m2.types(2);
+
+ DefaultModKey m3 = new DefaultModKey();
+ m3.types(3);
+
+ data = new DefaultModelObjectData.Builder();
+
+ data.addModelObject(m1).addModelObject(m2).addModelObject(m3);
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yms:test:ytb:tree:builder:for:list:having:list";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(1, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(3, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "modKey", nameSpace, MULTI_INSTANCE_NODE,
+ true, null);
+
+ DataNode dataNode = node;
+
+ Map<NodeKey, DataNode> childMap = ((InnerNode) dataNode).childNodes();
+ Iterator<Map.Entry<NodeKey, DataNode>> it = childMap.entrySet().iterator();
+ Map.Entry<NodeKey, DataNode> n = it.next();
+ validateDataNode(n.getValue(), "types", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE, true, "1");
+
+ Iterator<KeyLeaf> keyIt = ((ListKey) node.key()).keyLeafs().iterator();
+
+ validateLeafDataNode(keyIt.next(), "types", nameSpace, "1");
+
+ node = dataNodes.get(1);
+ validateDataNode(node, "modKey", nameSpace, MULTI_INSTANCE_NODE,
+ true, null);
+
+ dataNode = node;
+
+ childMap = ((InnerNode) dataNode).childNodes();
+ it = childMap.entrySet().iterator();
+ n = it.next();
+ validateDataNode(n.getValue(), "types", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE, true, "2");
+
+ keyIt = ((ListKey) node.key()).keyLeafs().iterator();
+
+ validateLeafDataNode(keyIt.next(), "types", nameSpace, "2");
+
+ node = dataNodes.get(2);
+ validateDataNode(node, "modKey", nameSpace, MULTI_INSTANCE_NODE,
+ true, null);
+
+ dataNode = node;
+
+ childMap = ((InnerNode) dataNode).childNodes();
+ it = childMap.entrySet().iterator();
+ n = it.next();
+ validateDataNode(n.getValue(), "types", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE, true, "3");
+
+ keyIt = ((ListKey) node.key()).keyLeafs().iterator();
+
+ validateLeafDataNode(keyIt.next(), "types", nameSpace, "3");
+ }
+
+ /**
+ * Unit test to test resource data generation of a module with multi
+ * instance of list with one leaf.resource id should start form "/" and
+ * should contain info about the list node as its part of model object
+ * identifier. list of data node will only contain leaf nodes because we
+ * have added list node objects in model object list.
+ */
+ @Test
+ public void processModuleListAndKeyListModId() {
+
+ setUp();
+
+ data = new DefaultModelObjectData.Builder();
+
+ LeafModelObject object = new LeafModelObject();
+ object.leafIdentifier(ModKey.LeafIdentifier.TYPES);
+ List<Object> objects = new ArrayList<>();
+ objects.add(1);
+ object.values(objects);
+
+ data.addModelObject(object);
+
+ object = new LeafModelObject();
+ object.leafIdentifier(ModKey.LeafIdentifier.TYPES);
+ objects = new ArrayList<>();
+ objects.add(2);
+ object.values(objects);
+
+ data.addModelObject(object);
+
+ object = new LeafModelObject();
+ object.leafIdentifier(ModKey.LeafIdentifier.TYPES);
+ objects = new ArrayList<>();
+ objects.add(3);
+ object.values(objects);
+
+ data.addModelObject(object);
+ ModKeyKeys keyKeys = new ModKeyKeys();
+ keyKeys.types(10);
+ mid = ModelObjectId.builder()
+ .addChild(DefaultModKey.class, keyKeys).build();
+
+ data.identifer(mid);
+ rscData = treeBuilder.getResourceData(data.build());
+
+ id = rscData.resourceId();
+ nameSpace = "yms:test:ytb:tree:builder:for:list:having:list";
+
+ keys = id.nodeKeys();
+ assertThat(2, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("modKey", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ ListKey listKey = (ListKey) keys.get(1);
+
+ Iterator<KeyLeaf> it = listKey.keyLeafs().iterator();
+ assertThat(1, is(listKey.keyLeafs().size()));
+
+ KeyLeaf keyLeaf = it.next();
+ sid = keyLeaf.leafSchema();
+ assertThat("types", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+ assertThat(10, is(keyLeaf.leafValue()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(3, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "types", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE, false, "1");
+
+ node = dataNodes.get(1);
+ validateDataNode(node, "types", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE, false, "2");
+
+ node = dataNodes.get(2);
+ validateDataNode(node, "types", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE, false, "3");
+ }
+
+
+ /**
+ * Unit test to test resource data generation of a module with multi
+ * instance of list with one leaf.resource id should start form "/" and
+ * should contain info about the list node and leaf node as these are part
+ * of model object identifier. list of data node not contain anything
+ * because in case of leaf being a part of model object identifier we
+ * can't have any model object in model object list. so we will not
+ * generate any data node.
+ */
+ @Test
+ public void processModuleListAndKeyLeafModId() {
+
+ setUp();
+
+ data = new DefaultModelObjectData
+ .Builder();
+ ModKeyKeys keyKeys = new ModKeyKeys();
+ keyKeys.types(10);
+ mid = ModelObjectId.builder()
+ .addChild(DefaultModKey.class, keyKeys)
+ .addChild(ModKey.LeafIdentifier.TYPES).build();
+
+ data.identifer(mid);
+ rscData = treeBuilder.getResourceData(data.build());
+
+ id = rscData.resourceId();
+ nameSpace = "yms:test:ytb:tree:builder:for:list:having:list";
+
+ keys = id.nodeKeys();
+ assertThat(3, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("modKey", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ ListKey listKey = (ListKey) keys.get(1);
+
+ Iterator<KeyLeaf> it = listKey.keyLeafs().iterator();
+ assertThat(1, is(listKey.keyLeafs().size()));
+
+ KeyLeaf keyLeaf = it.next();
+ sid = keyLeaf.leafSchema();
+ assertThat("types", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+ assertThat(10, is(keyLeaf.leafValue()));
+
+ sid = keys.get(2).schemaId();
+ assertThat("types", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ assertThat(true, is(rscData.dataNodes().isEmpty()));
+ }
+
+ /**
+ * Unit test to test resource data generation of a module node with leaf
+ * and multi instance leaf-list of enum types. resource identifier will
+ * only contain module info "/" and will not contain leaf info. data
+ * nodes will be for leaf and leaf-list. enum is an non data node so it
+ * will not have a data node created for him. for each instance of
+ * leaf-list one leaf instance data node will be added to data node list.
+ */
+ @Test
+ public void processWithTypeEnum() {
+ setUp();
+
+ data = new DefaultModelObjectData.Builder();
+ //As an application, creates the object.
+ LeafModelObject object = new LeafModelObject();
+ object.leafIdentifier(YtbIetfSchedule.LeafIdentifier.TIME);
+ List<Object> objects = new ArrayList<>();
+ objects.add(9);
+ object.values(objects);
+ data.addModelObject(object);
+
+ object = new LeafModelObject();
+ object.leafIdentifier(YtbIetfSchedule.LeafIdentifier.ENUM1);
+ objects = new ArrayList<>();
+ objects.add(Enum1Enum.HUNDRED);
+ object.values(objects);
+ data.addModelObject(object);
+
+ object = new LeafModelObject();
+ object.leafIdentifier(YtbIetfSchedule.LeafIdentifier.ENUM2);
+ objects = new ArrayList<>();
+ objects.add(Enum2Enum.HUNDRED_100);
+ objects.add(Enum2Enum.TEN_10);
+ objects.add(Enum2Enum.THOUSAND_1000);
+ object.values(objects);
+ data.addModelObject(object);
+
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yms:test:ytb:module:with:leaf:ietfschedule";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(1, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(5, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "time", nameSpace, SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "9");
+
+ node = dataNodes.get(1);
+ validateDataNode(node, "enum1", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "hundred");
+
+ node = dataNodes.get(2);
+ validateDataNode(node, "enum2", nameSpace,
+ MULTI_INSTANCE_LEAF_VALUE_NODE,
+ true, "hundred-100");
+
+ node = dataNodes.get(3);
+ validateDataNode(node, "enum2", nameSpace, MULTI_INSTANCE_LEAF_VALUE_NODE,
+ true, "ten-10");
+
+ node = dataNodes.get(4);
+ validateDataNode(node, "enum2", nameSpace, MULTI_INSTANCE_LEAF_VALUE_NODE,
+ true, "thousand-1000");
+ }
+
+ /**
+ * Unit test case for a module with container node in it. As model object
+ * identifier is null so resource identifier should start from "/" and
+ * should not contain any other info. Data node list should contain info
+ * about container node.
+ */
+ @Test
+ public void processModuleWithContainer() {
+ setUp();
+
+ // As an application, creates the object.
+
+ //Creates container object with leaf of decimal type.
+ BigDecimal dec = BigDecimal.valueOf(98989);
+ DefaultSched sched = new DefaultSched();
+ sched.predict(dec);
+
+ // Builds YANG tree in YTB.
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(sched);
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yms:test:ytb:module:with:container";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(1, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "sched", nameSpace, SINGLE_INSTANCE_NODE,
+ true, null);
+
+ Map<NodeKey, DataNode> child = ((InnerNode) node).childNodes();
+ assertThat(1, is(child.size()));
+
+ Iterator<Map.Entry<NodeKey, DataNode>> it = ((InnerNode) node)
+ .childNodes().entrySet().iterator();
+
+ Map.Entry<NodeKey, DataNode> n = it.next();
+
+ validateDataNode(n.getValue(), "predict", nameSpace, SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "98989");
+ }
+
+ /**
+ * Unit test case for a module with container node in it. As model object
+ * identifier is having container so resource identifier should start from
+ * "/" and it will have container node in it.and should not contain any
+ * other info. Data node list should contain info about container node's
+ * leaf node.
+ */
+ @Test
+ public void processModuleWithContainerModId() {
+
+ setUp();
+ data = new DefaultModelObjectData.Builder();
+ //As an application, creates the object.
+ LeafModelObject object = new LeafModelObject();
+ object.leafIdentifier(DefaultSched.LeafIdentifier.PREDICT);
+ List<Object> objects = new ArrayList<>();
+ objects.add(BigDecimal.valueOf(98989));
+ object.values(objects);
+ data.addModelObject(object);
+
+ // Builds YANG tree in YTB.
+ mid = ModelObjectId.builder().addChild(DefaultSched.class).build();
+ data.identifer(mid);
+
+ rscData = treeBuilder.getResourceData(data.build());
+
+ nameSpace = "yms:test:ytb:module:with:container";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(2, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("sched", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+ node = dataNodes.get(0);
+
+ validateDataNode(node, "predict", nameSpace, SINGLE_INSTANCE_LEAF_VALUE_NODE,
+ true, "98989");
+ }
+
+ /**
+ * Unit test to process a module with a list and another list as child of
+ * the list. Model object is null so resource id will be from "/". and
+ * data nodes will be created from the first child node. that is container.
+ */
+ @Test
+ public void processTreeBuilderForListHavingList() {
+ setUp();
+ // Creates two binary leaf -lists for two list app areas.
+ List<byte[]> destArea1 = new ArrayList<>();
+ byte[] arr = new byte[]{1, 6, 3};
+ byte[] arr1 = new byte[]{2, 7, 4};
+ destArea1.add(arr);
+ destArea1.add(arr1);
+
+ List<byte[]> destArea2 = new ArrayList<>();
+ byte[] arr2 = new byte[]{3, 8, 4};
+ byte[] arr3 = new byte[]{5, 6, 1};
+ destArea2.add(arr2);
+ destArea2.add(arr3);
+
+ //Creates two app areas list.
+ ApplicationAreas appArea1 = new DefaultApplicationAreas();
+ appArea1.destinationAreas(destArea1);
+ ApplicationAreas appArea2 = new DefaultApplicationAreas();
+ appArea2.destinationAreas(destArea2);
+
+ List<ApplicationAreas> applicationAreasList = new ArrayList<>();
+ applicationAreasList.add(appArea1);
+ applicationAreasList.add(appArea2);
+
+ //Adds two lists under the multiplex list for content 1.
+ DefaultMultiplexes mpx1 = new DefaultMultiplexes();
+ mpx1.types(TypesEnum.TIME_DIVISION);
+ mpx1.applicationAreas(applicationAreasList);
+
+ //Creates two binary leaf -lists for two list app areas.
+ List<byte[]> destArea3 = new ArrayList<>();
+ byte[] arrB = new byte[]{0, 0, 1};
+ byte[] arr1B = new byte[]{1, 0, 0};
+ destArea3.add(arrB);
+ destArea3.add(arr1B);
+
+ List<byte[]> destArea4 = new ArrayList<>();
+ byte[] arr2B = new byte[]{7, 7, 7};
+ byte[] arr3B = new byte[]{0, 1};
+ destArea4.add(arr2B);
+ destArea4.add(arr3B);
+
+ //Creates two app areas list.
+ ApplicationAreas appArea3 = new DefaultApplicationAreas();
+ appArea3.destinationAreas(destArea3);
+ ApplicationAreas appArea4 = new DefaultApplicationAreas();
+ appArea4.destinationAreas(destArea4);
+
+ List<ApplicationAreas> applicationAreasListB = new ArrayList<>();
+ applicationAreasListB.add(appArea3);
+ applicationAreasListB.add(appArea4);
+
+ //Adds two lists under the multiplex list for content 2.
+ DefaultMultiplexes mpx2 = new DefaultMultiplexes();
+ mpx2.types(TypesEnum.FREQUENCY_DIVISION);
+ mpx2.applicationAreas(applicationAreasListB);
+
+ List<Multiplexes> multiplexList = new ArrayList<>();
+ multiplexList.add(mpx1);
+ multiplexList.add(mpx2);
+
+ //Sets it in the container carrier.
+ DefaultCarrier carrier = new DefaultCarrier();
+ carrier.multiplexes(multiplexList);
+
+ data = new DefaultModelObjectData.Builder();
+ data.addModelObject(carrier);
+ rscData = treeBuilder.getResourceData(data.build());
+ nameSpace = "yms:test:ytb:tree:builder:for:list:having:list";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(1, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+ validateDataNode(node, "carrier", nameSpace,
+ SINGLE_INSTANCE_NODE, true, null);
+ Map<NodeKey, DataNode> child = ((InnerNode) node).childNodes();
+ assertThat(2, is(child.size()));
+ Iterator<Map.Entry<NodeKey, DataNode>> it1 = child.entrySet()
+ .iterator();
+
+ Map.Entry<NodeKey, DataNode> n = it1.next();
+ validateDataNode(n.getValue(), "multiplexes", nameSpace,
+ MULTI_INSTANCE_NODE, true, null);
+
+ NodeKey key = n.getKey();
+ assertThat(true, is(key instanceof ListKey));
+
+ ListKey listKey = (ListKey) key;
+ List<KeyLeaf> keyLeaves = listKey.keyLeafs();
+ assertThat(1, is(keyLeaves.size()));
+
+ validateLeafDataNode(keyLeaves.get(0), "types", nameSpace,
+ "time-division");
+
+ node = n.getValue();
+ child = ((InnerNode) node).childNodes();
+ assertThat(2, is(child.size()));
+ Iterator<Map.Entry<NodeKey, DataNode>> it = child.entrySet().iterator();
+
+ n = it.next();
+ validateDataNode(n.getValue(), "types", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE, true, "time-division");
+
+ n = it.next();
+ validateDataNode(n.getValue(), "application-areas", nameSpace,
+ MULTI_INSTANCE_NODE, true, null);
+
+ node = n.getValue();
+ child = ((InnerNode) node).childNodes();
+ assertThat(2, is(child.size()));
+ it = child.entrySet().iterator();
+
+ n = it.next();
+ key = n.getKey();
+ assertThat(true, is(key instanceof LeafListKey));
+
+ LeafListKey leafListKey = (LeafListKey) key;
+ assertThat("AwgE", is(leafListKey.value()));
+
+ sid = key.schemaId();
+ assertThat("destination-areas", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ n = it.next();
+ key = n.getKey();
+ assertThat(true, is(key instanceof LeafListKey));
+
+ leafListKey = (LeafListKey) key;
+ assertThat("BQYB", is(leafListKey.value()));
+
+ sid = key.schemaId();
+ assertThat("destination-areas", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+ //Check for max2.
+ n = it1.next();
+ validateDataNode(n.getValue(), "multiplexes", nameSpace,
+ MULTI_INSTANCE_NODE, true, null);
+
+ key = n.getKey();
+ assertThat(true, is(key instanceof ListKey));
+
+ listKey = (ListKey) key;
+ keyLeaves = listKey.keyLeafs();
+ assertThat(1, is(keyLeaves.size()));
+
+ validateLeafDataNode(keyLeaves.get(0), "types", nameSpace,
+ "frequency-division");
+
+ node = n.getValue();
+ child = ((InnerNode) node).childNodes();
+ assertThat(2, is(child.size()));
+ it = child.entrySet().iterator();
+
+ n = it.next();
+ validateDataNode(n.getValue(), "types", nameSpace,
+ SINGLE_INSTANCE_LEAF_VALUE_NODE, true, "frequency-division");
+ n = it.next();
+ validateDataNode(n.getValue(), "application-areas", nameSpace,
+ MULTI_INSTANCE_NODE, true, null);
+
+ node = n.getValue();
+ child = ((InnerNode) node).childNodes();
+ assertThat(2, is(child.size()));
+ it = child.entrySet().iterator();
+
+ n = it.next();
+ key = n.getKey();
+ assertThat(true, is(key instanceof LeafListKey));
+
+ leafListKey = (LeafListKey) key;
+ assertThat("BwcH", is(leafListKey.value()));
+
+ sid = key.schemaId();
+ assertThat("destination-areas", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ n = it.next();
+ key = n.getKey();
+ assertThat(true, is(key instanceof LeafListKey));
+
+ leafListKey = (LeafListKey) key;
+ assertThat("AAE=", is(leafListKey.value()));
+
+ sid = key.schemaId();
+ assertThat("destination-areas", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+ }
+
+ /**
+ * Unit test to process a module with notification. for notification we
+ * must add notification class in model object id. the resource
+ * identifier will contain "/ and notification node in it. and
+ * notification does not have any child not or leaf node datanodes will
+ * be empty.
+ */
+ @Test
+ public void processNotification() {
+ MoIdToRscIdTest ut = new MoIdToRscIdTest();
+ ut.addMockModWithNotification();
+
+ data = new DefaultModelObjectData.Builder();
+ mid = ModelObjectId.builder()
+ .addChild(DefaultTestNotification.class).build();
+ data.identifer(mid);
+
+ registry = ut.reg;
+ DefaultDataTreeBuilder builder = new DefaultDataTreeBuilder(registry);
+ rscData = builder.getResourceData(data.build());
+
+ nameSpace = "testNamespace";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(2, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("test-notification", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(0, is(dataNodes.size()));
+ }
+
+ /**
+ * Unit test to process a module with notification. for notification we
+ * must add notification class in model object id. the resource
+ * identifier will contain "/ and notification node in it. and
+ * notification's child node will be in data node list.
+ */
+ @Test
+ public void processNotificationWithContainer() {
+ MoIdToRscIdTest ut = new MoIdToRscIdTest();
+ ut.addMockModWithNotification();
+
+ data = new DefaultModelObjectData.Builder();
+ mid = ModelObjectId.builder()
+ .addChild(DefaultTestNotification.class).build();
+ data.identifer(mid);
+ data.addModelObject(new DefaultTestContainer());
+
+ registry = ut.reg;
+ DefaultDataTreeBuilder builder = new DefaultDataTreeBuilder(registry);
+ rscData = builder.getResourceData(data.build());
+
+ nameSpace = "testNamespace";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(2, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("test-notification", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+
+ validateDataNode(node, "test-container", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+ }
+
+ /**
+ * Unit test for a module containing rpc. Model object contains input
+ * class so resource identifier will start from "/" and will go till
+ * input node. it will contains rpc node as well. as object is given for
+ * input node so data node will be empty.
+ */
+ @Test
+ public void processRpcWithInput() {
+ MoIdToRscIdTest ut = new MoIdToRscIdTest();
+ ut.addMockModWithInput();
+
+ data = new DefaultModelObjectData.Builder();
+ mid = ModelObjectId.builder()
+ .addChild(DefaultTestInput.class).build();
+ data.identifer(mid);
+
+ registry = ut.reg;
+ DefaultDataTreeBuilder builder = new DefaultDataTreeBuilder(registry);
+ rscData = builder.getResourceData(data.build());
+
+ nameSpace = "testNamespace";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(3, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("test-rpc", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = keys.get(2).schemaId();
+ assertThat("input", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(0, is(dataNodes.size()));
+ }
+
+ /**
+ * Unit test for a module containing rpc. Model object contains input
+ * class so resource identifier will start from "/" and will go till
+ * input node. it will contains rpc node as well. as object is given for
+ * input node so data node will be for container node.
+ */
+ @Test
+ public void processRpcWithInputModId() {
+ MoIdToRscIdTest ut = new MoIdToRscIdTest();
+ ut.addMockModWithInput();
+
+ data = new DefaultModelObjectData.Builder();
+ mid = ModelObjectId.builder()
+ .addChild(DefaultTestInput.class).build();
+ data.identifer(mid);
+ data.addModelObject(new org.onosproject.yang.runtime.mockclass
+ .testmodule.testrpc.testinput.DefaultTestContainer());
+
+ registry = ut.reg;
+ DefaultDataTreeBuilder builder = new DefaultDataTreeBuilder(registry);
+ rscData = builder.getResourceData(data.build());
+
+ nameSpace = "testNamespace";
+ id = rscData.resourceId();
+ keys = id.nodeKeys();
+ assertThat(3, is(keys.size()));
+
+ sid = keys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = keys.get(1).schemaId();
+ assertThat("test-rpc", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = keys.get(2).schemaId();
+ assertThat("input", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ dataNodes = rscData.dataNodes();
+ assertThat(1, is(dataNodes.size()));
+
+ node = dataNodes.get(0);
+
+ validateDataNode(node, "test-container", nameSpace,
+ SINGLE_INSTANCE_NODE,
+ true, null);
+ }
+}
diff --git a/runtime/src/test/java/org/onosproject/yang/runtime/impl/MoIdToRscIdTest.java b/runtime/src/test/java/org/onosproject/yang/runtime/impl/MoIdToRscIdTest.java
new file mode 100644
index 0000000..0d65cdd
--- /dev/null
+++ b/runtime/src/test/java/org/onosproject/yang/runtime/impl/MoIdToRscIdTest.java
@@ -0,0 +1,925 @@
+/*
+ * Copyright 2017-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.yang.runtime.impl;
+
+import org.junit.Test;
+import org.onosproject.yang.compiler.datamodel.YangContainer;
+import org.onosproject.yang.compiler.datamodel.YangInput;
+import org.onosproject.yang.compiler.datamodel.YangLeaf;
+import org.onosproject.yang.compiler.datamodel.YangModule;
+import org.onosproject.yang.compiler.datamodel.YangNamespace;
+import org.onosproject.yang.compiler.datamodel.YangNode;
+import org.onosproject.yang.compiler.datamodel.YangNotification;
+import org.onosproject.yang.compiler.datamodel.YangOutput;
+import org.onosproject.yang.compiler.datamodel.YangRpc;
+import org.onosproject.yang.compiler.datamodel.YangType;
+import org.onosproject.yang.compiler.datamodel.exceptions.DataModelException;
+import org.onosproject.yang.gen.v1.modelobjecttest.check.Cont53;
+import org.onosproject.yang.gen.v1.modelobjecttest.check.DefaultCont53;
+import org.onosproject.yang.gen.v1.modelobjecttest.check.DefaultList56;
+import org.onosproject.yang.gen.v1.modelobjecttest.check.List56;
+import org.onosproject.yang.gen.v1.modelobjecttest.check.List56Keys;
+import org.onosproject.yang.gen.v1.modelobjecttest.check.group1.DefaultCont58;
+import org.onosproject.yang.gen.v1.modelobjecttest.check.group1.DefaultList57;
+import org.onosproject.yang.gen.v1.modelobjecttest.check.group1.List57Keys;
+import org.onosproject.yang.gen.v1.modelobjecttest.check.list56.augmentedlist56.Cont56;
+import org.onosproject.yang.gen.v1.modelobjecttest.check.list56.augmentedlist56.DefaultCont56;
+import org.onosproject.yang.gen.v1.modelobjecttest.check.list56.cont56.augmentedcont56.DefaultCont57;
+import org.onosproject.yang.gen.v1.yms.test.ytb.module.with.leaflist.rev20160826.YtbModuleWithLeafList;
+import org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.ytbtreebuilderforlisthavinglist.DefaultCarrier;
+import org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.ytbtreebuilderforlisthavinglist.carrier.DefaultMultiplexes;
+import org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.ytbtreebuilderforlisthavinglist.carrier.MultiplexesKeys;
+import org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.ytbtreebuilderforlisthavinglist.carrier.multiplexes.ApplicationAreasKeys;
+import org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.ytbtreebuilderforlisthavinglist.carrier.multiplexes.DefaultApplicationAreas;
+import org.onosproject.yang.model.KeyLeaf;
+import org.onosproject.yang.model.LeafListKey;
+import org.onosproject.yang.model.ListKey;
+import org.onosproject.yang.model.ModelObjectId;
+import org.onosproject.yang.model.NodeKey;
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.model.SchemaId;
+import org.onosproject.yang.runtime.mockclass.testmodule.DefaultTestNotification;
+import org.onosproject.yang.runtime.mockclass.testmodule.testnotification.DefaultTestContainer;
+import org.onosproject.yang.runtime.mockclass.testmodule.testrpc.DefaultTestInput;
+import org.slf4j.Logger;
+
+import java.util.List;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.onosproject.yang.compiler.datamodel.utils.builtindatatype.YangDataTypes.INT32;
+import static org.onosproject.yang.gen.v1.yms.test.ytb.tree.builder.yangautoprefixfor.yangautoprefixlist.having.yangautoprefixlist.rev20160826.ytbtreebuilderforlisthavinglist.carrier.multiplexes.TypesEnum.SPACE_DIVISION;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Unit test case for model object identifier to resource identifier converter.
+ */
+public class MoIdToRscIdTest {
+
+ private final Logger log = getLogger(getClass());
+ private final TestYangSchemaNodeProvider provider = new
+ TestYangSchemaNodeProvider();
+ ModIdToRscIdConverter builder;
+ DefaultYangModelRegistry reg;
+ private ResourceId rscId;
+ private List<NodeKey> nodeKeys;
+ private SchemaId sid;
+ private ModelObjectId mid;
+
+ /**
+ * Sets up all prerequisite.
+ */
+ private void setUp() {
+ provider.processSchemaRegistry();
+ reg = provider.registry();
+ builder = new ModIdToRscIdConverter(reg);
+ }
+
+ /**
+ * Adds mock node in registry.
+ */
+ void addMockModWithInput() {
+ setUp();
+ YangModule mod = null;
+ try {
+ mod = (YangModule) getModuleWithInput();
+ } catch (DataModelException e) {
+ log.info("test error");
+ }
+ provider.addMockNode(mod, getQualifiedName());
+ }
+
+ /**
+ * Adds mock node in registry.
+ */
+ void addMockModWithNotification() {
+ setUp();
+ YangModule mod = null;
+ try {
+ mod = (YangModule) getModuleWithNotification();
+ } catch (DataModelException e) {
+ log.info("test error");
+ }
+ provider.addMockNode(mod, getQualifiedName());
+ }
+
+ /**
+ * Unit test case for model object identifier as null.
+ */
+ @Test
+ public void nullMoId() {
+ setUp();
+ rscId = builder.fetchResourceId(null);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(1, is(nodeKeys.size()));
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+ }
+
+ /**
+ * Unit test case for model object identifier as empty.
+ */
+ @Test
+ public void emptyMoId() {
+ setUp();
+ mid = ModelObjectId.builder().build();
+ rscId = builder.fetchResourceId(mid);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(1, is(nodeKeys.size()));
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+ }
+
+ /**
+ * Unit test case for model object identifier with leaf list.
+ */
+ @Test
+ public void moIdWithLeaf() {
+ setUp();
+ mid = ModelObjectId.builder()
+ .addChild(YtbModuleWithLeafList.LeafIdentifier.TIME, 0)
+ .build();
+ rscId = builder.fetchResourceId(mid);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(2, is(nodeKeys.size()));
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = nodeKeys.get(1).schemaId();
+ assertThat("time", is(sid.name()));
+ assertThat("yms:test:ytb:module:with:leaflist", is(sid.namespace()));
+ }
+
+ /**
+ * Unit test case for model object identifier as container class.
+ */
+ @Test
+ public void moIdWithContainer() {
+ setUp();
+ mid = ModelObjectId.builder().addChild(DefaultCont53.class).build();
+ rscId = builder.fetchResourceId(mid);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(2, is(nodeKeys.size()));
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = nodeKeys.get(1).schemaId();
+ assertThat("cont53", is(sid.name()));
+ assertThat("modelObjectTest", is(sid.namespace()));
+ }
+
+ /**
+ * Unit test case for model object identifier as container class and leaf.
+ */
+ @Test
+ public void moIdWithContainerAndLeaf() {
+ setUp();
+ mid = ModelObjectId.builder().addChild(DefaultCont53.class)
+ .addChild(Cont53.LeafIdentifier.LEAF55).build();
+ rscId = builder.fetchResourceId(mid);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(3, is(nodeKeys.size()));
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = nodeKeys.get(1).schemaId();
+ assertThat("cont53", is(sid.name()));
+ assertThat("modelObjectTest", is(sid.namespace()));
+
+ sid = nodeKeys.get(2).schemaId();
+ assertThat("leaf55", is(sid.name()));
+ assertThat("modelObjectTest", is(sid.namespace()));
+ }
+
+ /**
+ * Unit test case for model object identifier as list.
+ */
+ @Test
+ public void moIdWithList() {
+ setUp();
+ List56Keys key = new List56Keys();
+ mid = new ModelObjectId.Builder()
+ .addChild(DefaultList56.class, key).build();
+
+ rscId = builder.fetchResourceId(mid);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(2, is(nodeKeys.size()));
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = nodeKeys.get(1).schemaId();
+ assertThat("list56", is(sid.name()));
+ assertThat("modelObjectTest", is(sid.namespace()));
+ }
+
+ /**
+ * Unit test case for model object identifier as list with leaf.
+ */
+ @Test
+ public void moIdWithListAndLeaf() {
+ setUp();
+ List56Keys key = new List56Keys();
+ mid = new ModelObjectId.Builder()
+ .addChild(DefaultList56.class, key)
+ .addChild(List56.LeafIdentifier.LEAF57, 10).build();
+
+ rscId = builder.fetchResourceId(mid);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(3, is(nodeKeys.size()));
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = nodeKeys.get(1).schemaId();
+ assertThat("list56", is(sid.name()));
+ assertThat("modelObjectTest", is(sid.namespace()));
+
+ sid = nodeKeys.get(2).schemaId();
+ assertThat("leaf57", is(sid.name()));
+ assertThat("modelObjectTest", is(sid.namespace()));
+
+ LeafListKey listKey = (LeafListKey) nodeKeys.get(2);
+ assertThat(10, is(listKey.value()));
+ }
+
+ //TODO: check this how to do or discuss.
+
+ /**
+ * Unit test case for model object identifier as input.
+ */
+ @Test
+ public void moIdWithInput() {
+ addMockModWithInput();
+
+ mid = new ModelObjectId.Builder()
+ .addChild(DefaultTestInput.class).build();
+
+ rscId = builder.fetchResourceId(mid);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(3, is(nodeKeys.size()));
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = nodeKeys.get(1).schemaId();
+ assertThat("test-rpc", is(sid.name()));
+ assertThat("testNamespace", is(sid.namespace()));
+
+ sid = nodeKeys.get(2).schemaId();
+ assertThat("input", is(sid.name()));
+ assertThat("testNamespace", is(sid.namespace()));
+ }
+
+ /**
+ * Unit test case for model object identifier input with leaf.
+ */
+ @Test
+ public void moIdWithInputAndContainer() {
+ addMockModWithInput();
+
+ mid = new ModelObjectId.Builder()
+ .addChild(DefaultTestInput.class)
+ .addChild(org.onosproject.yang.runtime.mockclass.testmodule
+ .testrpc.testinput.DefaultTestContainer.class)
+ .build();
+
+ rscId = builder.fetchResourceId(mid);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(4, is(nodeKeys.size()));
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = nodeKeys.get(1).schemaId();
+ assertThat("test-rpc", is(sid.name()));
+ assertThat("testNamespace", is(sid.namespace()));
+
+ sid = nodeKeys.get(2).schemaId();
+ assertThat("input", is(sid.name()));
+ assertThat("testNamespace", is(sid.namespace()));
+
+ sid = nodeKeys.get(3).schemaId();
+ assertThat("test-container", is(sid.name()));
+ assertThat("testNamespace", is(sid.namespace()));
+ }
+
+ /**
+ * Unit test case for model object identifier as notification.
+ */
+ @Test
+ public void moIdWithNotification() {
+ addMockModWithNotification();
+
+ mid = new ModelObjectId.Builder()
+ .addChild(DefaultTestNotification.class).build();
+
+ rscId = builder.fetchResourceId(mid);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(2, is(nodeKeys.size()));
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = nodeKeys.get(1).schemaId();
+ assertThat("test-notification", is(sid.name()));
+ assertThat("testNamespace", is(sid.namespace()));
+ }
+
+ /**
+ * Unit test case for model object identifier as notification with leaf.
+ */
+ @Test
+ public void moIdWithNotificationAndContainer() {
+ addMockModWithNotification();
+
+ mid = new ModelObjectId.Builder()
+ .addChild(DefaultTestNotification.class)
+ .addChild(DefaultTestContainer.class).build();
+
+ rscId = builder.fetchResourceId(mid);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(3, is(nodeKeys.size()));
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = nodeKeys.get(1).schemaId();
+ assertThat("test-notification", is(sid.name()));
+ assertThat("testNamespace", is(sid.namespace()));
+
+ sid = nodeKeys.get(2).schemaId();
+ assertThat("test-container", is(sid.name()));
+ assertThat("testNamespace", is(sid.namespace()));
+ }
+
+ @Test
+ public void modWithMultiChildren() {
+ setUp();
+
+ MultiplexesKeys keys1 = new MultiplexesKeys();
+ keys1.types(SPACE_DIVISION);
+ ApplicationAreasKeys key2 = new ApplicationAreasKeys();
+ mid = ModelObjectId.builder().addChild(DefaultCarrier.class)
+ .addChild(DefaultMultiplexes.class, keys1)
+ .addChild(DefaultApplicationAreas.class, key2).build();
+
+ rscId = builder.fetchResourceId(mid);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(4, is(nodeKeys.size()));
+ String nameSpace = "yms:test:ytb:tree:builder:for:list:having:list";
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = nodeKeys.get(1).schemaId();
+ assertThat("carrier", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = nodeKeys.get(2).schemaId();
+ assertThat("multiplexes", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = nodeKeys.get(3).schemaId();
+ assertThat("application-areas", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+ }
+
+ @Test
+ public void modIdWithAugment() {
+
+ setUp();
+ List56Keys keys = new List56Keys();
+ mid = ModelObjectId.builder()
+ .addChild(DefaultList56.class, keys)
+ .addChild(DefaultCont56.class).build();
+
+ rscId = builder.fetchResourceId(mid);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(3, is(nodeKeys.size()));
+ String nameSpace = "modelObjectTest";
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = nodeKeys.get(1).schemaId();
+ assertThat("list56", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = nodeKeys.get(2).schemaId();
+ assertThat("cont56", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ //-------------------------------------------//
+
+ mid = ModelObjectId.builder()
+ .addChild(DefaultList56.class, keys)
+ .addChild(DefaultCont56.class)
+ .addChild(Cont56.LeafIdentifier.CL56).build();
+
+ rscId = builder.fetchResourceId(mid);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(4, is(nodeKeys.size()));
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = nodeKeys.get(1).schemaId();
+ assertThat("list56", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = nodeKeys.get(2).schemaId();
+ assertThat("cont56", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = nodeKeys.get(3).schemaId();
+ assertThat("cl56", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+ }
+
+ @Test
+ public void modIdWithGroupings() {
+ setUp();
+ List56Keys keys = new List56Keys();
+ mid = ModelObjectId.builder()
+ .addChild(DefaultList56.class, keys)
+ .addChild(DefaultCont56.class).build();
+
+ rscId = builder.fetchResourceId(mid);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(3, is(nodeKeys.size()));
+ String nameSpace = "modelObjectTest";
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = nodeKeys.get(1).schemaId();
+ assertThat("list56", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = nodeKeys.get(2).schemaId();
+ assertThat("cont56", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ //-------------------------------------------//
+
+ mid = ModelObjectId.builder()
+ .addChild(DefaultList56.class, keys)
+ .addChild(DefaultCont56.class)
+ .addChild(Cont56.LeafIdentifier.CL56).build();
+
+ rscId = builder.fetchResourceId(mid);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(4, is(nodeKeys.size()));
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = nodeKeys.get(1).schemaId();
+ assertThat("list56", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = nodeKeys.get(2).schemaId();
+ assertThat("cont56", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = nodeKeys.get(3).schemaId();
+ assertThat("cl56", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ mid = ModelObjectId.builder()
+ .addChild(DefaultList56.class, keys)
+ .addChild(DefaultCont56.class)
+ .addChild(DefaultCont57.class).build();
+
+ rscId = builder.fetchResourceId(mid);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(4, is(nodeKeys.size()));
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = nodeKeys.get(1).schemaId();
+ assertThat("list56", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = nodeKeys.get(2).schemaId();
+ assertThat("cont56", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = nodeKeys.get(3).schemaId();
+ assertThat("cont57", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ //-------------------------------------------//
+
+ }
+
+ @Test
+ public void modIdWithGroupingTwo() {
+ setUp();
+
+ String nameSpace = "modelObjectTest";
+ List56Keys keys = new List56Keys();
+ mid = ModelObjectId.builder()
+ .addChild(DefaultList56.class, keys)
+ .addChild(DefaultCont56.class)
+ .addChild(DefaultCont57.class)
+ .addChild(DefaultCont58.class).build();
+
+ rscId = builder.fetchResourceId(mid);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(5, is(nodeKeys.size()));
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = nodeKeys.get(1).schemaId();
+ assertThat("list56", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = nodeKeys.get(2).schemaId();
+ assertThat("cont56", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = nodeKeys.get(3).schemaId();
+ assertThat("cont57", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = nodeKeys.get(4).schemaId();
+ assertThat("cont58", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ //-------------------------------------------//
+
+ List57Keys keys1 = new List57Keys();
+ keys1.gl57("gl57");
+ mid = ModelObjectId.builder()
+ .addChild(DefaultList56.class, keys)
+ .addChild(DefaultCont56.class)
+ .addChild(DefaultCont57.class)
+ .addChild(DefaultList57.class, keys1).build();
+
+ rscId = builder.fetchResourceId(mid);
+ nodeKeys = rscId.nodeKeys();
+ assertThat(5, is(nodeKeys.size()));
+
+ sid = nodeKeys.get(0).schemaId();
+ assertThat("/", is(sid.name()));
+ assertThat(null, is(sid.namespace()));
+
+ sid = nodeKeys.get(1).schemaId();
+ assertThat("list56", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = nodeKeys.get(2).schemaId();
+ assertThat("cont56", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ sid = nodeKeys.get(3).schemaId();
+ assertThat("cont57", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ NodeKey key = nodeKeys.get(4);
+ assertThat(true, is(key instanceof ListKey));
+
+ sid = key.schemaId();
+ assertThat("list57", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+
+ ListKey listKey = (ListKey) key;
+ List<KeyLeaf> leaves = listKey.keyLeafs();
+
+ assertThat(1, is(leaves.size()));
+
+ KeyLeaf leaf = leaves.get(0);
+ sid = leaf.leafSchema();
+ assertThat("gl57", is(sid.name()));
+ assertThat(nameSpace, is(sid.namespace()));
+ assertThat("gl57", is(leaf.leafValue()));
+ }
+
+
+ /**
+ * Returns mock node tree with module, rpc, input and output.
+ *
+ * @return mock node tree with module, rpc, input and output
+ * @throws DataModelException when fails to do data model operations
+ */
+ private YangNode getModuleWithInput() throws DataModelException {
+ YangModule mod = getYangModule();
+ YangRpc rpc = getRpcNode();
+ mod.addChild(rpc);
+ YangInput in = getInputNode();
+ rpc.addChild(in);
+ try {
+ in.addChild(getMockContainer("org.onosproject.yang.runtime.mockclass" +
+ ".testmodule.testrpc" +
+ ".testinput"));
+ } catch (DataModelException e) {
+ log.info("test error");
+ }
+ rpc.addChild(getOutputNode());
+ return mod;
+ }
+
+ /**
+ * Returns mock node tree with module and notification.
+ *
+ * @return mock node tree with module and notification
+ * @throws DataModelException when fails to do data model operations
+ */
+ private YangNode getModuleWithNotification() throws DataModelException {
+ YangModule mod = getYangModule();
+ YangNotification not = getNotificationNode();
+ mod.addChild(not);
+ try {
+ not.addChild(getMockContainer("org.onosproject.yang.runtime" +
+ ".mockclass.testmodule" +
+ ".testnotification"));
+ } catch (DataModelException e) {
+ log.info("test error");
+ }
+ return mod;
+ }
+
+ /**
+ * Returns mock module node.
+ *
+ * @return mock module node
+ */
+ private YangModule getYangModule() {
+ YangModule mod = new YangModule() {
+ @Override
+ public List<YangNode> getNotificationNodes() {
+ return null;
+ }
+
+ @Override
+ public String getJavaPackage() {
+ return "org.onosproject.yang.runtime.mockclass";
+ }
+
+ @Override
+ public String getJavaClassNameOrBuiltInType() {
+ return getJavaAttributeName();
+ }
+
+ @Override
+ public String getJavaAttributeName() {
+ return "testModule";
+ }
+ };
+ mod.setName("test-module");
+ mod.addLeaf(getLeafNode());
+ mod.setNameSpace(getMockNamespace());
+ return mod;
+ }
+
+ /**
+ * Returns mock rpc node.
+ *
+ * @return mock rpc node
+ */
+ private YangRpc getRpcNode() {
+ YangRpc rpc = new YangRpc() {
+ @Override
+ public String getJavaPackage() {
+ return null;
+ }
+
+ @Override
+ public String getJavaClassNameOrBuiltInType() {
+ return getJavaAttributeName();
+ }
+
+ @Override
+ public String getJavaAttributeName() {
+ return "testRpc";
+ }
+ };
+ rpc.setName("test-rpc");
+ rpc.setNameSpace(getMockNamespace());
+ return rpc;
+ }
+
+ /**
+ * Returns mock input node.
+ *
+ * @return mock input node
+ */
+ private YangInput getInputNode() {
+
+ YangInput in = new YangInput() {
+ @Override
+ public String getJavaPackage() {
+ return "org.onosproject.yang.runtime.mockclass" +
+ ".testmodule.testrpc";
+ }
+
+ @Override
+ public String getJavaClassNameOrBuiltInType() {
+ return getJavaAttributeName();
+ }
+
+ @Override
+ public String getJavaAttributeName() {
+ return "testInput";
+ }
+ };
+ in.setName("input");
+ in.setNameSpace(getMockNamespace());
+ return in;
+ }
+
+ /**
+ * Returns mock output node.
+ *
+ * @return mock output node
+ */
+ private YangOutput getOutputNode() {
+
+ YangOutput out = new YangOutput() {
+ @Override
+ public String getJavaPackage() {
+ return "org.onosproject.yang.runtime" +
+ ".mockclass.testmodule.testrpc";
+ }
+
+ @Override
+ public String getJavaClassNameOrBuiltInType() {
+ return getJavaAttributeName();
+ }
+
+ @Override
+ public String getJavaAttributeName() {
+ return "testOutput";
+ }
+ };
+ out.setName("output");
+ out.addLeaf(getLeafNode());
+ out.setNameSpace(getMockNamespace());
+ return out;
+ }
+
+ /**
+ * Returns mock notification node.
+ *
+ * @return mock notification node
+ */
+ private YangNotification getNotificationNode() {
+
+ YangNotification not = new YangNotification() {
+ @Override
+ public String getJavaPackage() {
+ return "org.onosproject.yang.runtime" +
+ ".mockclass.testmodule";
+ }
+
+ @Override
+ public String getJavaClassNameOrBuiltInType() {
+ return getJavaAttributeName();
+ }
+
+ @Override
+ public String getJavaAttributeName() {
+ return "testNotification";
+ }
+ };
+ not.setName("test-notification");
+ not.setNameSpace(getMockNamespace());
+ return not;
+ }
+
+ /**
+ * Returns mock container node.
+ *
+ * @return mock container node
+ */
+ private YangContainer getMockContainer(String pkg) {
+ YangContainer con = new YangContainer() {
+ @Override
+ public String getJavaPackage() {
+ return pkg;
+ }
+
+ @Override
+ public String getJavaClassNameOrBuiltInType() {
+ return getJavaAttributeName();
+ }
+
+ @Override
+ public String getJavaAttributeName() {
+ return "testContainer";
+ }
+ };
+ con.setName("test-container");
+ con.setNameSpace(getMockNamespace());
+ return con;
+ }
+
+ /**
+ * Returns mock leaf node.
+ *
+ * @return mock leaf node
+ */
+ private YangLeaf getLeafNode() {
+ YangLeaf leaf = new YangLeaf() {
+ @Override
+ public String getJavaPackage() {
+ return null;
+ }
+
+ @Override
+ public String getJavaClassNameOrBuiltInType() {
+ return getJavaAttributeName();
+ }
+
+ @Override
+ public String getJavaAttributeName() {
+ return "testLeaf";
+ }
+ };
+ leaf.setName("test-leaf");
+ leaf.setNameSpace(getMockNamespace());
+ leaf.setDataType(getMockYangType());
+ return leaf;
+ }
+
+ /**
+ * Returns mock YANG type.
+ *
+ * @return data type
+ */
+ private YangType<?> getMockYangType() {
+ YangType<?> type = new YangType<>();
+ type.setDataType(INT32);
+ type.setDataTypeName("int32");
+ return type;
+ }
+
+ /**
+ * Returns mock namespace.
+ *
+ * @return mock namespace
+ */
+ private YangNamespace getMockNamespace() {
+ return new YangNamespace() {
+ @Override
+ public String getModuleNamespace() {
+ return "testNamespace";
+ }
+
+ @Override
+ public String getModuleName() {
+ return "test-module";
+ }
+ };
+ }
+
+ /**
+ * Returns qualified java name of node.
+ *
+ * @return name
+ */
+ private String getQualifiedName() {
+ return "org.onosproject.yang.runtime.mockclass.TestModule";
+ }
+}
diff --git a/runtime/src/test/java/org/onosproject/yang/runtime/impl/TestUtils.java b/runtime/src/test/java/org/onosproject/yang/runtime/impl/TestUtils.java
index 1dcb1c0..a7b9675 100644
--- a/runtime/src/test/java/org/onosproject/yang/runtime/impl/TestUtils.java
+++ b/runtime/src/test/java/org/onosproject/yang/runtime/impl/TestUtils.java
@@ -75,7 +75,7 @@
}
/**
- * Returns the LOGGER with log for testing the YDT walker.
+ * Returns the LOGGER with log for testing the data tree walker.
*
* @return list of logs
*/
diff --git a/runtime/src/test/java/org/onosproject/yang/runtime/impl/TestYangSchemaNodeProvider.java b/runtime/src/test/java/org/onosproject/yang/runtime/impl/TestYangSchemaNodeProvider.java
index cf89988..1d62cb7 100644
--- a/runtime/src/test/java/org/onosproject/yang/runtime/impl/TestYangSchemaNodeProvider.java
+++ b/runtime/src/test/java/org/onosproject/yang/runtime/impl/TestYangSchemaNodeProvider.java
@@ -23,7 +23,6 @@
import org.onosproject.yang.runtime.DefaultAppModuleInfo;
import org.onosproject.yang.runtime.DefaultModelRegistrationParam;
import org.onosproject.yang.runtime.ModelRegistrationParam;
-import org.onosproject.yang.runtime.YangModelRegistry;
import java.io.File;
import java.io.IOException;
@@ -52,7 +51,7 @@
FS + "YangMetaData.ser";
private static final String META_PATH = PATH + SER_FILE_PATH;
private static final String TEMP_FOLDER_PATH = PATH + TEMP;
- private YangModelRegistry reg = new DefaultYangModelRegistry();
+ private DefaultYangModelRegistry reg = new DefaultYangModelRegistry();
private List<YangNode> nodes = new ArrayList<>();
/**
@@ -131,6 +130,16 @@
* @return schema registry
*/
public DefaultYangModelRegistry registry() {
- return (DefaultYangModelRegistry) reg;
+ return reg;
+ }
+
+ /**
+ * Adds a mock node in reg.
+ *
+ * @param node schema node
+ * @param name name of node
+ */
+ public void addMockNode(YangSchemaNode node, String name) {
+ reg.processApplicationContext(node, name);
}
}
diff --git a/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/TestModule.java b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/TestModule.java
new file mode 100644
index 0000000..331894e
--- /dev/null
+++ b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/TestModule.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017-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.yang.runtime.mockclass;
+
+/**
+ * Mock module class.
+ */
+public interface TestModule {
+ /**
+ * Identify the leaf of TestModule.
+ */
+ public enum LeafIdentifier implements org.onosproject.yang.model.LeafIdentifier {
+ /**
+ * Represents test leaf.
+ */
+ TEST_LEAF(1);
+
+ private int leafIndex;
+
+ public int getLeafIndex() {
+ return leafIndex;
+ }
+
+ LeafIdentifier(int value) {
+ this.leafIndex = value;
+ }
+ }
+
+ /**
+ * Sets test leaf value.
+ *
+ * @param val value
+ */
+ void testLeaf(int val);
+
+ /**
+ * Returns test leaf value.
+ *
+ * @return test leaf value
+ */
+ int testLeaf();
+}
diff --git a/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/TestModuleOpParam.java b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/TestModuleOpParam.java
new file mode 100644
index 0000000..ae0e30f
--- /dev/null
+++ b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/TestModuleOpParam.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2017-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.yang.runtime.mockclass;
+
+import org.onosproject.yang.model.InnerModelObject;
+import org.onosproject.yang.runtime.mockclass.testmodule.testrpc.DefaultTestOutput;
+import org.onosproject.yang.runtime.mockclass.testmodule.testrpc.TestInput;
+import org.onosproject.yang.runtime.mockclass.testmodule.testrpc.TestOutput;
+
+/**
+ * Mock module class.
+ */
+public class TestModuleOpParam extends InnerModelObject implements TestModule {
+
+ private int testLeaf;
+
+ /**
+ * Sets test leaf value.
+ *
+ * @param val value
+ */
+ public void testLeaf(int val) {
+ testLeaf = val;
+ }
+
+ /**
+ * Returns test leaf value.
+ *
+ * @return test leaf value
+ */
+ public int testLeaf() {
+ return testLeaf;
+ }
+
+ /**
+ * Rpc for test module.
+ *
+ * @param in input
+ * @return output
+ */
+ public TestOutput rpc(TestInput in) {
+ DefaultTestOutput out = new DefaultTestOutput();
+ out.testLeaf(in.testLeaf());
+ return out;
+ }
+}
diff --git a/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/DefaultTestNotification.java b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/DefaultTestNotification.java
new file mode 100644
index 0000000..5c522f5
--- /dev/null
+++ b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/DefaultTestNotification.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2017-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.yang.runtime.mockclass.testmodule;
+
+import org.onosproject.yang.model.InnerModelObject;
+import org.onosproject.yang.runtime.mockclass.testmodule.testnotification.TestContainer;
+
+/**
+ * Mock notification class.
+ */
+public class DefaultTestNotification extends InnerModelObject implements
+ TestNotification {
+
+ private int testLeaf;
+ private TestContainer con;
+
+ /**
+ * Sets test leaf value.
+ *
+ * @param val value
+ */
+ public void testLeaf(int val) {
+ testLeaf = val;
+ }
+
+ /**
+ * Returns test leaf value.
+ *
+ * @return test leaf value
+ */
+ public int testLeaf() {
+ return testLeaf;
+ }
+
+
+ @Override
+ public void testContainer(TestContainer con) {
+ this.con = con;
+ }
+
+ @Override
+ public TestContainer testContainer() {
+ return con;
+ }
+}
diff --git a/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/TestNotification.java b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/TestNotification.java
new file mode 100644
index 0000000..527c2c7
--- /dev/null
+++ b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/TestNotification.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017-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.yang.runtime.mockclass.testmodule;
+
+import org.onosproject.yang.runtime.mockclass.testmodule.testnotification.TestContainer;
+
+/**
+ * Mock notification class.
+ */
+public interface TestNotification {
+ /**
+ * Identify the leaf of TestModule.
+ */
+ public enum LeafIdentifier implements org.onosproject.yang.model.LeafIdentifier {
+ /**
+ * Represents test leaf.
+ */
+ TEST_LEAF(1);
+
+ private int leafIndex;
+
+ public int getLeafIndex() {
+ return leafIndex;
+ }
+
+ LeafIdentifier(int value) {
+ this.leafIndex = value;
+ }
+ }
+
+ /**
+ * Sets test leaf value.
+ *
+ * @param val value
+ */
+ void testLeaf(int val);
+
+ /**
+ * Returns test leaf value.
+ *
+ * @return test leaf value
+ */
+ int testLeaf();
+
+ /**
+ * Sets test container.
+ *
+ * @param con test container
+ */
+ void testContainer(TestContainer con);
+
+ /**
+ * Returns test container.
+ *
+ * @return test container
+ */
+ TestContainer testContainer();
+}
diff --git a/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testnotification/DefaultTestContainer.java b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testnotification/DefaultTestContainer.java
new file mode 100644
index 0000000..6f53484
--- /dev/null
+++ b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testnotification/DefaultTestContainer.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017-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.yang.runtime.mockclass.testmodule.testnotification;
+
+import org.onosproject.yang.model.InnerModelObject;
+
+/**
+ * Mock container class.
+ */
+public class DefaultTestContainer extends InnerModelObject implements TestContainer {
+}
diff --git a/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testnotification/TestContainer.java b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testnotification/TestContainer.java
new file mode 100644
index 0000000..a688080
--- /dev/null
+++ b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testnotification/TestContainer.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2017-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.yang.runtime.mockclass.testmodule.testnotification;
+
+/**
+ * Mock container class.
+ */
+public interface TestContainer {
+}
diff --git a/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testrpc/DefaultTestInput.java b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testrpc/DefaultTestInput.java
new file mode 100644
index 0000000..50aec0f
--- /dev/null
+++ b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testrpc/DefaultTestInput.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017-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.yang.runtime.mockclass.testmodule.testrpc;
+
+import org.onosproject.yang.model.InnerModelObject;
+import org.onosproject.yang.runtime.mockclass.testmodule.testnotification.TestContainer;
+
+/**
+ * Mock input class.
+ */
+public class DefaultTestInput extends InnerModelObject implements TestInput {
+
+ private int testLeaf;
+ private TestContainer con;
+
+ /**
+ * Sets test leaf value.
+ *
+ * @param val value
+ */
+ public void testLeaf(int val) {
+ testLeaf = val;
+ }
+
+ /**
+ * Returns test leaf value.
+ *
+ * @return test leaf value
+ */
+ public int testLeaf() {
+ return testLeaf;
+ }
+
+ @Override
+ public void testContainer(TestContainer con) {
+ this.con = con;
+ }
+
+ @Override
+ public TestContainer testContainer() {
+ return con;
+ }
+}
diff --git a/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testrpc/DefaultTestOutput.java b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testrpc/DefaultTestOutput.java
new file mode 100644
index 0000000..f75e708
--- /dev/null
+++ b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testrpc/DefaultTestOutput.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017-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.yang.runtime.mockclass.testmodule.testrpc;
+
+import org.onosproject.yang.model.InnerModelObject;
+
+/**
+ * Mock output class.
+ */
+public class DefaultTestOutput extends InnerModelObject implements TestOutput {
+
+ private int testLeaf;
+
+ /**
+ * Sets test leaf value.
+ *
+ * @param val value
+ */
+ public void testLeaf(int val) {
+ testLeaf = val;
+ }
+
+ /**
+ * Returns test leaf value.
+ *
+ * @return test leaf value
+ */
+ public int testLeaf() {
+ return testLeaf;
+ }
+}
diff --git a/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testrpc/TestInput.java b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testrpc/TestInput.java
new file mode 100644
index 0000000..aed1188
--- /dev/null
+++ b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testrpc/TestInput.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017-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.yang.runtime.mockclass.testmodule.testrpc;
+
+import org.onosproject.yang.runtime.mockclass.testmodule.testnotification.TestContainer;
+
+/**
+ * Mock input class.
+ */
+public interface TestInput {
+ /**
+ * Identify the leaf of TestModule.
+ */
+ public enum LeafIdentifier implements org.onosproject.yang.model.LeafIdentifier {
+ /**
+ * Represents test leaf.
+ */
+ TEST_LEAF(1);
+
+ private int leafIndex;
+
+ public int getLeafIndex() {
+ return leafIndex;
+ }
+
+ LeafIdentifier(int value) {
+ this.leafIndex = value;
+ }
+ }
+
+ /**
+ * Sets test leaf value.
+ *
+ * @param val value
+ */
+ void testLeaf(int val);
+
+ /**
+ * Returns test leaf value.
+ *
+ * @return test leaf value
+ */
+ int testLeaf();
+
+ /**
+ * Sets test container.
+ *
+ * @param con test container
+ */
+ void testContainer(TestContainer con);
+
+ /**
+ * Returns test container.
+ *
+ * @return test container
+ */
+ TestContainer testContainer();
+}
diff --git a/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testrpc/TestOutput.java b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testrpc/TestOutput.java
new file mode 100644
index 0000000..b33c3dc
--- /dev/null
+++ b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testrpc/TestOutput.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017-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.yang.runtime.mockclass.testmodule.testrpc;
+
+/**
+ * Mock output class.
+ */
+public interface TestOutput {
+ /**
+ * Identify the leaf of TestModule.
+ */
+ public enum LeafIdentifier implements org.onosproject.yang.model.LeafIdentifier {
+ /**
+ * Represents test leaf.
+ */
+ TEST_LEAF(1);
+
+ private int leafIndex;
+
+ public int getLeafIndex() {
+ return leafIndex;
+ }
+
+ LeafIdentifier(int value) {
+ this.leafIndex = value;
+ }
+ }
+
+ /**
+ * Sets test leaf value.
+ *
+ * @param val value
+ */
+ void testLeaf(int val);
+
+ /**
+ * Returns test leaf value.
+ *
+ * @return test leaf value
+ */
+ int testLeaf();
+}
diff --git a/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testrpc/testinput/DefaultTestContainer.java b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testrpc/testinput/DefaultTestContainer.java
new file mode 100644
index 0000000..ca534fa
--- /dev/null
+++ b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testrpc/testinput/DefaultTestContainer.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017-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.yang.runtime.mockclass.testmodule.testrpc.testinput;
+
+import org.onosproject.yang.model.InnerModelObject;
+
+/**
+ * Mock container class.
+ */
+public class DefaultTestContainer extends InnerModelObject implements TestContainer {
+}
diff --git a/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testrpc/testinput/TestContainer.java b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testrpc/testinput/TestContainer.java
new file mode 100644
index 0000000..c993cca
--- /dev/null
+++ b/runtime/src/test/java/org/onosproject/yang/runtime/mockclass/testmodule/testrpc/testinput/TestContainer.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2017-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.yang.runtime.mockclass.testmodule.testrpc.testinput;
+
+/**
+ * Mock container class.
+ */
+public interface TestContainer {
+}
diff --git a/runtime/src/test/resources/modelDataToResourceData/ModelDataToResourceDataInterFile.yang b/runtime/src/test/resources/modelDataToResourceData/ModelDataToResourceDataInterFile.yang
new file mode 100644
index 0000000..b2a9911
--- /dev/null
+++ b/runtime/src/test/resources/modelDataToResourceData/ModelDataToResourceDataInterFile.yang
@@ -0,0 +1,33 @@
+module model-data-to-resource-data-inter-file {
+ yang-version 1;
+ namespace "yrt:model:converter:model:data:to:resource:data";
+ prefix "sch-inter";
+ import model-data-to-resource-data {
+ prefix sch;
+ }
+ revision "2016-08-26";
+
+ augment /sch:first-level/sch:container-choice/sch:choice-case {
+ leaf leaf-inter-aug {
+ type sch:uri;
+ }
+ }
+
+ augment /sch:first-level/sch:container-choice/sch:choice-case/sch:leaf-case {
+ leaf leaf-inter-aug {
+ type decimal64 {
+ fraction-digits 2;
+ }
+ }
+ }
+
+ augment /sch:first-level {
+ container inter-container {
+ leaf leaf-inter-aug {
+ type decimal64 {
+ fraction-digits 2;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/runtime/src/test/resources/modelDataToResourceData/ModelDataToResourceDataTest.yang b/runtime/src/test/resources/modelDataToResourceData/ModelDataToResourceDataTest.yang
new file mode 100644
index 0000000..3a19205
--- /dev/null
+++ b/runtime/src/test/resources/modelDataToResourceData/ModelDataToResourceDataTest.yang
@@ -0,0 +1,146 @@
+module model-data-to-resource-data {
+ yang-version 1;
+ namespace "yrt:model:converter:model:data:to:resource:data";
+ prefix "sch";
+ revision "2016-08-26";
+
+ leaf leaf1 {
+ type int32;
+ }
+
+ leaf-list leaf-list1 {
+ type string;
+ }
+
+ typedef uri {
+ type string;
+ }
+
+ grouping group1 {
+ container group-container {
+ leaf group-leaf {
+ type uri;
+ }
+ }
+ }
+ container first-level {
+ container only-container {
+ }
+ container container-leaf {
+ leaf leaf2 {
+ type string;
+ }
+ }
+ container container-leaf-list {
+ leaf-list leaf-list2 {
+ type enumeration {
+ enum ten { value "10";}
+ enum hundred { value "100";}
+ enum thousand { value "1000"; }
+ }
+ }
+ }
+ container container-list {
+ list list-leaf {
+ key "name";
+ leaf name {
+ type string;
+ }
+ }
+ }
+ container container-choice {
+ choice choice-case {
+ case leaf-case {
+ leaf leaf3 {
+ type uint32;
+ }
+ }
+ case container-case {
+ container case-container {
+ leaf leaf4 {
+ type uri;
+ }
+ }
+ }
+ case list-case {
+ list case-list {
+ config false;
+ leaf leaf5 {
+ type uri;
+ }
+ }
+ }
+ }
+ }
+ container container-grouping {
+ uses group1;
+ }
+ list list-in-list {
+ key "list-key";
+ leaf list-key {
+ type uri;
+ }
+ list list2 {
+ key "key2";
+ leaf key2 {
+ type int32;
+ }
+ }
+ }
+ }
+
+ augment /first-level {
+ leaf leaf-aug {
+ type int32;
+ }
+ }
+
+ augment /first-level/container-leaf {
+ leaf leaf-aug {
+ type empty;
+ }
+ }
+
+ augment /first-level/container-list/list-leaf {
+ leaf leaf-aug {
+ type union-typedef;
+ }
+ }
+
+ augment /first-level/container-choice/choice-case {
+ leaf leaf-aug {
+ type bits-typedef;
+ }
+ }
+
+ augment /first-level/container-choice/choice-case/leaf-case {
+ leaf leaf-aug {
+ type binary-typedef;
+ }
+ }
+ typedef binary-typedef {
+ type binary;
+ }
+
+ typedef bits-typedef {
+ type bits {
+ bit index {
+ position 1;
+ }
+ bit name {
+ position 10;
+ }
+ bit signature {
+ position 100;
+ }
+ }
+ }
+
+ typedef union-typedef {
+ type union {
+ type int32;
+ type string;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/runtime/src/test/resources/modelObjectId/modelObjectIdTest.yang b/runtime/src/test/resources/modelObjectId/modelObjectIdTest.yang
index 24ec4eb..0c43edd 100644
--- a/runtime/src/test/resources/modelObjectId/modelObjectIdTest.yang
+++ b/runtime/src/test/resources/modelObjectId/modelObjectIdTest.yang
@@ -32,4 +32,35 @@
type string;
}
}
+
+ augment /list56 {
+ container cont56 {
+ leaf cl56 {
+ type int32;
+ }
+ }
+ }
+
+ augment /list56/cont56 {
+ container cont57 {
+ leaf cl57 {
+ type int32;
+ }
+ uses group1;
+ }
+ }
+
+ grouping group1 {
+ container cont58 {
+ leaf cl58 {
+ type int32;
+ }
+ }
+ list list57 {
+ key "gl57";
+ leaf gl57 {
+ type string;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/runtime/src/test/resources/ytbTestYangFiles/AugmentChoice.yang b/runtime/src/test/resources/ytbTestYangFiles/AugmentChoice.yang
new file mode 100644
index 0000000..cc68691
--- /dev/null
+++ b/runtime/src/test/resources/ytbTestYangFiles/AugmentChoice.yang
@@ -0,0 +1,27 @@
+module Augment-choice {
+ yang-version 1;
+ namespace yms:test:ytb:choice:with:container:and:leaf:list";
+ prefix "sch1";
+ import YtbChoiceWithContainerAndLeafList {
+ prefix sch;
+ }
+ revision "2016-08-26";
+
+ augment /sch:content-test/ {
+ list aug-choice-modKey {
+ key "types";
+ leaf types {
+ type int32;
+ }
+ }
+ }
+
+ augment /sch:content-test/sch:valid {
+ list aug-case-modKey {
+ key "types";
+ leaf types {
+ type int32;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/runtime/src/test/resources/ytbTestYangFiles/AugmentModuleListAndKey.yang b/runtime/src/test/resources/ytbTestYangFiles/AugmentModuleListAndKey.yang
new file mode 100644
index 0000000..3056053
--- /dev/null
+++ b/runtime/src/test/resources/ytbTestYangFiles/AugmentModuleListAndKey.yang
@@ -0,0 +1,18 @@
+module ModuleListAndKeyAugment {
+ yang-version 1;
+ namespace "yms:test:ytb:tree:builder:for:list:having:list";
+ prefix "sch1";
+ import ModuleListAndKey {
+ prefix sch;
+ }
+ revision "2016-08-26";
+
+ augment /sch:modKey/ {
+ list aug-list-modKey {
+ key "types";
+ leaf types {
+ type int32;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/runtime/src/test/resources/ytbTestYangFiles/ModuleAndListWithKey.yang b/runtime/src/test/resources/ytbTestYangFiles/ModuleAndListWithKey.yang
new file mode 100644
index 0000000..8810c6d
--- /dev/null
+++ b/runtime/src/test/resources/ytbTestYangFiles/ModuleAndListWithKey.yang
@@ -0,0 +1,12 @@
+module ModuleListAndKey {
+ yang-version 1;
+ namespace "yms:test:ytb:tree:builder:for:list:having:list";
+ prefix "sch";
+ revision "2016-08-26";
+ list modKey {
+ key "types";
+ leaf types {
+ type int32;
+ }
+ }
+}
\ No newline at end of file
diff --git a/runtime/src/test/resources/ytbTestYangFiles/YtbAugmentFromAnotherFile.yang b/runtime/src/test/resources/ytbTestYangFiles/YtbAugmentFromAnotherFile.yang
new file mode 100644
index 0000000..fb7bb51
--- /dev/null
+++ b/runtime/src/test/resources/ytbTestYangFiles/YtbAugmentFromAnotherFile.yang
@@ -0,0 +1,41 @@
+module YtbAugmentFromAnotherFile {
+ yang-version 1;
+ namespace "yms:test:ytb:augment:from:another:file";
+ prefix "sch";
+ import yrt-ietf-network {
+ prefix nd;
+ }
+ revision "2016-08-26";
+
+ augment "/nd:networks/nd:network/nd:node" {
+ list termination-point {
+ key "tp-id";
+ leaf tp-id {
+ type string;
+ }
+ list supporting-termination-point {
+ key "network-ref node-ref tp-ref";
+ leaf network-ref {
+ type leafref {
+ path "../../../nd:supporting-node/nd:network-ref";
+ require-instance false;
+ }
+ }
+ leaf node-ref {
+ type leafref {
+ path "../../../nd:supporting-node/nd:node-ref";
+ require-instance false;
+ }
+ }
+ leaf tp-ref {
+ type leafref {
+ path "/nd:networks/nd:network[nd:network-id=current()/"+
+ "../network-ref]/nd:node[nd:node-id=current()/../"+
+ "node-ref]/termination-point/tp-id";
+ require-instance false;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/runtime/src/test/resources/ytbTestYangFiles/YtbChoiceWithContainerAndLeafList.yang b/runtime/src/test/resources/ytbTestYangFiles/YtbChoiceWithContainerAndLeafList.yang
new file mode 100644
index 0000000..03eced9
--- /dev/null
+++ b/runtime/src/test/resources/ytbTestYangFiles/YtbChoiceWithContainerAndLeafList.yang
@@ -0,0 +1,53 @@
+module YtbChoiceWithContainerAndLeafList {
+ yang-version 1;
+ namespace "yms:test:ytb:choice:with:container:and:leaf:list";
+ prefix "sch";
+ revision "2016-08-26";
+ leaf refer {
+ type binary;
+ }
+
+ choice content-test {
+ leaf-list list-items {
+ type leafref {
+ path "/refer";
+ }
+ }
+ container choice-container {
+ list predict {
+ config "false";
+ container reproduce {
+ leaf catch {
+ type int16;
+ }
+ }
+ }
+ }
+ case valid {
+ list validlistincase {
+ config "false";
+ leaf validity {
+ type int32;
+ }
+ }
+ }
+ case invalid {
+ leaf create-invalid {
+ type uint16;
+ }
+ }
+ }
+
+ choice current-value {
+ case ytb-present {
+ leaf-list represent {
+ type uint32;
+ }
+ }
+ case ytb-absent {
+ leaf-list final {
+ type instance-identifier;
+ }
+ }
+ }
+}
diff --git a/runtime/src/test/resources/ytbTestYangFiles/YtbDataType.yang b/runtime/src/test/resources/ytbTestYangFiles/YtbDataType.yang
new file mode 100644
index 0000000..3d2e7c8
--- /dev/null
+++ b/runtime/src/test/resources/ytbTestYangFiles/YtbDataType.yang
@@ -0,0 +1,48 @@
+module YtbDataType {
+ yang-version 1;
+ namespace "yms:test:ytb:data:type";
+ prefix "data";
+ revision "2016-08-26";
+ // Enum with all combinations.
+ typedef enum-der-1 {
+ type enum-der-2;
+ }
+ typedef enum-der-2 {
+ type enumeration {
+ enum ten { value "10";}
+ enum hundred { value "100";}
+ enum thousand { value "1000"; }
+ }
+ }
+ leaf enum {
+ type enum-der-1;
+ }
+ leaf-list enum-leaf-list {
+ type union {
+ type uint64;
+ type enumeration {
+ enum ten { value "10";}
+ enum hundred { value "100";}
+ enum thousand { value "1000"; }
+ }
+ }
+ }
+ leaf union-enum {
+ type union {
+ type enumeration {
+ enum ten { value "10";}
+ enum hundred { value "100";}
+ enum thousand { value "1000"; }
+ }
+ type enum-der-1;
+ }
+ }
+ leaf-list leaf-ref-enum {
+ type leafref {
+ path "/enum";
+ }
+ }
+
+
+
+}
diff --git a/runtime/src/test/resources/ytbTestYangFiles/YtbDerivedTypeWithBitsAndBinary.yang b/runtime/src/test/resources/ytbTestYangFiles/YtbDerivedTypeWithBitsAndBinary.yang
new file mode 100644
index 0000000..1ca30a4
--- /dev/null
+++ b/runtime/src/test/resources/ytbTestYangFiles/YtbDerivedTypeWithBitsAndBinary.yang
@@ -0,0 +1,56 @@
+module YtbDerivedTypeWithBitsAndBinary {
+ yang-version 1;
+ namespace "yms:test:ytb:derived:type:with:bits:and:binary";
+ prefix "sch";
+ revision "2016-08-26";
+
+ typedef derivedbinarya {
+ type derivedbinaryb;
+ }
+
+ typedef derivedbinaryb {
+ type binary;
+ }
+
+ typedef derivedbitsa {
+ type derivedbitsb;
+ }
+
+ typedef derivedbitsb {
+ type bits {
+ bit index {
+ position 1;
+ }
+ bit name {
+ position 10;
+ }
+ bit signature {
+ position 100;
+ }
+ }
+ }
+
+ leaf forbinary {
+ type derivedbinarya;
+ }
+
+ leaf forbits {
+ type derivedbitsa;
+ }
+
+ leaf-list forbinarylist {
+ type derivedbinarya;
+ }
+
+ leaf-list forbitslist {
+ type derivedbitsa;
+ }
+
+ leaf forunion {
+ type union {
+ type binary;
+ type int8;
+ }
+ }
+}
+
diff --git a/runtime/src/test/resources/ytbTestYangFiles/YtbEmptyType.yang b/runtime/src/test/resources/ytbTestYangFiles/YtbEmptyType.yang
new file mode 100644
index 0000000..8fcb277
--- /dev/null
+++ b/runtime/src/test/resources/ytbTestYangFiles/YtbEmptyType.yang
@@ -0,0 +1,45 @@
+module YtbEmptyType {
+ yang-version 1;
+ namespace "yms:test:ytb:empty:type";
+ prefix "data";
+ revision "2016-08-26";
+ typedef emp-type {
+ type emp-type2;
+ }
+ typedef emp-type2 {
+ type empty;
+ }
+ typedef emp-type3 {
+ type leafref {
+ path "/empty";
+ }
+ }
+ leaf empty {
+ type empty;
+ }
+ leaf-list empty-list {
+ type empty;
+ }
+ leaf empty-ref {
+ type leafref {
+ path "/empty";
+ }
+ }
+ leaf-list empty-list-ref {
+ type leafref {
+ path "/empty-list";
+ }
+ }
+ leaf empty-type {
+ type emp-type;
+ }
+ leaf-list empty-list-type {
+ type emp-type;
+ }
+ leaf empty-ref-type {
+ type emp-type3;
+ }
+ leaf-list empty-list-ref-type {
+ type emp-type3;
+ }
+}
diff --git a/runtime/src/test/resources/ytbTestYangFiles/YtbIetfSchedule.yang b/runtime/src/test/resources/ytbTestYangFiles/YtbIetfSchedule.yang
new file mode 100644
index 0000000..84c908b
--- /dev/null
+++ b/runtime/src/test/resources/ytbTestYangFiles/YtbIetfSchedule.yang
@@ -0,0 +1,29 @@
+module YtbIetfSchedule {
+ yang-version 1;
+ namespace "yms:test:ytb:module:with:leaf:ietfschedule";
+ prefix "sch";
+ revision "2016-08-26";
+ leaf time {
+ type int8;
+ }
+ leaf enum1 {
+ type enumeration {
+ enum ten { value "10";}
+ enum hundred { value "100";}
+ enum thousand { value "1000"; }
+ }
+ }
+ leaf-list enum2 {
+ type enumeration {
+ enum ten-10 { value "10";}
+ enum hundred-100 { value "100";}
+ enum thousand-1000 { value "1000"; }
+ }
+ }
+ container monitor {
+ leaf check {
+ type uint8;
+ }
+ }
+}
+
diff --git a/runtime/src/test/resources/ytbTestYangFiles/YtbModuleWithContainer.yang b/runtime/src/test/resources/ytbTestYangFiles/YtbModuleWithContainer.yang
new file mode 100644
index 0000000..d611bee
--- /dev/null
+++ b/runtime/src/test/resources/ytbTestYangFiles/YtbModuleWithContainer.yang
@@ -0,0 +1,13 @@
+module YtbModuleWithContainer {
+ yang-version 1;
+ namespace "yms:test:ytb:module:with:container";
+ prefix "sch";
+ revision "2016-08-26";
+ container sched {
+ leaf predict {
+ type decimal64 {
+ fraction-digits 2;
+ }
+ }
+ }
+}
diff --git a/runtime/src/test/resources/ytbTestYangFiles/YtbModuleWithLeafList.yang b/runtime/src/test/resources/ytbTestYangFiles/YtbModuleWithLeafList.yang
new file mode 100644
index 0000000..3d02384
--- /dev/null
+++ b/runtime/src/test/resources/ytbTestYangFiles/YtbModuleWithLeafList.yang
@@ -0,0 +1,9 @@
+module YtbModuleWithLeafList {
+ yang-version 1;
+ namespace "yms:test:ytb:module:with:leaflist";
+ prefix "sch";
+ revision "2016-08-26";
+ leaf-list time {
+ type int64;
+ }
+}
diff --git a/runtime/src/test/resources/ytbTestYangFiles/YtbModuleWithList.yang b/runtime/src/test/resources/ytbTestYangFiles/YtbModuleWithList.yang
new file mode 100644
index 0000000..297a8f4
--- /dev/null
+++ b/runtime/src/test/resources/ytbTestYangFiles/YtbModuleWithList.yang
@@ -0,0 +1,15 @@
+module YtbModuleWithList {
+ yang-version 1;
+ namespace "yms:test:ytb:module:with:list";
+ prefix "sch";
+ revision "2016-08-26";
+ list ytblistlist {
+ config false;
+ leaf-list prediction {
+ type find;
+ }
+ }
+ typedef find {
+ type boolean;
+ }
+}
diff --git a/runtime/src/test/resources/ytbTestYangFiles/YtbMultiModulea.yang b/runtime/src/test/resources/ytbTestYangFiles/YtbMultiModulea.yang
new file mode 100644
index 0000000..523f400
--- /dev/null
+++ b/runtime/src/test/resources/ytbTestYangFiles/YtbMultiModulea.yang
@@ -0,0 +1,12 @@
+module YtbMultiModulea {
+ yang-version 1;
+ namespace "yms:test:ytb:multi:module:a";
+ prefix "sch";
+ revision "2016-08-26";
+ list ytbmultilist {
+ config false;
+ leaf-list check {
+ type uint64;
+ }
+ }
+}
diff --git a/runtime/src/test/resources/ytbTestYangFiles/YtbMultiModuleb.yang b/runtime/src/test/resources/ytbTestYangFiles/YtbMultiModuleb.yang
new file mode 100644
index 0000000..7c2c257
--- /dev/null
+++ b/runtime/src/test/resources/ytbTestYangFiles/YtbMultiModuleb.yang
@@ -0,0 +1,12 @@
+module YtbMultiModuleb {
+ yang-version 1;
+ namespace "yms:test:ytb:multi:module:b";
+ prefix "sch";
+ revision "2016-08-26";
+ list ytbmultilistb {
+ config false;
+ leaf-list checkin {
+ type string;
+ }
+ }
+}
diff --git a/runtime/src/test/resources/ytbTestYangFiles/YtbSimpleAugment.yang b/runtime/src/test/resources/ytbTestYangFiles/YtbSimpleAugment.yang
new file mode 100644
index 0000000..919d5ed
--- /dev/null
+++ b/runtime/src/test/resources/ytbTestYangFiles/YtbSimpleAugment.yang
@@ -0,0 +1,26 @@
+module YtbSimpleAugment {
+ yang-version 1;
+ namespace "yms:test:ytb:simple:augment";
+ prefix "sch";
+ revision "2016-08-26";
+ container cont1 {
+ container cont2 {
+ leaf fine {
+ type string;
+ }
+ }
+ }
+
+ augment /cont1/cont2 {
+ leaf leaf4 {
+ type int32;
+ }
+ container cont1s {
+ container cont1s {
+ leaf fine {
+ type string;
+ }
+ }
+ }
+ }
+}
diff --git a/runtime/src/test/resources/ytbTestYangFiles/YtbSimpleChoiceCase.yang b/runtime/src/test/resources/ytbTestYangFiles/YtbSimpleChoiceCase.yang
new file mode 100644
index 0000000..818d04e
--- /dev/null
+++ b/runtime/src/test/resources/ytbTestYangFiles/YtbSimpleChoiceCase.yang
@@ -0,0 +1,23 @@
+module YtbSimpleChoiceCase {
+ yang-version 1;
+ namespace "yms:test:ytb:simple:choice:case";
+ prefix "sch";
+ revision "2016-08-26";
+ container YtbFood {
+ choice YtbSnack {
+ case ytb-sports-arena {
+ leaf pretzel {
+ type string;
+ }
+ leaf beer {
+ type string;
+ }
+ }
+ case ytb-late-night {
+ leaf chocolate {
+ type string;
+ }
+ }
+ }
+ }
+}
diff --git a/runtime/src/test/resources/ytbTestYangFiles/YtbTreeBuilderForListHavingList.yang b/runtime/src/test/resources/ytbTestYangFiles/YtbTreeBuilderForListHavingList.yang
new file mode 100644
index 0000000..bd58e30
--- /dev/null
+++ b/runtime/src/test/resources/ytbTestYangFiles/YtbTreeBuilderForListHavingList.yang
@@ -0,0 +1,26 @@
+module YtbTreeBuilderForListHavingList {
+ yang-version 1;
+ namespace "yms:test:ytb:tree:builder:for:list:having:list";
+ prefix "sch";
+ revision "2016-08-26";
+ container carrier {
+ list multiplexes {
+ key "types";
+ list application-areas {
+ config false;
+ leaf-list destination-areas {
+ type binary;
+ }
+ }
+ leaf types {
+ type enumeration {
+ enum space-division;
+ enum frequency-division;
+ enum time-division {
+ value 3;
+ }
+ }
+ }
+ }
+ }
+}