Switch EditConfig class to use the new XML parser from YANG tools.
Introduce EditOperationNormalizedNodeStreamWriter as a replacement
of the old XML parser extension EditOperationStrategyProvider which
has been used for tracking edit-config data tree operations defined
in the parsed XML source.
Remove EditOperationStrategyProvider as it is not needed anymore.
Change-Id: I737b134805120368a352568fde3f19517a9871df
Signed-off-by: Igor Foltin <igor.foltin@pantheon.tech>
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
+import java.io.StringReader;
import java.net.URI;
import java.net.URISyntaxException;
-import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.opendaylight.netconf.mdsal.connector.TransactionProvider;
import org.opendaylight.netconf.mdsal.connector.ops.DataTreeChangeTracker.DataTreeChange;
import org.opendaylight.netconf.util.mapping.AbstractSingletonNetconfOperation;
+import org.opendaylight.yangtools.util.xml.UntrustedXML;
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.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.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.codec.xml.XmlParserStream;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
final DataSchemaNode schemaNode = getSchemaNodeFromNamespace(ns, element).get();
final DataTreeChangeTracker changeTracker = new DataTreeChangeTracker(defaultAction);
- final DomToNormalizedNodeParserFactory.BuildingStrategyProvider editOperationStrategyProvider =
- new EditOperationStrategyProvider(changeTracker);
- parseIntoNormalizedNode(schemaNode, element, editOperationStrategyProvider);
+ parseIntoNormalizedNode(schemaNode, element, changeTracker);
executeOperations(changeTracker);
}
}
}
+ @SuppressWarnings("checkstyle:IllegalCatch")
private NormalizedNode<?, ?> parseIntoNormalizedNode(final DataSchemaNode schemaNode, final XmlElement element,
- final DomToNormalizedNodeParserFactory.BuildingStrategyProvider editOperationStrategyProvider) {
- if (schemaNode instanceof ContainerSchemaNode) {
- return DomToNormalizedNodeParserFactory.getInstance(DomUtils.defaultValueCodecProvider(),
- schemaContext.getCurrentContext(), editOperationStrategyProvider)
- .getContainerNodeParser()
- .parse(Collections.singletonList(element.getDomElement()), (ContainerSchemaNode) schemaNode);
- } else if (schemaNode instanceof ListSchemaNode) {
- return DomToNormalizedNodeParserFactory.getInstance(DomUtils.defaultValueCodecProvider(),
- schemaContext.getCurrentContext(), editOperationStrategyProvider)
- .getMapNodeParser()
- .parse(Collections.singletonList(element.getDomElement()), (ListSchemaNode) schemaNode);
- } else {
+ final DataTreeChangeTracker changeTracker) throws DocumentedException {
+ if (!(schemaNode instanceof ContainerSchemaNode) && !(schemaNode instanceof ListSchemaNode)) {
//this should never happen since edit-config on any other node type should not be possible nor makes sense
LOG.debug("DataNode from module is not ContainerSchemaNode nor ListSchemaNode, aborting..");
+ throw new UnsupportedOperationException("implement exception if parse fails");
}
- throw new UnsupportedOperationException("implement exception if parse fails");
+
+ final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
+ final NormalizedNodeStreamWriter writer = new EditOperationNormalizedNodeStreamWriter(resultHolder,
+ changeTracker);
+ final XmlParserStream xmlParser = XmlParserStream.create(writer, schemaContext.getCurrentContext(), schemaNode);
+ try {
+ xmlParser.parse(UntrustedXML.createXMLStreamReader(new StringReader(XmlUtil.toString(element))));
+ } catch (final Exception ex) {
+ throw new NetconfDocumentedException("Error parsing input: " + ex.getMessage(), ex, ErrorType.PROTOCOL,
+ ErrorTag.MALFORMED_MESSAGE, ErrorSeverity.ERROR);
+ }
+
+ return resultHolder.getResult();
}
private Optional<DataSchemaNode> getSchemaNodeFromNamespace(final String namespace, final XmlElement element)
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Map;
+import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.EditConfigInput;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.ModifyAction;
+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.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamAttributeWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
+
+final class EditOperationNormalizedNodeStreamWriter extends ImmutableNormalizedNodeStreamWriter
+ implements NormalizedNodeStreamAttributeWriter {
+ private static final QName OPERATION_ATTRIBUTE = QName.create(EditConfigInput.QNAME.getNamespace(), null,
+ XmlNetconfConstants.OPERATION_ATTR_KEY);
+
+ private final DataTreeChangeTracker dataTreeChangeTracker;
+
+ EditOperationNormalizedNodeStreamWriter(final NormalizedNodeResult result,
+ final DataTreeChangeTracker dataTreeChangeTracker) {
+ super(result);
+ this.dataTreeChangeTracker = dataTreeChangeTracker;
+ }
+
+ @Override
+ public void leafNode(final NodeIdentifier name, final Object value, final Map<QName, String> attributes) {
+ super.leafNode(name, value);
+
+ final String operation = attributes.get(OPERATION_ATTRIBUTE);
+ if (operation == null) {
+ return;
+ }
+
+ final ModifyAction action = ModifyAction.fromXmlValue(operation);
+ if (dataTreeChangeTracker.getDeleteOperationTracker() == 0
+ && dataTreeChangeTracker.getRemoveOperationTracker() == 0) {
+ if (!action.equals(dataTreeChangeTracker.peekAction())) {
+ final LeafNode<Object> node = ImmutableNodes.leafNode(name, value);
+ dataTreeChangeTracker.pushPath(name);
+ dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(node, action,
+ new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
+ getCurrent().removeChild(dataTreeChangeTracker.popPath());
+ }
+ }
+ }
+
+ @Override
+ public void startLeafSet(final NodeIdentifier name, final int childSizeHint) {
+ super.startLeafSet(name, childSizeHint);
+ dataTreeChangeTracker.pushPath(name);
+ }
+
+ @Override
+ public void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) {
+ super.startOrderedLeafSet(name, childSizeHint);
+ dataTreeChangeTracker.pushPath(name);
+ }
+
+ @Override
+ public void leafSetEntryNode(final QName name, final Object value, final Map<QName, String> attributes) {
+ super.leafSetEntryNode(name, value);
+ final String operation = attributes.get(OPERATION_ATTRIBUTE);
+ if (operation == null) {
+ return;
+ }
+
+ ModifyAction action = ModifyAction.fromXmlValue(operation);
+ if (dataTreeChangeTracker.getDeleteOperationTracker() == 0
+ && dataTreeChangeTracker.getRemoveOperationTracker() == 0) {
+ if (!action.equals(dataTreeChangeTracker.peekAction())) {
+ final LeafSetEntryNode<?> node = Builders.leafSetEntryBuilder().withNodeIdentifier(
+ new NodeWithValue(name, value)).withValue(value).build();
+ dataTreeChangeTracker.pushPath(node.getIdentifier());
+ dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(node, action,
+ new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
+ getCurrent().removeChild(dataTreeChangeTracker.popPath());
+ }
+ }
+ }
+
+ @Override
+ public void startContainerNode(final NodeIdentifier name, final int childSizeHint,
+ final Map<QName, String> attributes) {
+ super.startContainerNode(name, childSizeHint);
+ trackDataContainerNode(name, attributes);
+ }
+
+ @Override
+ public void startYangModeledAnyXmlNode(final NodeIdentifier name, final int childSizeHint,
+ final Map<QName, String> attributes) {
+ super.startYangModeledAnyXmlNode(name, childSizeHint);
+ trackDataContainerNode(name, attributes);
+ }
+
+ @Override
+ public void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) {
+ super.startUnkeyedList(name, childSizeHint);
+ dataTreeChangeTracker.pushPath(name);
+ }
+
+ @Override
+ public void startUnkeyedListItem(final NodeIdentifier name, final int childSizeHint,
+ final Map<QName, String> attributes) {
+ super.startUnkeyedListItem(name, childSizeHint);
+ trackDataContainerNode(name, attributes);
+ }
+
+ @Override
+ public void startMapNode(final NodeIdentifier name, final int childSizeHint) {
+ super.startMapNode(name, childSizeHint);
+ dataTreeChangeTracker.pushPath(name);
+ }
+
+ @Override
+ public void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) {
+ super.startOrderedMapNode(name, childSizeHint);
+ dataTreeChangeTracker.pushPath(name);
+ }
+
+ @Override
+ public void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint,
+ final Map<QName, String> attributes) {
+ super.startMapEntryNode(identifier, childSizeHint);
+ trackDataContainerNode(identifier, attributes);
+ }
+
+ @Override
+ public void startAugmentationNode(final AugmentationIdentifier identifier) {
+ super.startAugmentationNode(identifier);
+ trackMixinNode(identifier);
+ }
+
+ @Override
+ public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) {
+ super.startChoiceNode(name, childSizeHint);
+ trackMixinNode(name);
+ }
+
+ // for augments and choices
+ private void trackMixinNode(final PathArgument identifier) {
+ dataTreeChangeTracker.pushPath(identifier);
+ dataTreeChangeTracker.pushAction(dataTreeChangeTracker.peekAction() != null
+ ? dataTreeChangeTracker.peekAction() : dataTreeChangeTracker.getDefaultAction());
+ }
+
+ // for containers, (unkeyed) list entries and yang-modeled-anyxmls
+ private void trackDataContainerNode(final PathArgument identifier, final Map<QName, String> attributes) {
+ dataTreeChangeTracker.pushPath(identifier);
+ final String operation = attributes.get(OPERATION_ATTRIBUTE);
+ if (operation != null) {
+ dataTreeChangeTracker.pushAction(ModifyAction.fromXmlValue(operation));
+ } else {
+ dataTreeChangeTracker.pushAction(dataTreeChangeTracker.peekAction() != null
+ ? dataTreeChangeTracker.peekAction() : dataTreeChangeTracker.getDefaultAction());
+ }
+ }
+
+ @Override
+ @SuppressWarnings({"rawtypes","unchecked"})
+ public void endNode() {
+ final NormalizedNodeContainerBuilder finishedBuilder = getBuilders().peek();
+ final NormalizedNode<PathArgument, ?> product = finishedBuilder.build();
+ super.endNode();
+
+ // for augments, choices, containers, (unkeyed) list entries and yang-modeled-anyxmls
+ if (finishedBuilder instanceof DataContainerNodeBuilder) {
+ final ModifyAction currentAction = dataTreeChangeTracker.popAction();
+
+ //if we know that we are going to delete a parent node just complete the entire subtree
+ if (dataTreeChangeTracker.getDeleteOperationTracker() > 0
+ || dataTreeChangeTracker.getRemoveOperationTracker() > 0) {
+ dataTreeChangeTracker.popPath();
+ } else {
+ //if parent and current actions don't match create a DataTreeChange and add it to the change list
+ //don't add a new child to the parent node
+ if (!currentAction.equals(dataTreeChangeTracker.peekAction())) {
+ dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(product,
+ currentAction, new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
+ if (getCurrent() instanceof NormalizedNodeResultBuilder) {
+ dataTreeChangeTracker.popPath();
+ return;
+ }
+ getCurrent().removeChild(dataTreeChangeTracker.popPath());
+ } else {
+ dataTreeChangeTracker.popPath();
+ return;
+ }
+ }
+ }
+
+ // for (ordered) leaf-lists, (ordered) lists and unkeyed lists
+ if (finishedBuilder instanceof CollectionNodeBuilder) {
+ dataTreeChangeTracker.popPath();
+ }
+ }
+}
+++ /dev/null
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * 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;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Map;
-import javax.annotation.Nullable;
-import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.EditConfigInput;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.ModifyAction;
-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.YangInstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
-import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
-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.api.schema.OrderedMapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.AttributesBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ExtensibleParser;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
-
-class EditOperationStrategyProvider extends DomToNormalizedNodeParserFactory.BuildingStrategyProvider {
-
- private static final QName OPERATION_ATTRIBUTE = QName.create(EditConfigInput.QNAME.getNamespace(), null,
- XmlNetconfConstants.OPERATION_ATTR_KEY);
-
- private final DataTreeChangeTracker changeTracker;
-
- EditOperationStrategyProvider(final DataTreeChangeTracker changeTracker) {
- this.changeTracker = changeTracker;
- }
-
- @Override
- protected ExtensibleParser.BuildingStrategy<NodeIdentifier, LeafNode<?>> forLeaf() {
- return new NetconfOperationLeafStrategy(changeTracker);
- }
-
- @Override
- protected ExtensibleParser.BuildingStrategy<NodeIdentifier, ContainerNode> forContainer() {
- return new NetconfOperationContainerStrategy<>(changeTracker);
- }
-
- @Override
- protected ExtensibleParser.BuildingStrategy<NodeIdentifier, MapNode> forMap() {
- return new NetconfOperationCollectionStrategy<>(changeTracker);
- }
-
- @Override
- protected ExtensibleParser.BuildingStrategy<NodeWithValue, LeafSetEntryNode<?>> forLeafSetEntry() {
- return new NetconfOperationLeafSetEntryStrategy(changeTracker);
- }
-
- @Override
- protected ExtensibleParser.BuildingStrategy<NodeIdentifierWithPredicates, MapEntryNode> forMapEntry() {
- return new NetconfOperationContainerStrategy<>(changeTracker);
- }
-
- @Override
- protected ExtensibleParser.BuildingStrategy<NodeIdentifier, OrderedMapNode> forOrderedList() {
- return new NetconfOperationCollectionStrategy<>(changeTracker);
- }
-
- @Override
- protected ExtensibleParser.BuildingStrategy<NodeIdentifier, UnkeyedListEntryNode> forUnkeyedListEntry() {
- return new NetconfOperationContainerStrategy<>(changeTracker);
- }
-
- @Override
- protected ExtensibleParser.BuildingStrategy<NodeIdentifier, UnkeyedListNode> forUnkeyedList() {
- return new NetconfOperationCollectionStrategy<>(changeTracker);
- }
-
- @Override
- protected ExtensibleParser.BuildingStrategy<NodeIdentifier, ChoiceNode> forChoice() {
- return new NetconfOperationContainerStrategy<>(changeTracker);
- }
-
- @Override
- public ExtensibleParser.BuildingStrategy<AugmentationIdentifier, AugmentationNode> forAugmentation() {
- return new NetconfOperationContainerStrategy<>(changeTracker);
- }
-
- private static class NetconfOperationCollectionStrategy<N extends NormalizedNode<NodeIdentifier, ?>>
- implements ExtensibleParser.BuildingStrategy<NodeIdentifier, N> {
- private final DataTreeChangeTracker changeTracker;
-
- NetconfOperationCollectionStrategy(final DataTreeChangeTracker changeTracker) {
- this.changeTracker = changeTracker;
- }
-
- @Nullable
- @Override
- public N build(final NormalizedNodeBuilder<NodeIdentifier, ?, N> builder) {
- changeTracker.popPath();
- return builder.build();
- }
-
- @Override
- public void prepareAttributes(
- final Map<QName, String> attributes,
- final NormalizedNodeBuilder<NodeIdentifier, ?, N> containerBuilder) {
- changeTracker.pushPath(containerBuilder.build().getIdentifier());
- }
- }
-
- public static final class NetconfOperationLeafStrategy
- implements ExtensibleParser.BuildingStrategy<NodeIdentifier, LeafNode<?>> {
-
- private final DataTreeChangeTracker dataTreeChangeTracker;
-
- NetconfOperationLeafStrategy(final DataTreeChangeTracker dataTreeChangeTracker) {
- this.dataTreeChangeTracker = dataTreeChangeTracker;
- }
-
- @Nullable
- @Override
- public LeafNode<?> build(
- final NormalizedNodeBuilder<NodeIdentifier, ?, LeafNode<?>> builder) {
- LeafNode<?> node = builder.build();
- String operation = (String) node.getAttributeValue(OPERATION_ATTRIBUTE);
- if (operation == null) {
- return node;
- }
-
- if (builder instanceof AttributesBuilder<?>) {
- ((AttributesBuilder<?>) builder).withAttributes(Collections.<QName, String>emptyMap());
- }
-
- node = builder.build();
-
- ModifyAction action = ModifyAction.fromXmlValue(operation);
- if (dataTreeChangeTracker.getDeleteOperationTracker() > 0
- || dataTreeChangeTracker .getRemoveOperationTracker() > 0) {
- return node;
- }
-
- if (action.equals(dataTreeChangeTracker.peekAction())) {
- return node;
- }
-
- dataTreeChangeTracker.pushPath(node.getIdentifier());
- dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(node, action,
- new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
- dataTreeChangeTracker.popPath();
- return null;
- }
-
- @Override
- public void prepareAttributes(
- final Map<QName, String> attributes,
- final NormalizedNodeBuilder<NodeIdentifier, ?, LeafNode<?>> containerBuilder) {
- // Noop
- }
- }
-
- public static final class NetconfOperationLeafSetEntryStrategy
- implements ExtensibleParser.BuildingStrategy<NodeWithValue, LeafSetEntryNode<?>> {
-
- private final DataTreeChangeTracker dataTreeChangeTracker;
-
- NetconfOperationLeafSetEntryStrategy(final DataTreeChangeTracker dataTreeChangeTracker) {
- this.dataTreeChangeTracker = dataTreeChangeTracker;
- }
-
- @Nullable
- @Override
- public LeafSetEntryNode<?> build(final NormalizedNodeBuilder<NodeWithValue, ?, LeafSetEntryNode<?>> builder) {
- LeafSetEntryNode<?> node = builder.build();
- String operation = (String) node.getAttributeValue(OPERATION_ATTRIBUTE);
- if (operation == null) {
- return node;
- }
-
- if (builder instanceof AttributesBuilder<?>) {
- ((AttributesBuilder<?>) builder).withAttributes(Collections.<QName, String>emptyMap());
- }
-
- node = builder.build();
-
- ModifyAction action = ModifyAction.fromXmlValue(operation);
- if (dataTreeChangeTracker.getDeleteOperationTracker() > 0
- || dataTreeChangeTracker.getRemoveOperationTracker() > 0) {
- return node;
- }
-
- if (action.equals(dataTreeChangeTracker.peekAction())) {
- return node;
- }
-
- dataTreeChangeTracker.pushPath(node.getIdentifier());
- dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(node, action,
- new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
- dataTreeChangeTracker.popPath();
- return null;
- }
-
- @Override
- public void prepareAttributes(
- final Map<QName, String> attributes,
- final NormalizedNodeBuilder<NodeWithValue, ?, LeafSetEntryNode<?>> containerBuilder) {
- }
- }
-
- public static final class NetconfOperationContainerStrategy<P extends PathArgument, N
- extends DataContainerNode<P>> implements ExtensibleParser.BuildingStrategy<P, N> {
-
- private final DataTreeChangeTracker dataTreeChangeTracker;
-
- NetconfOperationContainerStrategy(final DataTreeChangeTracker dataTreeChangeTracker) {
- this.dataTreeChangeTracker = dataTreeChangeTracker;
- }
-
- @Nullable
- @Override
- public N build(final NormalizedNodeBuilder<P, ?, N> builder) {
- if (builder instanceof AttributesBuilder<?>) {
- ((AttributesBuilder<?>) builder).withAttributes(Collections.<QName, String>emptyMap());
- }
-
- final N node = builder.build();
- final ModifyAction currentAction = dataTreeChangeTracker.popAction();
-
- //if we know that we are going to delete a parent node just complete the entire subtree
- if (dataTreeChangeTracker.getDeleteOperationTracker() > 0
- || dataTreeChangeTracker.getRemoveOperationTracker() > 0) {
- dataTreeChangeTracker.popPath();
- return node;
- }
-
- if (currentAction.equals(dataTreeChangeTracker.peekAction())) {
- dataTreeChangeTracker.popPath();
- return node;
- }
-
- //if parent and current actions dont match create a DataTreeChange and add it to the change list
- //dont add a new child to the parent node
- dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(node,
- currentAction, new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
- dataTreeChangeTracker.popPath();
- return null;
- }
-
- @Override
- public void prepareAttributes(final Map<QName, String> attributes,
- final NormalizedNodeBuilder<P, ?, N> containerBuilder) {
- dataTreeChangeTracker.pushPath(containerBuilder.build().getIdentifier());
- final String operation = attributes.get(OPERATION_ATTRIBUTE);
- if (operation != null) {
- dataTreeChangeTracker.pushAction(ModifyAction.fromXmlValue(operation));
- } else {
- dataTreeChangeTracker.pushAction(dataTreeChangeTracker.peekAction() != null
- ? dataTreeChangeTracker.peekAction() : dataTreeChangeTracker.getDefaultAction());
- }
- }
- }
-}