From 21e80918dfa04641ea069c9cb7290b598f1a5236 Mon Sep 17 00:00:00 2001 From: Michal Rehak Date: Thu, 27 Jun 2013 16:01:29 +0200 Subject: [PATCH] first implementation of yang-data-api created maven project added basic implementations of api added unit tests changed api according to implementation Change-Id: I888371d5a7afc46c843f882bee9bfcaa19d5ccbc Signed-off-by: Michal Rehak --- opendaylight/sal/yang-prototype/yang/pom.xml | 1 + .../data/api/CompositeNodeModification.java | 110 ----- .../yang/data/api/MutableCompositeNode.java | 23 + .../controller/yang/data/api/MutableNode.java | 34 ++ .../yang/data/api/MutableSimpleNode.java | 20 + .../controller/yang/data/api/Node.java | 2 +- .../yang/data/api/NodeModification.java | 21 + .../data/api/NodeModificationBuilder.java | 39 ++ .../yang/yang-data-impl/pom.xml | 72 +++ .../yang/data/impl/AbstractNodeTO.java | 72 +++ .../impl/CompositeNodeModificationTOImpl.java | 52 +++ .../yang/data/impl/CompositeNodeTOImpl.java | 120 +++++ .../data/impl/MutableCompositeNodeTOImpl.java | 61 +++ .../data/impl/MutableSimpleNodeTOImpl.java | 43 ++ .../yang/data/impl/NodeFactory.java | 204 +++++++++ .../impl/NodeModificationBuilderImpl.java | 204 +++++++++ .../controller/yang/data/impl/NodeUtils.java | 206 +++++++++ .../impl/SimpleNodeModificationTOImpl.java | 49 ++ .../yang/data/impl/SimpleNodeTOImpl.java | 31 ++ .../yang/data/impl/NodeFactoryTest.java | 147 ++++++ .../controller/yang/data/impl/NodeHelper.java | 327 ++++++++++++++ .../impl/NodeModificationBuilderImplTest.java | 92 ++++ .../yang/data/impl/NodeUtilsTest.java | 110 +++++ .../src/test/resources/config01.xml | 17 + .../src/test/resources/config02.content | 73 +++ .../src/test/resources/config02.xml | 74 ++++ .../src/test/resources/config02g.xml | 73 +++ .../src/test/resources/controller-network.xsd | 311 +++++++++++++ .../test/resources/controller-network.yang | 172 +++++++ .../src/test/resources/generateXml.groovy | 110 +++++ .../resources/ietf-inet-types@2010-09-24.xsd | 399 +++++++++++++++++ .../resources/ietf-inet-types@2010-09-24.yang | 418 ++++++++++++++++++ 32 files changed, 3576 insertions(+), 111 deletions(-) delete mode 100644 opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/CompositeNodeModification.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableCompositeNode.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableNode.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableSimpleNode.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/NodeModification.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/NodeModificationBuilder.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/pom.xml create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/AbstractNodeTO.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/CompositeNodeModificationTOImpl.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/CompositeNodeTOImpl.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/MutableCompositeNodeTOImpl.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/MutableSimpleNodeTOImpl.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeFactory.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeModificationBuilderImpl.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeUtils.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/SimpleNodeModificationTOImpl.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/SimpleNodeTOImpl.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeFactoryTest.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeHelper.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeModificationBuilderImplTest.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeUtilsTest.java create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config01.xml create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02.content create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02.xml create mode 100644 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02g.xml create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/controller-network.xsd create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/controller-network.yang create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/generateXml.groovy create mode 100644 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/ietf-inet-types@2010-09-24.xsd create mode 100755 opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/ietf-inet-types@2010-09-24.yang diff --git a/opendaylight/sal/yang-prototype/yang/pom.xml b/opendaylight/sal/yang-prototype/yang/pom.xml index 33c1604463..3076a6fd67 100644 --- a/opendaylight/sal/yang-prototype/yang/pom.xml +++ b/opendaylight/sal/yang-prototype/yang/pom.xml @@ -19,6 +19,7 @@ yang-common yang-data-api yang-data-util + yang-data-impl yang-model-api yang-model-util yang-binding diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/CompositeNodeModification.java b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/CompositeNodeModification.java deleted file mode 100644 index 1772ddf3be..0000000000 --- a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/CompositeNodeModification.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.yang.data.api; - -import org.opendaylight.controller.yang.common.QName; - -/** - * For the use cases of changing the state data, the node modifications are - * modeled as part of additional metadata in data tree. The modification types - * are based on Netconf edit-config RPCs. In order to modify the configuration - * or state data tree the user must create a tree representing the modification - * of the data and apply that modification to the target tree. - * - * - * @see Network Configuration - * Protocol (NETCONF) - * - */ -public interface CompositeNodeModification extends CompositeNode { - - ModifyAction getModificationAction(); - - // Container Modification - - /** - * The data identified by the node containing this modification is merged - * with the data at the corresponding level in the data tree - * - * @param node - * in data tree - */ - void mergeChild(CompositeNode node); - - /** - * The data identified by the node containing this modification replaces any - * related data in the target data tree If no such data exists in the target - * data tree, the child node is created. - * - * @param node - * composite node - */ - void replaceChild(CompositeNode node); - - /** - * Adds new composite node into data tree - * - * @param node - * composite node - */ - void addChild(CompositeNode node); - - /** - * The data identified by the node containing this modification is deleted - * from the target data tree if and only if the data currently exists in the - * target data tree. If the data does not exist, an error is returned with - * an error value of "data-missing". - * - * @param node - */ - void deleteChild(CompositeNode node); - - /** - * The data identified by the node containing this attribute is deleted from - * the target data tree if the data currently exists in the target data - * tree. If the data does not exist, the modification is silently ignored. - * - * @param node - * composite node - */ - void removeChild(CompositeNode node); - - // Leaf Modifications - - /** - * The data identified by the node containing this modification replaces any - * related data in the target data tree If no such data exists in the target - * data tree, it is created. - * - * @param leaf - */ - void replaceSimpleNode(SimpleNode leaf); - - /** - * The data identified by the node containing this modification is deleted - * from the target data tree if and only if the data currently exists in the - * target data tree. If the data does not exist, an error is returned with - * an error value of "data-missing". - * - * @param leaf - */ - void deleteSimpleNode(SimpleNode leaf); - - /** - * The data identified by the node containing this attribute is deleted from - * the target data tree if the data currently exists in the target data - * tree. If the data does not exist, the modification is silently ignored. - * - * @param leaf - */ - void removeSimpleNode(SimpleNode leaf); - - void removeLeaf(SimpleNode leaf); - - void removeLeaf(QName leaf); -} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableCompositeNode.java b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableCompositeNode.java new file mode 100755 index 0000000000..b1baf309c5 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableCompositeNode.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.data.api; + +import java.util.List; + + +/** + * @author michal.rehak + * + */ +public interface MutableCompositeNode extends MutableNode>>, CompositeNode { + + /** + * update internal map + */ + public void init(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableNode.java b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableNode.java new file mode 100755 index 0000000000..3eddbe5bec --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableNode.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.data.api; + + +/** + * Base representation of node in the data tree, defines basic parameters of + * node such as a QName. + * + * + * @param + */ +public interface MutableNode extends Node { + + /** + * @param parent value to set + */ + void setParent(CompositeNode parent); + + /** + * @param value value to set (children list or leaf value) + */ + void setValue(T value); + + /** + * @param action value to set + */ + void setModifyAction(ModifyAction action); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableSimpleNode.java b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableSimpleNode.java new file mode 100755 index 0000000000..9519fac792 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/MutableSimpleNode.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.data.api; + + +/** + * @author michal.rehak + * @param node value type + * + */ +public interface MutableSimpleNode extends MutableNode, SimpleNode { + + // nothing + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/Node.java b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/Node.java index 341a2866f0..f107dd8964 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/Node.java +++ b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/Node.java @@ -21,7 +21,7 @@ public interface Node { /** * Returns the name of the Node * - * @return + * @return qName of node */ QName getNodeType(); diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/NodeModification.java b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/NodeModification.java new file mode 100755 index 0000000000..c6b64f3add --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/NodeModification.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.data.api; + +/** + * @author michal.rehak + * + */ +public interface NodeModification { + + /** + * @return modify action + */ + ModifyAction getModificationAction(); + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/NodeModificationBuilder.java b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/NodeModificationBuilder.java new file mode 100755 index 0000000000..4e4af9bae5 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/NodeModificationBuilder.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.data.api; + + +/** + * @author michal.rehak + * + */ +public interface NodeModificationBuilder { + + public abstract Node getMutableEquivalent(Node originalNode); + + public abstract CompositeNode buildDiffTree(); + + public abstract void mergeNode(MutableCompositeNode alteredNode); + + public abstract void removeNode(MutableCompositeNode deadNode); + + public abstract void removeNode(MutableSimpleNode deadNode); + + public abstract void deleteNode(MutableSimpleNode deadNode); + + public abstract void deleteNode(MutableCompositeNode deadNode); + + public abstract void replaceNode(MutableCompositeNode replacementNode); + + public abstract void replaceNode(MutableSimpleNode replacementNode); + + public abstract void addNode(MutableCompositeNode newNode); + + public abstract void addNode(MutableSimpleNode newNode); + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/pom.xml b/opendaylight/sal/yang-prototype/yang/yang-data-impl/pom.xml new file mode 100755 index 0000000000..5843de1af2 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/pom.xml @@ -0,0 +1,72 @@ + + 4.0.0 + + org.opendaylight.controller + yang + 0.5.3-SNAPSHOT + + yang-data-impl + + + 2.1.5 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + -Dlog4j.configuration=log4j-test.xml + true + + + + + + + + + org.opendaylight.controller + yang-common + + + org.opendaylight.controller + yang-data-api + + + org.opendaylight.controller + yang-model-parser-impl + + + com.google.guava + guava + 14.0.1 + + + junit + junit + test + + + org.slf4j + slf4j-log4j12 + ${slf4j.version} + test + + + org.codehaus.groovy + groovy + ${groovy.version} + test + + + org.codehaus.groovy + groovy-xml + ${groovy.version} + test + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/AbstractNodeTO.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/AbstractNodeTO.java new file mode 100755 index 0000000000..cc4dfee5a5 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/AbstractNodeTO.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.data.impl; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.Node; + +/** + * @author michal.rehak + * @param + * type of node value + * + */ +public abstract class AbstractNodeTO implements Node { + + private QName qName; + private CompositeNode parent; + private T value; + + /** + * @param qname + * @param parent + * @param value + */ + public AbstractNodeTO(QName qname, CompositeNode parent, T value) { + this.qName = qname; + this.parent = parent; + this.value = value; + } + + @Override + public QName getNodeType() { + return qName; + } + + /** + * @return the qName + */ + protected QName getQName() { + return qName; + } + + @Override + public CompositeNode getParent() { + return parent; + } + + /** + * @param parent the parent to set + */ + public void setParent(CompositeNode parent) { + this.parent = parent; + } + + /** + * @param value the value to set + */ + protected void setValue(T value) { + this.value = value; + } + + @Override + public T getValue() { + return value; + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/CompositeNodeModificationTOImpl.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/CompositeNodeModificationTOImpl.java new file mode 100755 index 0000000000..7981df2f20 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/CompositeNodeModificationTOImpl.java @@ -0,0 +1,52 @@ +/** + * + */ +package org.opendaylight.controller.yang.data.impl; + +import java.util.List; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.ModifyAction; +import org.opendaylight.controller.yang.data.api.Node; +import org.opendaylight.controller.yang.data.api.NodeModification; + +/** + * @author michal.rehak + * + */ +public class CompositeNodeModificationTOImpl extends CompositeNodeTOImpl + implements NodeModification { + + private ModifyAction modifyAction; + + /** + * @param qname + * @param parent + * @param value + * @param modifyAction + */ + public CompositeNodeModificationTOImpl(QName qname, CompositeNode parent, + List> value, ModifyAction modifyAction) { + super(qname, parent, value); + this.modifyAction = modifyAction; + } + + /** + * @return modification action + * @see org.opendaylight.controller.yang.data.impl.NodeModificationSupport#getModificationAction() + */ + @Override + public ModifyAction getModificationAction() { + return modifyAction; + } + + /** + * @param modifyAction + * the modifyAction to set + */ + protected void setModificationAction(ModifyAction modifyAction) { + this.modifyAction = modifyAction; + } + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/CompositeNodeTOImpl.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/CompositeNodeTOImpl.java new file mode 100755 index 0000000000..f94163aa89 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/CompositeNodeTOImpl.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.data.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.Node; +import org.opendaylight.controller.yang.data.api.SimpleNode; + +/** + * @author michal.rehak + * + */ +public class CompositeNodeTOImpl extends AbstractNodeTO>> + implements CompositeNode { + + private Map>> nodeMap; + + /** + * @param qname + * @param parent use null to create top composite node (without parent) + * @param value + */ + public CompositeNodeTOImpl(QName qname, CompositeNode parent, + List> value) { + super(qname, parent, value); + if (value != null) { + nodeMap = NodeUtils.buildNodeMap(getValue()); + } + } + + + /** + * @return the nodeMap + */ + protected Map>> getNodeMap() { + return nodeMap; + } + + @Override + public List> getChildren() { + return getValue(); + } + + @Override + public SimpleNode getFirstSimpleByName(QName leafQName) { + List> list = getSimpleNodesByName(leafQName); + if (list.isEmpty()) + return null; + return list.get(0); + } + + @Override + public List getCompositesByName(QName children) { + List> toFilter = getNodeMap().get(children); + List list = new ArrayList(); + for (Node node : toFilter) { + if (node instanceof CompositeNode) + list.add((CompositeNode) node); + } + return list; + } + + @Override + public List> getSimpleNodesByName(QName children) { + List> toFilter = getNodeMap().get(children); + List> list = new ArrayList>(); + + for (Node node : toFilter) { + if (node instanceof SimpleNode) + list.add((SimpleNode) node); + } + return list; + } + + @Override + public CompositeNode getFirstCompositeByName(QName container) { + List list = getCompositesByName(container); + if (list.isEmpty()) { + return null; + } + return list.get(0); + } + + /** + * @param leaf + * @return TODO:: do we need this method? + */ + public SimpleNode getFirstLeafByName(QName leaf) { + List> list = getSimpleNodesByName(leaf); + if (list.isEmpty()) { + return null; + } + return list.get(0); + } + + @Override + public List getCompositesByName(String children) { + return getCompositesByName(localQName(children)); + } + + @Override + public List> getSimpleNodesByName(String children) { + return getSimpleNodesByName(localQName(children)); + } + + private QName localQName(String str) { + return new QName(getNodeType(), str); + } + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/MutableCompositeNodeTOImpl.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/MutableCompositeNodeTOImpl.java new file mode 100755 index 0000000000..997b5025a7 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/MutableCompositeNodeTOImpl.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.data.impl; + +import java.util.List; +import java.util.Map; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.ModifyAction; +import org.opendaylight.controller.yang.data.api.MutableCompositeNode; +import org.opendaylight.controller.yang.data.api.Node; + +/** + * @author michal.rehak + * + */ +public class MutableCompositeNodeTOImpl extends CompositeNodeModificationTOImpl + implements MutableCompositeNode { + + private Map>> nodeMap; + + /** + * @param qname + * @param parent + * @param value + * @param modifyAction + */ + public MutableCompositeNodeTOImpl(QName qname, CompositeNode parent, + List> value, ModifyAction modifyAction) { + super(qname, parent, value, modifyAction); + } + + /** + * update nodeMap + */ + @Override + public void init() { + nodeMap = NodeUtils.buildNodeMap(getChildren()); + } + + @Override + public void setValue(List> value) { + super.setValue(value); + } + + @Override + public void setModifyAction(ModifyAction action) { + super.setModificationAction(action); + } + + @Override + protected Map>> getNodeMap() { + return nodeMap; + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/MutableSimpleNodeTOImpl.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/MutableSimpleNodeTOImpl.java new file mode 100755 index 0000000000..17cbb8dcad --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/MutableSimpleNodeTOImpl.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.data.impl; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.ModifyAction; +import org.opendaylight.controller.yang.data.api.MutableSimpleNode; + +/** + * @author michal.rehak + * @param type of simple node value + * + */ +public class MutableSimpleNodeTOImpl extends SimpleNodeModificationTOImpl + implements MutableSimpleNode { + + /** + * @param qname + * @param parent + * @param value + * @param modifyAction + */ + public MutableSimpleNodeTOImpl(QName qname, CompositeNode parent, T value, + ModifyAction modifyAction) { + super(qname, parent, value, modifyAction); + } + + @Override + public void setValue(T value) { + super.setValue(value); + } + + @Override + public void setModifyAction(ModifyAction action) { + super.setModificationAction(action); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeFactory.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeFactory.java new file mode 100755 index 0000000000..8b3b7d45ae --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeFactory.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.data.impl; + +import java.util.AbstractMap.SimpleEntry; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.ModifyAction; +import org.opendaylight.controller.yang.data.api.MutableCompositeNode; +import org.opendaylight.controller.yang.data.api.MutableSimpleNode; +import org.opendaylight.controller.yang.data.api.Node; +import org.opendaylight.controller.yang.data.api.SimpleNode; + +/** + * @author michal.rehak + * + */ +public abstract class NodeFactory { + + /** + * @param qName + * @param parent + * @param value + * @return simple node modification, based on given qname, value and parent + */ + public static SimpleNode createSimpleNode(QName qName, + CompositeNode parent, T value) { + SimpleNodeTOImpl simpleNodeTOImpl = new SimpleNodeTOImpl(qName, parent, value); + return simpleNodeTOImpl; + } + + /** + * @param qName + * @param parent + * @param value + * @return simple node modification, based on given qname, value and parent + */ + public static MutableSimpleNode createMutableSimpleNode(QName qName, + CompositeNode parent, T value) { + MutableSimpleNodeTOImpl simpleNodeTOImpl = + new MutableSimpleNodeTOImpl(qName, parent, value, null); + return simpleNodeTOImpl; + } + + /** + * @param qName + * @param parent + * @param value + * @return composite node modification, based on given qname, value (children), parent and modifyAction + */ + public static CompositeNode createCompositeNode(QName qName, + CompositeNode parent, List> value) { + CompositeNode compositeNodeTOImpl = new CompositeNodeTOImpl(qName, parent, value); + return compositeNodeTOImpl; + } + + /** + * @param qName + * @param parent + * @param value + * @return composite node modification, based on given qname, value (children), parent and modifyAction + */ + public static MutableCompositeNode createMutableCompositeNode(QName qName, + CompositeNode parent, List> value) { + MutableCompositeNodeTOImpl compositeNodeTOImpl = + new MutableCompositeNodeTOImpl(qName, parent, value, null); + return compositeNodeTOImpl; + } + + + /** + * @param qName + * @param parent + * @param value + * @param modifyAction + * @return simple node modification, based on given qname, value, parent and modifyAction + */ + public static SimpleNodeModificationTOImpl createSimpleNodeModification(QName qName, + CompositeNode parent, T value, ModifyAction modifyAction) { + SimpleNodeModificationTOImpl simpleNodeModTOImpl = + new SimpleNodeModificationTOImpl(qName, parent, value, modifyAction); + return simpleNodeModTOImpl; + } + + /** + * @param qName + * @param parent + * @param value + * @param modifyAction + * @return composite node modification, based on given qname, value (children), parent and modifyAction + */ + public static CompositeNodeModificationTOImpl createCompositeNodeModification(QName qName, + CompositeNode parent, List> value, ModifyAction modifyAction) { + CompositeNodeModificationTOImpl compositeNodeModTOImpl = + new CompositeNodeModificationTOImpl(qName, parent, value, modifyAction); + return compositeNodeModTOImpl; + } + + /** + * @param node + * @return copy of given node, parent and value are the same, but parent + * has no reference to this copy + */ + public static SimpleNode copyNode(SimpleNode node) { + SimpleNode twinNode = createSimpleNode( + node.getNodeType(), node.getParent(), node.getValue()); + return twinNode; + } + + /** + * @param node + * @return copy of given node, parent and value are the same, but parent + * has no reference to this copy + */ + public static SimpleNode copyNodeAsMutable(SimpleNode node) { + SimpleNode twinNode = createMutableSimpleNode( + node.getNodeType(), node.getParent(), node.getValue()); + return twinNode; + } + + /** + * @param node + * @param children + * @return copy of given node, parent and children are the same, but parent and children + * have no reference to this copy + */ + public static CompositeNode copyNode(CompositeNode node, Node... children) { + CompositeNode twinNode = createCompositeNode( + node.getNodeType(), node.getParent(), Arrays.asList(children)); + return twinNode; + } + + /** + * @param node + * @return copy of given node, parent and children are the same, but parent and children + * have no reference to this copy + */ + public static CompositeNode copyNode(CompositeNode node) { + return copyNode(node, node.getChildren().toArray(new Node[0])); + } + + /** + * @param node root of original tree + * @param originalToMutable (optional) empty map, where binding between original and copy + * will be stored + * @return copy of given node, parent and children are the same, but parent and children + * have no reference to this copy + */ + public static MutableCompositeNode copyDeepNode(CompositeNode node, + Map, Node> originalToMutable) { + + MutableCompositeNode mutableRoot = + createMutableCompositeNode(node.getNodeType(), null, null); + Stack> jobQueue = new Stack<>(); + jobQueue.push(new SimpleEntry(node, mutableRoot)); + if (originalToMutable != null) { + originalToMutable.put(node, mutableRoot); + } + + while (!jobQueue.isEmpty()) { + SimpleEntry job = jobQueue.pop(); + CompositeNode originalNode = job.getKey(); + MutableCompositeNode mutableNode = job.getValue(); + mutableNode.setValue(new ArrayList>()); + + for (Node child : originalNode.getChildren()) { + Node mutableAscendant = null; + if (child instanceof CompositeNode) { + MutableCompositeNode newMutable = + createMutableCompositeNode(child.getNodeType(), mutableNode, null); + jobQueue.push(new SimpleEntry( + (CompositeNode) child, newMutable)); + mutableAscendant = newMutable; + } else if (child instanceof SimpleNode) { + mutableAscendant = + createMutableSimpleNode(child.getNodeType(), mutableNode, child.getValue()); + } else { + throw new IllegalStateException("Node class deep copy not supported: " + +child.getClass().getName()); + } + + mutableNode.getChildren().add(mutableAscendant); + if (originalToMutable != null) { + originalToMutable.put(child, mutableAscendant); + } + } + mutableNode.init(); + } + + return mutableRoot; + } + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeModificationBuilderImpl.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeModificationBuilderImpl.java new file mode 100755 index 0000000000..cd717316d3 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeModificationBuilderImpl.java @@ -0,0 +1,204 @@ +/** + * + */ +package org.opendaylight.controller.yang.data.impl; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.ModifyAction; +import org.opendaylight.controller.yang.data.api.MutableCompositeNode; +import org.opendaylight.controller.yang.data.api.MutableNode; +import org.opendaylight.controller.yang.data.api.MutableSimpleNode; +import org.opendaylight.controller.yang.data.api.Node; +import org.opendaylight.controller.yang.data.api.NodeModificationBuilder; +import org.opendaylight.controller.yang.model.api.ListSchemaNode; +import org.opendaylight.controller.yang.model.api.SchemaContext; + +/** + * @author michal.rehak + * + */ +public class NodeModificationBuilderImpl implements NodeModificationBuilder { + + private SchemaContext context; + + private Set> changeLog; + private Map, Node> originalToMutable; + + private MutableCompositeNode mutableRoot; + + /** + * @param originalTreeRootNode + * @param context + */ + public NodeModificationBuilderImpl(CompositeNode originalTreeRootNode, SchemaContext context) { + this.context = context; + originalToMutable = new HashMap<>(); + mutableRoot = NodeFactory.copyDeepNode(originalTreeRootNode, originalToMutable); + changeLog = new HashSet<>(); + } + + /** + * add given node to it's parent's list of children + * @param newNode + */ + private static void fixParentRelation(Node newNode) { + if (newNode.getParent() != null) { + List> siblings = newNode.getParent().getChildren(); + if (!siblings.contains(newNode)) { + siblings.add(newNode); + } + } + } + + /** + * @param modNode + * @param action + */ + private void addModificationToLog(MutableNode modNode, ModifyAction action) { + modNode.setModifyAction(action); + changeLog.add(modNode); + } + + @Override + public void addNode(MutableSimpleNode newNode) { + fixParentRelation(newNode); + addModificationToLog(newNode, ModifyAction.CREATE); + } + + @Override + public void addNode(MutableCompositeNode newNode) { + fixParentRelation(newNode); + addModificationToLog(newNode, ModifyAction.CREATE); + } + + @Override + public void replaceNode(MutableSimpleNode replacementNode) { + addModificationToLog(replacementNode, ModifyAction.REPLACE); + } + + @Override + public void replaceNode(MutableCompositeNode replacementNode) { + addModificationToLog(replacementNode, ModifyAction.REPLACE); + } + + @Override + public void deleteNode(MutableCompositeNode deadNode) { + addModificationToLog(deadNode, ModifyAction.DELETE); + } + + @Override + public void deleteNode(MutableSimpleNode deadNode) { + addModificationToLog(deadNode, ModifyAction.DELETE); + } + + @Override + public void removeNode(MutableSimpleNode deadNode) { + addModificationToLog(deadNode, ModifyAction.REMOVE); + } + + @Override + public void removeNode(MutableCompositeNode deadNode) { + addModificationToLog(deadNode, ModifyAction.REMOVE); + } + + @Override + public void mergeNode(MutableCompositeNode alteredNode) { + addModificationToLog(alteredNode, ModifyAction.MERGE); + } + + /** + * @return minimalistic tree containing diffs only + */ + @Override + public CompositeNode buildDiffTree() { + Set> wanted = new HashSet<>(); + + // walk changeLog, collect all required nodes + for (MutableNode mutant : changeLog) { + wanted.addAll(collectSelfAndAllParents(mutant)); + } + + // TODO:: walk wanted and add relevant keys + Map mapOfLists = NodeUtils.buildMapOfListNodes(context); + Set> wantedKeys = new HashSet<>(); + for (Node outlaw : wanted) { + if (outlaw instanceof CompositeNode) { + String path = NodeUtils.buildPath(outlaw); + if (mapOfLists.containsKey(path)) { + ListSchemaNode listSchema = mapOfLists.get(path); + if (listSchema.getQName().equals(outlaw.getNodeType())) { + // try to add key subnode to wanted list + List supportedKeys = listSchema.getKeyDefinition(); + for (Node outlawChildren : ((CompositeNode) outlaw).getChildren()) { + if (supportedKeys.contains(outlawChildren.getNodeType())) { + wantedKeys.add(outlawChildren); + } + } + } + } + } + } + wanted.addAll(wantedKeys); + + // remove all unwanted nodes from tree + removeUnrelevantNodes(mutableRoot, wanted); + + return mutableRoot; + } + + /** + * @param mutableRoot2 + * @param wanted + */ + private static void removeUnrelevantNodes(MutableCompositeNode mutRoot, + Set> wanted) { + Stack> jobQueue = new Stack<>(); + jobQueue.push(mutRoot); + while (!jobQueue.isEmpty()) { + MutableNode mutNode = jobQueue.pop(); + if (!wanted.contains(mutNode)) { + if (mutNode.getParent() != null) { + mutNode.getParent().getChildren().remove(mutNode); + } + } else { + if (mutNode instanceof MutableCompositeNode) { + for (Node mutChild : ((MutableCompositeNode) mutNode).getChildren()) { + jobQueue.push((MutableNode) mutChild); + } + } + } + } + } + + /** + * @param focusedAncestor + * @return set of parents and focusedAncestor itself + */ + private static Set> collectSelfAndAllParents(Node focusedAncestor) { + Set> family = new HashSet<>(); + Node tmpNode = focusedAncestor; + while (tmpNode != null) { + family.add(tmpNode); + tmpNode = tmpNode.getParent(); + } + return family; + } + + /** + * @param originalNode + * @return mutable version of given node + */ + @Override + public Node getMutableEquivalent(Node originalNode) { + return originalToMutable.get(originalNode); + } + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeUtils.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeUtils.java new file mode 100755 index 0000000000..b3a7640775 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/NodeUtils.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.data.impl; + +import java.util.AbstractMap.SimpleEntry; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; +import java.util.Vector; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.ModifyAction; +import org.opendaylight.controller.yang.data.api.Node; +import org.opendaylight.controller.yang.data.api.NodeModification; +import org.opendaylight.controller.yang.data.api.SimpleNode; +import org.opendaylight.controller.yang.model.api.DataNodeContainer; +import org.opendaylight.controller.yang.model.api.DataSchemaNode; +import org.opendaylight.controller.yang.model.api.ListSchemaNode; +import org.opendaylight.controller.yang.model.api.SchemaContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import com.google.common.base.Joiner; + + +/** + * @author michal.rehak + * + */ +public abstract class NodeUtils { + + /** + * + */ + private static final String USER_KEY_NODE = "node"; + private static final Logger LOG = LoggerFactory.getLogger(NodeUtils.class); + + /** + * @param node + * @return node path up till root node + */ + public static String buildPath(Node node) { + Vector breadCrumbs = new Vector<>(); + Node tmpNode = node; + while (tmpNode != null) { + breadCrumbs.insertElementAt(tmpNode.getNodeType().getLocalName(), 0); + tmpNode = tmpNode.getParent(); + } + + return Joiner.on(".").join(breadCrumbs); + } + + + /** + * @param treeRootNode + * @return dom tree, containing same node structure, yang nodes are associated + * to dom nodes as user data + */ + public static Document buildShadowDomTree(CompositeNode treeRootNode) { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + Document doc = null; + try { + DocumentBuilder bob = dbf.newDocumentBuilder(); + doc = bob.newDocument(); + } catch (ParserConfigurationException e) { + LOG.error("documentBuilder problem", e); + return null; + } + + Stack>> jobQueue = new Stack<>(); + jobQueue.push(new SimpleEntry>(doc, treeRootNode)); + + while (!jobQueue.isEmpty()) { + SimpleEntry> job = jobQueue.pop(); + org.w3c.dom.Node jointPlace = job.getKey(); + Node item = job.getValue(); + Element itemEl = doc.createElement(item.getNodeType().getLocalName()); + itemEl.setUserData(USER_KEY_NODE, item, null); + if (item instanceof SimpleNode) { + Object value = ((SimpleNode) item).getValue(); + itemEl.setTextContent(String.valueOf(value)); + itemEl.setAttribute("type", value.getClass().getSimpleName()); + } + if (item instanceof NodeModification) { + ModifyAction modificationAction = ((NodeModification) item).getModificationAction(); + if (modificationAction != null) { + itemEl.setAttribute("modifyAction", modificationAction.toString()); + } + } + + jointPlace.appendChild(itemEl); + + if (item instanceof CompositeNode) { + for (Node child : ((CompositeNode) item).getChildren()) { + jobQueue.push(new SimpleEntry>(itemEl, child)); + } + } + } + + return doc; + } + + /** + * @param doc + * @param xpathEx + * @return user data value on found node + * @throws XPathExpressionException + */ + @SuppressWarnings("unchecked") + public static T findNodeByXpath(Document doc, String xpathEx) + throws XPathExpressionException { + T userNode = null; + XPathFactory xPathfactory = XPathFactory.newInstance(); + XPath xpath = xPathfactory.newXPath(); + XPathExpression expr = xpath.compile(xpathEx); + + org.w3c.dom.Node result = (org.w3c.dom.Node) expr.evaluate(doc, XPathConstants.NODE); + if (result != null) { + userNode = (T) result.getUserData(USER_KEY_NODE); + } + + return userNode; + } + + + /** + * build NodeMap, where key = qName; value = node + * + * @param value + * @return map of children, where key = qName and value is list of children groupped by qName + */ + public static Map>> buildNodeMap(List> value) { + Map>> nodeMapTmp = new HashMap<>(); + if (value == null || value.isEmpty()) { + throw new IllegalStateException( + "nodeList should not be null or empty"); + } + for (Node node : value) { + List> qList = nodeMapTmp.get(node.getNodeType()); + if (qList == null) { + qList = new ArrayList<>(); + nodeMapTmp.put(node.getNodeType(), qList); + } + qList.add(node); + } + return nodeMapTmp; + } + + + /** + * @param context + * @return map of lists, where key = path; value = {@link DataSchemaNode} + */ + public static Map buildMapOfListNodes( + SchemaContext context) { + Map mapOfLists = new HashMap<>(); + + Stack jobQueue = new Stack<>(); + jobQueue.addAll(context.getDataDefinitions()); + + while (!jobQueue.isEmpty()) { + DataSchemaNode dataSchema = jobQueue.pop(); + if (dataSchema instanceof ListSchemaNode) { + mapOfLists.put(schemaPathToPath(dataSchema.getPath().getPath()), (ListSchemaNode) dataSchema); + } + + if (dataSchema instanceof DataNodeContainer) { + jobQueue.addAll(((DataNodeContainer) dataSchema).getChildNodes()); + } + } + + return mapOfLists; + } + + + /** + * @param path + * @return + */ + private static String schemaPathToPath(List qNamesPath) { + List pathSeed = new ArrayList<>(); + for (QName qNameItem : qNamesPath) { + pathSeed.add(qNameItem.getLocalName()); + } + return Joiner.on(".").join(pathSeed); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/SimpleNodeModificationTOImpl.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/SimpleNodeModificationTOImpl.java new file mode 100755 index 0000000000..7268637377 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/SimpleNodeModificationTOImpl.java @@ -0,0 +1,49 @@ +/** + * + */ +package org.opendaylight.controller.yang.data.impl; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.ModifyAction; +import org.opendaylight.controller.yang.data.api.NodeModification; + +/** + * @author michal.rehak + * @param type of node value + * + */ +public class SimpleNodeModificationTOImpl extends SimpleNodeTOImpl + implements NodeModification { + + private ModifyAction modifyAction; + + /** + * @param qname + * @param parent + * @param value + * @param modifyAction + */ + public SimpleNodeModificationTOImpl(QName qname, CompositeNode parent, + T value, ModifyAction modifyAction) { + super(qname, parent, value); + this.modifyAction = modifyAction; + } + + /** + * @return modification action + * @see org.opendaylight.controller.yang.data.impl.NodeModificationSupport#getModificationAction() + */ + @Override + public ModifyAction getModificationAction() { + return modifyAction; + } + + /** + * @param modifyAction + * the modifyAction to set + */ + protected void setModificationAction(ModifyAction modifyAction) { + this.modifyAction = modifyAction; + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/SimpleNodeTOImpl.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/SimpleNodeTOImpl.java new file mode 100755 index 0000000000..5cfc03aa7b --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/main/java/org/opendaylight/controller/yang/data/impl/SimpleNodeTOImpl.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.data.impl; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.SimpleNode; + +/** + * @author michal.rehak + * @param type of simple node value + * + */ +public class SimpleNodeTOImpl extends AbstractNodeTO implements + SimpleNode { + + /** + * @param qname + * @param parent + * @param value + */ + public SimpleNodeTOImpl(QName qname, CompositeNode parent, T value) { + super(qname, parent, value); + } + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeFactoryTest.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeFactoryTest.java new file mode 100755 index 0000000000..3d97cc83ca --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeFactoryTest.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.data.impl; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.net.URI; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.ModifyAction; +import org.opendaylight.controller.yang.data.api.MutableCompositeNode; +import org.opendaylight.controller.yang.data.api.Node; +import org.opendaylight.controller.yang.data.api.NodeModification; +import org.w3c.dom.Document; + +/** + * @author michal.rehak + * + */ +public class NodeFactoryTest { + + /** + * Test method for methods creating immutable nodes in + * {@link org.opendaylight.controller.yang.data.impl.NodeFactory}. + * @throws Exception + */ + @Test + public void testImmutableNodes() throws Exception { + QName qName = new QName( + new URI("urn:opendaylight:controller:network"), + new Date(42), "yang-data-impl-immutableTest_", null); + + CompositeNode network = NodeHelper.buildTestConfigTree(qName); + + + Assert.assertEquals(1, network.getChildren().size()); + Document domTree = NodeUtils.buildShadowDomTree(network); + NodeHelper.dumpDoc(domTree, System.out); + + CompositeNode tpList = NodeUtils.findNodeByXpath(domTree, + "//node[node-id/text()='nodeId_19']/termination-points"); + + + Assert.assertEquals(2, tpList.getCompositesByName("termination-point").size()); +// Assert.assertEquals(1, topologies.getCompositesByName("topology").size()); +// Assert.assertEquals(2, destination.getChildren().size()); + } + + /** + * Test method for methods creating immutable nodes in + * {@link org.opendaylight.controller.yang.data.impl.NodeFactory}. + * @throws Exception + */ + @Test + public void testMutableNodes() throws Exception { + // + // + // + // Ethernet0/0 + // 1500 + // + // + // Ethernet0/1 + // 1501 + // + // + // + + QName qName = new QName( + new URI("urn:ietf:params:xml:ns:netconf:base:1.0"), + new Date(42), "yang-data-impl-mutableTest"); + + List> value = new ArrayList>(); + value.add(NodeFactory.createSimpleNode(new QName(qName, "name"), null, "Ethernet0/0")); + value.add(NodeFactory.createSimpleNode(new QName(qName, "mtu"), null, 1500)); + + CompositeNodeModificationTOImpl ifNode = NodeFactory.createCompositeNodeModification( + new QName(qName, "interface"), null, value, ModifyAction.DELETE); + NodeHelper.assignParentToChildren(ifNode); + + value = new ArrayList>(); + value.add(NodeFactory.createSimpleNode(new QName(qName, "name"), null, "Ethernet1/0")); + value.add(NodeFactory.createSimpleNode(new QName(qName, "mtu"), null, 1501)); + + CompositeNode ifNode2 = NodeFactory.createCompositeNode(new QName(qName, "interface"), null, value); + NodeHelper.assignParentToChildren(ifNode2); + + value = new ArrayList>(); + value.add(ifNode); + value.add(ifNode2); + + CompositeNode topNode = NodeFactory.createCompositeNode(new QName(qName, "top"), null, value); + NodeHelper.assignParentToChildren(topNode); + value = new ArrayList>(); + value.add(topNode); + + CompositeNode root = NodeFactory.createCompositeNode(new QName(qName, "config"), null, value); + + + Assert.assertEquals(1, root.getChildren().size()); + Assert.assertEquals(1, ifNode.getSimpleNodesByName("name").size()); + Assert.assertEquals(1, ifNode.getSimpleNodesByName("mtu").size()); + Assert.assertEquals(2, topNode.getCompositesByName("interface").size()); + NodeModification interfaceMod = (NodeModification) + topNode.getCompositesByName("interface").get(0); + Assert.assertEquals(ModifyAction.DELETE, interfaceMod.getModificationAction()); + } + + /** + * test modifications builder + * @throws Exception + */ + @Test + public void testCopyDeepNode() throws Exception { + QName qName = new QName( + new URI("urn:opendaylight:controller:network"), + new Date(42), "yang-data-impl-immutableTest_", null); + + CompositeNode network = NodeHelper.buildTestConfigTree(qName); + Map, Node> mutableToOrig = new HashMap<>(); + MutableCompositeNode mutableNetwork = NodeFactory.copyDeepNode(network, mutableToOrig ); + + Document networkShadow = NodeUtils.buildShadowDomTree(network); + ByteArrayOutputStream expected = new ByteArrayOutputStream(); + NodeHelper.dumpDoc(networkShadow, new PrintStream(expected)); + + Document mutableNetworkShadow = NodeUtils.buildShadowDomTree(mutableNetwork); + ByteArrayOutputStream actual = new ByteArrayOutputStream(); + NodeHelper.dumpDoc(mutableNetworkShadow, new PrintStream(actual)); + + Assert.assertEquals(new String(expected.toByteArray()), new String(actual.toByteArray())); + } + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeHelper.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeHelper.java new file mode 100755 index 0000000000..3b7c0d0fee --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeHelper.java @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.data.impl; + +import java.io.InputStream; +import java.io.PrintStream; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.Node; +import org.opendaylight.controller.yang.model.api.Module; +import org.opendaylight.controller.yang.model.api.SchemaContext; +import org.opendaylight.controller.yang.model.parser.api.YangModelParser; +import org.opendaylight.controller.yang.parser.impl.YangParserImpl; +import org.w3c.dom.Document; + +/** + * @author michal.rehak + * + */ +public abstract class NodeHelper { + + /** xml source of example network configuration */ + public static final String NETWORK_XML = + "\n" + + //"\n" + + " \n" + + " \n" + + " topId_01\n" + + " \n" + + " \n" + + " nodeId_02\n" + + " networkId_02\n" + + " \n" + + " \n" + + " tpId_03\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " nodeId_16\n" + + " networkId_17\n" + + " \n" + + " \n" + + " tpId_18\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " nodeId_19\n" + + " networkId_20\n" + + " \n" + + " \n" + + " tpId_18\n" + + " \n" + + " \n" + + " tpId_19\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " linkId_04\n" + + " \n" + + " nodeId_05\n" + + " tpId_06\n" + + " \n" + + " \n" + + " nodeId_07\n" + + " tpId_08\n" + + " \n" + + " \n" + + " \n" + + " linkId_11\n" + + " \n" + + " nodeId_12\n" + + " tpId_13\n" + + " \n" + + " \n" + + " nodeId_14\n" + + " tpId_15\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " ntElementId_09\n" + + " \n" + + " \n" + + " ntElementId_10\n" + + " \n" + + " \n" + + ""; + + /** + * @param domTree + * @param out + * @throws Exception + */ + public static void dumpDoc(Document domTree, PrintStream out) throws Exception { + TransformerFactory transformerFact = TransformerFactory.newInstance(); + transformerFact.setAttribute("indent-number", 4); + Transformer transformer = transformerFact.newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + //initialize StreamResult with File object to save to file + StreamResult result = new StreamResult(new StringWriter()); + DOMSource source = new DOMSource(domTree); + transformer.transform(source, result); + String xmlString = result.getWriter().toString(); + out.println(xmlString); + } + + /** + * @param qName + * @return example tree, see {@link #NETWORK_XML} + */ + public static CompositeNode buildTestConfigTree(QName qName) { + List> value = new ArrayList>(); + value.add(NodeFactory.createSimpleNode(new QName(qName, "element-id"), null, "ntElementId_09")); + CompositeNode ntElementNode1 = NodeFactory.createCompositeNode(new QName(qName, "network-element"), null, value); + assignParentToChildren(ntElementNode1); + + value = new ArrayList>(); + value.add(NodeFactory.createSimpleNode(new QName(qName, "element-id"), null, "ntElementId_10")); + CompositeNode ntElementNode2 = NodeFactory.createCompositeNode(new QName(qName, "network-element"), null, value); + assignParentToChildren(ntElementNode2); + + value = new ArrayList>(); + value.add(ntElementNode1); + value.add(ntElementNode2); + CompositeNode ntElementsNode = NodeFactory.createCompositeNode( + new QName(qName, "network-elements"), null, value); + assignParentToChildren(ntElementsNode); + + value = new ArrayList>(); + value.add(NodeFactory.createSimpleNode(new QName(qName, "dest-node"), null, "nodeId_07")); + value.add(NodeFactory.createSimpleNode(new QName(qName, "dest-tp"), null, "tpId_08")); + CompositeNode destination = NodeFactory.createCompositeNode( + new QName(qName, "destination"), null, value); + assignParentToChildren(destination); + + value = new ArrayList>(); + value.add(NodeFactory.createSimpleNode(new QName(qName, "source-node"), null, "nodeId_05")); + value.add(NodeFactory.createSimpleNode(new QName(qName, "source-tp"), null, "tpId_06")); + CompositeNode source = NodeFactory.createCompositeNode( + new QName(qName, "source"), null, value); + assignParentToChildren(source); + + value = new ArrayList>(); + value.add(NodeFactory.createSimpleNode(new QName(qName, "link-id"), null, "linkId_04")); + value.add(source); + value.add(destination); + CompositeNode link1 = NodeFactory.createCompositeNode( + new QName(qName, "link"), null, value); + assignParentToChildren(link1); + + value = new ArrayList>(); + value.add(NodeFactory.createSimpleNode(new QName(qName, "dest-node"), null, "nodeId_14")); + value.add(NodeFactory.createSimpleNode(new QName(qName, "dest-tp"), null, "tpId_15")); + destination = NodeFactory.createCompositeNode( + new QName(qName, "destination"), null, value); + assignParentToChildren(destination); + + value = new ArrayList>(); + value.add(NodeFactory.createSimpleNode(new QName(qName, "source-node"), null, "nodeId_12")); + value.add(NodeFactory.createSimpleNode(new QName(qName, "source-tp"), null, "tpId_13")); + source = NodeFactory.createCompositeNode( + new QName(qName, "source"), null, value); + assignParentToChildren(source); + + value = new ArrayList>(); + value.add(NodeFactory.createSimpleNode(new QName(qName, "link-id"), null, "linkId_11")); + value.add(source); + value.add(destination); + CompositeNode link2 = NodeFactory.createCompositeNode( + new QName(qName, "link"), null, value); + assignParentToChildren(link2); + + value = new ArrayList>(); + value.add(link1); + value.add(link2); + CompositeNode links = NodeFactory.createCompositeNode( + new QName(qName, "links"), null, value); + assignParentToChildren(links); + + + value = new ArrayList>(); + value.add(NodeFactory.createSimpleNode(new QName(qName, "tp-id"), null, "tpId_03")); + CompositeNode terminationPointNode1 = NodeFactory.createCompositeNode( + new QName(qName, "termination-point"), null, value); + assignParentToChildren(terminationPointNode1); + + value = new ArrayList>(); + value.add(terminationPointNode1); + CompositeNode terminationPointsNode = NodeFactory.createCompositeNode( + new QName(qName, "termination-points"), null, value); + assignParentToChildren(terminationPointsNode); + + value = new ArrayList>(); + value.add(NodeFactory.createSimpleNode(new QName(qName, "node-id"), null, "nodeId_02")); + value.add(NodeFactory.createSimpleNode(new QName(qName, "supporting-ne"), null, "networkId_02")); + value.add(terminationPointsNode); + CompositeNode node1Node = NodeFactory.createCompositeNode( + new QName(qName, "node"), null, value); + assignParentToChildren(node1Node); + + value = new ArrayList>(); + value.add(NodeFactory.createSimpleNode(new QName(qName, "tp-id"), null, "tpId_18")); + terminationPointNode1 = NodeFactory.createCompositeNode( + new QName(qName, "termination-point"), null, value); + assignParentToChildren(terminationPointNode1); + + value = new ArrayList>(); + value.add(terminationPointNode1); + terminationPointsNode = NodeFactory.createCompositeNode( + new QName(qName, "termination-points"), null, value); + assignParentToChildren(terminationPointsNode); + + value = new ArrayList>(); + value.add(NodeFactory.createSimpleNode(new QName(qName, "node-id"), null, "nodeId_16")); + value.add(NodeFactory.createSimpleNode(new QName(qName, "supporting-ne"), null, "networkId_17")); + value.add(terminationPointsNode); + CompositeNode node2Node = NodeFactory.createCompositeNode( + new QName(qName, "node"), null, value); + assignParentToChildren(node2Node); + + value = new ArrayList>(); + value.add(NodeFactory.createSimpleNode(new QName(qName, "tp-id"), null, "tpId_18")); + terminationPointNode1 = NodeFactory.createCompositeNode( + new QName(qName, "termination-point"), null, value); + assignParentToChildren(terminationPointNode1); + + value = new ArrayList>(); + value.add(NodeFactory.createSimpleNode(new QName(qName, "tp-id"), null, "tpId_19")); + CompositeNode terminationPointNode2 = NodeFactory.createCompositeNode( + new QName(qName, "termination-point"), null, value); + assignParentToChildren(terminationPointNode2); + + value = new ArrayList>(); + value.add(terminationPointNode1); + value.add(terminationPointNode2); + terminationPointsNode = NodeFactory.createCompositeNode( + new QName(qName, "termination-points"), null, value); + assignParentToChildren(terminationPointsNode); + + value = new ArrayList>(); + value.add(NodeFactory.createSimpleNode(new QName(qName, "node-id"), null, "nodeId_19")); + value.add(NodeFactory.createSimpleNode(new QName(qName, "supporting-ne"), null, "networkId_20")); + value.add(terminationPointsNode); + CompositeNode node3Node = NodeFactory.createCompositeNode( + new QName(qName, "node"), null, value); + assignParentToChildren(node3Node); + + value = new ArrayList>(); + value.add(node1Node); + value.add(node2Node); + value.add(node3Node); + CompositeNode nodesNode = NodeFactory.createCompositeNode( + new QName(qName, "nodes"), null, value); + assignParentToChildren(nodesNode); + + value = new ArrayList>(); + value.add(links); + value.add(nodesNode); + value.add(NodeFactory.createSimpleNode(new QName(qName, "topology-id"), null, "topId_01")); + CompositeNode topology = NodeFactory.createCompositeNode( + new QName(qName, "topology"), null, value); + assignParentToChildren(topology); + + value = new ArrayList>(); + value.add(topology); + CompositeNode topologies = NodeFactory.createCompositeNode( + new QName(qName, "topologies"), null, value); + assignParentToChildren(topologies); + + value = new ArrayList>(); + value.add(topologies); + CompositeNode network = NodeFactory.createCompositeNode( + new QName(qName, "network"), null, value); + assignParentToChildren(network); + + return network; + } + + /** + * @param parentNode + */ + public static void assignParentToChildren(CompositeNode parentNode) { + for (Node child : parentNode.getChildren()) { + ((AbstractNodeTO) child).setParent(parentNode); + } + } + + /** + * @return schema context of controller-network.yang + */ + public static SchemaContext loadSchemaContext() { + YangModelParser yParser = new YangParserImpl(); + List yangInputStreams = new ArrayList<>(); + yangInputStreams.add(NodeHelper.class.getResourceAsStream( + "/controller-network.yang")); + yangInputStreams.add(NodeHelper.class.getResourceAsStream( + "/ietf-inet-types@2010-09-24.yang")); + Set modules = yParser + .parseYangModelsFromStreams(yangInputStreams); + return yParser.resolveSchemaContext(modules); + } + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeModificationBuilderImplTest.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeModificationBuilderImplTest.java new file mode 100755 index 0000000000..2df397a9ed --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeModificationBuilderImplTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.data.impl; + +import java.net.URI; +import java.util.Date; + +import junit.framework.Assert; + +import org.junit.Before; +import org.junit.Test; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.MutableCompositeNode; +import org.opendaylight.controller.yang.data.api.MutableSimpleNode; +import org.opendaylight.controller.yang.data.api.SimpleNode; +import org.opendaylight.controller.yang.model.api.SchemaContext; +import org.w3c.dom.Document; + +/** + * @author michal.rehak + * + */ +public class NodeModificationBuilderImplTest { + + private SchemaContext schemaCtx; + private QName qName; + private CompositeNode network; + private NodeModificationBuilderImpl nodeModificationBuilder; + + /** + * prepare schemaContext + * @throws Exception + */ + @Before + public void setUp() throws Exception { + schemaCtx = NodeHelper.loadSchemaContext(); + + qName = new QName( + new URI("urn:opendaylight:controller:network"), + new Date(1369000800000L), "topos"); + network = NodeHelper.buildTestConfigTree(qName); + + nodeModificationBuilder = new NodeModificationBuilderImpl(network, schemaCtx); + } + + /** + * Test method for + * {@link org.opendaylight.controller.yang.data.impl.NodeModificationBuilderImpl#buildDiffTree()} + * . + * @throws Exception + */ + @Test + public void testBuildDiffTree() throws Exception { + Document networkShadow = NodeUtils.buildShadowDomTree(network); + SimpleNode needle = NodeUtils.findNodeByXpath(networkShadow, + "//node[node-id='nodeId_19']//termination-point[2]/tp-id"); + + @SuppressWarnings("unchecked") + MutableSimpleNode mutableNeedle = (MutableSimpleNode) + nodeModificationBuilder.getMutableEquivalent(needle); + + mutableNeedle.setValue("tpId_18x"); + nodeModificationBuilder.replaceNode(mutableNeedle); + CompositeNode diffTree = nodeModificationBuilder.buildDiffTree(); + + Document diffShadow = NodeUtils.buildShadowDomTree(diffTree); + NodeHelper.dumpDoc(diffShadow, System.out); + } + + /** + * Test method for + * {@link org.opendaylight.controller.yang.data.impl.NodeModificationBuilderImpl#getMutableEquivalent(org.opendaylight.controller.yang.data.api.Node)} + * . + */ + @Test + public void testGetMutableEquivalent() { + MutableCompositeNode rootMutable = (MutableCompositeNode) + nodeModificationBuilder.getMutableEquivalent(network); + + CompositeNode topologies = network.getCompositesByName("topologies").iterator().next(); + CompositeNode topologiesMutable = rootMutable.getCompositesByName("topologies").iterator().next(); + + Assert.assertSame(topologiesMutable, nodeModificationBuilder.getMutableEquivalent(topologies)); + } + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeUtilsTest.java b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeUtilsTest.java new file mode 100755 index 0000000000..487c10cbf9 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/java/org/opendaylight/controller/yang/data/impl/NodeUtilsTest.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.data.impl; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.net.URI; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.Node; +import org.opendaylight.controller.yang.data.api.SimpleNode; +import org.opendaylight.controller.yang.model.api.ListSchemaNode; +import org.opendaylight.controller.yang.model.api.SchemaContext; +import org.w3c.dom.Document; + +/** + * @author michal.rehak + * + */ +public class NodeUtilsTest { + + private QName qName; + private CompositeNode network; + + /** + * @throws Exception + */ + @Before + public void setUp() throws Exception { + qName = new QName( + new URI("urn:ietf:params:xml:ns:netconf:base:1.0"), + new Date(42), "yang-data-impl-mutableTest"); + network = NodeHelper.buildTestConfigTree(qName); + } + + /** + * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildPath(org.opendaylight.controller.yang.data.api.Node)}. + * @throws Exception + */ + @Test + public void testBuildPath() throws Exception { + SimpleNode needle = network.getCompositesByName("topologies").iterator().next() + .getCompositesByName("topology").iterator().next() + .getSimpleNodesByName("topology-id").iterator().next(); + String breadCrumbs = NodeUtils.buildPath(needle); + + Assert.assertEquals("network.topologies.topology.topology-id", breadCrumbs); + } + + /** + * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildShadowDomTree(org.opendaylight.controller.yang.data.api.CompositeNode)}. + * @throws Exception + */ + @Test + public void testBuildShadowDomTree() throws Exception { + Document networkShadow = NodeUtils.buildShadowDomTree(network); + ByteArrayOutputStream actual = new ByteArrayOutputStream(); + NodeHelper.dumpDoc(networkShadow, new PrintStream(actual)); + + Assert.assertEquals(2760, new String(actual.toByteArray()).length()); + } + + /** + * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#findNodeByXpath(org.w3c.dom.Document, java.lang.String)}. + * @throws Exception + */ + @Test + public void testFindNodeByXpath() throws Exception { + Document networkShadow = NodeUtils.buildShadowDomTree(network); + SimpleNode needle = NodeUtils.findNodeByXpath(networkShadow, + "//node[node-id='nodeId_19']//termination-point[2]/tp-id"); + Assert.assertNotNull(needle); + Assert.assertEquals("tpId_18", needle.getValue()); + } + + /** + * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildNodeMap(java.util.List)}. + */ + @Test + public void testBuildNodeMap() { + CompositeNode topology = network.getCompositesByName("topologies").iterator().next() + .getCompositesByName("topology").iterator().next(); + + Map>> nodeMap = NodeUtils.buildNodeMap(topology.getChildren()); + Assert.assertEquals(3, nodeMap.size()); + } + + /** + * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildMapOfListNodes(org.opendaylight.controller.yang.model.api.SchemaContext)}. + */ + @Test + public void testBuildMapOfListNodes() { + SchemaContext schemaCtx = NodeHelper.loadSchemaContext(); + Map mapOfLists = NodeUtils.buildMapOfListNodes(schemaCtx); + Assert.assertEquals(5, mapOfLists.size()); + } + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config01.xml b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config01.xml new file mode 100755 index 0000000000..8ffac5b65f --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config01.xml @@ -0,0 +1,17 @@ + + + + + + + + + + Ethernet0/0 + 1500 + + + + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02.content b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02.content new file mode 100755 index 0000000000..e9c05c9652 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02.content @@ -0,0 +1,73 @@ +xmlDoc.network(xmlns: 'urn:opendaylight:controller:network') { + topologies { + topology { + 'topology-id'('topId_'+cnt.get()) + + types() + nodes { + node { + 'node-id'('nodeId_'+cnt.get()) + 'supporting-ne'('networkId_'+cnt.get()) + 'termination-points' { + 'termination-point' { + 'tp-id'('tpId_'+cnt.get()) + } + } + } + node { + 'node-id'('nodeId_'+cnt.get()) + 'supporting-ne'('networkId_'+cnt.get()) + 'termination-points' { + 'termination-point' { + 'tp-id'('tpId_'+cnt.get()) + } + } + } + node { + 'node-id'('nodeId_'+cnt.get()) + 'supporting-ne'('networkId_'+cnt.get()) + 'termination-points' { + 'termination-point' { + 'tp-id'('tpId_'+cnt.get()) + } + 'termination-point' { + 'tp-id'('tpId_'+cnt.get()) + } + } + } + } + links { + link { + 'link-id'('linkId_'+cnt.get()) + source { + 'source-node'('nodeId_'+cnt.get()) + 'source-tp'('tpId_'+cnt.get(false)) + } + destination { + 'dest-node'('nodeId_'+cnt.get()) + 'dest-tp'('tpId_'+cnt.get(false)) + } + } + link { + 'link-id'('linkId_'+cnt.get()) + source { + 'source-node'('nodeId_'+cnt.get()) + 'source-tp'('tpId_'+cnt.get(false)) + } + destination { + 'dest-node'('nodeId_'+cnt.get()) + 'dest-tp'('tpId_'+cnt.get(false)) + } + } + } + } + } + 'network-elements' { + 'network-element' { + 'element-id'('ntElementId_'+cnt.get()) + } + 'network-element' { + 'element-id'('ntElementId_'+cnt.get()) + } + } + } \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02.xml b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02.xml new file mode 100755 index 0000000000..99b862bd30 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02.xml @@ -0,0 +1,74 @@ + + + + + topId_01 + + + + nodeId_02 + networkId_02 + + + tpId_03 + + + + + nodeId_16 + networkId_17 + + + tpId_18 + + + + + nodeId_19 + networkId_20 + + + tpId_18 + + + tpId_19 + + + + + + + linkId_04 + + nodeId_05 + tpId_06 + + + nodeId_07 + tpId_08 + + + + linkId_11 + + nodeId_12 + tpId_13 + + + nodeId_14 + tpId_15 + + + + + + + + ntElementId_09 + + + ntElementId_10 + + + + diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02g.xml b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02g.xml new file mode 100644 index 0000000000..d1ac68c014 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/config02g.xml @@ -0,0 +1,73 @@ + + + + + topId_01 + + + + nodeId_02 + networkId_03 + + + tpId_04 + + + + + nodeId_05 + networkId_06 + + + tpId_07 + + + + + nodeId_08 + networkId_09 + + + tpId_10 + + + tpId_11 + + + + + + + linkId_12 + + nodeId_13 + tpId_13 + + + nodeId_14 + tpId_14 + + + + linkId_15 + + nodeId_16 + tpId_16 + + + nodeId_17 + tpId_17 + + + + + + + + ntElementId_18 + + + ntElementId_19 + + + diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/controller-network.xsd b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/controller-network.xsd new file mode 100755 index 0000000000..6cadb69565 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/controller-network.xsd @@ -0,0 +1,311 @@ + + + + + + + + This schema was generated from the YANG module controller-network + by pyang version 1.2. + + The schema describes an instance document consisting + of the entire configuration data store, operational + data, rpc operations, and notifications. + This schema can thus NOT be used as-is to + validate NETCONF PDUs. + + + + + + + + + + + + + + + + + + + + + identifier for termination points on a port + + + + + + + + + + + + + + This type is used for leafs that reference topology identifier instance. + + + + + + + + + + This type is used for leafs that reference a node instance. + + + + + + + + + + This type is used for leafs that reference a link instance. + + + + + + + + + + + + + + + + + + + + + + + + + + This is the model of abstract topology which contains only Network + Nodes and Network Links. Each topology MUST be identified by + unique topology-id for reason that the store could contain many + topologies. + + + + + + + + + + It is presumed that datastore will contain many topologies. To + distinguish between topologies it is vital to have UNIQUE + topology identifier. + + + + + + + + + The container for definition of topology types. + The augmenting modules should add empty optional leaf + to this container to signalize topology type. + + + + + + + + + + + + + + + + The list of network nodes defined for topology. + + + + + + + + The Topology identifier of network-node. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The Network Link which is defined by Local (Source) and + Remote (Destination) Network Nodes. Every link MUST be + defined either by identifier and his local and remote + Network Nodes (in real applications it is common that many + links are originated from one node and end up in same + remote node). To ensure that we would always know to + distinguish between links, every link SHOULD have + identifier. + + + + + + + + + + + + + + Source node identifier. + + + + + + + + + + + + + + + + Destination node identifier. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/controller-network.yang b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/controller-network.yang new file mode 100755 index 0000000000..022ece914a --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/controller-network.yang @@ -0,0 +1,172 @@ +module controller-network { + yang-version 1; + namespace "urn:opendaylight:controller:network"; + prefix "topos"; + + import ietf-inet-types { prefix "inet"; } + + revision 2013-05-20 { + description "Initial demo"; + } + + + + + typedef topology-id { + type string; + } + + typedef node-id { + type string; + } + + typedef link-id { + type string; + } + + typedef tp-id { + type string; + description "identifier for termination points on a port"; + } + + typedef tp-ref { + type leafref { + path "/network/topologies/topology/nodes/node/termination-points/termination-point/tp-id"; + } + } + typedef topology-ref { + type leafref { + path "/network/topologies/topology/topology-id"; + } + description "This type is used for leafs that reference topology identifier instance."; + // currently not used + } + + typedef node-ref { + type leafref { + path "/network/topologies/topology/nodes/node/node-id"; + } + description "This type is used for leafs that reference a node instance."; + } + + typedef link-ref { + type leafref { + path "/network/topologies/topology/links/link/link-id"; + } + description "This type is used for leafs that reference a link instance."; + // currently not used + } + + typedef network-element-ref { + type leafref { + path "/network/network-elements/network-element/element-id"; + } + } + + + typedef element-id { + type string; + } + + container network { + container topologies { + list topology { + description " + This is the model of abstract topology which contains only Network + Nodes and Network Links. Each topology MUST be identified by + unique topology-id for reason that the store could contain many + topologies. + "; + key "topology-id"; + leaf topology-id { + type topology-id; + description " + It is presumed that datastore will contain many topologies. To + distinguish between topologies it is vital to have UNIQUE + topology identifier. + "; + } + + container types { + description " + The container for definition of topology types. + The augmenting modules should add empty optional leaf + to this container to signalize topology type. + "; + } + + container nodes { + list node { + description "The list of network nodes defined for topology."; + + key "node-id"; + leaf node-id { + type node-id; + description "The Topology identifier of network-node."; + } + + leaf supporting-ne { + type network-element-ref; + } + + container termination-points { + list termination-point { + key "tp-id"; + leaf tp-id { + type tp-id; + } + } + } + } + } + + container links { + list link { + description " + The Network Link which is defined by Local (Source) and + Remote (Destination) Network Nodes. Every link MUST be + defined either by identifier and his local and remote + Network Nodes (in real applications it is common that many + links are originated from one node and end up in same + remote node). To ensure that we would always know to + distinguish between links, every link SHOULD have + identifier. + "; + key "link-id"; + + leaf link-id { + type link-id; + } + container source { + leaf source-node { + type node-ref; + description "Source node identifier."; + } + leaf source-tp { + type tp-ref; + } + } + container destination { + leaf dest-node { + type node-ref; + description "Destination node identifier."; + } + leaf dest-tp { + type tp-ref; + } + } + } + } + } + } + container network-elements { + config true; + list network-element { + key "element-id"; + leaf element-id { + type element-id; + } + } + } + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/generateXml.groovy b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/generateXml.groovy new file mode 100755 index 0000000000..a778137beb --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/generateXml.groovy @@ -0,0 +1,110 @@ +//import groovy.xml.StreamingMarkupBuilder +import groovy.xml.MarkupBuilder +import groovy.xml.XmlUtil + +class Counter { + def counter = 0 + def get() { + return get(true) + } + def get(isInc) { + if (isInc) { + counter++ + } + return String.format('%02d', counter) + } +} + + +cnt = new Counter() +def writer = new StringWriter() +xmlDoc = new MarkupBuilder(writer) +xmlDoc.setDoubleQuotes(true) +xmlDoc.getMkp().xmlDeclaration(version:'1.0', encoding: 'UTF-8') + +//def data = { +// mkp.xmlDeclaration() +// network(xmlns: 'urn:opendaylight:controller:network') { +dataFile = new File(args[0]) +evaluate(dataFile) +// xmlDoc.network(xmlns: 'urn:opendaylight:controller:network') { + // topologies { + // topology { + // 'topology-id'('topId_'+cnt.get()) + // types() + // nodes { + // node { + // 'node-id'('nodeId_'+cnt.get()) + // 'supporting-ne'('networkId_'+cnt.get()) + // 'termination-points' { + // 'termination-point' { + // 'tp-id'('tpId_'+cnt.get()) + // } + // } + // } + // node { + // 'node-id'('nodeId_'+cnt.get()) + // 'supporting-ne'('networkId_'+cnt.get()) + // 'termination-points' { + // 'termination-point' { + // 'tp-id'('tpId_'+cnt.get()) + // } + // } + // } + // node { + // 'node-id'('nodeId_'+cnt.get()) + // 'supporting-ne'('networkId_'+cnt.get()) + // 'termination-points' { + // 'termination-point' { + // 'tp-id'('tpId_'+cnt.get()) + // } + // 'termination-point' { + // 'tp-id'('tpId_'+cnt.get()) + // } + // } + // } + // } + // links { + // link { + // 'link-id'('linkId_'+cnt.get()) + // source { + // 'source-node'('nodeId_'+cnt.get()) + // 'source-tp'('tpId_'+cnt.get(false)) + // } + // destination { + // 'dest-node'('nodeId_'+cnt.get()) + // 'dest-tp'('tpId_'+cnt.get(false)) + // } + // } + // link { + // 'link-id'('linkId_'+cnt.get()) + // source { + // 'source-node'('nodeId_'+cnt.get()) + // 'source-tp'('tpId_'+cnt.get(false)) + // } + // destination { + // 'dest-node'('nodeId_'+cnt.get()) + // 'dest-tp'('tpId_'+cnt.get(false)) + // } + // } + // } + // } + // } + // 'network-elements' { + // 'network-element' { + // 'element-id'('ntElementId_'+cnt.get()) + // } + // 'network-element' { + // 'element-id'('ntElementId_'+cnt.get()) + // } + // } + // } + +//} + + +// def xmlDoc = new StreamingMarkupBuilder() +// xmlDoc.encoding = 'UTF' +//println XmlUtil.serialize(xmlDoc.bind(data)) + +println writer diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/ietf-inet-types@2010-09-24.xsd b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/ietf-inet-types@2010-09-24.xsd new file mode 100644 index 0000000000..3da8ec7b30 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/ietf-inet-types@2010-09-24.xsd @@ -0,0 +1,399 @@ + + + + + + This schema was generated from the YANG module ietf-inet-types + by pyang version 1.2. + + The schema describes an instance document consisting + of the entire configuration data store, operational + data, rpc operations, and notifications. + This schema can thus NOT be used as-is to + validate NETCONF PDUs. + + + + + + This module contains a collection of generally useful derived + YANG data types for Internet addresses and related things. + + Copyright (c) 2010 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, is permitted pursuant to, and subject to the license + terms contained in, the Simplified BSD License set forth in Section + 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 6021; see + the RFC itself for full legal notices. + + + + + + + + This value represents the version of the IP protocol. + + In the value set and its semantics, this type is equivalent + to the InetVersion textual convention of the SMIv2. + + + + + + + + + + + + + The dscp type represents a Differentiated Services Code-Point + that may be used for marking packets in a traffic stream. + + In the value set and its semantics, this type is equivalent + to the Dscp textual convention of the SMIv2. + + + + + + + + + + + + The flow-label type represents flow identifier or Flow Label + in an IPv6 packet header that may be used to discriminate + traffic flows. + + In the value set and its semantics, this type is equivalent + to the IPv6FlowLabel textual convention of the SMIv2. + + + + + + + + + + + + The port-number type represents a 16-bit port number of an + Internet transport layer protocol such as UDP, TCP, DCCP, or + SCTP. Port numbers are assigned by IANA. A current list of + all assignments is available from <http://www.iana.org/>. + + Note that the port number value zero is reserved by IANA. In + situations where the value zero does not make sense, it can + be excluded by subtyping the port-number type. + + In the value set and its semantics, this type is equivalent + to the InetPortNumber textual convention of the SMIv2. + + + + + + + + + + + + The as-number type represents autonomous system numbers + which identify an Autonomous System (AS). An AS is a set + of routers under a single technical administration, using + an interior gateway protocol and common metrics to route + packets within the AS, and using an exterior gateway + protocol to route packets to other ASs'. IANA maintains + the AS number space and has delegated large parts to the + regional registries. + + Autonomous system numbers were originally limited to 16 + bits. BGP extensions have enlarged the autonomous system + number space to 32 bits. This type therefore uses an uint32 + base type without a range restriction in order to support + a larger autonomous system number space. + + In the value set and its semantics, this type is equivalent + to the InetAutonomousSystemNumber textual convention of + the SMIv2. + + + + + + + + + + The ip-address type represents an IP address and is IP + version neutral. The format of the textual representations + implies the IP version. + + + + + + + + + + + + + + + + + + The ipv4-address type represents an IPv4 address in + dotted-quad notation. The IPv4 address may include a zone + index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format for the zone index is the numerical + format + + + + + + + + + + + The ipv6-address type represents an IPv6 address in full, + mixed, shortened, and shortened-mixed notation. The IPv6 + address may include a zone index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format of IPv6 addresses uses the compressed + format described in RFC 4291, Section 2.2, item 2 with the + following additional rules: the :: substitution must be + applied to the longest sequence of all-zero 16-bit chunks + in an IPv6 address. If there is a tie, the first sequence + of all-zero 16-bit chunks is replaced by ::. Single + all-zero 16-bit chunks are not compressed. The canonical + format uses lowercase characters and leading zeros are + not allowed. The canonical format for the zone index is + the numerical format as described in RFC 4007, Section + 11.2. + + + + + + + + + + + The ip-prefix type represents an IP prefix and is IP + version neutral. The format of the textual representations + implies the IP version. + + + + + + + + + + + + + + + + + + The ipv4-prefix type represents an IPv4 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 32. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The canonical format of an IPv4 prefix has all bits of + the IPv4 address set to zero that are not part of the + IPv4 prefix. + + + + + + + + + + + The ipv6-prefix type represents an IPv6 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal 128. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The IPv6 address should have all bits that do not belong + to the prefix set to zero. + + The canonical format of an IPv6 prefix has all bits of + the IPv6 address set to zero that are not part of the + IPv6 prefix. Furthermore, IPv6 address is represented + in the compressed format described in RFC 4291, Section + 2.2, item 2 with the following additional rules: the :: + substitution must be applied to the longest sequence of + all-zero 16-bit chunks in an IPv6 address. If there is + a tie, the first sequence of all-zero 16-bit chunks is + replaced by ::. Single all-zero 16-bit chunks are not + compressed. The canonical format uses lowercase + characters and leading zeros are not allowed. + + + + + + + + + + + The domain-name type represents a DNS domain name. The + name SHOULD be fully qualified whenever possible. + + Internet domain names are only loosely specified. Section + 3.5 of RFC 1034 recommends a syntax (modified in Section + 2.1 of RFC 1123). The pattern above is intended to allow + for current practice in domain name use, and some possible + future expansion. It is designed to hold various types of + domain names, including names used for A or AAAA records + (host names) and other records, such as SRV records. Note + that Internet host names have a stricter syntax (described + in RFC 952) than the DNS recommendations in RFCs 1034 and + 1123, and that systems that want to store host names in + schema nodes using the domain-name type are recommended to + adhere to this stricter standard to ensure interoperability. + + The encoding of DNS names in the DNS protocol is limited + to 255 characters. Since the encoding consists of labels + prefixed by a length bytes and there is a trailing NULL + byte, only 253 characters can appear in the textual dotted + notation. + + The description clause of schema nodes using the domain-name + type MUST describe when and how these names are resolved to + IP addresses. Note that the resolution of a domain-name value + may require to query multiple DNS records (e.g., A for IPv4 + and AAAA for IPv6). The order of the resolution process and + which DNS record takes precedence can either be defined + explicitely or it may depend on the configuration of the + resolver. + + Domain-name values use the US-ASCII encoding. Their canonical + format uses lowercase US-ASCII characters. Internationalized + domain names MUST be encoded in punycode as described in RFC + 3492 + + + + + + + + + + + + The host type represents either an IP address or a DNS + domain name. + + + + + + + + + + + + + + + + + + The uri type represents a Uniform Resource Identifier + (URI) as defined by STD 66. + + Objects using the uri type MUST be in US-ASCII encoding, + and MUST be normalized as described by RFC 3986 Sections + 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary + percent-encoding is removed, and all case-insensitive + characters are set to lowercase except for hexadecimal + digits, which are normalized to uppercase as described in + Section 6.2.2.1. + + The purpose of this normalization is to help provide + unique URIs. Note that this normalization is not + sufficient to provide uniqueness. Two URIs that are + textually distinct after this normalization may still be + equivalent. + + Objects using the uri type may restrict the schemes that + they permit. For example, 'data:' and 'urn:' schemes + might not be appropriate. + + A zero-length URI is not a valid URI. This can be used to + express 'URI absent' where required. + + In the value set and its semantics, this type is equivalent + to the Uri SMIv2 textual convention defined in RFC 5017. + + + + + + + + + + + + + + + + + diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/ietf-inet-types@2010-09-24.yang b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/ietf-inet-types@2010-09-24.yang new file mode 100755 index 0000000000..de20febbb7 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-impl/src/test/resources/ietf-inet-types@2010-09-24.yang @@ -0,0 +1,418 @@ + module ietf-inet-types { + + namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types"; + prefix "inet"; + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: David Partain + + + WG Chair: David Kessens + + + Editor: Juergen Schoenwaelder + "; + + description + "This module contains a collection of generally useful derived + YANG data types for Internet addresses and related things. + + Copyright (c) 2010 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, is permitted pursuant to, and subject to the license + terms contained in, the Simplified BSD License set forth in Section + 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 6021; see + the RFC itself for full legal notices."; + + revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; + } + + /*** collection of protocol field related types ***/ + + typedef ip-version { + type enumeration { + enum unknown { + value "0"; + description + "An unknown or unspecified version of the Internet protocol."; + } + enum ipv4 { + value "1"; + description + "The IPv4 protocol as defined in RFC 791."; + } + enum ipv6 { + value "2"; + description + "The IPv6 protocol as defined in RFC 2460."; + } + } + description + "This value represents the version of the IP protocol. + + In the value set and its semantics, this type is equivalent + to the InetVersion textual convention of the SMIv2."; + reference + "RFC 791: Internet Protocol + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + typedef dscp { + type uint8 { + range "0..63"; + } + description + "The dscp type represents a Differentiated Services Code-Point + that may be used for marking packets in a traffic stream. + + In the value set and its semantics, this type is equivalent + to the Dscp textual convention of the SMIv2."; + reference + "RFC 3289: Management Information Base for the Differentiated + Services Architecture + RFC 2474: Definition of the Differentiated Services Field + (DS Field) in the IPv4 and IPv6 Headers + RFC 2780: IANA Allocation Guidelines For Values In + the Internet Protocol and Related Headers"; + } + + typedef ipv6-flow-label { + type uint32 { + range "0..1048575"; + } + description + "The flow-label type represents flow identifier or Flow Label + in an IPv6 packet header that may be used to discriminate + traffic flows. + + In the value set and its semantics, this type is equivalent + to the IPv6FlowLabel textual convention of the SMIv2."; + reference + "RFC 3595: Textual Conventions for IPv6 Flow Label + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification"; + } + + typedef port-number { + type uint16 { + range "0..65535"; + } + description + "The port-number type represents a 16-bit port number of an + Internet transport layer protocol such as UDP, TCP, DCCP, or + SCTP. Port numbers are assigned by IANA. A current list of + all assignments is available from . + + Note that the port number value zero is reserved by IANA. In + situations where the value zero does not make sense, it can + be excluded by subtyping the port-number type. + + In the value set and its semantics, this type is equivalent + to the InetPortNumber textual convention of the SMIv2."; + reference + "RFC 768: User Datagram Protocol + RFC 793: Transmission Control Protocol + RFC 4960: Stream Control Transmission Protocol + RFC 4340: Datagram Congestion Control Protocol (DCCP) + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + /*** collection of autonomous system related types ***/ + + typedef as-number { + type uint32; + description + "The as-number type represents autonomous system numbers + which identify an Autonomous System (AS). An AS is a set + of routers under a single technical administration, using + an interior gateway protocol and common metrics to route + packets within the AS, and using an exterior gateway + protocol to route packets to other ASs'. IANA maintains + the AS number space and has delegated large parts to the + regional registries. + + Autonomous system numbers were originally limited to 16 + bits. BGP extensions have enlarged the autonomous system + number space to 32 bits. This type therefore uses an uint32 + base type without a range restriction in order to support + a larger autonomous system number space. + + In the value set and its semantics, this type is equivalent + to the InetAutonomousSystemNumber textual convention of + the SMIv2."; + reference + "RFC 1930: Guidelines for creation, selection, and registration + of an Autonomous System (AS) + RFC 4271: A Border Gateway Protocol 4 (BGP-4) + RFC 4893: BGP Support for Four-octet AS Number Space + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + /*** collection of IP address and hostname related types ***/ + + typedef ip-address { + type union { + type inet:ipv4-address; + type inet:ipv6-address; + } + description + "The ip-address type represents an IP address and is IP + version neutral. The format of the textual representations + implies the IP version."; + } + + typedef ipv4-address { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '(%[\p{N}\p{L}]+)?'; + } + description + "The ipv4-address type represents an IPv4 address in + dotted-quad notation. The IPv4 address may include a zone + index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format for the zone index is the numerical + format"; + } + + typedef ipv6-address { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(%[\p{N}\p{L}]+)?'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(%.+)?'; + } + description + "The ipv6-address type represents an IPv6 address in full, + mixed, shortened, and shortened-mixed notation. The IPv6 + address may include a zone index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format of IPv6 addresses uses the compressed + format described in RFC 4291, Section 2.2, item 2 with the + following additional rules: the :: substitution must be + applied to the longest sequence of all-zero 16-bit chunks + in an IPv6 address. If there is a tie, the first sequence + of all-zero 16-bit chunks is replaced by ::. Single + all-zero 16-bit chunks are not compressed. The canonical + format uses lowercase characters and leading zeros are + not allowed. The canonical format for the zone index is + the numerical format as described in RFC 4007, Section + 11.2."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text Representation"; + } + + typedef ip-prefix { + type union { + type inet:ipv4-prefix; + type inet:ipv6-prefix; + } + description + "The ip-prefix type represents an IP prefix and is IP + version neutral. The format of the textual representations + implies the IP version."; + } + + typedef ipv4-prefix { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '/(([0-9])|([1-2][0-9])|(3[0-2]))'; + } + description + "The ipv4-prefix type represents an IPv4 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 32. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The canonical format of an IPv4 prefix has all bits of + the IPv4 address set to zero that are not part of the + IPv4 prefix."; + } + + typedef ipv6-prefix { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(/.+)'; + } + description + "The ipv6-prefix type represents an IPv6 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal 128. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The IPv6 address should have all bits that do not belong + to the prefix set to zero. + + The canonical format of an IPv6 prefix has all bits of + the IPv6 address set to zero that are not part of the + IPv6 prefix. Furthermore, IPv6 address is represented + in the compressed format described in RFC 4291, Section + 2.2, item 2 with the following additional rules: the :: + substitution must be applied to the longest sequence of + all-zero 16-bit chunks in an IPv6 address. If there is + a tie, the first sequence of all-zero 16-bit chunks is + replaced by ::. Single all-zero 16-bit chunks are not + compressed. The canonical format uses lowercase + characters and leading zeros are not allowed."; + reference + "RFC 4291: IP Version 6 Addressing Architecture"; + } + + /*** collection of domain name and URI types ***/ + + typedef domain-name { + type string { + pattern '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*' + + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)' + + '|\.'; + length "1..253"; + } + description + "The domain-name type represents a DNS domain name. The + name SHOULD be fully qualified whenever possible. + + Internet domain names are only loosely specified. Section + 3.5 of RFC 1034 recommends a syntax (modified in Section + 2.1 of RFC 1123). The pattern above is intended to allow + for current practice in domain name use, and some possible + future expansion. It is designed to hold various types of + domain names, including names used for A or AAAA records + (host names) and other records, such as SRV records. Note + that Internet host names have a stricter syntax (described + in RFC 952) than the DNS recommendations in RFCs 1034 and + 1123, and that systems that want to store host names in + schema nodes using the domain-name type are recommended to + adhere to this stricter standard to ensure interoperability. + + The encoding of DNS names in the DNS protocol is limited + to 255 characters. Since the encoding consists of labels + prefixed by a length bytes and there is a trailing NULL + byte, only 253 characters can appear in the textual dotted + notation. + + The description clause of schema nodes using the domain-name + type MUST describe when and how these names are resolved to + IP addresses. Note that the resolution of a domain-name value + may require to query multiple DNS records (e.g., A for IPv4 + and AAAA for IPv6). The order of the resolution process and + which DNS record takes precedence can either be defined + explicitely or it may depend on the configuration of the + resolver. + + Domain-name values use the US-ASCII encoding. Their canonical + format uses lowercase US-ASCII characters. Internationalized + domain names MUST be encoded in punycode as described in RFC + 3492"; + reference + "RFC 952: DoD Internet Host Table Specification + RFC 1034: Domain Names - Concepts and Facilities + RFC 1123: Requirements for Internet Hosts -- Application + and Support + RFC 2782: A DNS RR for specifying the location of services + (DNS SRV) + RFC 3492: Punycode: A Bootstring encoding of Unicode for + Internationalized Domain Names in Applications + (IDNA) + RFC 5891: Internationalizing Domain Names in Applications + (IDNA): Protocol"; + } + + typedef host { + type union { + type inet:ip-address; + type inet:domain-name; + } + description + "The host type represents either an IP address or a DNS + domain name."; + } + + typedef uri { + type string; + description + "The uri type represents a Uniform Resource Identifier + (URI) as defined by STD 66. + + Objects using the uri type MUST be in US-ASCII encoding, + and MUST be normalized as described by RFC 3986 Sections + 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary + percent-encoding is removed, and all case-insensitive + characters are set to lowercase except for hexadecimal + digits, which are normalized to uppercase as described in + Section 6.2.2.1. + + The purpose of this normalization is to help provide + unique URIs. Note that this normalization is not + sufficient to provide uniqueness. Two URIs that are + textually distinct after this normalization may still be + equivalent. + + Objects using the uri type may restrict the schemes that + they permit. For example, 'data:' and 'urn:' schemes + might not be appropriate. + + A zero-length URI is not a valid URI. This can be used to + express 'URI absent' where required. + + In the value set and its semantics, this type is equivalent + to the Uri SMIv2 textual convention defined in RFC 5017."; + reference + "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax + RFC 3305: Report from the Joint W3C/IETF URI Planning Interest + Group: Uniform Resource Identifiers (URIs), URLs, + and Uniform Resource Names (URNs): Clarifications + and Recommendations + RFC 5017: MIB Textual Conventions for Uniform Resource + Identifiers (URIs)"; + } + + } -- 2.36.6