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.controller.cluster.datastore.node.utils.transformer;
11 import com.google.common.annotations.VisibleForTesting;
12 import com.google.common.base.Optional;
13 import com.google.common.base.Preconditions;
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;
34 * The NormalizedNodePruner removes all nodes from the input NormalizedNode that do not have a corresponding
35 * schema element in the passed in SchemaContext.
37 public class NormalizedNodePruner implements NormalizedNodeStreamWriter {
38 private static final Logger LOG = LoggerFactory.getLogger(NormalizedNodePruner.class);
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;
46 public NormalizedNodePruner(YangInstanceIdentifier nodePath, SchemaContext schemaContext) {
47 nodePathSchemaNode = findSchemaNodeForNodePath(nodePath, schemaContext);
50 @SuppressWarnings("unchecked")
52 public void leafNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, Object value)
53 throws IllegalArgumentException {
57 NormalizedNodeBuilderWrapper parent = stack.peek();
58 LeafNode<Object> leafNode = Builders.leafBuilder().withNodeIdentifier(nodeIdentifier).withValue(value).build();
60 if (hasValidSchema(nodeIdentifier.getNodeType(), parent)) {
61 parent.builder().addChild(leafNode);
64 // If there's no parent node then this is a stand alone LeafNode.
65 if (nodePathSchemaNode != null) {
66 this.normalizedNode = leafNode;
74 public void startLeafSet(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int count)
75 throws IllegalArgumentException {
78 addBuilder(Builders.leafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
82 public void startOrderedLeafSet(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int str)
83 throws IllegalArgumentException {
86 addBuilder(Builders.orderedLeafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
89 @SuppressWarnings({ "unchecked" })
91 public void leafSetEntryNode(QName name, Object value) throws IllegalArgumentException {
94 NormalizedNodeBuilderWrapper parent = stack.peek();
96 if (hasValidSchema(name, parent)) {
97 parent.builder().addChild(Builders.leafSetEntryBuilder().withValue(value)
98 .withNodeIdentifier(new YangInstanceIdentifier.NodeWithValue<>(parent.nodeType(), value))
102 // If there's no parent LeafSetNode then this is a stand alone
104 if (nodePathSchemaNode != null) {
105 this.normalizedNode = Builders.leafSetEntryBuilder().withValue(value).withNodeIdentifier(
106 new YangInstanceIdentifier.NodeWithValue<>(name, value)).build();
114 public void startContainerNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int count)
115 throws IllegalArgumentException {
118 addBuilder(Builders.containerBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
122 public void startYangModeledAnyXmlNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int count)
123 throws IllegalArgumentException {
124 throw new UnsupportedOperationException("Not implemented yet");
128 public void startUnkeyedList(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int count)
129 throws IllegalArgumentException {
132 addBuilder(Builders.unkeyedListBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
136 public void startUnkeyedListItem(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int count)
137 throws IllegalStateException {
140 addBuilder(Builders.unkeyedListEntryBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
144 public void startMapNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int count)
145 throws IllegalArgumentException {
148 addBuilder(Builders.mapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
152 public void startMapEntryNode(YangInstanceIdentifier.NodeIdentifierWithPredicates nodeIdentifierWithPredicates,
153 int count) throws IllegalArgumentException {
156 addBuilder(Builders.mapEntryBuilder().withNodeIdentifier(nodeIdentifierWithPredicates),
157 nodeIdentifierWithPredicates);
161 public void startOrderedMapNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int count)
162 throws IllegalArgumentException {
165 addBuilder(Builders.orderedMapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
169 public void startChoiceNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int count)
170 throws IllegalArgumentException {
173 addBuilder(Builders.choiceBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
177 public void startAugmentationNode(YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifier)
178 throws IllegalArgumentException {
182 addBuilder(Builders.augmentationBuilder().withNodeIdentifier(augmentationIdentifier), augmentationIdentifier);
185 @SuppressWarnings("unchecked")
187 public void anyxmlNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, Object value)
188 throws IllegalArgumentException {
191 NormalizedNodeBuilderWrapper parent = stack.peek();
192 AnyXmlNode anyXmlNode = Builders.anyXmlBuilder().withNodeIdentifier(nodeIdentifier).withValue((DOMSource) value)
194 if (parent != null) {
195 if (hasValidSchema(nodeIdentifier.getNodeType(), parent)) {
196 parent.builder().addChild(anyXmlNode);
199 // If there's no parent node then this is a stand alone AnyXmlNode.
200 if (nodePathSchemaNode != null) {
201 this.normalizedNode = anyXmlNode;
208 @SuppressWarnings("unchecked")
210 public void endNode() throws IllegalStateException {
213 NormalizedNodeBuilderWrapper child = stack.pop();
215 Preconditions.checkState(child != null, "endNode called on an empty stack");
217 if (!child.getSchema().isPresent()) {
218 LOG.debug("Schema not found for {}", child.identifier());
222 NormalizedNode<?,?> newNode = child.builder().build();
224 if (stack.size() > 0) {
225 NormalizedNodeBuilderWrapper parent = stack.peek();
226 parent.builder().addChild(newNode);
228 this.normalizedNode = newNode;
234 public void close() {
239 public void flush() {
243 public NormalizedNode<?,?> normalizedNode() {
244 return normalizedNode;
247 private void checkNotSealed() {
248 Preconditions.checkState(!sealed, "Pruner can be used only once");
251 private static boolean hasValidSchema(QName name, NormalizedNodeBuilderWrapper parent) {
252 boolean valid = parent.getSchema().isPresent() && parent.getSchema().get().getChild(name) != null;
254 LOG.debug("Schema not found for {}", name);
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));
269 schemaNode = Optional.absent();
272 NormalizedNodeBuilderWrapper wrapper = new NormalizedNodeBuilderWrapper(builder, identifier, schemaNode);
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) {
291 static class SimpleStack<E> {
292 List<E> stack = new LinkedList<>();
294 void push(E element) {
302 return stack.remove(stack.size() - 1);
310 return stack.get(stack.size() - 1);