ModifAction enum added NONE operation + additional checks 73/5473/3
authorMaros Marsalek <mmarsale@cisco.com>
Tue, 25 Feb 2014 14:04:24 +0000 (15:04 +0100)
committerTony Tkacik <ttkacik@cisco.com>
Mon, 3 Mar 2014 10:43:45 +0000 (10:43 +0000)
Added Modify Action to SimpleNode and CompositeNode

Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/ModifyAction.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/AbstractNodeTO.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/ImmutableCompositeNode.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/NodeUtils.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/SimpleNodeTOImpl.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlDocumentUtils.java

index 1ae847200cf14a21dc47df4b06c99e1546547115..b4eeb763817d829a7974563054230d68d673e8ba 100644 (file)
@@ -7,6 +7,45 @@
  */\r
 package org.opendaylight.yangtools.yang.data.api;\r
 \r
+import java.util.Arrays;\r
+\r
+// TODO rename to ModifyOperation\r
+\r
+/**\r
+ * http://tools.ietf.org/html/rfc6241#section-7.2\r
+ */\r
 public enum ModifyAction {\r
-    MERGE, REPLACE, CREATE, DELETE, REMOVE\r
+    MERGE, REPLACE, CREATE, DELETE, REMOVE, NONE;\r
+\r
+    public static ModifyAction fromXmlValue(String xmlNameOfAction) {\r
+        switch (xmlNameOfAction) {\r
+        case "merge":\r
+            return MERGE;\r
+        case "replace":\r
+            return REPLACE;\r
+        case "remove":\r
+            return REMOVE;\r
+        case "delete":\r
+            return DELETE;\r
+        case "create":\r
+            return CREATE;\r
+        case "none":\r
+            return NONE;\r
+        default:\r
+            throw new IllegalArgumentException("Unknown operation " + xmlNameOfAction + " available operations "\r
+                    + Arrays.toString(ModifyAction.values()));\r
+        }\r
+    }\r
+\r
+    public boolean isAsDefaultPermitted() {\r
+        boolean isPermitted = this == MERGE;\r
+        isPermitted |= this == REPLACE;\r
+        isPermitted |= this == NONE;\r
+        return isPermitted;\r
+    }\r
+\r
+    public boolean isOnElementPermitted() {\r
+        return this != NONE;\r
+    }\r
+\r
 }\r
index 8876247bc257c13855dd1259b90bbe5f6e5324f7..5b130f59b588b5097720926efe67609d55b50b66 100644 (file)
@@ -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 <T>
  *            type of node value
- * 
+ *
  */
 public abstract class AbstractNodeTO<T> implements Node<T>, NodeModification {
 
@@ -37,9 +40,7 @@ public abstract class AbstractNodeTO<T> implements Node<T>, 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<T> implements Node<T>, 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<T> implements Node<T>, 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<T> implements Node<T>, NodeModification {
         }
         @SuppressWarnings("unchecked")
         AbstractNodeTO<T> other = (AbstractNodeTO<T>) obj;
-        if (modifyAction != other.modifyAction) {
-            return false;
-        }
         if (parent == null) {
             if (other.parent != null) {
                 return false;
index 257745fd4f789f2f82bea74c8a1a16c11cbedd7b..de90279fd9f525cb3ea9e57bc8e30e865927a277 100644 (file)
@@ -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<List<Node<?>>>
     public static ImmutableCompositeNode create(QName qName, List<Node<?>> childNodes) {
         return new ImmutableCompositeNode(qName, ImmutableMap.<QName, String>of(),childNodes);
     }
-    
+
     public static ImmutableCompositeNode create(QName qName, Map<QName, String> attributes, List<Node<?>> childNodes) {
         return new ImmutableCompositeNode(qName, attributes,childNodes);
     }
+
+    public static ImmutableCompositeNode create(QName qName, List<Node<?>> childNodes, ModifyAction modifyAction) {
+        return new ImmutableCompositeNode(qName, childNodes, modifyAction);
+    }
 }
index d33ae60b913a6b756a86da3a36727a93679a96e0..56c814bfde79844310d11fa7b278d00be54a1029 100644 (file)
@@ -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<QName, List<Node<?>>> buildNodeMap(List<Node<?>> value) {
-        Map<QName, List<Node<?>>> nodeMapTmp = new HashMap<>();
+        Map<QName, List<Node<?>>> 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) {
index 9a545937e5f2ca0edff183f9e8a79d39fef216aa..0bce4d434d2adc214aefe2af564e4680021bb1f6 100644 (file)
@@ -17,6 +17,7 @@ import java.io.IOException;
 import java.io.ObjectInputStream;\r
 import java.io.ObjectOutputStream;\r
 import java.io.Serializable;\r
+import java.util.Map;\r
 \r
 /**\r
  * @author michal.rehak\r
@@ -47,7 +48,6 @@ public class SimpleNodeTOImpl<T> extends AbstractNodeTO<T> implements
         super(qname, parent, value, modifyAction);\r
     }\r
 \r
-\r
     @Override\r
     public MutableSimpleNode<T> asMutable() {\r
         throw new IllegalAccessError("cast to mutable is not supported - "+getClass().getSimpleName());\r
@@ -79,4 +79,5 @@ public class SimpleNodeTOImpl<T> extends AbstractNodeTO<T> implements
         aStream.writeObject(getValue());\r
         aStream.writeObject(getModificationAction());\r
     }\r
+\r
 }\r
index 29a44ce4247c2a94a08849c3b3e4ac3348fcf07f..b16ff3664e9480fbc3eda96972540897cfe007fa 100644 (file)
@@ -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<Object>(schema.getQName(), null, value);
+
+        Optional<ModifyAction> 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<Object>(schema.getQName(), null, value);
+
+        Optional<ModifyAction> 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<Node<?>> values = toDomNodes(xmlElement, Optional.fromNullable(schema.getChildNodes()));
-        return ImmutableCompositeNode.create(qName, values);
+        Optional<ModifyAction> 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<ModifyAction> 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. <br>
@@ -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