X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=netconf%2Fsal-netconf-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetconf%2Fsal%2Fconnect%2Fnetconf%2Futil%2FSchemalessRpcStructureTransformer.java;h=45058eb17cd2945f2145c744ea8f82598b9aa99a;hb=4f8fe6ca68115fecdb9ce43573af5a2e26c50b50;hp=98d3d30f91066802cc1ce715caa716ae7da412d3;hpb=a3022c29beea055ec8e7cacaa30dd64d5a80887c;p=netconf.git diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/util/SchemalessRpcStructureTransformer.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/util/SchemalessRpcStructureTransformer.java index 98d3d30f91..45058eb17c 100644 --- a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/util/SchemalessRpcStructureTransformer.java +++ b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/util/SchemalessRpcStructureTransformer.java @@ -7,23 +7,33 @@ */ package org.opendaylight.netconf.sal.connect.netconf.util; +import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_CONFIG_NODEID; import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_CONFIG_QNAME; +import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_DATA_NODEID; +import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_FILTER_NODEID; +import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_FILTER_QNAME; +import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_OPERATION_QNAME; +import static org.opendaylight.netconf.util.NetconfUtil.NETCONF_DATA_QNAME; +import static org.opendaylight.netconf.util.NetconfUtil.appendListKeyNodes; +import static org.opendaylight.netconf.util.NetconfUtil.writeSchemalessFilter; -import com.google.common.base.Optional; import com.google.common.base.Preconditions; import java.util.Collections; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; import javax.xml.transform.dom.DOMSource; -import org.opendaylight.controller.config.util.xml.DocumentedException; -import org.opendaylight.controller.config.util.xml.XmlElement; -import org.opendaylight.controller.config.util.xml.XmlUtil; +import org.opendaylight.netconf.api.DocumentedException; +import org.opendaylight.netconf.api.ModifyAction; +import org.opendaylight.netconf.api.xml.XmlElement; +import org.opendaylight.netconf.api.xml.XmlUtil; import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.data.api.ModifyAction; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; -import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.AnyxmlNode; +import org.opendaylight.yangtools.yang.data.api.schema.DOMSourceAnyxmlNode; import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.impl.schema.Builders; @@ -40,26 +50,25 @@ class SchemalessRpcStructureTransformer implements RpcStructureTransformer { /** * Selects elements in anyxml data node, which matches path arguments QNames. Since class in not context aware, * method searches for all elements as they are named in path. - * @param data data, must be of type {@link AnyXmlNode} + * @param data data, must be of type {@link DOMSourceAnyxmlNode} * @param path path to select * @return selected data */ @Override - public Optional> selectFromDataStructure( - final DataContainerChild data, + public Optional selectFromDataStructure(final DataContainerChild data, final YangInstanceIdentifier path) { - Preconditions.checkArgument(data instanceof AnyXmlNode); - final List xmlElements = selectMatchingNodes(getSourceElement(((AnyXmlNode)data).getValue()), path); + Preconditions.checkArgument(data instanceof DOMSourceAnyxmlNode); + final List xmlElements = selectMatchingNodes( + getSourceElement(((DOMSourceAnyxmlNode)data).body()), path); final Document result = XmlUtil.newDocument(); - final QName dataQName = NetconfMessageTransformUtil.NETCONF_DATA_QNAME; final Element dataElement = - result.createElementNS(dataQName.getNamespace().toString(), dataQName.getLocalName()); + result.createElementNS(NETCONF_DATA_QNAME.getNamespace().toString(), NETCONF_DATA_QNAME.getLocalName()); result.appendChild(dataElement); for (XmlElement xmlElement : xmlElements) { dataElement.appendChild(result.importNode(xmlElement.getDomElement(), true)); } - final AnyXmlNode resultAnyxml = Builders.anyXmlBuilder() - .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(dataQName)) + final DOMSourceAnyxmlNode resultAnyxml = Builders.anyXmlBuilder() + .withNodeIdentifier(NETCONF_DATA_NODEID) .withValue(new DOMSource(result)) .build(); return Optional.of(resultAnyxml); @@ -74,15 +83,14 @@ class SchemalessRpcStructureTransformer implements RpcStructureTransformer { * @return config structure */ @Override - public AnyXmlNode createEditConfigStructure(final Optional> data, - final YangInstanceIdentifier dataPath, - final Optional operation) { + public DOMSourceAnyxmlNode createEditConfigStructure(final Optional data, + final YangInstanceIdentifier dataPath, final Optional operation) { Preconditions.checkArgument(data.isPresent()); - Preconditions.checkArgument(data.get() instanceof AnyXmlNode); + Preconditions.checkArgument(data.get() instanceof DOMSourceAnyxmlNode); - final AnyXmlNode anxmlData = (AnyXmlNode) data.get(); + final DOMSourceAnyxmlNode anxmlData = (DOMSourceAnyxmlNode) data.get(); final Document document = XmlUtil.newDocument(); - final Element dataNode = (Element) document.importNode(getSourceElement(anxmlData.getValue()), true); + final Element dataNode = (Element) document.importNode(getSourceElement(anxmlData.body()), true); checkDataValidForPath(dataPath, dataNode); final Element configElement = document.createElementNS(NETCONF_CONFIG_QNAME.getNamespace().toString(), @@ -90,23 +98,19 @@ class SchemalessRpcStructureTransformer implements RpcStructureTransformer { document.appendChild(configElement); final Element parentXmlStructure; - if (dataPath.equals(YangInstanceIdentifier.EMPTY)) { + if (dataPath.isEmpty()) { parentXmlStructure = dataNode; configElement.appendChild(parentXmlStructure); } else { - final List pathArguments = dataPath.getPathArguments(); + final List pathArguments = dataPath.getPathArguments(); //last will be appended later - final List pathWithoutLast = - pathArguments.subList(0, pathArguments.size() - 1); + final List pathWithoutLast = pathArguments.subList(0, pathArguments.size() - 1); parentXmlStructure = instanceIdToXmlStructure(pathWithoutLast, configElement); } - if (operation.isPresent()) { - setOperationAttribute(operation, document, dataNode); - } + operation.ifPresent(modifyAction -> setOperationAttribute(modifyAction, document, dataNode)); //append data parentXmlStructure.appendChild(document.importNode(dataNode, true)); - return Builders.anyXmlBuilder() - .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(NETCONF_CONFIG_QNAME)) + return Builders.anyXmlBuilder().withNodeIdentifier(NETCONF_CONFIG_NODEID) .withValue(new DOMSource(document.getDocumentElement())) .build(); } @@ -118,47 +122,61 @@ class SchemalessRpcStructureTransformer implements RpcStructureTransformer { * @return filter structure */ @Override - public DataContainerChild toFilterStructure(final YangInstanceIdentifier path) { + public AnyxmlNode toFilterStructure(final YangInstanceIdentifier path) { + final Document document = XmlUtil.newDocument(); + final Element filterElement = prepareFilterElement(document); + instanceIdToXmlStructure(path.getPathArguments(), filterElement); + return buildFilterXmlNode(document); + } + + @Override + public AnyxmlNode toFilterStructure(final List fieldsFilters) { final Document document = XmlUtil.newDocument(); - final QName filterQname = NetconfMessageTransformUtil.NETCONF_FILTER_QNAME; - final Element filter = - document.createElementNS(filterQname.getNamespace().toString(), filterQname.getLocalName()); - final Attr a = document.createAttributeNS(filterQname.getNamespace().toString(), "type"); + final Element filterElement = prepareFilterElement(document); + for (final FieldsFilter filter : fieldsFilters) { + writeSchemalessFilter(filter.path(), filter.fields(), filterElement); + } + return buildFilterXmlNode(document); + } + + private static Element prepareFilterElement(final Document document) { + final String filterNs = NETCONF_FILTER_QNAME.getNamespace().toString(); + final Element filter = document.createElementNS(filterNs, NETCONF_FILTER_QNAME.getLocalName()); + final Attr a = document.createAttributeNS(filterNs, "type"); a.setTextContent("subtree"); filter.setAttributeNode(a); document.appendChild(filter); - instanceIdToXmlStructure(path.getPathArguments(), filter); + return filter; + } + + private static AnyxmlNode buildFilterXmlNode(final Document document) { return Builders.anyXmlBuilder() - .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(filterQname)) + .withNodeIdentifier(NETCONF_FILTER_NODEID) .withValue(new DOMSource(document.getDocumentElement())) .build(); } private static void checkDataValidForPath(final YangInstanceIdentifier dataPath, final Element dataNode) { //if datapath is empty, consider dataNode to be a root node - if (dataPath.equals(YangInstanceIdentifier.EMPTY)) { + if (dataPath.isEmpty()) { return; } final XmlElement dataElement = XmlElement.fromDomElement(dataNode); - final YangInstanceIdentifier.PathArgument lastPathArgument = dataPath.getLastPathArgument(); + final PathArgument lastPathArgument = dataPath.getLastPathArgument(); final QName nodeType = lastPathArgument.getNodeType(); if (!nodeType.getNamespace().toString().equals(dataNode.getNamespaceURI()) || !nodeType.getLocalName().equals(dataElement.getName())) { throw new IllegalStateException( String.format("Can't write data '%s' to path %s", dataNode.getTagName(), dataPath)); } - if (lastPathArgument instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) { + if (lastPathArgument instanceof NodeIdentifierWithPredicates) { checkKeyValuesValidForPath(dataElement, lastPathArgument); } - } - private static void checkKeyValuesValidForPath(final XmlElement dataElement, - final YangInstanceIdentifier.PathArgument lastPathArgument) { - final YangInstanceIdentifier.NodeIdentifierWithPredicates keyedId = - (YangInstanceIdentifier.NodeIdentifierWithPredicates) lastPathArgument; - final Map keyValues = keyedId.getKeyValues(); - for (Entry entry : keyValues.entrySet()) { + private static void checkKeyValuesValidForPath(final XmlElement dataElement, final PathArgument lastPathArgument) { + final NodeIdentifierWithPredicates keyedId = (NodeIdentifierWithPredicates) lastPathArgument; + for (Entry entry : keyedId.entrySet()) { QName qualifiedName = entry.getKey(); final List key = dataElement.getChildElementsWithinNamespace(qualifiedName.getLocalName(), @@ -181,33 +199,24 @@ class SchemalessRpcStructureTransformer implements RpcStructureTransformer { } } - private static void setOperationAttribute(final Optional operation, final Document document, - final Element dataNode) { - final QName operationQname = NetconfMessageTransformUtil.NETCONF_OPERATION_QNAME; - final Attr operationAttribute = - document.createAttributeNS(operationQname.getNamespace().toString(), operationQname.getLocalName()); - operationAttribute.setTextContent(toOperationString(operation.get())); + private static void setOperationAttribute(final ModifyAction operation, final Document document, + final Element dataNode) { + final Attr operationAttribute = document.createAttributeNS(NETCONF_OPERATION_QNAME.getNamespace().toString(), + NETCONF_OPERATION_QNAME.getLocalName()); + operationAttribute.setTextContent(toOperationString(operation)); dataNode.setAttributeNode(operationAttribute); } - private static Element instanceIdToXmlStructure(final List pathArguments, - final Element data) { + private static Element instanceIdToXmlStructure(final List pathArguments, final Element data) { final Document doc = data.getOwnerDocument(); Element parent = data; - for (YangInstanceIdentifier.PathArgument pathArgument : pathArguments) { + for (PathArgument pathArgument : pathArguments) { final QName nodeType = pathArgument.getNodeType(); final Element element = doc.createElementNS(nodeType.getNamespace().toString(), nodeType.getLocalName()); parent.appendChild(element); //if path argument is list id, add also keys to resulting xml - if (pathArgument instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) { - YangInstanceIdentifier.NodeIdentifierWithPredicates listNode = - (YangInstanceIdentifier.NodeIdentifierWithPredicates) pathArgument; - for (Map.Entry key : listNode.getKeyValues().entrySet()) { - final Element keyElement = - doc.createElementNS(key.getKey().getNamespace().toString(), key.getKey().getLocalName()); - keyElement.setTextContent(key.getValue().toString()); - element.appendChild(keyElement); - } + if (pathArgument instanceof NodeIdentifierWithPredicates) { + appendListKeyNodes(element, (NodeIdentifierWithPredicates) pathArgument); } parent = element; } @@ -216,7 +225,7 @@ class SchemalessRpcStructureTransformer implements RpcStructureTransformer { private static List selectMatchingNodes(final Element domElement, final YangInstanceIdentifier path) { XmlElement element = XmlElement.fromDomElement(domElement); - for (YangInstanceIdentifier.PathArgument pathArgument : path.getPathArguments()) { + for (PathArgument pathArgument : path.getPathArguments()) { List childElements = element.getChildElements(pathArgument.getNodeType().getLocalName()); if (childElements.size() == 1) { element = childElements.get(0);