[ONOS-5085][ONOS-5086][ONOS-5199][ONOS-5212] Yang application broker implemetation
Change-Id: I22f2ab0d98ae43fc8c0ab65d6dbf581fcd76bd47
diff --git a/apps/yms/app/src/main/java/org/onosproject/yms/app/yab/YangApplicationBroker.java b/apps/yms/app/src/main/java/org/onosproject/yms/app/yab/YangApplicationBroker.java
new file mode 100644
index 0000000..cb6f7d7
--- /dev/null
+++ b/apps/yms/app/src/main/java/org/onosproject/yms/app/yab/YangApplicationBroker.java
@@ -0,0 +1,872 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yms.app.yab;
+
+import org.onosproject.yangutils.datamodel.YangAugment;
+import org.onosproject.yangutils.datamodel.YangAugmentableNode;
+import org.onosproject.yangutils.datamodel.YangInput;
+import org.onosproject.yangutils.datamodel.YangModule;
+import org.onosproject.yangutils.datamodel.YangNode;
+import org.onosproject.yangutils.datamodel.YangRpc;
+import org.onosproject.yangutils.datamodel.YangSchemaNode;
+import org.onosproject.yms.app.utils.TraversalType;
+import org.onosproject.yms.app.yab.exceptions.YabException;
+import org.onosproject.yms.app.ydt.DefaultYdtAppContext;
+import org.onosproject.yms.app.ydt.YangRequestWorkBench;
+import org.onosproject.yms.app.ydt.YangResponseWorkBench;
+import org.onosproject.yms.app.ydt.YdtAppContext;
+import org.onosproject.yms.app.ydt.YdtExtendedContext;
+import org.onosproject.yms.app.ydt.YdtMultiInstanceNode;
+import org.onosproject.yms.app.ydt.YdtNode;
+import org.onosproject.yms.app.yob.DefaultYobBuilder;
+import org.onosproject.yms.app.ysr.YangSchemaRegistry;
+import org.onosproject.yms.app.ytb.DefaultYangTreeBuilder;
+import org.onosproject.yms.ydt.YdtBuilder;
+import org.onosproject.yms.ydt.YdtContext;
+import org.onosproject.yms.ydt.YdtResponse;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.yms.app.utils.TraversalType.CHILD;
+import static org.onosproject.yms.app.utils.TraversalType.PARENT;
+import static org.onosproject.yms.app.utils.TraversalType.ROOT;
+import static org.onosproject.yms.app.utils.TraversalType.SIBLING;
+import static org.onosproject.yms.app.ydt.AppNodeFactory.getAppContext;
+import static org.onosproject.yms.app.ydt.YdtAppNodeOperationType.DELETE_ONLY;
+import static org.onosproject.yms.app.ydt.YdtAppNodeOperationType.OTHER_EDIT;
+import static org.onosproject.yms.ydt.YdtContextOperationType.DELETE;
+import static org.onosproject.yms.ydt.YmsOperationExecutionStatus.EXECUTION_SUCCESS;
+
+/**
+ * Represents YANG application broker. It acts as a broker between Protocol and
+ * YANG based application.
+ */
+public class YangApplicationBroker {
+
+ private static final String GET = "get";
+ private static final String SET = "set";
+ private static final String AUGMENTED = "Augmented";
+ private static final String VOID = "void";
+ private final YangSchemaRegistry schemaRegistry;
+
+ /**
+ * Creates a new YANG application broker.
+ *
+ * @param schemaRegistry YANG schema registry
+ */
+ public YangApplicationBroker(YangSchemaRegistry schemaRegistry) {
+ this.schemaRegistry = schemaRegistry;
+ }
+
+ /**
+ * Processes query request of a NBI protocol.
+ *
+ * @param ydtWorkBench YANG request work bench
+ * @return YANG response data tree node context
+ * @throws YabException violation in execution of YAB
+ */
+ public YdtResponse processQuery(YdtBuilder ydtWorkBench)
+ throws YabException {
+ List<Object> responseObjects = new LinkedList<>();
+ YangRequestWorkBench workBench = (YangRequestWorkBench) ydtWorkBench;
+
+ for (YdtAppContext appContext = workBench.getAppRootNode().getFirstChild();
+ appContext != null; appContext = appContext.getNextSibling()) {
+ Object responseObject = processQueryOfApplication(appContext);
+ responseObjects.add(responseObject);
+ }
+
+ YdtContext rootYdtContext = workBench.getRootNode();
+ YdtBuilder responseYdt = buildResponseYdt(responseObjects,
+ rootYdtContext.getName(),
+ rootYdtContext.getNamespace());
+
+ return new YangResponseWorkBench(responseYdt.getRootNode(),
+ EXECUTION_SUCCESS,
+ ydtWorkBench.getYmsOperationType());
+ }
+
+ /**
+ * Processes edit request of a NBI protocol.
+ *
+ * @param ydtWorkBench YANG request work bench
+ * @return YANG response data tree node context
+ * @throws YabException violation in execution of YAB
+ * @throws CloneNotSupportedException clone is not supported
+ */
+ public YdtResponse processEdit(YdtBuilder ydtWorkBench)
+ throws CloneNotSupportedException, YabException {
+ YangRequestWorkBench workBench = (YangRequestWorkBench) ydtWorkBench;
+
+ for (YdtAppContext appContext = workBench.getAppRootNode().getFirstChild();
+ appContext != null; appContext = appContext.getNextSibling()) {
+ processEditOfApplication(appContext);
+ }
+
+ /*
+ * Since for set operation return type is void, there will not be
+ * response ydt tree so returning null.
+ */
+ return new YangResponseWorkBench(null, EXECUTION_SUCCESS,
+ workBench.getYmsOperationType());
+ }
+
+ /**
+ * Processes operation request of a NBI protocol.
+ *
+ * @param ydtWorkBench YANG request work bench
+ * @return YANG response data tree node context
+ * @throws YabException violation in execution of YAB
+ */
+ public YdtResponse processOperation(YdtBuilder ydtWorkBench)
+ throws YabException {
+ YangRequestWorkBench workBench = (YangRequestWorkBench) ydtWorkBench;
+ YdtAppContext appContext = workBench.getAppRootNode().getFirstChild();
+ YdtContext ydtNode = appContext.getModuleContext();
+ while (ydtNode != null) {
+ YdtContext childYdtNode = ydtNode.getFirstChild();
+ YangSchemaNode yangNode = ((YdtNode) childYdtNode).getYangSchemaNode();
+ if (yangNode instanceof YangRpc) {
+ return processRpcOperationOfApplication(childYdtNode,
+ appContext, yangNode,
+ workBench);
+ }
+ ydtNode = ydtNode.getNextSibling();
+ }
+ return new YangResponseWorkBench(null, EXECUTION_SUCCESS,
+ ydtWorkBench.getYmsOperationType());
+ }
+
+ /**
+ * Processes rpc request of an application.
+ *
+ * @param appContext application context
+ * @return response object from application
+ */
+ private YdtResponse processRpcOperationOfApplication(YdtContext rpcYdt,
+ YdtAppContext appContext,
+ YangSchemaNode yangRpc,
+ YangRequestWorkBench workBench)
+ throws YabException {
+ Object inputObject = null;
+ YdtContext inputYdtNode = getInputYdtNode(rpcYdt);
+ if (inputYdtNode != null) {
+ inputObject = getYangObject(inputYdtNode);
+ }
+
+ Object appObject = getApplicationObjectForRpc(appContext);
+
+ String methodName = yangRpc.getJavaClassNameOrBuiltInType();
+ Object outputObject = invokeRpcApplicationsMethod(appObject,
+ inputObject,
+ methodName);
+
+ String returnType = getReturnTypeOfRpcResponse(appObject,
+ inputObject, yangRpc);
+
+ if (!returnType.equals(VOID)) {
+ YdtBuilder responseYdt = buildRpcResponseYdt(outputObject,
+ workBench);
+ return new YangResponseWorkBench(responseYdt.getRootNode(),
+ EXECUTION_SUCCESS,
+ workBench.getYmsOperationType());
+ }
+
+ return new YangResponseWorkBench(null, EXECUTION_SUCCESS,
+ workBench.getYmsOperationType());
+ }
+
+ /**
+ * Processes query request of an application.
+ *
+ * @param appContext application context
+ * @return response object from application
+ */
+ private Object processQueryOfApplication(YdtAppContext appContext)
+ throws YabException {
+ YdtContext ydtNode = appContext.getModuleContext();
+
+ // Update application context tree if any node is augmented
+ YangNode yangNode = (YangNode) appContext.getYangSchemaNode();
+ if (yangNode.isDescendantNodeAugmented()) {
+ processAugmentForChildNode(appContext, yangNode);
+ }
+
+ String appName = getCapitalCase(((YdtNode) appContext.getModuleContext())
+ .getYangSchemaNode()
+ .getJavaClassNameOrBuiltInType());
+
+ // get YangObject of YdtContext from YOB
+ Object outputObject = getYangObject(ydtNode);
+
+ TraversalType curTraversal = ROOT;
+ do {
+ if (curTraversal != PARENT) {
+
+ // find application and get application's object using YSR
+ Object appManagerObject = getApplicationObject(appContext);
+
+ // find which method to invoke
+ String methodName = getApplicationMethodName(appContext,
+ appName, GET);
+
+ // invoke application's getter method
+ outputObject = invokeApplicationsMethod(appManagerObject,
+ outputObject,
+ methodName);
+ }
+
+ /*
+ * AppContext may contain other nodes if it is augmented, so
+ * traverse the appContext tree
+ */
+ if (curTraversal != PARENT && appContext.getFirstChild() != null) {
+ curTraversal = CHILD;
+ appContext = appContext.getFirstChild();
+ } else if (appContext.getNextSibling() != null) {
+ curTraversal = SIBLING;
+ appContext = appContext.getNextSibling();
+ } else {
+ curTraversal = PARENT;
+ if (appContext.getParent().getParent() != null) {
+ appContext = appContext.getParent();
+ }
+ }
+ // no need to do any operation for logical root node
+ } while (appContext.getParent().getParent() != null);
+ return outputObject;
+ }
+
+ /**
+ * Processes edit request of an application.
+ *
+ * @param appContext application context
+ * @throws YabException violation in execution of YAB
+ * @throws CloneNotSupportedException clone is not supported
+ */
+ private void processEditOfApplication(YdtAppContext appContext)
+ throws CloneNotSupportedException, YabException {
+
+ // process delete request if operation type is delete and both
+ if (appContext.getOperationType() != OTHER_EDIT) {
+ processDeleteRequestOfApplication(appContext);
+ }
+
+ // process edit request if operation type is other edit and both
+ if (appContext.getOperationType() != DELETE_ONLY) {
+ YdtContext ydtNode = appContext.getModuleContext();
+
+ String appName = getCapitalCase(((YdtNode) appContext.getModuleContext())
+ .getYangSchemaNode()
+ .getJavaClassNameOrBuiltInType());
+
+ // get YO from YOB
+ Object outputObject = getYangObject(ydtNode);
+
+ TraversalType curTraversal = ROOT;
+ do {
+ if (curTraversal != PARENT) {
+
+ // find application and get application's object using YSR
+ Object appManagerObject = getApplicationObject(appContext);
+
+ // find which method to invoke
+ String methodName = getApplicationMethodName(appContext,
+ appName, SET);
+
+ // invoke application's setter method
+ invokeApplicationsMethod(appManagerObject, outputObject,
+ methodName);
+ }
+
+ /*
+ * AppContext may contain other nodes if it is augmented,
+ * so traverse the appContext tree
+ */
+ if (curTraversal != PARENT && appContext.getFirstChild() != null) {
+ curTraversal = CHILD;
+ appContext = appContext.getFirstChild();
+ } else if (appContext.getNextSibling() != null) {
+ curTraversal = SIBLING;
+ appContext = appContext.getNextSibling();
+ } else {
+ curTraversal = PARENT;
+ if (appContext.getParent().getParent() != null) {
+ appContext = appContext.getParent();
+ }
+ }
+ // no need to do any operation for logical root node
+ } while (appContext.getParent().getParent() != null);
+ }
+ }
+
+ /**
+ * Processes delete request of an application.
+ *
+ * @param appContext application context
+ * @throws YabException violation in execution of YAB
+ * @throws CloneNotSupportedException clone is not supported
+ */
+ private void processDeleteRequestOfApplication(YdtAppContext appContext)
+ throws CloneNotSupportedException, YabException {
+ TraversalType curTraversal = ROOT;
+ List<YdtContext> deleteNodes = appContext.getDeleteNodes();
+
+ if (deleteNodes != null && !deleteNodes.isEmpty()) {
+
+ /*
+ * Split the current Ydt tree into two trees.
+ * Delete Tree with all nodes with delete operation and other
+ * tree with other edit operation
+ */
+ YdtContext deleteTree = buildDeleteTree(deleteNodes);
+
+ /*
+ * If any of nodes in ydt delete tree is augmented then add
+ * augmented nodes to current ydt tree
+ */
+ processAugmentedNodesForDelete(deleteTree.getFirstChild(), appContext);
+
+ Object inputObject = getYangObject(deleteTree.getFirstChild());
+
+ String appName = getCapitalCase(((YdtNode) appContext.getModuleContext())
+ .getYangSchemaNode()
+ .getJavaClassNameOrBuiltInType());
+
+ do {
+ if (curTraversal == ROOT || curTraversal == SIBLING) {
+ while (appContext.getLastChild() != null) {
+ appContext = appContext.getLastChild();
+ }
+ }
+
+ // getAugmentApplication manager object
+ Object appManagerObject = getApplicationObject(appContext);
+
+ // find which method to invoke
+ String methodName = getApplicationMethodName(appContext,
+ appName, SET);
+
+ // invoke application's setter method
+ invokeApplicationsMethod(appManagerObject, inputObject, methodName);
+
+ if (appContext.getPreviousSibling() != null) {
+ curTraversal = SIBLING;
+ appContext = appContext.getPreviousSibling();
+ } else if (appContext.getParent() != null) {
+ curTraversal = PARENT;
+ appContext = appContext.getParent();
+ }
+ } while (appContext.getParent() != null);
+ }
+ }
+
+ /**
+ * Traverses data model tree and if any node is augmented, then
+ * adds child to current application context.
+ *
+ * @param curAppContext current application context
+ * @param schemaNode YANG data model node, either module or augment
+ */
+ protected void processAugmentForChildNode(YdtAppContext curAppContext,
+ YangNode schemaNode) {
+ YangNode yangNode = schemaNode.getChild();
+ if (yangNode == null) {
+ return;
+ }
+
+ TraversalType curTraversal = CHILD;
+ while (!yangNode.equals(schemaNode)) {
+ if (curTraversal != PARENT && yangNode instanceof YangAugmentableNode
+ && !((YangAugmentableNode) yangNode).getAugmentedInfoList()
+ .isEmpty()) {
+ updateAppTreeWithAugmentNodes(yangNode, curAppContext);
+ }
+
+ if (curTraversal != PARENT && yangNode.getChild() != null
+ && yangNode.isDescendantNodeAugmented()) {
+ curTraversal = CHILD;
+ yangNode = yangNode.getChild();
+ } else if (yangNode.getNextSibling() != null) {
+ curTraversal = SIBLING;
+ yangNode = yangNode.getNextSibling();
+ } else {
+ curTraversal = PARENT;
+ yangNode = yangNode.getParent();
+ }
+ }
+ }
+
+ /**
+ * Traverses YDT delete tree and if any YDT node is augmented then
+ * updates the YDT delete tree with augment nodes.
+ *
+ * @param deleteTree YDT delete tree
+ * @param appContext application context
+ */
+ protected void processAugmentedNodesForDelete(YdtContext deleteTree,
+ YdtAppContext appContext) {
+ TraversalType curTraversal = ROOT;
+ YdtContext ydtContext = deleteTree.getFirstChild();
+
+ if (ydtContext == null) {
+ /*
+ * Delete request is for module, so check all the nodes under
+ * module whether it is augmented.
+ */
+ YangNode yangNode = ((YangNode) ((YdtNode) deleteTree)
+ .getYangSchemaNode());
+ if (yangNode.isDescendantNodeAugmented()) {
+ processAugmentForChildNode(appContext, yangNode);
+ }
+ return;
+ }
+
+ while (!ydtContext.equals(deleteTree)) {
+ if (curTraversal != PARENT && ((YdtNode) ydtContext)
+ .getYdtContextOperationType() == DELETE) {
+ YangNode yangNode = ((YangNode) ((YdtNode) ydtContext)
+ .getYangSchemaNode());
+ if (yangNode instanceof YangAugmentableNode) {
+ updateAppTreeWithAugmentNodes(yangNode, appContext);
+ }
+ if (yangNode.isDescendantNodeAugmented()) {
+ processAugmentForChildNode(appContext, yangNode);
+ }
+ }
+
+ if (curTraversal != PARENT && ydtContext.getFirstChild() != null) {
+ curTraversal = CHILD;
+ ydtContext = ydtContext.getFirstChild();
+ } else if (ydtContext.getNextSibling() != null) {
+ curTraversal = SIBLING;
+ ydtContext = ydtContext.getNextSibling();
+ } else {
+ curTraversal = PARENT;
+ ydtContext = ydtContext.getParent();
+ }
+ }
+ }
+
+ /**
+ * Returns response YANG data tree using YTB.
+ *
+ * @param responseObjects list of application's response objects
+ * @param name application YANG name
+ * @param namespace application YANG namespace
+ * @return response YANG data tree
+ */
+ private YdtBuilder buildResponseYdt(List<Object> responseObjects,
+ String name, String namespace) {
+ DefaultYangTreeBuilder treeBuilder = new DefaultYangTreeBuilder();
+ return treeBuilder.getYdtBuilderForYo(responseObjects,
+ name, namespace, null, schemaRegistry);
+ }
+
+ private YdtBuilder buildRpcResponseYdt(Object responseObject,
+ YangRequestWorkBench requestWorkBench) {
+ DefaultYangTreeBuilder treeBuilder = new DefaultYangTreeBuilder();
+ return treeBuilder.getYdtForRpcResponse(responseObject, requestWorkBench);
+ }
+
+ /**
+ * Builds delete tree for list of delete nodes.
+ *
+ * @param deleteNodes list of delete nodes
+ * @return deleteTree YANG data tree for delete operation
+ * @throws CloneNotSupportedException clone is not supported
+ */
+ protected YdtContext buildDeleteTree(List<YdtContext> deleteNodes) throws
+ CloneNotSupportedException {
+ Iterator<YdtContext> iterator = deleteNodes.iterator();
+ YdtContext deleteTree = null;
+ while (iterator.hasNext()) {
+ YdtContext deleteNode = iterator.next();
+ if (((YdtExtendedContext) deleteNode.getParent())
+ .getYdtContextOperationType() != DELETE) {
+ cloneAncestorsOfDeleteNode(deleteNode);
+ deleteTree = unlinkDeleteNodeFromCurrentTree((YdtNode) deleteNode);
+ }
+ }
+
+ if (deleteTree != null) {
+ while (deleteTree.getParent() != null) {
+ deleteTree = deleteTree.getParent();
+ }
+ }
+ return deleteTree;
+ }
+
+ /**
+ * Clones ancestor nodes of delete node.
+ *
+ * @param deleteNode node to be deleted
+ * @throws CloneNotSupportedException clone not supported
+ */
+ private void cloneAncestorsOfDeleteNode(YdtContext deleteNode)
+ throws CloneNotSupportedException {
+ YdtNode clonedNode;
+ YdtNode previousNode = null;
+
+ // Clone the parents of delete node to form delete tree
+ YdtNode nodeToClone = (YdtNode) deleteNode.getParent();
+ while (nodeToClone != null) {
+ // If node is not cloned yet
+ if (nodeToClone.getClonedNode() == null) {
+ clonedNode = nodeToClone.clone();
+ unlinkCurrentYdtNode(clonedNode);
+ if (nodeToClone instanceof YdtMultiInstanceNode) {
+ addKeyLeavesToClonedNode(nodeToClone, clonedNode);
+ }
+ nodeToClone.setClonedNode(clonedNode);
+ } else {
+ // already node is cloned
+ clonedNode = (YdtNode) nodeToClone.getClonedNode();
+ }
+
+ if (previousNode != null) {
+ /*
+ * add previous cloned node as child of current cloned node
+ * so that tree will be formed from delete node parent to
+ * logical root node.
+ */
+ clonedNode.addChild(previousNode, false);
+ }
+ previousNode = clonedNode;
+ nodeToClone = nodeToClone.getParent();
+ }
+ }
+
+ /**
+ * Unlinks delete node from current YANG data tree of application
+ * and links it to cloned delete tree.
+ *
+ * @param deleteNode node to be unlinked
+ * @return deleteNode delete node linked to cloned delete tree
+ */
+ private YdtNode unlinkDeleteNodeFromCurrentTree(YdtNode deleteNode) {
+ YdtNode parentClonedNode = (YdtNode) deleteNode.getParent().getClonedNode();
+ unlinkNodeFromParent(deleteNode);
+ unlinkNodeFromSibling(deleteNode);
+
+ /*
+ * Set all the pointers of node to null before adding as child
+ * to parent's cloned node.
+ */
+ deleteNode.setParent(null);
+ deleteNode.setPreviousSibling(null);
+ deleteNode.setNextSibling(null);
+
+ parentClonedNode.addChild(deleteNode, false);
+ return deleteNode;
+ }
+
+ /**
+ * Adds key leaf nodes to cloned YDT node from current Ydt node.
+ *
+ * @param curNode current YDT node
+ * @param clonedNode cloned YDT node
+ */
+ private void addKeyLeavesToClonedNode(YdtNode curNode, YdtNode clonedNode)
+ throws CloneNotSupportedException {
+ YdtNode keyClonedLeaf;
+ List<YdtContext> keyList = ((YdtMultiInstanceNode) curNode)
+ .getKeyNodeList();
+ if (keyList != null && !keyList.isEmpty()) {
+ for (YdtContext keyLeaf : keyList) {
+ keyClonedLeaf = ((YdtNode) keyLeaf).clone();
+ unlinkCurrentYdtNode(keyClonedLeaf);
+ clonedNode.addChild(keyClonedLeaf, true);
+ }
+ }
+ }
+
+ /**
+ * Updates application context tree if any of the nodes in current
+ * application context tree is augmented.
+ *
+ * @param yangNode YANG schema node which is augmented
+ * @param curAppContext current application context tree
+ */
+ private void updateAppTreeWithAugmentNodes(YangNode yangNode,
+ YdtAppContext curAppContext) {
+ YdtAppContext childAppContext;
+ for (YangAugment yangAugment : ((YangAugmentableNode) yangNode)
+ .getAugmentedInfoList()) {
+ Object appManagerObject = schemaRegistry
+ .getRegisteredApplication(yangAugment.getParent());
+ if (appManagerObject != null) {
+ childAppContext = addChildToYdtAppTree(curAppContext,
+ yangAugment);
+ processAugmentForChildNode(childAppContext, yangAugment);
+ }
+ }
+ }
+
+ /**
+ * Adds child node to current application context tree.
+ *
+ * @param curAppContext current application context
+ * @param augment augment data model node
+ * @return childAppContext child node added
+ */
+ private YdtAppContext addChildToYdtAppTree(YdtAppContext curAppContext,
+ YangNode augment) {
+ DefaultYdtAppContext childAppContext = getAppContext(true);
+ childAppContext.setParent(curAppContext);
+ childAppContext.setOperationType(curAppContext.getOperationType());
+ childAppContext.setAugmentingSchemaNode(augment);
+ curAppContext.addChild(childAppContext);
+ return childAppContext;
+ }
+
+ /**
+ * Unlinks the current node from its parent.
+ *
+ * @param deleteNode node which should be unlinked from YDT tree
+ */
+ private void unlinkNodeFromParent(YdtNode deleteNode) {
+ YdtNode parentNode = deleteNode.getParent();
+ if (parentNode.getFirstChild().equals(deleteNode)
+ && parentNode.getLastChild().equals(deleteNode)) {
+ parentNode.setChild(null);
+ parentNode.setLastChild(null);
+ } else if (parentNode.getFirstChild().equals(deleteNode)) {
+ parentNode.setChild(deleteNode.getNextSibling());
+ } else if (parentNode.getLastChild().equals(deleteNode)) {
+ parentNode.setLastChild(deleteNode.getPreviousSibling());
+ }
+ }
+
+ /**
+ * Unlinks the current node from its sibling.
+ *
+ * @param deleteNode node which should be unlinked from YDT tree
+ */
+ private void unlinkNodeFromSibling(YdtNode deleteNode) {
+ YdtNode previousSibling = deleteNode.getPreviousSibling();
+ YdtNode nextSibling = deleteNode.getNextSibling();
+ if (nextSibling != null && previousSibling != null) {
+ previousSibling.setNextSibling(nextSibling);
+ nextSibling.setPreviousSibling(previousSibling);
+ } else if (nextSibling != null) {
+ nextSibling.setPreviousSibling(null);
+ } else if (previousSibling != null) {
+ previousSibling.setNextSibling(null);
+ }
+ }
+
+ /**
+ * Unlinks current Ydt node from parent, sibling and child.
+ *
+ * @param ydtNode YANG data tree node
+ */
+ private void unlinkCurrentYdtNode(YdtNode ydtNode) {
+ ydtNode.setParent(null);
+ ydtNode.setNextSibling(null);
+ ydtNode.setPreviousSibling(null);
+ ydtNode.setChild(null);
+ ydtNode.setLastChild(null);
+ }
+
+ /**
+ * Returns YANG object for YDT node.
+ *
+ * @param ydtNode YANG data node
+ * @return YANG object for YDT node
+ */
+ private Object getYangObject(YdtContext ydtNode) {
+ checkNotNull(ydtNode);
+ DefaultYobBuilder yobBuilder = new DefaultYobBuilder();
+ return yobBuilder.getYangObject((YdtExtendedContext) ydtNode,
+ schemaRegistry);
+ }
+
+ /**
+ * Returns application manager object for YDT node.
+ *
+ * @param appContext YDT application context
+ * @return application manager object
+ */
+ private Object getApplicationObjectForRpc(YdtAppContext appContext) {
+ checkNotNull(appContext);
+ while (appContext.getFirstChild() != null) {
+ appContext = appContext.getFirstChild();
+ }
+ return schemaRegistry.getRegisteredApplication(appContext.getAppData()
+ .getRootSchemaNode());
+ }
+
+ /**
+ * Returns application manager object of application.
+ *
+ * @param appContext application context
+ * @return application manager object
+ */
+ private Object getApplicationObject(YdtAppContext appContext) {
+ return schemaRegistry.getRegisteredApplication(appContext.getAppData()
+ .getRootSchemaNode());
+ }
+
+ /**
+ * Converts name to capital case.
+ *
+ * @param yangIdentifier identifier
+ * @return name to capital case
+ */
+ private String getCapitalCase(String yangIdentifier) {
+ return yangIdentifier.substring(0, 1).toUpperCase() +
+ yangIdentifier.substring(1);
+ }
+
+ /**
+ * Returns get/set method name for application's request.
+ *
+ * @param appContext application context
+ * @return get/set method name for application's query request
+ */
+ private String getApplicationMethodName(YdtAppContext appContext,
+ String appName,
+ String operation) {
+ if (appContext.getYangSchemaNode() instanceof YangModule) {
+ return operation + appName;
+ }
+
+ String augment = ((YangAugment) appContext
+ .getAugmentingSchemaNode()).getTargetNode().get(0)
+ .getResolvedNode().getJavaClassNameOrBuiltInType();
+ return new StringBuilder().append(operation).append(AUGMENTED)
+ .append(appName).append(getCapitalCase(augment)).toString();
+ }
+
+ /**
+ * Returns rpc's input schema node.
+ *
+ * @param rpcNode rpc schema node
+ * @return rpc's input YDT node
+ */
+ private YdtContext getInputYdtNode(YdtContext rpcNode) {
+ YdtContext inputNode = rpcNode.getFirstChild();
+ while (inputNode != null) {
+ YangSchemaNode yangInputNode = ((YdtNode) inputNode)
+ .getYangSchemaNode();
+ if (yangInputNode instanceof YangInput) {
+ return inputNode;
+ }
+ inputNode = rpcNode.getNextSibling();
+ }
+ return null;
+ }
+
+ /**
+ * Invokes application method for RPC request.
+ *
+ * @param appManagerObject application manager object
+ * @param inputObject input parameter object of method
+ * @param methodName method name which should be invoked
+ * @return response object from application
+ * @throws YabException violation in execution of YAB
+ */
+ private Object invokeApplicationsMethod(Object appManagerObject,
+ Object inputObject,
+ String methodName) throws YabException {
+ checkNotNull(appManagerObject);
+ Class<?> appClass = appManagerObject.getClass();
+ try {
+ Method methodObject = appClass.getDeclaredMethod(methodName,
+ inputObject.getClass());
+ if (methodObject != null) {
+ return methodObject.invoke(appManagerObject, inputObject);
+ }
+ throw new YabException("No such method in application");
+ } catch (IllegalAccessException | NoSuchMethodException |
+ InvocationTargetException e) {
+ throw new YabException(e);
+ }
+ }
+
+ /**
+ * Invokes application method for RPC request.
+ *
+ * @param appObject application manager object
+ * @param inputObject input parameter object of method
+ * @param yangNode method name which should be invoked
+ * @return response object from application
+ * @throws YabException violation in execution of YAB
+ */
+ private String getReturnTypeOfRpcResponse(Object appObject,
+ Object inputObject, YangSchemaNode
+ yangNode) throws YabException {
+ Method methodObject = null;
+ try {
+ if (inputObject == null) {
+ methodObject = appObject.getClass()
+ .getDeclaredMethod(yangNode.getJavaClassNameOrBuiltInType(),
+ null);
+ } else {
+ methodObject = appObject.getClass()
+ .getDeclaredMethod(yangNode.getJavaClassNameOrBuiltInType(),
+ inputObject.getClass().getInterfaces());
+ }
+ } catch (NoSuchMethodException e) {
+ new YabException(e);
+ }
+ return methodObject.getReturnType().getSimpleName();
+ }
+
+ /**
+ * Invokes application method for RPC request.
+ *
+ * @param appManagerObject application manager object
+ * @param inputParamObject input parameter object of method
+ * @param methodName method name which should be invoked
+ * @return response object from application
+ * @throws YabException violation in execution of YAB
+ */
+ private Object invokeRpcApplicationsMethod(Object appManagerObject,
+ Object inputParamObject,
+ String methodName) throws YabException {
+ checkNotNull(appManagerObject);
+ Class<?> appClass = appManagerObject.getClass();
+ try {
+ Method methodObject;
+ if (inputParamObject == null) {
+ methodObject = appClass.getDeclaredMethod(methodName, null);
+ if (methodObject != null) {
+ return methodObject.invoke(appManagerObject);
+ }
+ } else {
+ methodObject = appClass.getDeclaredMethod(methodName,
+ inputParamObject
+ .getClass()
+ .getInterfaces());
+ if (methodObject != null) {
+ return methodObject.invoke(appManagerObject, inputParamObject);
+ }
+ }
+ throw new YabException("No such method in application");
+ } catch (IllegalAccessException | NoSuchMethodException |
+ InvocationTargetException e) {
+ throw new YabException(e);
+ }
+ }
+}
diff --git a/apps/yms/app/src/main/java/org/onosproject/yms/app/yab/exceptions/YabException.java b/apps/yms/app/src/main/java/org/onosproject/yms/app/yab/exceptions/YabException.java
new file mode 100644
index 0000000..846276c
--- /dev/null
+++ b/apps/yms/app/src/main/java/org/onosproject/yms/app/yab/exceptions/YabException.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yms.app.yab.exceptions;
+
+/**
+ * Represents base class for exceptions in YDT operations.
+ */
+public class YabException extends RuntimeException {
+
+ private static final long serialVersionUID = 20160211L;
+
+ /**
+ * Creates a new YDT exception.
+ */
+ public YabException() {
+ }
+
+ /**
+ * Creates a new YDT exception with given message.
+ *
+ * @param message the detail of exception in string
+ */
+ public YabException(String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new YDT exception from given message and cause.
+ *
+ * @param message the detail of exception in string
+ * @param cause underlying cause of the error
+ */
+ public YabException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a new YDT exception from cause.
+ *
+ * @param cause underlying cause of the error
+ */
+ public YabException(final Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/apps/yms/app/src/main/java/org/onosproject/yms/app/yab/exceptions/package-info.java b/apps/yms/app/src/main/java/org/onosproject/yms/app/yab/exceptions/package-info.java
new file mode 100644
index 0000000..a00b592
--- /dev/null
+++ b/apps/yms/app/src/main/java/org/onosproject/yms/app/yab/exceptions/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+/**
+ * YANG application broker exception.
+ */
+package org.onosproject.yms.app.yab.exceptions;
diff --git a/apps/yms/app/src/main/java/org/onosproject/yms/app/yab/package-info.java b/apps/yms/app/src/main/java/org/onosproject/yms/app/yab/package-info.java
new file mode 100644
index 0000000..aabbc22
--- /dev/null
+++ b/apps/yms/app/src/main/java/org/onosproject/yms/app/yab/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Provides interfaces to YANG request broker. YRB is responsible for
+ * interaction with applications in YANG modeled objects.
+ */
+package org.onosproject.yms.app.yab;
\ No newline at end of file
diff --git a/apps/yms/app/src/main/java/org/onosproject/yms/app/ydt/YangRequestWorkBench.java b/apps/yms/app/src/main/java/org/onosproject/yms/app/ydt/YangRequestWorkBench.java
index 5ae1230..625f1ed 100644
--- a/apps/yms/app/src/main/java/org/onosproject/yms/app/ydt/YangRequestWorkBench.java
+++ b/apps/yms/app/src/main/java/org/onosproject/yms/app/ydt/YangRequestWorkBench.java
@@ -125,7 +125,7 @@
/*
* Flag to identify data validation need to be done by YDT or not.
*/
- private final boolean validate;
+ private boolean validate = false;
// TODO validate need to be handle later with interaction type basis in
// future when it will be supported
@@ -164,6 +164,19 @@
}
/**
+ * Creates an instance of YANG request work bench which is used to build YDT
+ * tree in YAB.
+ *
+ * @param curNode current YDT node
+ * @param operationType YMS operation type
+ */
+ public YangRequestWorkBench(YdtNode curNode,
+ YmsOperationType operationType) {
+ this.curNode = curNode;
+ ymsOperationType = operationType;
+ }
+
+ /**
* Sets the logical root context information available in YDT node.
*
* @param node logical root node
diff --git a/apps/yms/app/src/main/java/org/onosproject/yms/app/ymsm/YmsManager.java b/apps/yms/app/src/main/java/org/onosproject/yms/app/ymsm/YmsManager.java
index b9ea3a8..ba0554b 100644
--- a/apps/yms/app/src/main/java/org/onosproject/yms/app/ymsm/YmsManager.java
+++ b/apps/yms/app/src/main/java/org/onosproject/yms/app/ymsm/YmsManager.java
@@ -25,6 +25,7 @@
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.IdGenerator;
+import org.onosproject.yms.app.yab.YangApplicationBroker;
import org.onosproject.yms.app.ydt.DefaultYdtWalker;
import org.onosproject.yms.app.ydt.YangRequestWorkBench;
import org.onosproject.yms.app.ynh.YangNotificationExtendedService;
@@ -126,6 +127,24 @@
@Override
public YdtResponse executeOperation(YdtBuilder operationRequest) {
+ YangApplicationBroker requestBroker =
+ new YangApplicationBroker(schemaRegistry);
+ switch (operationRequest.getYmsOperationType()) {
+ case EDIT_CONFIG_REQUEST:
+ try {
+ return requestBroker.processEdit(operationRequest);
+ } catch (CloneNotSupportedException e) {
+ log.error("YAB: failed to process edit request.");
+ }
+ case QUERY_CONFIG_REQUEST:
+ // TODO : to be implemented
+ case QUERY_REQUEST:
+ return requestBroker.processQuery(operationRequest);
+ case RPC_REQUEST:
+ return requestBroker.processOperation(operationRequest);
+ default:
+ // TODO : throw exception
+ }
return null;
}
diff --git a/apps/yms/app/src/main/java/org/onosproject/yms/app/yob/YobHandler.java b/apps/yms/app/src/main/java/org/onosproject/yms/app/yob/YobHandler.java
index 7e12be3..e2190f0 100755
--- a/apps/yms/app/src/main/java/org/onosproject/yms/app/yob/YobHandler.java
+++ b/apps/yms/app/src/main/java/org/onosproject/yms/app/yob/YobHandler.java
@@ -21,6 +21,7 @@
import org.onosproject.yangutils.datamodel.YangSchemaNode;
import org.onosproject.yangutils.datamodel.YangType;
import org.onosproject.yms.app.ydt.YdtExtendedContext;
+import org.onosproject.yms.app.yob.exception.YobExceptions;
import org.onosproject.yms.app.ysr.YangSchemaRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -70,8 +71,9 @@
YangSchemaNode node = curYdtNode.getYangSchemaNode();
String qualName = getQualifiedDefaultClassName(node);
- ClassLoader classLoader = getClassLoader(registry, qualName,
- curYdtNode);
+ ClassLoader classLoader = getClassLoader(registry,
+ qualName,
+ curYdtNode, rootYdtNode);
if (curYdtNode != rootYdtNode) {
setterName = node.getJavaAttributeName();
@@ -248,7 +250,7 @@
String qualifiedClassName = packageName + PERIOD + className;
ClassLoader classLoader = getClassLoader(registry,
qualifiedClassName,
- ydtExtendedContext);
+ ydtExtendedContext, null);
try {
childSetClass = classLoader.loadClass(qualifiedClassName);
} catch (ClassNotFoundException e) {
@@ -292,27 +294,35 @@
* Updates class loader for all the classes.
*
* @param registry YANG schema registry
- * @param context YDT context
+ * @param curNode YDT context
* @param qualifiedClassName qualified class name
* @return current class loader
*/
private ClassLoader getClassLoader(YangSchemaRegistry registry,
String qualifiedClassName,
+ YdtExtendedContext curNode,
YdtExtendedContext context) {
- YangSchemaNode yangSchemaNode = context.getYangSchemaNode();
- if (yangSchemaNode instanceof RpcNotificationContainer) {
+ if (context != null && curNode == context) {
+ YangSchemaNode yangSchemaNode = curNode.getYangSchemaNode();
+ while (!(yangSchemaNode instanceof RpcNotificationContainer)) {
+ curNode = (YdtExtendedContext) curNode.getParent();
+ if (curNode == null) {
+ throw new YobExceptions("Invalid YANG data tree");
+ }
+ yangSchemaNode = curNode.getYangSchemaNode();
+ }
+
Class<?> regClass = registry.getRegisteredClass(yangSchemaNode,
qualifiedClassName);
return regClass.getClassLoader();
} else {
-
YdtExtendedContext parent =
- (YdtExtendedContext) context.getParent();
+ (YdtExtendedContext) curNode.getParent();
YobWorkBench parentBuilderContainer =
(YobWorkBench) parent.getAppInfo(YOB);
Object parentObj =
- parentBuilderContainer.getParentBuilder(context, registry);
+ parentBuilderContainer.getParentBuilder(curNode, registry);
return parentObj.getClass().getClassLoader();
}
}
diff --git a/apps/yms/app/src/test/java/org/onosproject/yms/app/yab/MockYmsManager.java b/apps/yms/app/src/test/java/org/onosproject/yms/app/yab/MockYmsManager.java
new file mode 100644
index 0000000..22f4fd9
--- /dev/null
+++ b/apps/yms/app/src/test/java/org/onosproject/yms/app/yab/MockYmsManager.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yms.app.yab;
+
+import org.onosproject.yms.app.ydt.YangRequestWorkBench;
+import org.onosproject.yms.app.ysr.TestYangSchemaNodeProvider;
+import org.onosproject.yms.app.ysr.YangSchemaRegistry;
+import org.onosproject.yms.ych.YangCodecHandler;
+import org.onosproject.yms.ych.YangDataTreeCodec;
+import org.onosproject.yms.ych.YangProtocolEncodingFormat;
+import org.onosproject.yms.ydt.YdtBuilder;
+import org.onosproject.yms.ydt.YdtResponse;
+import org.onosproject.yms.ydt.YdtWalker;
+import org.onosproject.yms.ydt.YmsOperationType;
+import org.onosproject.yms.ymsm.YmsService;
+import org.onosproject.yms.ynh.YangNotificationService;
+import org.onosproject.yms.ysr.YangModuleIdentifier;
+import org.onosproject.yms.ysr.YangModuleLibrary;
+
+import java.util.List;
+
+/**
+ * Represents implementation of YANG application management system manager.
+ */
+public class MockYmsManager
+ implements YmsService {
+
+ YangSchemaRegistry schemaRegistry;
+ TestYangSchemaNodeProvider testYangSchemaNodeProvider =
+ new TestYangSchemaNodeProvider();
+
+ @Override
+ public YdtBuilder getYdtBuilder(String logicalRootName,
+ String rootNamespace,
+ YmsOperationType operationType) {
+ testYangSchemaNodeProvider.processSchemaRegistry(new TestManager());
+ schemaRegistry = testYangSchemaNodeProvider.getDefaultYangSchemaRegistry();
+ return new YangRequestWorkBench(logicalRootName, rootNamespace,
+ operationType, schemaRegistry, false);
+ }
+
+ @Override
+ public YdtBuilder getYdtBuilder(String logicalRootName,
+ String rootNamespace,
+ YmsOperationType operationType,
+ Object schemaRegistryForYdt) {
+ return null;
+ }
+
+ @Override
+ public YdtWalker getYdtWalker() {
+ return null;
+ }
+
+ @Override
+ public YdtResponse executeOperation(YdtBuilder operationRequest) {
+ YangApplicationBroker requestBroker =
+ new YangApplicationBroker(schemaRegistry);
+ switch (operationRequest.getYmsOperationType()) {
+ case EDIT_CONFIG_REQUEST:
+ try {
+ return requestBroker.processEdit(operationRequest);
+ } catch (CloneNotSupportedException e) {
+ }
+ break;
+ case QUERY_CONFIG_REQUEST:
+ case QUERY_REQUEST:
+ return requestBroker.processQuery(operationRequest);
+ case RPC_REQUEST:
+ return requestBroker.processOperation(operationRequest);
+ default:
+ }
+ return null;
+ }
+
+ @Override
+ public YangNotificationService getYangNotificationService() {
+ return null;
+ }
+
+ @Override
+ public void registerService(Object appManager, Class<?> yangService,
+ List<String> supportedFeatureList) {
+ }
+
+ @Override
+ public void unRegisterService(Object appManager, Class<?> yangService) {
+
+ }
+
+ @Override
+ public YangModuleLibrary getYangModuleLibrary() {
+ return null;
+ }
+
+ @Override
+ public String getYangFile(YangModuleIdentifier moduleIdentifier) {
+ return null;
+ }
+
+ @Override
+ public void registerDefaultCodec(YangDataTreeCodec defaultCodec,
+ YangProtocolEncodingFormat dataFormat) {
+ }
+
+ @Override
+ public YangCodecHandler getYangCodecHandler() {
+ return null;
+ }
+}
diff --git a/apps/yms/app/src/test/java/org/onosproject/yms/app/yab/TestManager.java b/apps/yms/app/src/test/java/org/onosproject/yms/app/yab/TestManager.java
new file mode 100644
index 0000000..c07a18f
--- /dev/null
+++ b/apps/yms/app/src/test/java/org/onosproject/yms/app/yab/TestManager.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yms.app.yab;
+
+import org.onosproject.yang.gen.v1.ydt.test.rev20160524.Test;
+import org.onosproject.yang.gen.v1.ydt.test.rev20160524.TestOpParam;
+import org.onosproject.yang.gen.v1.ydt.test.rev20160524.TestService;
+import org.onosproject.yang.gen.v1.ydt.test.rev20160524.test.Cont1;
+import org.onosproject.yang.gen.v1.ydt.test.rev20160524.test.DefaultCont1;
+import org.onosproject.yang.gen.v1.ydt.test.rev20160524.test.rockthehouse.DefaultRockTheHouseOutput;
+import org.onosproject.yang.gen.v1.ydt.test.rev20160524.test.rockthehouse.RockTheHouseInput;
+import org.onosproject.yang.gen.v1.ydt.test.rev20160524.test.rockthehouse.RockTheHouseOutput;
+import org.onosproject.yang.gen.v1.ydt.test.rev20160524.test.rockthehouse1.RockTheHouse1Input;
+import org.onosproject.yang.gen.v1.ydt.test.rev20160524.test.rockthehouse2.DefaultRockTheHouse2Output;
+import org.onosproject.yang.gen.v1.ydt.test.rev20160524.test.rockthehouse2.RockTheHouse2Output;
+
+/**
+ * Implementation of the application management service.
+ */
+public class TestManager implements TestService {
+
+ Test response;
+
+ @Override
+ public Test getTest(TestOpParam test) {
+ Cont1 cont = new DefaultCont1.Cont1Builder().leaf4("4").build();
+ Test response = new TestOpParam.TestBuilder().cont1(cont).build();
+ return response;
+ }
+
+ @Override
+ public void setTest(TestOpParam test) {
+ response = test;
+ }
+
+ @Override
+ public Test getAugmentedTestCont4(TestOpParam test) {
+ Cont1 cont = new DefaultCont1.Cont1Builder().leaf4("4").build();
+ Test response = new TestOpParam.TestBuilder().cont1(cont).build();
+ return response;
+ }
+
+ @Override
+ public void setAugmentedTestCont4(TestOpParam augmentedTestCont4) {
+ response = augmentedTestCont4;
+ }
+
+ @Override
+ public RockTheHouseOutput rockTheHouse(RockTheHouseInput inputVar) {
+ return DefaultRockTheHouseOutput.builder().hello("hello").build();
+ }
+
+
+ @Override
+ public void rockTheHouse1(RockTheHouse1Input inputVar) {
+ // TODO : to be implemented
+ }
+
+ @Override
+ public RockTheHouse2Output rockTheHouse2() {
+ return DefaultRockTheHouse2Output
+ .builder().leaf14("14").build();
+ }
+
+ @Override
+ public void rockTheHouse3() {
+ }
+}
diff --git a/apps/yms/app/src/test/java/org/onosproject/yms/app/yab/YangApplicationBrokerTest.java b/apps/yms/app/src/test/java/org/onosproject/yms/app/yab/YangApplicationBrokerTest.java
new file mode 100644
index 0000000..0d77306
--- /dev/null
+++ b/apps/yms/app/src/test/java/org/onosproject/yms/app/yab/YangApplicationBrokerTest.java
@@ -0,0 +1,1088 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yms.app.yab;
+
+import org.junit.Test;
+import org.onosproject.yangutils.datamodel.YangAugment;
+import org.onosproject.yangutils.datamodel.YangNode;
+import org.onosproject.yms.app.ydt.YangRequestWorkBench;
+import org.onosproject.yms.app.ydt.YdtAppContext;
+import org.onosproject.yms.app.ydt.YdtAppNodeOperationType;
+import org.onosproject.yms.app.ydt.YdtNode;
+import org.onosproject.yms.ydt.YdtContext;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.onosproject.yms.ydt.YdtContextOperationType.DELETE;
+import static org.onosproject.yms.ydt.YdtContextOperationType.MERGE;
+import static org.onosproject.yms.ydt.YmsOperationType.EDIT_CONFIG_REQUEST;
+import static org.onosproject.yms.ydt.YmsOperationType.QUERY_CONFIG_REQUEST;
+import static org.onosproject.yms.ydt.YmsOperationType.RPC_REQUEST;
+
+/**
+ * Unit test case for YANG application broker.
+ */
+public class YangApplicationBrokerTest {
+
+ MockYmsManager ymsManager = new MockYmsManager();
+
+ /**
+ * Returns YANG data tree to check edit operation of container.
+ *
+ * @return YANG data tree
+ */
+ private YangRequestWorkBench buildYdtForEditOperationWithoutDelete() {
+ String rootName = "root";
+ YangRequestWorkBench defaultYdtBuilder =
+ (YangRequestWorkBench) ymsManager.getYdtBuilder(rootName, null,
+ EDIT_CONFIG_REQUEST);
+ defaultYdtBuilder.addChild("test", "ydt.test", MERGE);
+ defaultYdtBuilder.addChild("cont1", null, MERGE);
+ defaultYdtBuilder.addChild("cont2", null, MERGE);
+ defaultYdtBuilder.addChild("cont3", null, MERGE);
+ defaultYdtBuilder.addLeaf("leaf1", null, "1");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf4", null, "4");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addChild("cont4", null, MERGE);
+ defaultYdtBuilder.addChild("cont5", null, MERGE);
+ defaultYdtBuilder.addLeaf("leaf9", null, "9");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf10", null, "10");
+ return defaultYdtBuilder;
+ }
+
+ private YangRequestWorkBench buildYdtForKeyLeavesInDeleteTree() {
+ String rootName = "root";
+ YangRequestWorkBench defaultYdtBuilder =
+ (YangRequestWorkBench) ymsManager.getYdtBuilder(rootName, null,
+ EDIT_CONFIG_REQUEST);
+ defaultYdtBuilder.addChild("test", "ydt.test", MERGE);
+ defaultYdtBuilder.addChild("list2", null, MERGE);
+ defaultYdtBuilder.addLeaf("leaf5", null, "5");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf6", null, "6");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf7", null, "7");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addChild("cont7", null, DELETE);
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ return defaultYdtBuilder;
+ }
+
+ /**
+ * Returns YANG data tree to check delete operation of container.
+ *
+ * @return YANG data tree
+ */
+ private YangRequestWorkBench buildYdtForEditOperationWithDelete() {
+ String rootName = "rootNode";
+ YangRequestWorkBench defaultYdtBuilder =
+ (YangRequestWorkBench) ymsManager.getYdtBuilder(rootName, null,
+ EDIT_CONFIG_REQUEST);
+ defaultYdtBuilder.addChild("test", "ydt.test", MERGE);
+ defaultYdtBuilder.addChild("cont1", null, MERGE);
+ defaultYdtBuilder.addChild("cont2", null, DELETE);
+ defaultYdtBuilder.addChild("cont3", null, DELETE);
+ defaultYdtBuilder.addLeaf("leaf1", null, "1");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf4", null, "4");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addChild("cont4", null, DELETE);
+ defaultYdtBuilder.addChild("cont5", null, DELETE);
+ defaultYdtBuilder.addLeaf("leaf9", null, "9");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf10", null, "10");
+ return defaultYdtBuilder;
+ }
+
+ /**
+ * Returns YANG data tree to check edit operation of list.
+ *
+ * @return YANG data tree
+ */
+ private YangRequestWorkBench buildYdtForListEditOperationWithoutDelete() {
+ String rootName = "listWithoutDelete";
+ Set<String> valueSet = new HashSet<>();
+ valueSet.add("10");
+ YangRequestWorkBench defaultYdtBuilder =
+ (YangRequestWorkBench) ymsManager.getYdtBuilder(rootName, null,
+ EDIT_CONFIG_REQUEST);
+ defaultYdtBuilder.addChild("test", "ydt.test", MERGE);
+ defaultYdtBuilder.addChild("cont1", null, MERGE);
+ defaultYdtBuilder.addChild("list1", null, MERGE);
+ defaultYdtBuilder.addLeaf("leaf2", null, "2");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf3", null, "3");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf4", null, "4");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addChild("list2", null, MERGE);
+ defaultYdtBuilder.addLeaf("leaf5", null, "5");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf6", null, "6");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf7", null, "7");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaflist8", null, valueSet);
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf10", null, "10");
+ return defaultYdtBuilder;
+ }
+
+ /**
+ * Returns YANG data tree to check delete operation of list.
+ *
+ * @return YANG data tree
+ */
+ private YangRequestWorkBench buildYdtForListEditOperationWithDelete() {
+ String rootName = "listWithDelete";
+ YangRequestWorkBench defaultYdtBuilder =
+ (YangRequestWorkBench) ymsManager.getYdtBuilder(rootName, null,
+ EDIT_CONFIG_REQUEST);
+ defaultYdtBuilder.addChild("test", "ydt.test", MERGE);
+ defaultYdtBuilder.addChild("cont1", null, MERGE);
+ defaultYdtBuilder.addChild("list1", null, DELETE);
+ defaultYdtBuilder.addLeaf("leaf2", null, "2");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf3", null, "3");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf4", null, "4");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addChild("list2", null, DELETE);
+ defaultYdtBuilder.addLeaf("leaf5", null, "5");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf6", null, "6");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf10", null, "10");
+ return defaultYdtBuilder;
+ }
+
+ /**
+ * Returns YANG data tree to check query operation of container.
+ *
+ * @return YANG data tree
+ */
+ private YangRequestWorkBench buildYdtForQueryOperation() {
+ String rootName = "root";
+ YangRequestWorkBench defaultYdtBuilder =
+ (YangRequestWorkBench) ymsManager.getYdtBuilder(rootName, null,
+ QUERY_CONFIG_REQUEST);
+ defaultYdtBuilder.addChild("test", "ydt.test");
+ defaultYdtBuilder.addChild("cont1", null);
+ defaultYdtBuilder.addChild("cont2", null);
+ defaultYdtBuilder.addChild("cont3", null);
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addChild("cont4", null);
+ defaultYdtBuilder.addChild("cont5", null);
+ return defaultYdtBuilder;
+ }
+
+ /**
+ * Returns YANG data tree to check query operation of list.
+ *
+ * @return YANG data tree
+ */
+ private YangRequestWorkBench buildYdtForListQueryOperation() {
+ String rootName = "listQuery";
+ YangRequestWorkBench defaultYdtBuilder =
+ (YangRequestWorkBench) ymsManager.getYdtBuilder(rootName, null,
+ QUERY_CONFIG_REQUEST);
+ defaultYdtBuilder.addChild("test", "ydt.test");
+ defaultYdtBuilder.addChild("cont1", null);
+ defaultYdtBuilder.addChild("list1", null);
+ defaultYdtBuilder.addLeaf("leaf2", null, "2");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addChild("list2", null);
+ defaultYdtBuilder.addLeaf("leaf5", null, "5");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf6", null, "6");
+ return defaultYdtBuilder;
+ }
+
+ /**
+ * Returns YANG data tree to check delete operation of a node.
+ *
+ * @return YANG data tree
+ */
+ private YangRequestWorkBench buildYdtWithOneDeleteNode() {
+ String rootName = "root";
+ YangRequestWorkBench defaultYdtBuilder =
+ (YangRequestWorkBench) ymsManager.getYdtBuilder(rootName, null,
+ EDIT_CONFIG_REQUEST);
+ defaultYdtBuilder.addChild("test", "ydt.test");
+ defaultYdtBuilder.addChild("cont1", null, MERGE);
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addChild("cont4", null, DELETE);
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf10", null, "10");
+ return defaultYdtBuilder;
+ }
+
+ /**
+ * Returns YANG data tree to check delete operation of last node.
+ *
+ * @return YANG data tree
+ */
+ private YangRequestWorkBench buildYdtWithDeleteNodeAsLastChild() {
+ String rootName = "root";
+ YangRequestWorkBench defaultYdtBuilder =
+ (YangRequestWorkBench) ymsManager.getYdtBuilder(rootName, null,
+ EDIT_CONFIG_REQUEST);
+ defaultYdtBuilder.addChild("test", "ydt.test", MERGE);
+ defaultYdtBuilder.addChild("cont1", null, MERGE);
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addChild("list2", null, MERGE);
+ defaultYdtBuilder.addLeaf("leaf5", null, "10");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf6", null, "10");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addChild("cont4", null, DELETE);
+ return defaultYdtBuilder;
+ }
+
+ /**
+ * Returns YANG data tree to with delete operation of all the nodes.
+ *
+ * @return YANG data tree
+ */
+ private YangRequestWorkBench buildYdtWithAllDeleteNode() {
+ String rootName = "root";
+ YangRequestWorkBench defaultYdtBuilder =
+ (YangRequestWorkBench) ymsManager.getYdtBuilder(rootName, null,
+ EDIT_CONFIG_REQUEST);
+ defaultYdtBuilder.addChild("test", "ydt.test", DELETE);
+ defaultYdtBuilder.addChild("cont1", null, DELETE);
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addChild("list2", null, DELETE);
+ defaultYdtBuilder.addLeaf("leaf5", null, "10");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addLeaf("leaf6", null, "10");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addChild("cont4", null, DELETE);
+ return defaultYdtBuilder;
+ }
+
+ /**
+ * Returns YANG data tree to check rpc operation with only input.
+ *
+ * @return YANG data tree
+ */
+ private YangRequestWorkBench buildYdtForRpcWithOnlyInput() {
+ String rootName = "root";
+ YangRequestWorkBench defaultYdtBuilder =
+ (YangRequestWorkBench) ymsManager.getYdtBuilder(rootName, null,
+ RPC_REQUEST);
+ defaultYdtBuilder.addChild("test", "ydt.test");
+ defaultYdtBuilder.addChild("rock-the-house1", null);
+ defaultYdtBuilder.addChild("input", null);
+ defaultYdtBuilder.addLeaf("leaf13", null, "5");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ return defaultYdtBuilder;
+ }
+
+ /**
+ * Returns YANG data tree to check rpc operation with only output.
+ *
+ * @return YANG data tree
+ */
+ private YangRequestWorkBench buildYdtForRpcWithOnlyOutput() {
+ String rootName = "root";
+ YangRequestWorkBench defaultYdtBuilder =
+ (YangRequestWorkBench) ymsManager.getYdtBuilder(rootName, null,
+ RPC_REQUEST);
+ defaultYdtBuilder.addChild("test", "ydt.test");
+ defaultYdtBuilder.addChild("rock-the-house2", null);
+ defaultYdtBuilder.addChild("output", null);
+ defaultYdtBuilder.addLeaf("leaf14", null, "14");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ return defaultYdtBuilder;
+ }
+
+ /**
+ * Returns YANG data tree to check rpc operation with both input and output.
+ *
+ * @return YANG data tree
+ */
+ private YangRequestWorkBench buildYdtForRpcWithBothInputOutput() {
+ String rootName = "root";
+ YangRequestWorkBench defaultYdtBuilder =
+ (YangRequestWorkBench) ymsManager.getYdtBuilder(rootName, null,
+ RPC_REQUEST);
+ defaultYdtBuilder.addChild("test", "ydt.test");
+ defaultYdtBuilder.addChild("rock-the-house", null);
+ defaultYdtBuilder.addChild("input", null);
+ defaultYdtBuilder.addLeaf("zip-code", null, "5");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.addChild("output", null);
+ defaultYdtBuilder.addLeaf("hello", null, "5");
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ return defaultYdtBuilder;
+ }
+
+ /**
+ * Returns YANG data tree to check rpc operation.
+ *
+ * @return YANG data tree
+ */
+ private YangRequestWorkBench buildYdtForRpc() {
+ String rootName = "root";
+ YangRequestWorkBench defaultYdtBuilder =
+ (YangRequestWorkBench) ymsManager.getYdtBuilder(rootName, null,
+ RPC_REQUEST);
+ defaultYdtBuilder.addChild("test", "ydt.test");
+ defaultYdtBuilder.addChild("rock-the-house3", null);
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ return defaultYdtBuilder;
+ }
+
+ /**
+ * Returns YANG data tree to check query operation with multiple level of
+ * augment.
+ *
+ * @return YANG data tree
+ */
+ private YangRequestWorkBench buildYdtForQueryWithMultipleAugment() {
+ String rootName = "root";
+ YangRequestWorkBench defaultYdtBuilder =
+ (YangRequestWorkBench) ymsManager.getYdtBuilder(rootName, null,
+ QUERY_CONFIG_REQUEST);
+ defaultYdtBuilder.addChild("test", "ydt.test");
+ defaultYdtBuilder.traverseToParent();
+ return defaultYdtBuilder;
+ }
+
+ /**
+ * Returns YANG data tree to check delete operation with multiple level of
+ * augment.
+ *
+ * @return YANG data tree
+ */
+ private YangRequestWorkBench buildYdtForDeleteWithMultipleAugment() {
+ String rootName = "root";
+ YangRequestWorkBench defaultYdtBuilder =
+ (YangRequestWorkBench) ymsManager.getYdtBuilder(rootName, null,
+ EDIT_CONFIG_REQUEST);
+ defaultYdtBuilder.addChild("test", "ydt.test");
+ defaultYdtBuilder.addChild("cont4", null, DELETE);
+ defaultYdtBuilder.traverseToParent();
+ defaultYdtBuilder.traverseToParent();
+ return defaultYdtBuilder;
+ }
+
+ /**
+ * Checks whether YANG data tree and delete tree is correct.
+ */
+ @Test
+ public void validateDeleteTreeOnlyOneNodeInDeleteList()
+ throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder =
+ buildYdtForEditOperationWithDelete();
+ YdtAppContext appContext =
+ defaultYdtBuilder.getAppRootNode().getFirstChild();
+ YdtContext ydtContext = appContext.getModuleContext();
+ List<YdtContext> deleteNodes = appContext.getDeleteNodes();
+
+ YdtContext cont1YdtContext;
+ YdtContext cont2YdtContext;
+ YdtContext cont3YdtContext;
+ YdtContext cont4YdtContext;
+ YdtContext deleteTree;
+
+ // verify whether ydt tree is correct
+ assertThat(ydtContext.getName(), is("test"));
+
+ cont1YdtContext = ydtContext.getFirstChild();
+ assertThat(cont1YdtContext.getName(), is("cont1"));
+
+ cont2YdtContext = cont1YdtContext.getFirstChild();
+ assertThat(cont2YdtContext.getName(), is("cont2"));
+
+ cont3YdtContext = cont2YdtContext.getFirstChild();
+ assertThat(cont3YdtContext.getName(), is("cont3"));
+
+ ydtContext = cont3YdtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("leaf1"));
+ assertThat(ydtContext.getValue(), is("1"));
+
+ ydtContext = cont2YdtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("leaf4"));
+ assertThat(ydtContext.getValue(), is("4"));
+
+ cont4YdtContext = cont1YdtContext.getNextSibling();
+ assertThat(cont4YdtContext.getName(), is("cont4"));
+
+ ydtContext = cont4YdtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("cont5"));
+
+ ydtContext = ydtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("leaf9"));
+ assertThat(ydtContext.getValue(), is("9"));
+
+ ydtContext = cont4YdtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("leaf10"));
+ assertThat(ydtContext.getValue(), is("10"));
+
+ // build delete tree
+ YangApplicationBroker yab = new YangApplicationBroker(null);
+ deleteTree = yab.buildDeleteTree(deleteNodes);
+
+ // verify whether delete ydt tree is correct
+ assertThat(deleteTree.getFirstChild().getName(), is("test"));
+
+ cont1YdtContext = deleteTree.getFirstChild().getFirstChild();
+ assertThat(cont1YdtContext.getName(), is("cont1"));
+
+ cont2YdtContext = cont1YdtContext.getFirstChild();
+ assertThat(cont2YdtContext.getName(), is("cont2"));
+
+ cont3YdtContext = cont2YdtContext.getFirstChild();
+ assertThat(cont3YdtContext.getName(), is("cont3"));
+
+ ydtContext = cont3YdtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("leaf1"));
+ assertThat(ydtContext.getValue(), is("1"));
+
+ assertThat(cont2YdtContext.getNextSibling(), nullValue());
+
+ cont4YdtContext = cont1YdtContext.getNextSibling();
+ assertThat(cont4YdtContext.getName(), is("cont4"));
+
+ ydtContext = cont4YdtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("cont5"));
+
+ ydtContext = ydtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("leaf9"));
+ assertThat(ydtContext.getValue(), is("9"));
+
+ assertThat(cont4YdtContext.getNextSibling(), nullValue());
+
+ // ydtTree after removing delete nodes
+ ydtContext = appContext.getModuleContext();
+ assertThat(ydtContext.getName(), is("test"));
+
+ cont1YdtContext = ydtContext.getFirstChild();
+ assertThat(cont1YdtContext.getName(), is("cont1"));
+
+ ydtContext = cont1YdtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("leaf4"));
+ assertThat(ydtContext.getValue(), is("4"));
+
+ ydtContext = cont1YdtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("leaf10"));
+ assertThat(ydtContext.getValue(), is("10"));
+ }
+
+ /**
+ * Checks whether YANG data tree and delete tree is correct.
+ */
+ @Test
+ public void validateListDeleteTree()
+ throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder =
+ buildYdtForListEditOperationWithDelete();
+ YdtAppContext appContext =
+ defaultYdtBuilder.getAppRootNode().getFirstChild();
+ YdtContext ydtContext = appContext.getModuleContext();
+ List<YdtContext> deleteNodes = appContext.getDeleteNodes();
+
+ YdtContext cont1YdtContext;
+ YdtContext list1YdtContext;
+ YdtContext list2YdtContext;
+ YdtContext deleteTree;
+
+ // verify whether ydt tree is correct
+ assertThat(ydtContext.getName(), is("test"));
+
+ cont1YdtContext = ydtContext.getFirstChild();
+ assertThat(cont1YdtContext.getName(), is("cont1"));
+
+ list1YdtContext = cont1YdtContext.getFirstChild();
+ assertThat(list1YdtContext.getName(), is("list1"));
+
+ ydtContext = list1YdtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("leaf2"));
+ assertThat(ydtContext.getValue(), is("2"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("leaf3"));
+ assertThat(ydtContext.getValue(), is("3"));
+
+ ydtContext = list1YdtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("leaf4"));
+ assertThat(ydtContext.getValue(), is("4"));
+
+ list2YdtContext = cont1YdtContext.getNextSibling();
+ assertThat(list2YdtContext.getName(), is("list2"));
+
+ ydtContext = list2YdtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("leaf5"));
+ assertThat(ydtContext.getValue(), is("5"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("leaf6"));
+ assertThat(ydtContext.getValue(), is("6"));
+
+ ydtContext = list2YdtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("leaf10"));
+ assertThat(ydtContext.getValue(), is("10"));
+
+ // build delete tree
+ YangApplicationBroker yab = new YangApplicationBroker(null);
+ deleteTree = yab.buildDeleteTree(deleteNodes);
+
+ assertThat(deleteTree.getFirstChild().getName(), is("test"));
+
+ cont1YdtContext = deleteTree.getFirstChild().getFirstChild();
+ assertThat(cont1YdtContext.getName(), is("cont1"));
+
+ list1YdtContext = cont1YdtContext.getFirstChild();
+ assertThat(list1YdtContext.getName(), is("list1"));
+
+ ydtContext = list1YdtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("leaf2"));
+ assertThat(ydtContext.getValue(), is("2"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("leaf3"));
+ assertThat(ydtContext.getValue(), is("3"));
+
+ assertThat(list1YdtContext.getNextSibling(), nullValue());
+
+ list2YdtContext = cont1YdtContext.getNextSibling();
+ assertThat(list2YdtContext.getName(), is("list2"));
+
+ ydtContext = list2YdtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("leaf5"));
+ assertThat(ydtContext.getValue(), is("5"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("leaf6"));
+ assertThat(ydtContext.getValue(), is("6"));
+
+ assertThat(ydtContext.getNextSibling(), nullValue());
+
+ // verify whether ydt tree is correct
+ ydtContext = appContext.getModuleContext();
+ assertThat(ydtContext.getName(), is("test"));
+
+ cont1YdtContext = ydtContext.getFirstChild();
+ assertThat(cont1YdtContext.getName(), is("cont1"));
+
+ ydtContext = cont1YdtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("leaf4"));
+ assertThat(ydtContext.getValue(), is("4"));
+
+ ydtContext = cont1YdtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("leaf10"));
+ assertThat(ydtContext.getValue(), is("10"));
+ }
+
+ /**
+ * Checks whether there is no exception when there is valid edit
+ * request.
+ */
+ @Test
+ public void testExecuteEditOperationWithoutDelete()
+ throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder =
+ buildYdtForEditOperationWithoutDelete();
+ ymsManager.executeOperation(defaultYdtBuilder);
+ }
+
+ /**
+ * Checks whether there is no exception when there is valid delete
+ * request.
+ */
+ @Test
+ public void testExecuteEditOperationWithDelete()
+ throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder =
+ buildYdtForEditOperationWithDelete();
+ ymsManager.executeOperation(defaultYdtBuilder);
+ }
+
+ /**
+ * Checks whether there is no exception when there is valid edit
+ * request for list.
+ */
+ @Test
+ public void testExecuteListEditOperationWithoutDelete()
+ throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder =
+ buildYdtForListEditOperationWithoutDelete();
+ ymsManager.executeOperation(defaultYdtBuilder);
+ }
+
+ /**
+ * Checks whether there is no exception when there is valid delete
+ * request for list.
+ */
+ @Test
+ public void testExecuteListEditOperationWithDelete()
+ throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder =
+ buildYdtForListEditOperationWithDelete();
+ ymsManager.executeOperation(defaultYdtBuilder);
+ }
+
+ /**
+ * Checks whether there is no exception when there is valid query
+ * request.
+ */
+ @Test
+ public void testExecuteQueryOperation()
+ throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder = buildYdtForQueryOperation();
+ ymsManager.executeOperation(defaultYdtBuilder);
+ }
+
+ /**
+ * Checks whether there is no exception when there is valid query
+ * request for list.
+ */
+ @Test
+ public void testExecuteListQueryOperation()
+ throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder =
+ buildYdtForListQueryOperation();
+ ymsManager.executeOperation(defaultYdtBuilder);
+ }
+
+ /**
+ * Checks whether delete tree is updated correctly.
+ */
+ @Test
+ public void testSiblingsInDeleteTree()
+ throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder = buildYdtWithOneDeleteNode();
+ YdtAppContext appContext =
+ defaultYdtBuilder.getAppRootNode().getFirstChild();
+ YdtContext ydtContext = appContext.getModuleContext();
+ List<YdtContext> deleteNodes = appContext.getDeleteNodes();
+
+ // verify whether ydt tree is correct
+ assertThat(ydtContext.getName(), is("test"));
+
+ ydtContext = ydtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("cont1"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("cont4"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("leaf10"));
+ assertThat(ydtContext.getValue(), is("10"));
+
+ // build delete tree
+ YangApplicationBroker yab = new YangApplicationBroker(null);
+ YdtContext deleteTree = yab.buildDeleteTree(deleteNodes);
+
+ assertThat(deleteTree.getFirstChild().getName(), is("test"));
+
+ ydtContext = deleteTree.getFirstChild().getFirstChild();
+ assertThat(ydtContext.getName(), is("cont4"));
+
+ assertThat(ydtContext.getNextSibling(), nullValue());
+ assertThat(ydtContext.getPreviousSibling(), nullValue());
+
+ ydtContext = appContext.getModuleContext();
+
+ // verify whether ydt tree is correct
+ assertThat(ydtContext.getName(), is("test"));
+
+ ydtContext = ydtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("cont1"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("leaf10"));
+ assertThat(ydtContext.getValue(), is("10"));
+
+ assertThat(ydtContext.getNextSibling(), nullValue());
+ }
+
+ /**
+ * Checks last child is updated correctly after delete tree is built.
+ */
+ @Test
+ public void testLastChildInYdtTree()
+ throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder =
+ buildYdtWithDeleteNodeAsLastChild();
+ YdtAppContext appContext =
+ defaultYdtBuilder.getAppRootNode().getFirstChild();
+ YdtContext ydtContext = appContext.getModuleContext();
+ List<YdtContext> deleteNodes = appContext.getDeleteNodes();
+ assertThat(YdtAppNodeOperationType.BOTH,
+ is(appContext.getOperationType()));
+
+ // verify whether ydt tree is correct
+ assertThat(ydtContext.getName(), is("test"));
+
+ ydtContext = ydtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("cont1"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("list2"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("cont4"));
+
+ assertThat(ydtContext.getNextSibling(), nullValue());
+
+ // build delete tree
+ YangApplicationBroker yab = new YangApplicationBroker(null);
+ YdtContext deleteTree = yab.buildDeleteTree(deleteNodes);
+
+ assertThat(deleteTree.getFirstChild().getName(), is("test"));
+
+ ydtContext = deleteTree.getFirstChild().getFirstChild();
+ assertThat(ydtContext.getName(), is("cont4"));
+
+ ydtContext = deleteTree.getFirstChild().getLastChild();
+ assertThat(ydtContext.getName(), is("cont4"));
+
+ assertThat(ydtContext.getNextSibling(), nullValue());
+ assertThat(ydtContext.getPreviousSibling(), nullValue());
+
+ ydtContext = appContext.getModuleContext();
+
+ assertThat(ydtContext.getLastChild().getName(), is("list2"));
+
+ // verify whether ydt tree is correct
+ assertThat(ydtContext.getName(), is("test"));
+
+ ydtContext = ydtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("cont1"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("list2"));
+
+ assertThat(ydtContext.getNextSibling(), nullValue());
+ }
+
+ /**
+ * Checks YDT tree with all delete nodes.
+ */
+ @Test
+ public void testYdtTreeWithAllDeleteNodes()
+ throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder = buildYdtWithAllDeleteNode();
+ YdtAppContext appContext =
+ defaultYdtBuilder.getAppRootNode().getFirstChild();
+ YdtContext ydtContext = appContext.getModuleContext();
+ List<YdtContext> deleteNodes = appContext.getDeleteNodes();
+
+ assertThat(YdtAppNodeOperationType.DELETE_ONLY,
+ is(appContext.getOperationType()));
+
+ // verify whether ydt tree is correct
+ assertThat(ydtContext.getName(), is("test"));
+
+ ydtContext = ydtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("cont1"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("list2"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("cont4"));
+
+ assertThat(ydtContext.getNextSibling(), nullValue());
+
+ // build delete tree
+ YangApplicationBroker yab = new YangApplicationBroker(null);
+ YdtContext deleteTree = yab.buildDeleteTree(deleteNodes);
+
+ assertThat(deleteTree.getFirstChild().getName(), is("test"));
+
+ ydtContext = deleteTree.getFirstChild().getFirstChild();
+ assertThat(ydtContext.getName(), is("cont1"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("list2"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("cont4"));
+
+ assertThat(ydtContext.getNextSibling(), nullValue());
+ }
+
+ /**
+ * Checks whether key leaves are also available when there is delete
+ * request for list.
+ */
+ @Test
+ public void testKeyLeavesInDeleteTree() throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder = buildYdtForKeyLeavesInDeleteTree();
+
+ YdtAppContext appContext =
+ defaultYdtBuilder.getAppRootNode().getFirstChild();
+ YdtContext ydtContext = appContext.getModuleContext();
+ List<YdtContext> deleteNodes = appContext.getDeleteNodes();
+
+ assertThat(YdtAppNodeOperationType.BOTH, is(appContext.getOperationType()));
+
+ // verify whether ydt tree is correct
+ assertThat(ydtContext.getName(), is("test"));
+
+ ydtContext = ydtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("list2"));
+
+ ydtContext = ydtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("leaf5"));
+ assertThat(ydtContext.getValue(), is("5"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("leaf6"));
+ assertThat(ydtContext.getValue(), is("6"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("leaf7"));
+ assertThat(ydtContext.getValue(), is("7"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("cont7"));
+
+ assertThat(ydtContext.getNextSibling(), nullValue());
+
+ // build delete tree
+ YangApplicationBroker yab = new YangApplicationBroker(null);
+ YdtContext deleteTree = yab.buildDeleteTree(deleteNodes);
+
+ assertThat(deleteTree.getFirstChild().getName(), is("test"));
+
+ ydtContext = deleteTree.getFirstChild().getFirstChild();
+ assertThat(ydtContext.getName(), is("list2"));
+
+ ydtContext = ydtContext.getFirstChild();
+ assertThat(ydtContext, notNullValue());
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext, notNullValue());
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("cont7"));
+
+ assertThat(ydtContext.getNextSibling(), nullValue());
+
+ ydtContext = appContext.getModuleContext();
+
+ // verify whether ydt tree is correct
+ assertThat(ydtContext.getName(), is("test"));
+
+ ydtContext = ydtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("list2"));
+
+ ydtContext = ydtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("leaf5"));
+ assertThat(ydtContext.getValue(), is("5"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("leaf6"));
+ assertThat(ydtContext.getValue(), is("6"));
+
+ ydtContext = ydtContext.getNextSibling();
+ assertThat(ydtContext.getName(), is("leaf7"));
+ assertThat(ydtContext.getValue(), is("7"));
+
+ assertThat(ydtContext.getNextSibling(), nullValue());
+ }
+
+ /**
+ * Checks YDT tree and application tree for query request with mutiple
+ * augments.
+ */
+ @Test
+ public void testApptreeForQueryWithMultipleAugment()
+ throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder = buildYdtForQueryWithMultipleAugment();
+ YdtAppContext appContext = defaultYdtBuilder.getAppRootNode()
+ .getFirstChild();
+ YdtContext ydtNode = appContext.getModuleContext();
+ YangNode yangNode = (YangNode) ((YdtNode) ydtNode).getYangSchemaNode();
+
+ YangApplicationBroker yab = new YangApplicationBroker(defaultYdtBuilder.
+ getYangSchemaRegistry());
+ yab.processAugmentForChildNode(appContext, yangNode);
+
+ assertThat(appContext.getModuleContext().getName(), is("test"));
+
+ appContext = appContext.getFirstChild();
+
+ String augmentName = ((YangAugment) appContext
+ .getAugmentingSchemaNode()).getTargetNode().get(0)
+ .getResolvedNode().getJavaClassNameOrBuiltInType();
+ assertThat(augmentName, is("cont4"));
+
+ appContext = appContext.getFirstChild();
+ augmentName = ((YangAugment) appContext
+ .getAugmentingSchemaNode()).getTargetNode().get(0)
+ .getResolvedNode().getJavaClassNameOrBuiltInType();
+ assertThat(augmentName, is("cont4"));
+ assertThat(appContext.getFirstChild(), nullValue());
+ assertThat(appContext.getLastChild(), nullValue());
+ }
+
+ /**
+ * Checks whether there is no exception when there is valid query request
+ * for data resource with multiple augments.
+ */
+ @Test
+ public void testQueryWithMultipleAugment()
+ throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder = buildYdtForQueryWithMultipleAugment();
+ ymsManager.executeOperation(defaultYdtBuilder);
+ }
+
+ /**
+ * Checks whether YDT is updated correctly for delete with multiple augment.
+ */
+ @Test
+ public void testYdtForDeleteWithMultipleAugment()
+ throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder =
+ buildYdtForDeleteWithMultipleAugment();
+ YdtAppContext appContext = defaultYdtBuilder.getAppRootNode()
+ .getFirstChild();
+
+ YangApplicationBroker yab = new YangApplicationBroker(defaultYdtBuilder.
+ getYangSchemaRegistry());
+ YdtContext deleteTree = yab.buildDeleteTree(appContext.getDeleteNodes());
+ yab.processAugmentedNodesForDelete(deleteTree.getFirstChild(),
+ appContext);
+
+ assertThat(appContext.getModuleContext().getName(), is("test"));
+
+ appContext = appContext.getFirstChild();
+ String augmentName = ((YangAugment) appContext
+ .getAugmentingSchemaNode()).getTargetNode().get(0)
+ .getResolvedNode().getJavaClassNameOrBuiltInType();
+ assertThat(augmentName, is("cont4"));
+
+ appContext = appContext.getFirstChild();
+ augmentName = ((YangAugment) appContext
+ .getAugmentingSchemaNode()).getTargetNode().get(0)
+ .getResolvedNode().getJavaClassNameOrBuiltInType();
+ assertThat(augmentName, is("cont4"));
+ assertThat(appContext.getFirstChild(), nullValue());
+ assertThat(appContext.getLastChild(), nullValue());
+
+ YdtContext ydtContext = deleteTree.getFirstChild();
+ assertThat(ydtContext.getName(), is("test"));
+
+ ydtContext = ydtContext.getFirstChild();
+ assertThat(ydtContext.getName(), is("cont4"));
+ }
+
+ /**
+ * Checks whether there is no exception when there is valid delete request
+ * for data resource with multiple augments.
+ */
+ @Test
+ public void testDeleteWithMultipleAugment() {
+ YangRequestWorkBench defaultYdtBuilder =
+ buildYdtForDeleteWithMultipleAugment();
+ ymsManager.executeOperation(defaultYdtBuilder);
+ }
+
+ /**
+ * Checks execute operation for rpc request with only output.
+ */
+ @Test
+ public void testRpcWithOutput()
+ throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder =
+ buildYdtForRpcWithOnlyOutput();
+ ymsManager.executeOperation(defaultYdtBuilder);
+ }
+
+ /**
+ * Checks execute operation for rpc request with only input.
+ */
+ @Test
+ public void testRpcWithInput()
+ throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder =
+ buildYdtForRpcWithOnlyInput();
+ ymsManager.executeOperation(defaultYdtBuilder);
+ }
+
+ /**
+ * Checks execute operation for rpc request with input and output.
+ */
+ @Test
+ public void testRpcWithInputOutput()
+ throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder =
+ buildYdtForRpcWithBothInputOutput();
+ ymsManager.executeOperation(defaultYdtBuilder);
+ }
+
+ /**
+ * Checks execute operation for rpc request without input and
+ * output.
+ */
+ @Test
+ public void testRpcWithoutInputOutput()
+ throws IOException, CloneNotSupportedException {
+ YangRequestWorkBench defaultYdtBuilder =
+ buildYdtForRpc();
+ ymsManager.executeOperation(defaultYdtBuilder);
+ }
+}
\ No newline at end of file
diff --git a/apps/yms/app/src/test/resources/yabTestYangFiles/test.yang b/apps/yms/app/src/test/resources/yabTestYangFiles/test.yang
new file mode 100644
index 0000000..e37bed6
--- /dev/null
+++ b/apps/yms/app/src/test/resources/yabTestYangFiles/test.yang
@@ -0,0 +1,111 @@
+module test {
+
+ yang-version 1;
+ namespace "ydt.test";
+ prefix "t6";
+ organization "ON-LAB";
+
+ revision "2016-05-24" {
+ description "Initial revision.";
+ }
+
+ container cont1 {
+ container cont2 {
+ container cont3 {
+ leaf leaf1 {
+ type string;
+ }
+ }
+ }
+ list list1 {
+ key leaf2;
+ leaf leaf2 {
+ type string;
+ }
+ leaf leaf3 {
+ type string;
+ }
+ }
+ leaf leaf4 {
+ type string;
+ }
+ }
+ list list2 {
+ key "leaf5 leaf6";
+ leaf leaf5 {
+ type string;
+ }
+ leaf leaf6 {
+ type string;
+ }
+ leaf leaf7 {
+ type string;
+ }
+ leaf-list leaflist8 {
+ type string;
+ }
+ container cont7 {
+ leaf leaf12 {
+ type string;
+ }
+ }
+ }
+ container cont4 {
+ container cont5 {
+ leaf leaf9 {
+ type string;
+ }
+ }
+ }
+ leaf leaf10 {
+ type string;
+ }
+
+ rpc rock-the-house {
+ input {
+ leaf zip-code {
+ type string;
+ }
+ }
+ output {
+ leaf hello {
+ type string;
+ }
+ }
+ }
+
+ rpc rock-the-house1 {
+ input {
+ leaf leaf13 {
+ type string;
+ }
+ }
+ }
+
+ rpc rock-the-house2 {
+ output {
+ leaf leaf14 {
+ type string;
+ }
+ }
+ }
+
+ rpc rock-the-house3 {
+ }
+
+ augment "/cont4" {
+ container cont6 {
+ leaf leaf11 {
+ type string;
+ }
+ }
+ }
+
+ augment "/cont4/cont6" {
+ container cont7 {
+ leaf leaf12 {
+ type string;
+ }
+ }
+ }
+}