* 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.netconf.mdsal.connector.ops;
+// FIXME: document, rename to LegacyDatastore (as per NMDA), add XML interaction values
public enum Datastore {
candidate, running
}
*/
package org.opendaylight.netconf.mdsal.connector.ops;
-import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
import java.util.List;
-import java.util.ListIterator;
import java.util.concurrent.ExecutionException;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteOperations;
import org.opendaylight.netconf.api.DocumentedException;
import org.opendaylight.netconf.api.ModifyAction;
import org.opendaylight.netconf.api.xml.XmlElement;
import org.opendaylight.yangtools.yang.common.ErrorTag;
import org.opendaylight.yangtools.yang.common.ErrorType;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
public final class EditConfig extends AbstractEdit {
-
private static final Logger LOG = LoggerFactory.getLogger(EditConfig.class);
-
private static final String OPERATION_NAME = "edit-config";
- private static final String DEFAULT_OPERATION_KEY = "default-operation";
+ private static final String DEFAULT_OPERATION = "default-operation";
+
private final TransactionProvider transactionProvider;
public EditConfig(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext,
final TransactionProvider transactionProvider) {
super(netconfSessionIdForReporting, schemaContext);
- this.transactionProvider = transactionProvider;
+ this.transactionProvider = requireNonNull(transactionProvider);
+ }
+
+ @Override
+ protected String getOperationName() {
+ return OPERATION_NAME;
}
@Override
protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement)
throws DocumentedException {
- final XmlElement targetElement = extractTargetElement(operationElement, OPERATION_NAME);
- final Datastore targetDatastore = Datastore.valueOf(targetElement.getName());
- if (targetDatastore == Datastore.running) {
+ if (Datastore.valueOf(extractTargetElement(operationElement, OPERATION_NAME).getName()) == Datastore.running) {
throw new DocumentedException("edit-config on running datastore is not supported",
ErrorType.PROTOCOL, ErrorTag.OPERATION_NOT_SUPPORTED, ErrorSeverity.ERROR);
}
- final ModifyAction defaultAction = getDefaultOperation(operationElement);
-
- final XmlElement configElement = getConfigElement(operationElement);
-
- for (final XmlElement element : configElement.getChildElements()) {
- final SplittingNormalizedNodeMetadataStreamWriter writer = new SplittingNormalizedNodeMetadataStreamWriter(
- defaultAction);
+ final var defaultAction = getDefaultOperation(operationElement);
+ for (var element : getConfigElement(operationElement).getChildElements()) {
+ final var writer = new SplittingNormalizedNodeMetadataStreamWriter(defaultAction);
parseIntoNormalizedNode(getSchemaNodeFromNamespace(element.getNamespace(), element), element, writer);
executeOperations(writer.getDataTreeChanges());
}
}
private void executeOperations(final List<DataTreeChange> changes) throws DocumentedException {
- final DOMDataTreeReadWriteTransaction rwTx = transactionProvider.getOrCreateTransaction();
- final ListIterator<DataTreeChange> iterator = changes.listIterator(changes.size());
-
+ final var rwTx = transactionProvider.getOrCreateTransaction();
+ final var iterator = changes.listIterator(changes.size());
while (iterator.hasPrevious()) {
- final DataTreeChange dtc = iterator.previous();
- executeChange(rwTx, dtc);
+ executeChange(rwTx, iterator.previous());
}
}
+ // FIXME: we should have proper ReadWriteOperations
private void executeChange(final DOMDataTreeReadWriteTransaction rwtx, final DataTreeChange change)
throws DocumentedException {
- final YangInstanceIdentifier path = change.getPath();
- final NormalizedNode changeData = change.getChangeRoot();
+ final var path = change.getPath();
+ final var changeData = change.getChangeRoot();
switch (change.getAction()) {
case NONE:
return;
break;
case CREATE:
try {
+ // FIXME: synchronous operation: can we get a rwTx.create() with a per-operation result instead?
if (rwtx.exists(LogicalDatastoreType.CONFIGURATION, path).get()) {
throw new DocumentedException("Data already exists, cannot execute CREATE operation",
ErrorType.PROTOCOL, ErrorTag.DATA_EXISTS, ErrorSeverity.ERROR);
break;
case DELETE:
try {
+ // FIXME: synchronous operation: can we get a rwTx.delete() semantics with a per-operation result
+ // instead?
if (!rwtx.exists(LogicalDatastoreType.CONFIGURATION, path).get()) {
throw new DocumentedException("Data is missing, cannot execute DELETE operation",
ErrorType.PROTOCOL, ErrorTag.DATA_MISSING, ErrorSeverity.ERROR);
}
}
- private void mergeParentMixin(final DOMDataTreeReadWriteTransaction rwtx, final YangInstanceIdentifier path,
+ private void mergeParentMixin(final DOMDataTreeWriteOperations rwtx, final YangInstanceIdentifier path,
final NormalizedNode change) {
- final YangInstanceIdentifier parentNodeYid = path.getParent();
+ final var parentNodeYid = path.getParent();
if (change instanceof MapEntryNode) {
- final DataSchemaNode schemaNode = DataSchemaContextTree.from(schemaContext.getCurrentContext())
+ final var dataSchemaNode = DataSchemaContextTree.from(schemaContext.getCurrentContext())
.findChild(parentNodeYid)
.orElseThrow(() -> new IllegalStateException("Cannot find schema for " + parentNodeYid))
.getDataSchemaNode();
// we should have the schema node that points to the parent list now, enforce it
- checkState(schemaNode instanceof ListSchemaNode, "Schema node is not pointing to a list.");
-
- //merge empty ordered or unordered map
- if (((ListSchemaNode) schemaNode).isUserOrdered()) {
- final MapNode mixinNode = Builders.orderedMapBuilder()
- .withNodeIdentifier(
- new YangInstanceIdentifier.NodeIdentifier(
- parentNodeYid.getLastPathArgument().getNodeType()))
- .build();
- rwtx.merge(LogicalDatastoreType.CONFIGURATION, parentNodeYid, mixinNode);
- return;
+ if (!(dataSchemaNode instanceof ListSchemaNode listSchemaNode)) {
+ throw new IllegalStateException("Schema node is not pointing to a list");
}
- final MapNode mixinNode = Builders.mapBuilder()
- .withNodeIdentifier(
- new YangInstanceIdentifier.NodeIdentifier(
- parentNodeYid.getLastPathArgument().getNodeType()))
- .build();
- rwtx.merge(LogicalDatastoreType.CONFIGURATION, parentNodeYid, mixinNode);
- } else if (parentNodeYid.getLastPathArgument() instanceof YangInstanceIdentifier.AugmentationIdentifier) {
+ // merge empty ordered or unordered map
+ rwtx.merge(LogicalDatastoreType.CONFIGURATION, parentNodeYid,
+ (listSchemaNode.isUserOrdered() ? Builders.orderedMapBuilder() : Builders.mapBuilder())
+ .withNodeIdentifier(new NodeIdentifier(parentNodeYid.getLastPathArgument().getNodeType()))
+ .build());
+ } else if (parentNodeYid.getLastPathArgument() instanceof AugmentationIdentifier augId) {
// merge empty augmentation node
- final YangInstanceIdentifier.AugmentationIdentifier augmentationYid =
- (YangInstanceIdentifier.AugmentationIdentifier) parentNodeYid.getLastPathArgument();
- final AugmentationNode augmentationNode = Builders.augmentationBuilder()
- .withNodeIdentifier(augmentationYid).build();
- rwtx.merge(LogicalDatastoreType.CONFIGURATION, parentNodeYid, augmentationNode);
+ rwtx.merge(LogicalDatastoreType.CONFIGURATION, parentNodeYid, Builders.augmentationBuilder()
+ .withNodeIdentifier(augId)
+ .build());
}
}
private static ModifyAction getDefaultOperation(final XmlElement operationElement) throws DocumentedException {
- final NodeList elementsByTagName = getElementsByTagName(operationElement, DEFAULT_OPERATION_KEY);
- if (elementsByTagName.getLength() == 0) {
- return ModifyAction.MERGE;
- } else if (elementsByTagName.getLength() > 1) {
- throw new DocumentedException("Multiple " + DEFAULT_OPERATION_KEY + " elements", ErrorType.RPC,
+ final var elementsByTagName = getElementsByTagName(operationElement, DEFAULT_OPERATION);
+ return switch (elementsByTagName.getLength()) {
+ case 0 -> ModifyAction.MERGE;
+ case 1 -> ModifyAction.ofXmlValue(elementsByTagName.item(0).getTextContent());
+ default -> throw new DocumentedException("Multiple " + DEFAULT_OPERATION + " elements", ErrorType.RPC,
ErrorTag.UNKNOWN_ATTRIBUTE, ErrorSeverity.ERROR);
- } else {
- return ModifyAction.fromXmlValue(elementsByTagName.item(0).getTextContent());
- }
-
- }
-
- @Override
- protected String getOperationName() {
- return OPERATION_NAME;
+ };
}
}
@Override
public void metadata(final ImmutableMap<QName, Object> metadata) throws IOException {
- final Object operation = metadata.get(OPERATION_ATTRIBUTE);
- if (operation != null) {
- checkState(operation instanceof String, "Unexpected operation attribute value %s", operation);
- final ModifyAction newAction = ModifyAction.fromXmlValue((String) operation);
- currentAction = newAction;
+ final var operation = metadata.get(OPERATION_ATTRIBUTE);
+ if (operation instanceof String str) {
+ currentAction = ModifyAction.ofXmlValue(str);
+ } else if (operation != null) {
+ throw new IllegalStateException("Unexpected operation attribute value " + operation);
}
-
writer.metadata(filterMeta(metadata));
}
@Override
public void endNode() throws IOException {
- final ModifyAction prevAction = actions.peek();
+ final var prevAction = actions.peek();
if (prevAction != null) {
// We only split out a builder if we a changing action relative to parent and we are not inside
// a remove/delete operation
*/
package org.opendaylight.netconf.api;
-import java.util.Arrays;
+import static java.util.Objects.requireNonNull;
+import org.eclipse.jdt.annotation.NonNull;
+
+/**
+ * NETCONF modification actions, as allowed for in {@code operation} and {@code default-operation} attributes of
+ * {@code <edit-config>} operation, as defined in
+ * <a href="https://www.rfc-editor.org/rfc/rfc6241#section-7.2">RFC6241 section 7.2</a>.
+ *
+ * <p>
+ * This concept is uncharacteristically bound to two separate semantics, but for a good reason: at the end of the day we
+ * want to know what the effective operation is.
+ */
public enum ModifyAction {
- MERGE(true), REPLACE(true), CREATE(false), DELETE(false), REMOVE(false), NONE(true, false);
-
- public static ModifyAction fromXmlValue(final 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()));
- }
- }
+ // operation and default-operation
+ MERGE("merge", true, true),
+ REPLACE("replace", true, true),
+ // operation only
+ CREATE("create", true, false),
+ DELETE("delete", true, false),
+ REMOVE("remove", true, false),
+
+ // default-operation-only
+ NONE("none", false, true);
+
+ private final @NonNull String xmlValue;
+ private final boolean isDefaultOperation;
+ private final boolean isOperation;
- private final boolean asDefaultPermitted;
- private final boolean onElementPermitted;
+ ModifyAction(final String xmlValue, final boolean isOperation, final boolean isDefaultOperation) {
+ this.xmlValue = requireNonNull(xmlValue);
+ this.isDefaultOperation = isDefaultOperation;
+ this.isOperation = isOperation;
+ }
- ModifyAction(final boolean asDefaultPermitted, final boolean onElementPermitted) {
- this.asDefaultPermitted = asDefaultPermitted;
- this.onElementPermitted = onElementPermitted;
+ /**
+ * Return the {@link ModifyAction} corresponding to a {@link #xmlValue}.
+ *
+ * @param xmlValue XML attribute or element value
+ * @return A {@link ModifyAction}
+ * @throws NullPointerException if {@code xmlValue} is {@code null}
+ * @throws IllegalArgumentException if {@code xmlValue} is not recognized
+ */
+ public static @NonNull ModifyAction ofXmlValue(final String xmlValue) {
+ return switch (xmlValue) {
+ case "merge" -> MERGE;
+ case "replace" -> REPLACE;
+ case "remove" -> REMOVE;
+ case "delete" -> DELETE;
+ case "create" -> CREATE;
+ case "none" -> NONE;
+ default -> throw new IllegalArgumentException("Unknown operation " + xmlValue);
+ };
}
- ModifyAction(final boolean asDefaultPermitted) {
- this(asDefaultPermitted, true);
+ /**
+ * Return an XML string literal corresponding to this {@link ModifyAction}.
+ *
+ * @return An XML string literal
+ */
+ public @NonNull String xmlValue() {
+ return xmlValue;
}
/**
* Check if this operation is a candidate for {@code default-operation} argument.
*
- * @return True if this operation can be used as {@code default-operation}.
+ * @return {@code true} if this operation can be used as {@code default-operation}, {@code false} otherwise.
+ * @deprecated Use {@link #isDefaultOperation()} instead
*/
+ @Deprecated(since = "5.0.0", forRemoval = true)
public boolean isAsDefaultPermitted() {
- return asDefaultPermitted;
+ return isDefaultOperation;
+ }
+
+ /**
+ * Check if this operation is a candidate for {@code default-operation} argument.
+ *
+ * @return {@code true} if this operation can be used as {@code default-operation}, {@code false} otherwise.
+ */
+ public boolean isDefaultOperation() {
+ return isDefaultOperation;
}
+ @Deprecated(since = "5.0.0", forRemoval = true)
public boolean isOnElementPermitted() {
- return onElementPermitted;
+ return isOperation;
+ }
+
+ /**
+ * Check if this operation is a candidate for {@code operation} attribute.
+ *
+ * @return {@code true} if this operation can be used as {@code operation}, {@code false} otherwise.
+ */
+ public boolean isOperation() {
+ return isOperation;
}
}
import static org.opendaylight.netconf.util.NetconfUtil.appendListKeyNodes;
import static org.opendaylight.netconf.util.NetconfUtil.writeSchemalessFilter;
-import com.google.common.base.Preconditions;
-import java.util.Collections;
import java.util.List;
-import java.util.Locale;
-import java.util.Map.Entry;
import java.util.Optional;
import javax.xml.transform.dom.DOMSource;
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.YangInstanceIdentifier;
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.DataContainerChild;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
-import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@Override
public Optional<NormalizedNode> selectFromDataStructure(final DataContainerChild data,
final YangInstanceIdentifier path) {
- Preconditions.checkArgument(data instanceof DOMSourceAnyxmlNode);
- final List<XmlElement> xmlElements = selectMatchingNodes(
- getSourceElement(((DOMSourceAnyxmlNode)data).body()), path);
- final Document result = XmlUtil.newDocument();
- final Element dataElement =
- result.createElementNS(NETCONF_DATA_QNAME.getNamespace().toString(), NETCONF_DATA_QNAME.getLocalName());
+ if (!(data instanceof DOMSourceAnyxmlNode anyxml)) {
+ throw new IllegalArgumentException("Unexpected data " + data.prettyTree());
+ }
+
+ final var result = XmlUtil.newDocument();
+ final var dataElement = result.createElementNS(NETCONF_DATA_QNAME.getNamespace().toString(),
+ NETCONF_DATA_QNAME.getLocalName());
result.appendChild(dataElement);
- for (XmlElement xmlElement : xmlElements) {
+ for (var xmlElement : selectMatchingNodes(getSourceElement(anyxml.body()), path)) {
dataElement.appendChild(result.importNode(xmlElement.getDomElement(), true));
}
- final DOMSourceAnyxmlNode resultAnyxml = Builders.anyXmlBuilder()
- .withNodeIdentifier(NETCONF_DATA_NODEID)
- .withValue(new DOMSource(result))
- .build();
- return Optional.of(resultAnyxml);
+ return Optional.of(Builders.anyXmlBuilder()
+ .withNodeIdentifier(NETCONF_DATA_NODEID)
+ .withValue(new DOMSource(result))
+ .build());
}
/**
@Override
public DOMSourceAnyxmlNode createEditConfigStructure(final Optional<NormalizedNode> data,
final YangInstanceIdentifier dataPath, final Optional<ModifyAction> operation) {
- Preconditions.checkArgument(data.isPresent());
- Preconditions.checkArgument(data.get() instanceof DOMSourceAnyxmlNode);
+ final var dataValue = data.orElseThrow();
+ if (!(dataValue instanceof DOMSourceAnyxmlNode anxmlData)) {
+ throw new IllegalArgumentException("Unexpected data " + dataValue.prettyTree());
+ }
- final DOMSourceAnyxmlNode anxmlData = (DOMSourceAnyxmlNode) data.get();
- final Document document = XmlUtil.newDocument();
- final Element dataNode = (Element) document.importNode(getSourceElement(anxmlData.body()), true);
+ final var document = XmlUtil.newDocument();
+ final var dataNode = (Element) document.importNode(getSourceElement(anxmlData.body()), true);
checkDataValidForPath(dataPath, dataNode);
- final Element configElement = document.createElementNS(NETCONF_CONFIG_QNAME.getNamespace().toString(),
+ final var configElement = document.createElementNS(NETCONF_CONFIG_QNAME.getNamespace().toString(),
NETCONF_CONFIG_QNAME.getLocalName());
document.appendChild(configElement);
parentXmlStructure = dataNode;
configElement.appendChild(parentXmlStructure);
} else {
- final List<PathArgument> pathArguments = dataPath.getPathArguments();
- //last will be appended later
- final List<PathArgument> pathWithoutLast = pathArguments.subList(0, pathArguments.size() - 1);
- parentXmlStructure = instanceIdToXmlStructure(pathWithoutLast, configElement);
+ final var pathArguments = dataPath.getPathArguments();
+ // last will be appended later
+ parentXmlStructure = instanceIdToXmlStructure(pathArguments.subList(0, pathArguments.size() - 1),
+ configElement);
}
operation.ifPresent(modifyAction -> setOperationAttribute(modifyAction, document, dataNode));
//append data
parentXmlStructure.appendChild(document.importNode(dataNode, true));
- return Builders.anyXmlBuilder().withNodeIdentifier(NETCONF_CONFIG_NODEID)
- .withValue(new DOMSource(document.getDocumentElement()))
- .build();
+ return Builders.anyXmlBuilder()
+ .withNodeIdentifier(NETCONF_CONFIG_NODEID)
+ .withValue(new DOMSource(document.getDocumentElement()))
+ .build();
}
/**
*/
@Override
public AnyxmlNode<?> toFilterStructure(final YangInstanceIdentifier path) {
- final Document document = XmlUtil.newDocument();
- final Element filterElement = prepareFilterElement(document);
- instanceIdToXmlStructure(path.getPathArguments(), filterElement);
+ final var document = XmlUtil.newDocument();
+ instanceIdToXmlStructure(path.getPathArguments(), prepareFilterElement(document));
return buildFilterXmlNode(document);
}
@Override
public AnyxmlNode<?> toFilterStructure(final List<FieldsFilter> fieldsFilters) {
- final Document document = XmlUtil.newDocument();
- final Element filterElement = prepareFilterElement(document);
- for (final FieldsFilter filter : fieldsFilters) {
+ final var document = XmlUtil.newDocument();
+ final var filterElement = prepareFilterElement(document);
+ for (var 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);
+ // FIXME: use a constant
+ final var filterNs = NETCONF_FILTER_QNAME.getNamespace().toString();
+ final var filter = document.createElementNS(filterNs, NETCONF_FILTER_QNAME.getLocalName());
+ final var attr = document.createAttributeNS(filterNs, "type");
+ attr.setTextContent("subtree");
+ filter.setAttributeNode(attr);
document.appendChild(filter);
return filter;
}
private static AnyxmlNode<?> buildFilterXmlNode(final Document document) {
return Builders.anyXmlBuilder()
- .withNodeIdentifier(NETCONF_FILTER_NODEID)
- .withValue(new DOMSource(document.getDocumentElement()))
- .build();
+ .withNodeIdentifier(NETCONF_FILTER_NODEID)
+ .withValue(new DOMSource(document.getDocumentElement()))
+ .build();
}
private static void checkDataValidForPath(final YangInstanceIdentifier dataPath, final Element dataNode) {
if (dataPath.isEmpty()) {
return;
}
- final XmlElement dataElement = XmlElement.fromDomElement(dataNode);
- final PathArgument lastPathArgument = dataPath.getLastPathArgument();
- final QName nodeType = lastPathArgument.getNodeType();
+ final var dataElement = XmlElement.fromDomElement(dataNode);
+ final var lastPathArgument = dataPath.getLastPathArgument();
+ final var nodeType = lastPathArgument.getNodeType();
if (!nodeType.getNamespace().toString().equals(dataNode.getNamespaceURI())
|| !nodeType.getLocalName().equals(dataElement.getName())) {
throw new IllegalStateException(
}
private static void checkKeyValuesValidForPath(final XmlElement dataElement, final PathArgument lastPathArgument) {
- final NodeIdentifierWithPredicates keyedId = (NodeIdentifierWithPredicates) lastPathArgument;
- for (Entry<QName, Object> entry : keyedId.entrySet()) {
- QName qualifiedName = entry.getKey();
- final List<XmlElement> key =
- dataElement.getChildElementsWithinNamespace(qualifiedName.getLocalName(),
- qualifiedName.getNamespace().toString());
+ for (var entry : ((NodeIdentifierWithPredicates) lastPathArgument).entrySet()) {
+ final var qname = entry.getKey();
+ final var key = dataElement.getChildElementsWithinNamespace(qname.getLocalName(),
+ qname.getNamespace().toString());
if (key.isEmpty()) {
throw new IllegalStateException("No key present in xml");
}
}
private static void setOperationAttribute(final ModifyAction operation, final Document document,
- final Element dataNode) {
- final Attr operationAttribute = document.createAttributeNS(NETCONF_OPERATION_QNAME.getNamespace().toString(),
+ final Element dataNode) {
+ final var operationAttribute = document.createAttributeNS(NETCONF_OPERATION_QNAME.getNamespace().toString(),
NETCONF_OPERATION_QNAME.getLocalName());
- operationAttribute.setTextContent(toOperationString(operation));
+ operationAttribute.setTextContent(operation.xmlValue());
dataNode.setAttributeNode(operationAttribute);
}
private static Element instanceIdToXmlStructure(final List<PathArgument> pathArguments, final Element data) {
- final Document doc = data.getOwnerDocument();
- Element parent = data;
- for (PathArgument pathArgument : pathArguments) {
- final QName nodeType = pathArgument.getNodeType();
- final Element element = doc.createElementNS(nodeType.getNamespace().toString(), nodeType.getLocalName());
+ final var doc = data.getOwnerDocument();
+ var parent = data;
+ for (var pathArgument : pathArguments) {
+ final var nodeType = pathArgument.getNodeType();
+ final var 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 NodeIdentifierWithPredicates) {
- appendListKeyNodes(element, (NodeIdentifierWithPredicates) pathArgument);
+ if (pathArgument instanceof NodeIdentifierWithPredicates nip) {
+ appendListKeyNodes(element, nip);
}
parent = element;
}
}
private static List<XmlElement> selectMatchingNodes(final Element domElement, final YangInstanceIdentifier path) {
- XmlElement element = XmlElement.fromDomElement(domElement);
- for (PathArgument pathArgument : path.getPathArguments()) {
- List<XmlElement> childElements = element.getChildElements(pathArgument.getNodeType().getLocalName());
+ var element = XmlElement.fromDomElement(domElement);
+ for (var pathArgument : path.getPathArguments()) {
+ var childElements = element.getChildElements(pathArgument.getNodeType().getLocalName());
if (childElements.size() == 1) {
element = childElements.get(0);
} else {
return childElements;
}
}
- return Collections.singletonList(element);
- }
-
- private static String toOperationString(final ModifyAction operation) {
- return operation.name().toLowerCase(Locale.ROOT);
+ return List.of(element);
}
private static Element getSourceElement(final DOMSource source) {
- final Node node = source.getNode();
- switch (node.getNodeType()) {
- case Node.DOCUMENT_NODE:
- return ((Document)node).getDocumentElement();
- case Node.ELEMENT_NODE:
- return (Element) node;
- default:
- throw new IllegalStateException("DOMSource node must be document or element.");
- }
+ final var node = source.getNode();
+ return switch (node.getNodeType()) {
+ case Node.DOCUMENT_NODE -> ((Document) node).getDocumentElement();
+ case Node.ELEMENT_NODE -> (Element) node;
+ default -> throw new IllegalStateException("DOMSource node must be document or element.");
+ };
}
-
}