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;
20 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
21 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
22 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
23 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
24 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
25 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
27 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
28 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
29 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
30 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
32 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.AttributesBuilder;
33 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
34 import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ExtensibleParser;
35 import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
37 class EditOperationStrategyProvider extends DomToNormalizedNodeParserFactory.BuildingStrategyProvider {
39 private static final QName OPERATION_ATTRIBUTE = QName.create(EditConfigInput.QNAME.getNamespace(), null, XmlNetconfConstants.OPERATION_ATTR_KEY);
41 private final DataTreeChangeTracker changeTracker;
43 public EditOperationStrategyProvider(final DataTreeChangeTracker changeTracker) {
44 this.changeTracker = changeTracker;
48 protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, LeafNode<?>> forLeaf() {
49 return new NetconfOperationLeafStrategy(changeTracker);
53 protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, ContainerNode> forContainer() {
54 return new NetconfOperationContainerStrategy<>(changeTracker);
58 protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, MapNode> forMap() {
59 return new NetconfOperationCollectionStrategy<>(changeTracker);
63 protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeWithValue, LeafSetEntryNode<?>> forLeafSetEntry() {
64 return new NetconfOperationLeafSetEntryStrategy(changeTracker);
68 protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> forMapEntry() {
69 return new NetconfOperationContainerStrategy<>(changeTracker);
73 protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, OrderedMapNode> forOrderedList() {
74 return new NetconfOperationCollectionStrategy<>(changeTracker);
78 protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, UnkeyedListEntryNode> forUnkeyedListEntry() {
79 return new NetconfOperationContainerStrategy<>(changeTracker);
83 protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, UnkeyedListNode> forUnkeyedList() {
84 return new NetconfOperationCollectionStrategy<>(changeTracker);
88 protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, ChoiceNode> forChoice() {
89 return new NetconfOperationContainerStrategy<>(changeTracker);
93 public ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.AugmentationIdentifier, AugmentationNode> forAugmentation() {
94 return new NetconfOperationContainerStrategy<>(changeTracker);
97 private static class NetconfOperationCollectionStrategy<N extends NormalizedNode<YangInstanceIdentifier.NodeIdentifier, ?>> implements ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, N> {
98 private final DataTreeChangeTracker changeTracker;
100 public NetconfOperationCollectionStrategy(final DataTreeChangeTracker changeTracker) {
101 this.changeTracker = changeTracker;
106 public N build(final NormalizedNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ?, N> builder) {
107 changeTracker.popPath();
108 return builder.build();
112 public void prepareAttributes(final Map<QName, String> attributes, final NormalizedNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ?, N> containerBuilder) {
113 changeTracker.pushPath(containerBuilder.build().getIdentifier());
117 public static final class NetconfOperationLeafStrategy implements ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, LeafNode<?>> {
119 private final DataTreeChangeTracker dataTreeChangeTracker;
121 public NetconfOperationLeafStrategy(final DataTreeChangeTracker dataTreeChangeTracker) {
122 this.dataTreeChangeTracker = dataTreeChangeTracker;
127 public LeafNode<?> build(final NormalizedNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ?, LeafNode<?>> builder) {
128 LeafNode<?> node = builder.build();
129 String operation = (String) node.getAttributeValue(OPERATION_ATTRIBUTE);
130 if (operation == null) {
134 if(builder instanceof AttributesBuilder<?>) {
135 ((AttributesBuilder<?>) builder).withAttributes(Collections.<QName, String>emptyMap());
138 node = builder.build();
140 ModifyAction action = ModifyAction.fromXmlValue(operation);
141 if (dataTreeChangeTracker.getDeleteOperationTracker() > 0 || dataTreeChangeTracker.getRemoveOperationTracker() > 0) {
144 if (!action.equals(dataTreeChangeTracker.peekAction())) {
145 dataTreeChangeTracker.pushPath(node.getIdentifier());
146 dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(node, action, new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
147 dataTreeChangeTracker.popPath();
156 public void prepareAttributes(final Map<QName, String> attributes, final NormalizedNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ?, LeafNode<?>> containerBuilder) {
161 public static final class NetconfOperationLeafSetEntryStrategy implements ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeWithValue, LeafSetEntryNode<?>> {
163 private final DataTreeChangeTracker dataTreeChangeTracker;
165 public NetconfOperationLeafSetEntryStrategy(final DataTreeChangeTracker dataTreeChangeTracker) {
166 this.dataTreeChangeTracker = dataTreeChangeTracker;
171 public LeafSetEntryNode<?> build(final NormalizedNodeBuilder<YangInstanceIdentifier.NodeWithValue, ?, LeafSetEntryNode<?>> builder) {
172 LeafSetEntryNode<?> node = builder.build();
173 String operation = (String) node.getAttributeValue(OPERATION_ATTRIBUTE);
174 if (operation == null) {
178 if (builder instanceof AttributesBuilder<?>) {
179 ((AttributesBuilder<?>) builder).withAttributes(Collections.<QName, String>emptyMap());
182 node = builder.build();
184 ModifyAction action = ModifyAction.fromXmlValue(operation);
185 if (dataTreeChangeTracker.getDeleteOperationTracker() > 0 || dataTreeChangeTracker.getRemoveOperationTracker() > 0) {
188 if (!action.equals(dataTreeChangeTracker.peekAction())) {
189 dataTreeChangeTracker.pushPath(node.getIdentifier());
190 dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(node, action, new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
191 dataTreeChangeTracker.popPath();
200 public void prepareAttributes(final Map<QName, String> attributes, final NormalizedNodeBuilder<YangInstanceIdentifier.NodeWithValue, ?, LeafSetEntryNode<?>> containerBuilder) {
205 public static final class NetconfOperationContainerStrategy<P extends YangInstanceIdentifier.PathArgument, N extends DataContainerNode<P>> implements ExtensibleParser.BuildingStrategy<P, N> {
207 private final DataTreeChangeTracker dataTreeChangeTracker;
209 public NetconfOperationContainerStrategy(final DataTreeChangeTracker dataTreeChangeTracker) {
210 this.dataTreeChangeTracker = dataTreeChangeTracker;
215 public N build(final NormalizedNodeBuilder<P, ?, N> builder) {
216 if (builder instanceof AttributesBuilder<?>) {
217 ((AttributesBuilder<?>) builder).withAttributes(Collections.<QName, String>emptyMap());
220 final N node = builder.build();
221 final ModifyAction currentAction = dataTreeChangeTracker.popAction();
223 //if we know that we are going to delete a parent node just complete the entire subtree
224 if (dataTreeChangeTracker.getDeleteOperationTracker() > 0 || dataTreeChangeTracker.getRemoveOperationTracker() > 0) {
225 dataTreeChangeTracker.popPath();
228 //if parent and current actions dont match create a DataTreeChange and add it to the change list
229 //dont add a new child to the parent node
230 if (!currentAction.equals(dataTreeChangeTracker.peekAction())) {
231 dataTreeChangeTracker.addDataTreeChange(new DataTreeChangeTracker.DataTreeChange(node, currentAction, new ArrayList<>(dataTreeChangeTracker.getCurrentPath())));
232 dataTreeChangeTracker.popPath();
235 dataTreeChangeTracker.popPath();
242 public void prepareAttributes(final Map<QName, String> attributes, final NormalizedNodeBuilder<P, ?, N> containerBuilder) {
243 dataTreeChangeTracker.pushPath(containerBuilder.build().getIdentifier());
244 final String operation = attributes.get(OPERATION_ATTRIBUTE);
245 if (operation != null) {
246 dataTreeChangeTracker.pushAction(ModifyAction.fromXmlValue(operation));
248 dataTreeChangeTracker.pushAction(dataTreeChangeTracker.peekAction() != null
249 ? dataTreeChangeTracker.peekAction() : dataTreeChangeTracker.getDefaultAction());