Remove unused exceptions
[controller.git] / opendaylight / md-sal / sal-clustering-commons / src / main / java / org / opendaylight / controller / cluster / datastore / node / utils / transformer / NormalizedNodePruner.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. 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.controller.cluster.datastore.node.utils.transformer;
10
11 import com.google.common.annotations.VisibleForTesting;
12 import com.google.common.base.Optional;
13 import com.google.common.base.Preconditions;
14 import java.net.URI;
15 import java.util.LinkedList;
16 import java.util.List;
17 import javax.xml.transform.dom.DOMSource;
18 import org.opendaylight.yangtools.yang.common.QName;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
21 import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
22 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
23 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
24 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
25 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
26 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
27 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
28 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
29 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * The NormalizedNodePruner removes all nodes from the input NormalizedNode that do not have a corresponding
35  * schema element in the passed in SchemaContext.
36  */
37 public class NormalizedNodePruner implements NormalizedNodeStreamWriter {
38     private static final Logger LOG = LoggerFactory.getLogger(NormalizedNodePruner.class);
39
40     public static final URI BASE_NAMESPACE = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0");
41     private final SimpleStack<NormalizedNodeBuilderWrapper> stack = new SimpleStack<>();
42     private NormalizedNode<?,?> normalizedNode;
43     private final DataSchemaContextNode<?> nodePathSchemaNode;
44     private boolean sealed = false;
45
46     public NormalizedNodePruner(YangInstanceIdentifier nodePath, SchemaContext schemaContext) {
47         nodePathSchemaNode = findSchemaNodeForNodePath(nodePath, schemaContext);
48     }
49
50     @SuppressWarnings("unchecked")
51     @Override
52     public void leafNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, Object value)
53             throws IllegalArgumentException {
54
55         checkNotSealed();
56
57         NormalizedNodeBuilderWrapper parent = stack.peek();
58         LeafNode<Object> leafNode = Builders.leafBuilder().withNodeIdentifier(nodeIdentifier).withValue(value).build();
59         if (parent != null) {
60             if (hasValidSchema(nodeIdentifier.getNodeType(), parent)) {
61                 parent.builder().addChild(leafNode);
62             }
63         } else {
64             // If there's no parent node then this is a stand alone LeafNode.
65             if (nodePathSchemaNode != null) {
66                 this.normalizedNode = leafNode;
67             }
68
69             sealed = true;
70         }
71     }
72
73     @Override
74     public void startLeafSet(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int count)
75             throws IllegalArgumentException {
76         checkNotSealed();
77
78         addBuilder(Builders.leafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
79     }
80
81     @Override
82     public void startOrderedLeafSet(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int str)
83             throws IllegalArgumentException {
84         checkNotSealed();
85
86         addBuilder(Builders.orderedLeafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
87     }
88
89     @SuppressWarnings({ "unchecked" })
90     @Override
91     public void leafSetEntryNode(QName name, Object value) throws IllegalArgumentException {
92         checkNotSealed();
93
94         NormalizedNodeBuilderWrapper parent = stack.peek();
95         if (parent != null) {
96             if (hasValidSchema(name, parent)) {
97                 parent.builder().addChild(Builders.leafSetEntryBuilder().withValue(value)
98                         .withNodeIdentifier(new YangInstanceIdentifier.NodeWithValue<>(parent.nodeType(), value))
99                         .build());
100             }
101         } else {
102             // If there's no parent LeafSetNode then this is a stand alone
103             // LeafSetEntryNode.
104             if (nodePathSchemaNode != null) {
105                 this.normalizedNode = Builders.leafSetEntryBuilder().withValue(value).withNodeIdentifier(
106                         new YangInstanceIdentifier.NodeWithValue<>(name, value)).build();
107             }
108
109             sealed = true;
110         }
111     }
112
113     @Override
114     public void startContainerNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int count)
115             throws IllegalArgumentException {
116         checkNotSealed();
117
118         addBuilder(Builders.containerBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
119     }
120
121     @Override
122     public void startYangModeledAnyXmlNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int count)
123             throws IllegalArgumentException {
124         throw new UnsupportedOperationException("Not implemented yet");
125     }
126
127     @Override
128     public void startUnkeyedList(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int count)
129             throws IllegalArgumentException {
130         checkNotSealed();
131
132         addBuilder(Builders.unkeyedListBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
133     }
134
135     @Override
136     public void startUnkeyedListItem(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int count)
137             throws IllegalStateException {
138         checkNotSealed();
139
140         addBuilder(Builders.unkeyedListEntryBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
141     }
142
143     @Override
144     public void startMapNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int count)
145             throws IllegalArgumentException {
146         checkNotSealed();
147
148         addBuilder(Builders.mapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
149     }
150
151     @Override
152     public void startMapEntryNode(YangInstanceIdentifier.NodeIdentifierWithPredicates nodeIdentifierWithPredicates,
153             int count)  throws IllegalArgumentException {
154         checkNotSealed();
155
156         addBuilder(Builders.mapEntryBuilder().withNodeIdentifier(nodeIdentifierWithPredicates),
157                 nodeIdentifierWithPredicates);
158     }
159
160     @Override
161     public void startOrderedMapNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int count)
162             throws IllegalArgumentException {
163         checkNotSealed();
164
165         addBuilder(Builders.orderedMapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
166     }
167
168     @Override
169     public void startChoiceNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int count)
170             throws IllegalArgumentException {
171         checkNotSealed();
172
173         addBuilder(Builders.choiceBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
174     }
175
176     @Override
177     public void startAugmentationNode(YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifier)
178             throws IllegalArgumentException {
179
180         checkNotSealed();
181
182         addBuilder(Builders.augmentationBuilder().withNodeIdentifier(augmentationIdentifier), augmentationIdentifier);
183     }
184
185     @SuppressWarnings("unchecked")
186     @Override
187     public void anyxmlNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, Object value)
188             throws IllegalArgumentException {
189         checkNotSealed();
190
191         NormalizedNodeBuilderWrapper parent = stack.peek();
192         AnyXmlNode anyXmlNode = Builders.anyXmlBuilder().withNodeIdentifier(nodeIdentifier).withValue((DOMSource) value)
193                 .build();
194         if (parent != null) {
195             if (hasValidSchema(nodeIdentifier.getNodeType(), parent)) {
196                 parent.builder().addChild(anyXmlNode);
197             }
198         } else {
199             // If there's no parent node then this is a stand alone AnyXmlNode.
200             if (nodePathSchemaNode != null) {
201                 this.normalizedNode = anyXmlNode;
202             }
203
204             sealed = true;
205         }
206     }
207
208     @SuppressWarnings("unchecked")
209     @Override
210     public void endNode() throws IllegalStateException {
211         checkNotSealed();
212
213         NormalizedNodeBuilderWrapper child = stack.pop();
214
215         Preconditions.checkState(child != null, "endNode called on an empty stack");
216
217         if (!child.getSchema().isPresent()) {
218             LOG.debug("Schema not found for {}", child.identifier());
219             return;
220         }
221
222         NormalizedNode<?,?> newNode = child.builder().build();
223
224         if (stack.size() > 0) {
225             NormalizedNodeBuilderWrapper parent = stack.peek();
226             parent.builder().addChild(newNode);
227         } else {
228             this.normalizedNode = newNode;
229             sealed = true;
230         }
231     }
232
233     @Override
234     public void close() {
235         sealed = true;
236     }
237
238     @Override
239     public void flush() {
240
241     }
242
243     public NormalizedNode<?,?> normalizedNode() {
244         return normalizedNode;
245     }
246
247     private void checkNotSealed() {
248         Preconditions.checkState(!sealed, "Pruner can be used only once");
249     }
250
251     private static boolean hasValidSchema(QName name, NormalizedNodeBuilderWrapper parent) {
252         boolean valid = parent.getSchema().isPresent() && parent.getSchema().get().getChild(name) != null;
253         if (!valid) {
254             LOG.debug("Schema not found for {}", name);
255         }
256
257         return valid;
258     }
259
260     private NormalizedNodeBuilderWrapper addBuilder(NormalizedNodeContainerBuilder<?,?,?,?> builder,
261             PathArgument identifier) {
262         final Optional<DataSchemaContextNode<?>> schemaNode;
263         NormalizedNodeBuilderWrapper parent = stack.peek();
264         if (parent == null) {
265             schemaNode = Optional.fromNullable(nodePathSchemaNode);
266         } else if (parent.getSchema().isPresent()) {
267             schemaNode = Optional.fromNullable(parent.getSchema().get().getChild(identifier));
268         } else {
269             schemaNode = Optional.absent();
270         }
271
272         NormalizedNodeBuilderWrapper wrapper = new NormalizedNodeBuilderWrapper(builder, identifier, schemaNode);
273         stack.push(wrapper);
274         return wrapper;
275     }
276
277     private static DataSchemaContextNode<?> findSchemaNodeForNodePath(YangInstanceIdentifier nodePath,
278             SchemaContext schemaContext) {
279         DataSchemaContextNode<?> schemaNode = DataSchemaContextTree.from(schemaContext).getRoot();
280         for (PathArgument arg : nodePath.getPathArguments()) {
281             schemaNode = schemaNode.getChild(arg);
282             if (schemaNode == null) {
283                 break;
284             }
285         }
286
287         return schemaNode;
288     }
289
290     @VisibleForTesting
291     static class SimpleStack<E> {
292         List<E> stack = new LinkedList<>();
293
294         void push(E element) {
295             stack.add(element);
296         }
297
298         E pop() {
299             if (size() == 0) {
300                 return null;
301             }
302             return stack.remove(stack.size() - 1);
303         }
304
305         E peek() {
306             if (size() == 0) {
307                 return null;
308             }
309
310             return stack.get(stack.size() - 1);
311         }
312
313         int size() {
314             return stack.size();
315         }
316     }
317 }