*/\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
*/
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 {
* @param value
*/
public AbstractNodeTO(QName qname, CompositeNode parent, T value) {
- this.qName = qname;
- this.parent = parent;
- this.value = value;
+ this(qname, parent, value, null);
}
/**
.getLocalName(), getModificationAction() == null ? "n/a" : getModificationAction()));
return out.toString();
}
-
-
+
+
@Override
public final QName getKey() {
return getNodeType();
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;
}
@SuppressWarnings("unchecked")
AbstractNodeTO<T> other = (AbstractNodeTO<T>) obj;
- if (modifyAction != other.modifyAction) {
- return false;
- }
if (parent == null) {
if (other.parent != null) {
return false;
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;
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);
+ }
}
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;
/**
* @author michal.rehak
- *
+ *
*/
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");
}
/**
* add given node to it's parent's list of children
- *
+ *
* @param newNode
*/
public static void fixParentRelation(Node<?> newNode) {
/**
* crawl all children of given node and assign it as their parent
- *
+ *
* @param parentNode
*/
public static void fixChildrenRelation(CompositeNode parentNode) {
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;
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;
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
Preconditions.checkNotNull(schema);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
Document doc = null;
try {
DocumentBuilder bob = dbf.newDocumentBuilder();
* 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
Preconditions.checkNotNull(data);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
Document doc = null;
try {
DocumentBuilder bob = dbf.newDocumentBuilder();
} 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,
} 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) {
});
}
-
+
/**
* Converts XML Document containing notification data from Netconf device to
* Data DOM Nodes. <br>
* 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