2 * Copyright (c) 2015 Cisco Systems, Inc. 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;
12 import java.util.Collections;
14 import javax.annotation.Nullable;
15 import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
16 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.EditConfigInput;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.data.api.ModifyAction;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
24 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
25 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
27 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
28 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
29 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
30 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
32 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
33 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
34 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
35 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
36 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.AttributesBuilder;
37 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
38 import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ExtensibleParser;
39 import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
41 class EditOperationStrategyProvider extends DomToNormalizedNodeParserFactory.BuildingStrategyProvider {
43 private static final QName OPERATION_ATTRIBUTE = QName.create(EditConfigInput.QNAME.getNamespace(), null,
44 XmlNetconfConstants.OPERATION_ATTR_KEY);
46 private final DataTreeChangeTracker changeTracker;
48 EditOperationStrategyProvider(final DataTreeChangeTracker changeTracker) {
49 this.changeTracker = changeTracker;
53 protected ExtensibleParser.BuildingStrategy<NodeIdentifier, LeafNode<?>> forLeaf() {
54 return new NetconfOperationLeafStrategy(changeTracker);
58 protected ExtensibleParser.BuildingStrategy<NodeIdentifier, ContainerNode> forContainer() {
59 return new NetconfOperationContainerStrategy<>(changeTracker);
63 protected ExtensibleParser.BuildingStrategy<NodeIdentifier, MapNode> forMap() {
64 return new NetconfOperationCollectionStrategy<>(changeTracker);
68 protected ExtensibleParser.BuildingStrategy<NodeWithValue, LeafSetEntryNode<?>> forLeafSetEntry() {
69 return new NetconfOperationLeafSetEntryStrategy(changeTracker);
73 protected ExtensibleParser.BuildingStrategy<NodeIdentifierWithPredicates, MapEntryNode> forMapEntry() {
74 return new NetconfOperationContainerStrategy<>(changeTracker);
78 protected ExtensibleParser.BuildingStrategy<NodeIdentifier, OrderedMapNode> forOrderedList() {
79 return new NetconfOperationCollectionStrategy<>(changeTracker);
83 protected ExtensibleParser.BuildingStrategy<NodeIdentifier, UnkeyedListEntryNode> forUnkeyedListEntry() {
84 return new NetconfOperationContainerStrategy<>(changeTracker);
88 protected ExtensibleParser.BuildingStrategy<NodeIdentifier, UnkeyedListNode> forUnkeyedList() {
89 return new NetconfOperationCollectionStrategy<>(changeTracker);
93 protected ExtensibleParser.BuildingStrategy<NodeIdentifier, ChoiceNode> forChoice() {
94 return new NetconfOperationContainerStrategy<>(changeTracker);
98 public ExtensibleParser.BuildingStrategy<AugmentationIdentifier, AugmentationNode> forAugmentation() {
99 return new NetconfOperationContainerStrategy<>(changeTracker);
102 private static class NetconfOperationCollectionStrategy<N extends NormalizedNode<NodeIdentifier, ?>>
103 implements ExtensibleParser.BuildingStrategy<NodeIdentifier, N> {
104 private final DataTreeChangeTracker changeTracker;
106 NetconfOperationCollectionStrategy(final DataTreeChangeTracker changeTracker) {
107 this.changeTracker = changeTracker;
112 public N build(final NormalizedNodeBuilder<NodeIdentifier, ?, N> builder) {
113 changeTracker.popPath();
114 return builder.build();
118 public void prepareAttributes(
119 final Map<QName, String> attributes,
120 final NormalizedNodeBuilder<NodeIdentifier, ?, N> containerBuilder) {
121 changeTracker.pushPath(containerBuilder.build().getIdentifier());
125 public static final class NetconfOperationLeafStrategy
126 implements ExtensibleParser.BuildingStrategy<NodeIdentifier, LeafNode<?>> {
128 private final DataTreeChangeTracker dataTreeChangeTracker;
130 NetconfOperationLeafStrategy(final DataTreeChangeTracker dataTreeChangeTracker) {
131 this.dataTreeChangeTracker = dataTreeChangeTracker;
136 public LeafNode<?> build(
137 final NormalizedNodeBuilder<NodeIdentifier, ?, LeafNode<?>> builder) {
138 LeafNode<?> node = builder.build();
139 String operation = (String) node.getAttributeValue(OPERATION_ATTRIBUTE);
140 if (operation == null) {
144 if (builder instanceof AttributesBuilder<?>) {
145 ((AttributesBuilder<?>) builder).withAttributes(Collections.<QName, String>emptyMap());
148 node = builder.build();
150 ModifyAction action = ModifyAction.fromXmlValue(operation);
151 if (dataTreeChangeTracker.getDeleteOperationTracker() > 0
152 || dataTreeChangeTracker .getRemoveOperationTracker() > 0) {
156 if (action.equals(dataTreeChangeTracker.peekAction())) {
160 dataTreeChangeTracker.pushPath(node.getIdentifier());
161 dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(node, action,
162 new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
163 dataTreeChangeTracker.popPath();
168 public void prepareAttributes(
169 final Map<QName, String> attributes,
170 final NormalizedNodeBuilder<NodeIdentifier, ?, LeafNode<?>> containerBuilder) {
175 public static final class NetconfOperationLeafSetEntryStrategy
176 implements ExtensibleParser.BuildingStrategy<NodeWithValue, LeafSetEntryNode<?>> {
178 private final DataTreeChangeTracker dataTreeChangeTracker;
180 NetconfOperationLeafSetEntryStrategy(final DataTreeChangeTracker dataTreeChangeTracker) {
181 this.dataTreeChangeTracker = dataTreeChangeTracker;
186 public LeafSetEntryNode<?> build(final NormalizedNodeBuilder<NodeWithValue, ?, LeafSetEntryNode<?>> builder) {
187 LeafSetEntryNode<?> node = builder.build();
188 String operation = (String) node.getAttributeValue(OPERATION_ATTRIBUTE);
189 if (operation == null) {
193 if (builder instanceof AttributesBuilder<?>) {
194 ((AttributesBuilder<?>) builder).withAttributes(Collections.<QName, String>emptyMap());
197 node = builder.build();
199 ModifyAction action = ModifyAction.fromXmlValue(operation);
200 if (dataTreeChangeTracker.getDeleteOperationTracker() > 0
201 || dataTreeChangeTracker.getRemoveOperationTracker() > 0) {
205 if (action.equals(dataTreeChangeTracker.peekAction())) {
209 dataTreeChangeTracker.pushPath(node.getIdentifier());
210 dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(node, action,
211 new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
212 dataTreeChangeTracker.popPath();
217 public void prepareAttributes(
218 final Map<QName, String> attributes,
219 final NormalizedNodeBuilder<NodeWithValue, ?, LeafSetEntryNode<?>> containerBuilder) {
223 public static final class NetconfOperationContainerStrategy<P extends PathArgument, N
224 extends DataContainerNode<P>> implements ExtensibleParser.BuildingStrategy<P, N> {
226 private final DataTreeChangeTracker dataTreeChangeTracker;
228 NetconfOperationContainerStrategy(final DataTreeChangeTracker dataTreeChangeTracker) {
229 this.dataTreeChangeTracker = dataTreeChangeTracker;
234 public N build(final NormalizedNodeBuilder<P, ?, N> builder) {
235 if (builder instanceof AttributesBuilder<?>) {
236 ((AttributesBuilder<?>) builder).withAttributes(Collections.<QName, String>emptyMap());
239 final N node = builder.build();
240 final ModifyAction currentAction = dataTreeChangeTracker.popAction();
242 //if we know that we are going to delete a parent node just complete the entire subtree
243 if (dataTreeChangeTracker.getDeleteOperationTracker() > 0
244 || dataTreeChangeTracker.getRemoveOperationTracker() > 0) {
245 dataTreeChangeTracker.popPath();
249 if (currentAction.equals(dataTreeChangeTracker.peekAction())) {
250 dataTreeChangeTracker.popPath();
254 //if parent and current actions dont match create a DataTreeChange and add it to the change list
255 //dont add a new child to the parent node
256 dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(node,
257 currentAction, new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
258 dataTreeChangeTracker.popPath();
263 public void prepareAttributes(final Map<QName, String> attributes,
264 final NormalizedNodeBuilder<P, ?, N> containerBuilder) {
265 dataTreeChangeTracker.pushPath(containerBuilder.build().getIdentifier());
266 final String operation = attributes.get(OPERATION_ATTRIBUTE);
267 if (operation != null) {
268 dataTreeChangeTracker.pushAction(ModifyAction.fromXmlValue(operation));
270 dataTreeChangeTracker.pushAction(dataTreeChangeTracker.peekAction() != null
271 ? dataTreeChangeTracker.peekAction() : dataTreeChangeTracker.getDefaultAction());