2 * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.netconf.mdsal.connector.ops;
11 import java.util.ArrayList;
13 import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
14 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.EditConfigInput;
15 import org.opendaylight.yangtools.yang.common.QName;
16 import org.opendaylight.yangtools.yang.data.api.ModifyAction;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
22 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
23 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
24 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
25 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamAttributeWriter;
26 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
27 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
28 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
29 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
30 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
31 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
32 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
34 final class EditOperationNormalizedNodeStreamWriter extends ImmutableNormalizedNodeStreamWriter
35 implements NormalizedNodeStreamAttributeWriter {
36 private static final QName OPERATION_ATTRIBUTE = QName.create(EditConfigInput.QNAME.getNamespace(),
37 XmlNetconfConstants.OPERATION_ATTR_KEY);
39 private final DataTreeChangeTracker dataTreeChangeTracker;
41 EditOperationNormalizedNodeStreamWriter(final NormalizedNodeResult result,
42 final DataTreeChangeTracker dataTreeChangeTracker) {
44 this.dataTreeChangeTracker = dataTreeChangeTracker;
48 public void leafNode(final NodeIdentifier name, final Object value, final Map<QName, String> attributes) {
49 super.leafNode(name, value);
51 final String operation = attributes.get(OPERATION_ATTRIBUTE);
52 if (operation == null) {
56 final ModifyAction action = ModifyAction.fromXmlValue(operation);
57 if (dataTreeChangeTracker.getDeleteOperationTracker() == 0
58 && dataTreeChangeTracker.getRemoveOperationTracker() == 0) {
59 if (!action.equals(dataTreeChangeTracker.peekAction())) {
60 final LeafNode<Object> node = ImmutableNodes.leafNode(name, value);
61 dataTreeChangeTracker.pushPath(name);
62 dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(node, action,
63 new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
64 getCurrent().removeChild(dataTreeChangeTracker.popPath());
70 public void startLeafSet(final NodeIdentifier name, final int childSizeHint) {
71 super.startLeafSet(name, childSizeHint);
72 dataTreeChangeTracker.pushPath(name);
76 public void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) {
77 super.startOrderedLeafSet(name, childSizeHint);
78 dataTreeChangeTracker.pushPath(name);
82 public void leafSetEntryNode(final QName name, final Object value, final Map<QName, String> attributes) {
83 super.leafSetEntryNode(name, value);
84 final String operation = attributes.get(OPERATION_ATTRIBUTE);
85 if (operation == null) {
89 ModifyAction action = ModifyAction.fromXmlValue(operation);
90 if (dataTreeChangeTracker.getDeleteOperationTracker() == 0
91 && dataTreeChangeTracker.getRemoveOperationTracker() == 0) {
92 if (!action.equals(dataTreeChangeTracker.peekAction())) {
93 final LeafSetEntryNode<?> node = Builders.leafSetEntryBuilder().withNodeIdentifier(
94 new NodeWithValue(name, value)).withValue(value).build();
95 dataTreeChangeTracker.pushPath(node.getIdentifier());
96 dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(node, action,
97 new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
98 getCurrent().removeChild(dataTreeChangeTracker.popPath());
104 public void startContainerNode(final NodeIdentifier name, final int childSizeHint,
105 final Map<QName, String> attributes) {
106 super.startContainerNode(name, childSizeHint);
107 trackDataContainerNode(name, attributes);
111 public void startYangModeledAnyXmlNode(final NodeIdentifier name, final int childSizeHint,
112 final Map<QName, String> attributes) {
113 super.startYangModeledAnyXmlNode(name, childSizeHint);
114 trackDataContainerNode(name, attributes);
118 public void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) {
119 super.startUnkeyedList(name, childSizeHint);
120 dataTreeChangeTracker.pushPath(name);
124 public void startUnkeyedListItem(final NodeIdentifier name, final int childSizeHint,
125 final Map<QName, String> attributes) {
126 super.startUnkeyedListItem(name, childSizeHint);
127 trackDataContainerNode(name, attributes);
131 public void startMapNode(final NodeIdentifier name, final int childSizeHint) {
132 super.startMapNode(name, childSizeHint);
133 dataTreeChangeTracker.pushPath(name);
137 public void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) {
138 super.startOrderedMapNode(name, childSizeHint);
139 dataTreeChangeTracker.pushPath(name);
143 public void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint,
144 final Map<QName, String> attributes) {
145 super.startMapEntryNode(identifier, childSizeHint);
146 trackDataContainerNode(identifier, attributes);
150 public void startAugmentationNode(final AugmentationIdentifier identifier) {
151 super.startAugmentationNode(identifier);
152 trackMixinNode(identifier);
156 public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) {
157 super.startChoiceNode(name, childSizeHint);
158 trackMixinNode(name);
161 // for augments and choices
162 private void trackMixinNode(final PathArgument identifier) {
163 dataTreeChangeTracker.pushPath(identifier);
164 dataTreeChangeTracker.pushAction(dataTreeChangeTracker.peekAction() != null
165 ? dataTreeChangeTracker.peekAction() : dataTreeChangeTracker.getDefaultAction());
168 // for containers, (unkeyed) list entries and yang-modeled-anyxmls
169 private void trackDataContainerNode(final PathArgument identifier, final Map<QName, String> attributes) {
170 dataTreeChangeTracker.pushPath(identifier);
171 final String operation = attributes.get(OPERATION_ATTRIBUTE);
172 if (operation != null) {
173 dataTreeChangeTracker.pushAction(ModifyAction.fromXmlValue(operation));
175 dataTreeChangeTracker.pushAction(dataTreeChangeTracker.peekAction() != null
176 ? dataTreeChangeTracker.peekAction() : dataTreeChangeTracker.getDefaultAction());
181 @SuppressWarnings({"rawtypes","unchecked"})
182 public void endNode() {
183 final NormalizedNodeContainerBuilder finishedBuilder = getBuilders().peek();
184 final NormalizedNode<PathArgument, ?> product = finishedBuilder.build();
187 // for augments, choices, containers, (unkeyed) list entries and yang-modeled-anyxmls
188 if (finishedBuilder instanceof DataContainerNodeBuilder) {
189 final ModifyAction currentAction = dataTreeChangeTracker.popAction();
191 //if we know that we are going to delete a parent node just complete the entire subtree
192 if (dataTreeChangeTracker.getDeleteOperationTracker() > 0
193 || dataTreeChangeTracker.getRemoveOperationTracker() > 0) {
194 dataTreeChangeTracker.popPath();
196 //if parent and current actions don't match create a DataTreeChange and add it to the change list
197 //don't add a new child to the parent node
198 if (!currentAction.equals(dataTreeChangeTracker.peekAction())) {
199 dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(product,
200 currentAction, new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
201 if (getCurrent() instanceof NormalizedNodeResultBuilder) {
202 dataTreeChangeTracker.popPath();
205 getCurrent().removeChild(dataTreeChangeTracker.popPath());
207 dataTreeChangeTracker.popPath();
213 // for (ordered) leaf-lists, (ordered) lists and unkeyed lists
214 if (finishedBuilder instanceof CollectionNodeBuilder) {
215 dataTreeChangeTracker.popPath();