Clean up netconf-parent root pom
[netconf.git] / netconf / mdsal-netconf-connector / src / main / java / org / opendaylight / netconf / mdsal / connector / ops / EditOperationNormalizedNodeStreamWriter.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.netconf.mdsal.connector.ops;
10
11 import java.util.ArrayList;
12 import java.util.Map;
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;
33
34 final class EditOperationNormalizedNodeStreamWriter extends ImmutableNormalizedNodeStreamWriter
35         implements NormalizedNodeStreamAttributeWriter {
36     private static final QName OPERATION_ATTRIBUTE = QName.create(EditConfigInput.QNAME.getNamespace(), null,
37             XmlNetconfConstants.OPERATION_ATTR_KEY);
38
39     private final DataTreeChangeTracker dataTreeChangeTracker;
40
41     EditOperationNormalizedNodeStreamWriter(final NormalizedNodeResult result,
42             final DataTreeChangeTracker dataTreeChangeTracker) {
43         super(result);
44         this.dataTreeChangeTracker = dataTreeChangeTracker;
45     }
46
47     @Override
48     public void leafNode(final NodeIdentifier name, final Object value, final Map<QName, String> attributes) {
49         super.leafNode(name, value);
50
51         final String operation = attributes.get(OPERATION_ATTRIBUTE);
52         if (operation == null) {
53             return;
54         }
55
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());
65             }
66         }
67     }
68
69     @Override
70     public void startLeafSet(final NodeIdentifier name, final int childSizeHint) {
71         super.startLeafSet(name, childSizeHint);
72         dataTreeChangeTracker.pushPath(name);
73     }
74
75     @Override
76     public void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) {
77         super.startOrderedLeafSet(name, childSizeHint);
78         dataTreeChangeTracker.pushPath(name);
79     }
80
81     @Override
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) {
86             return;
87         }
88
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());
99             }
100         }
101     }
102
103     @Override
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);
108     }
109
110     @Override
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);
115     }
116
117     @Override
118     public void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) {
119         super.startUnkeyedList(name, childSizeHint);
120         dataTreeChangeTracker.pushPath(name);
121     }
122
123     @Override
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);
128     }
129
130     @Override
131     public void startMapNode(final NodeIdentifier name, final int childSizeHint) {
132         super.startMapNode(name, childSizeHint);
133         dataTreeChangeTracker.pushPath(name);
134     }
135
136     @Override
137     public void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) {
138         super.startOrderedMapNode(name, childSizeHint);
139         dataTreeChangeTracker.pushPath(name);
140     }
141
142     @Override
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);
147     }
148
149     @Override
150     public void startAugmentationNode(final AugmentationIdentifier identifier) {
151         super.startAugmentationNode(identifier);
152         trackMixinNode(identifier);
153     }
154
155     @Override
156     public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) {
157         super.startChoiceNode(name, childSizeHint);
158         trackMixinNode(name);
159     }
160
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());
166     }
167
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));
174         } else {
175             dataTreeChangeTracker.pushAction(dataTreeChangeTracker.peekAction() != null
176                     ? dataTreeChangeTracker.peekAction() : dataTreeChangeTracker.getDefaultAction());
177         }
178     }
179
180     @Override
181     @SuppressWarnings({"rawtypes","unchecked"})
182     public void endNode() {
183         final NormalizedNodeContainerBuilder finishedBuilder = getBuilders().peek();
184         final NormalizedNode<PathArgument, ?> product = finishedBuilder.build();
185         super.endNode();
186
187         // for augments, choices, containers, (unkeyed) list entries and yang-modeled-anyxmls
188         if (finishedBuilder instanceof DataContainerNodeBuilder) {
189             final ModifyAction currentAction = dataTreeChangeTracker.popAction();
190
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();
195             } else {
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();
203                         return;
204                     }
205                     getCurrent().removeChild(dataTreeChangeTracker.popPath());
206                 } else {
207                     dataTreeChangeTracker.popPath();
208                     return;
209                 }
210             }
211         }
212
213         // for (ordered) leaf-lists, (ordered) lists and unkeyed lists
214         if (finishedBuilder instanceof CollectionNodeBuilder) {
215             dataTreeChangeTracker.popPath();
216         }
217     }
218 }