From 6246ee13ddd081b62b3dd1d46f15d290f2b54bdb Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Tue, 25 Feb 2014 15:04:24 +0100 Subject: [PATCH] ModifAction enum added NONE operation + additional checks Added Modify Action to SimpleNode and CompositeNode Signed-off-by: Maros Marsalek --- .../yangtools/yang/data/api/ModifyAction.java | 41 ++++++++++++++- .../yang/data/impl/AbstractNodeTO.java | 25 ++++------ .../data/impl/ImmutableCompositeNode.java | 12 ++--- .../yangtools/yang/data/impl/NodeUtils.java | 11 ++-- .../yang/data/impl/SimpleNodeTOImpl.java | 3 +- .../data/impl/codec/xml/XmlDocumentUtils.java | 50 ++++++++++++------- 6 files changed, 98 insertions(+), 44 deletions(-) diff --git a/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/ModifyAction.java b/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/ModifyAction.java index 1ae847200c..b4eeb76381 100644 --- a/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/ModifyAction.java +++ b/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/ModifyAction.java @@ -7,6 +7,45 @@ */ package org.opendaylight.yangtools.yang.data.api; +import java.util.Arrays; + +// TODO rename to ModifyOperation + +/** + * http://tools.ietf.org/html/rfc6241#section-7.2 + */ public enum ModifyAction { - MERGE, REPLACE, CREATE, DELETE, REMOVE + MERGE, REPLACE, CREATE, DELETE, REMOVE, NONE; + + public static ModifyAction fromXmlValue(String xmlNameOfAction) { + switch (xmlNameOfAction) { + case "merge": + return MERGE; + case "replace": + return REPLACE; + case "remove": + return REMOVE; + case "delete": + return DELETE; + case "create": + return CREATE; + case "none": + return NONE; + default: + throw new IllegalArgumentException("Unknown operation " + xmlNameOfAction + " available operations " + + Arrays.toString(ModifyAction.values())); + } + } + + public boolean isAsDefaultPermitted() { + boolean isPermitted = this == MERGE; + isPermitted |= this == REPLACE; + isPermitted |= this == NONE; + return isPermitted; + } + + public boolean isOnElementPermitted() { + return this != NONE; + } + } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/AbstractNodeTO.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/AbstractNodeTO.java index 8876247bc2..5b130f59b5 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/AbstractNodeTO.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/AbstractNodeTO.java @@ -7,17 +7,20 @@ */ package org.opendaylight.yangtools.yang.data.impl; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.data.api.CompositeNode; -import org.opendaylight.yangtools.yang.data.api.ModifyAction; -import org.opendaylight.yangtools.yang.data.api.Node; -import org.opendaylight.yangtools.yang.data.api.NodeModification; +import org.opendaylight.yangtools.yang.data.api.*; + +import java.net.URI; +import java.util.Map; /** * @author michal.rehak * @param * type of node value - * + * */ public abstract class AbstractNodeTO implements Node, NodeModification { @@ -37,9 +40,7 @@ public abstract class AbstractNodeTO implements Node, NodeModification { * @param value */ public AbstractNodeTO(QName qname, CompositeNode parent, T value) { - this.qName = qname; - this.parent = parent; - this.value = value; + this(qname, parent, value, null); } /** @@ -119,8 +120,8 @@ public abstract class AbstractNodeTO implements Node, NodeModification { .getLocalName(), getModificationAction() == null ? "n/a" : getModificationAction())); return out.toString(); } - - + + @Override public final QName getKey() { return getNodeType(); @@ -131,7 +132,6 @@ public abstract class AbstractNodeTO implements Node, NodeModification { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((modifyAction == null) ? 0 : modifyAction.hashCode()); result = prime * result + ((qName == null) ? 0 : qName.hashCode()); result = prime * result + ((value == null) ? 0 : value.hashCode()); return result % 2; @@ -150,9 +150,6 @@ public abstract class AbstractNodeTO implements Node, NodeModification { } @SuppressWarnings("unchecked") AbstractNodeTO other = (AbstractNodeTO) obj; - if (modifyAction != other.modifyAction) { - return false; - } if (parent == null) { if (other.parent != null) { return false; diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/ImmutableCompositeNode.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/ImmutableCompositeNode.java index 257745fd4f..de90279fd9 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/ImmutableCompositeNode.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/ImmutableCompositeNode.java @@ -9,12 +9,8 @@ package org.opendaylight.yangtools.yang.data.impl; import org.opendaylight.yangtools.concepts.Immutable; import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.data.api.AttributesContainer; -import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.*; import org.opendaylight.yangtools.yang.data.api.ModifyAction; -import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode; -import org.opendaylight.yangtools.yang.data.api.Node; -import org.opendaylight.yangtools.yang.data.api.SimpleNode; import org.opendaylight.yangtools.yang.data.impl.util.AbstractCompositeNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder; import com.google.common.collect.ImmutableList; @@ -301,8 +297,12 @@ public final class ImmutableCompositeNode extends AbstractNodeTO>> public static ImmutableCompositeNode create(QName qName, List> childNodes) { return new ImmutableCompositeNode(qName, ImmutableMap.of(),childNodes); } - + public static ImmutableCompositeNode create(QName qName, Map attributes, List> childNodes) { return new ImmutableCompositeNode(qName, attributes,childNodes); } + + public static ImmutableCompositeNode create(QName qName, List> childNodes, ModifyAction modifyAction) { + return new ImmutableCompositeNode(qName, childNodes, modifyAction); + } } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/NodeUtils.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/NodeUtils.java index d33ae60b91..56c814bfde 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/NodeUtils.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/NodeUtils.java @@ -23,6 +23,7 @@ import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; +import com.google.common.collect.Maps; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.data.api.ModifyAction; @@ -42,7 +43,7 @@ import com.google.common.collect.Lists; /** * @author michal.rehak - * + * */ public abstract class NodeUtils { @@ -142,13 +143,13 @@ public abstract class NodeUtils { /** * 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<>(); + Map>> nodeMapTmp = Maps.newLinkedHashMap(); if (value == null) { throw new IllegalStateException("nodeList should not be null or empty"); } @@ -201,7 +202,7 @@ public abstract class NodeUtils { /** * add given node to it's parent's list of children - * + * * @param newNode */ public static void fixParentRelation(Node newNode) { @@ -215,7 +216,7 @@ public abstract class NodeUtils { /** * crawl all children of given node and assign it as their parent - * + * * @param parentNode */ public static void fixChildrenRelation(CompositeNode parentNode) { diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/SimpleNodeTOImpl.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/SimpleNodeTOImpl.java index 9a545937e5..0bce4d434d 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/SimpleNodeTOImpl.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/SimpleNodeTOImpl.java @@ -17,6 +17,7 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.util.Map; /** * @author michal.rehak @@ -47,7 +48,6 @@ public class SimpleNodeTOImpl extends AbstractNodeTO implements super(qname, parent, value, modifyAction); } - @Override public MutableSimpleNode asMutable() { throw new IllegalAccessError("cast to mutable is not supported - "+getClass().getSimpleName()); @@ -79,4 +79,5 @@ public class SimpleNodeTOImpl extends AbstractNodeTO implements aStream.writeObject(getValue()); aStream.writeObject(getModificationAction()); } + } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlDocumentUtils.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlDocumentUtils.java index 29a44ce424..b16ff3664e 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlDocumentUtils.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlDocumentUtils.java @@ -23,15 +23,13 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import com.google.common.collect.Maps; import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.data.api.AttributesContainer; -import org.opendaylight.yangtools.yang.data.api.CompositeNode; -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.*; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.Node; -import org.opendaylight.yangtools.yang.data.api.SimpleNode; import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode; import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl; import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec; @@ -51,9 +49,7 @@ import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; +import org.w3c.dom.*; import com.google.common.base.Function; import com.google.common.base.Objects; @@ -75,11 +71,11 @@ public class XmlDocumentUtils { private static final Logger logger = LoggerFactory.getLogger(XmlDocumentUtils.class); /** - * Converts Data DOM structure to XML Document for specified XML Codec Provider and corresponding - * Data Node Container schema. The CompositeNode data parameter enters as root of Data DOM tree and will - * be transformed to root in XML Document. Each element of Data DOM tree is compared against specified Data + * Converts Data DOM structure to XML Document for specified XML Codec Provider and corresponding + * Data Node Container schema. The CompositeNode data parameter enters as root of Data DOM tree and will + * be transformed to root in XML Document. Each element of Data DOM tree is compared against specified Data * Node Container Schema and transformed accordingly. - * + * * @param data Data DOM root element * @param schema Data Node Container Schema * @param codecProvider XML Codec Provider @@ -92,6 +88,7 @@ public class XmlDocumentUtils { Preconditions.checkNotNull(schema); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); Document doc = null; try { DocumentBuilder bob = dbf.newDocumentBuilder(); @@ -113,7 +110,7 @@ public class XmlDocumentUtils { * Converts Data DOM structure to XML Document for specified XML Codec Provider. The CompositeNode * data parameter enters as root of Data DOM tree and will be transformed to root in XML Document. The child * nodes of Data Tree are transformed accordingly. - * + * * @param data Data DOM root element * @param codecProvider XML Codec Provider * @return new instance of XML Document @@ -124,6 +121,7 @@ public class XmlDocumentUtils { Preconditions.checkNotNull(data); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); Document doc = null; try { DocumentBuilder bob = dbf.newDocumentBuilder(); @@ -372,7 +370,9 @@ public class XmlDocumentUtils { } else { value = xmlElement.getTextContent(); } - return new SimpleNodeTOImpl(schema.getQName(), null, value); + + Optional modifyAction = getModifyOperationFromAttributes(xmlElement); + return new SimpleNodeTOImpl<>(schema.getQName(), null, value, modifyAction.orNull()); } private static Node toSimpleNodeWithType(Element xmlElement, LeafListSchemaNode schema, @@ -386,13 +386,29 @@ public class XmlDocumentUtils { } else { value = xmlElement.getTextContent(); } - return new SimpleNodeTOImpl(schema.getQName(), null, value); + + Optional modifyAction = getModifyOperationFromAttributes(xmlElement); + return new SimpleNodeTOImpl<>(schema.getQName(), null, value, modifyAction.orNull()); } private static Node toCompositeNodeWithSchema(Element xmlElement, QName qName, DataNodeContainer schema, XmlCodecProvider codecProvider) { List> values = toDomNodes(xmlElement, Optional.fromNullable(schema.getChildNodes())); - return ImmutableCompositeNode.create(qName, values); + Optional modifyAction = getModifyOperationFromAttributes(xmlElement); + return ImmutableCompositeNode.create(qName, values, modifyAction.orNull()); + } + + public static final QName OPERATION_ATTRIBUTE_QNAME = QName.create(URI.create("urn:ietf:params:xml:ns:netconf:base:1.0"), null, "operation"); + + public static Optional getModifyOperationFromAttributes(Element xmlElement) { + Attr attributeNodeNS = xmlElement.getAttributeNodeNS(OPERATION_ATTRIBUTE_QNAME.getNamespace().toString(), OPERATION_ATTRIBUTE_QNAME.getLocalName()); + if(attributeNodeNS == null) + return Optional.absent(); + + ModifyAction action = ModifyAction.fromXmlValue(attributeNodeNS.getValue()); + Preconditions.checkArgument(action.isOnElementPermitted(), "Unexpected operation %s on %s", action, xmlElement); + + return Optional.of(action); } private static void checkQName(Element xmlElement, QName qName) { @@ -467,7 +483,7 @@ public class XmlDocumentUtils { }); } - + /** * Converts XML Document containing notification data from Netconf device to * Data DOM Nodes.
@@ -480,7 +496,7 @@ public class XmlDocumentUtils { * begins in element which is equal to notifications name defined in * corresponding yang model. Rest of notification metadata are obfuscated, * thus Data DOM contains only pure notification body. - * + * * @param document * XML Document containing notification body * @param notifications -- 2.36.6