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
8 package org.opendaylight.controller.cluster.datastore.node.utils.transformer;
10 import static com.google.common.base.Preconditions.checkState;
12 import com.google.common.annotations.VisibleForTesting;
13 import com.google.common.base.Optional;
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.AugmentationIdentifier;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
24 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
25 import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
27 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
28 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
29 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
30 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
31 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
32 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
33 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
38 * The NormalizedNodePruner removes all nodes from the input NormalizedNode that do not have a corresponding
39 * schema element in the passed in SchemaContext.
41 public class NormalizedNodePruner implements NormalizedNodeStreamWriter {
42 private static final Logger LOG = LoggerFactory.getLogger(NormalizedNodePruner.class);
44 public static final URI BASE_NAMESPACE = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0");
46 private final SimpleStack<NormalizedNodeBuilderWrapper> stack = new SimpleStack<>();
47 private final DataSchemaContextNode<?> nodePathSchemaNode;
49 private NormalizedNode<?, ?> normalizedNode;
50 private boolean sealed = false;
52 public NormalizedNodePruner(final YangInstanceIdentifier nodePath, final SchemaContext schemaContext) {
53 nodePathSchemaNode = findSchemaNodeForNodePath(nodePath, schemaContext);
56 @SuppressWarnings("unchecked")
58 public void leafNode(final NodeIdentifier nodeIdentifier, final Object value) {
61 NormalizedNodeBuilderWrapper parent = stack.peek();
62 LeafNode<Object> leafNode = Builders.leafBuilder().withNodeIdentifier(nodeIdentifier).withValue(value).build();
64 if (hasValidSchema(nodeIdentifier.getNodeType(), parent)) {
65 parent.builder().addChild(leafNode);
68 // If there's no parent node then this is a stand alone LeafNode.
69 if (nodePathSchemaNode != null) {
70 this.normalizedNode = leafNode;
78 public void startLeafSet(final NodeIdentifier nodeIdentifier, final int count) {
80 addBuilder(Builders.leafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
84 public void startOrderedLeafSet(final NodeIdentifier nodeIdentifier, final int str) {
86 addBuilder(Builders.orderedLeafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
89 @SuppressWarnings("unchecked")
91 public void leafSetEntryNode(final QName name, final Object value) {
94 NormalizedNodeBuilderWrapper parent = stack.peek();
96 if (hasValidSchema(name, parent)) {
97 parent.builder().addChild(Builders.leafSetEntryBuilder().withValue(value)
98 .withNodeIdentifier(new 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 NodeWithValue<>(name, value)).build();
114 public void startContainerNode(final NodeIdentifier nodeIdentifier, final int count) {
116 addBuilder(Builders.containerBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
120 public void startYangModeledAnyXmlNode(final NodeIdentifier nodeIdentifier, final int count) {
121 throw new UnsupportedOperationException("Not implemented yet");
125 public void startUnkeyedList(final NodeIdentifier nodeIdentifier, final int count) {
127 addBuilder(Builders.unkeyedListBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
131 public void startUnkeyedListItem(final NodeIdentifier nodeIdentifier, final int count) {
133 addBuilder(Builders.unkeyedListEntryBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
137 public void startMapNode(final NodeIdentifier nodeIdentifier, final int count) {
139 addBuilder(Builders.mapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
143 public void startMapEntryNode(final NodeIdentifierWithPredicates nodeIdentifierWithPredicates, final int count) {
145 addBuilder(Builders.mapEntryBuilder().withNodeIdentifier(nodeIdentifierWithPredicates),
146 nodeIdentifierWithPredicates);
150 public void startOrderedMapNode(final NodeIdentifier nodeIdentifier, final int count) {
152 addBuilder(Builders.orderedMapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
156 public void startChoiceNode(final NodeIdentifier nodeIdentifier, final int count) {
158 addBuilder(Builders.choiceBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
162 public void startAugmentationNode(final AugmentationIdentifier augmentationIdentifier) {
164 addBuilder(Builders.augmentationBuilder().withNodeIdentifier(augmentationIdentifier), augmentationIdentifier);
167 @SuppressWarnings("unchecked")
169 public void anyxmlNode(final NodeIdentifier nodeIdentifier, final Object value) {
172 NormalizedNodeBuilderWrapper parent = stack.peek();
173 AnyXmlNode anyXmlNode = Builders.anyXmlBuilder().withNodeIdentifier(nodeIdentifier).withValue((DOMSource) value)
175 if (parent != null) {
176 if (hasValidSchema(nodeIdentifier.getNodeType(), parent)) {
177 parent.builder().addChild(anyXmlNode);
180 // If there's no parent node then this is a stand alone AnyXmlNode.
181 if (nodePathSchemaNode != null) {
182 this.normalizedNode = anyXmlNode;
189 @SuppressWarnings("unchecked")
191 public void endNode() {
194 NormalizedNodeBuilderWrapper child = stack.pop();
196 checkState(child != null, "endNode called on an empty stack");
198 if (!child.getSchema().isPresent()) {
199 LOG.debug("Schema not found for {}", child.identifier());
203 NormalizedNode<?, ?> newNode = child.builder().build();
204 if (stack.size() > 0) {
205 NormalizedNodeBuilderWrapper parent = stack.peek();
206 parent.builder().addChild(newNode);
208 this.normalizedNode = newNode;
214 public void close() {
219 public void flush() {
223 public NormalizedNode<?, ?> normalizedNode() {
224 return normalizedNode;
227 private void checkNotSealed() {
228 checkState(!sealed, "Pruner can be used only once");
231 private static boolean hasValidSchema(final QName name, final NormalizedNodeBuilderWrapper parent) {
232 boolean valid = parent.getSchema().isPresent() && parent.getSchema().get().getChild(name) != null;
234 LOG.debug("Schema not found for {}", name);
240 private NormalizedNodeBuilderWrapper addBuilder(final NormalizedNodeContainerBuilder<?, ?, ?, ?> builder,
241 final PathArgument identifier) {
242 final Optional<DataSchemaContextNode<?>> schemaNode;
243 NormalizedNodeBuilderWrapper parent = stack.peek();
244 if (parent == null) {
245 schemaNode = Optional.fromNullable(nodePathSchemaNode);
246 } else if (parent.getSchema().isPresent()) {
247 schemaNode = Optional.fromNullable(parent.getSchema().get().getChild(identifier));
249 schemaNode = Optional.absent();
252 NormalizedNodeBuilderWrapper wrapper = new NormalizedNodeBuilderWrapper(builder, identifier, schemaNode);
257 private static DataSchemaContextNode<?> findSchemaNodeForNodePath(final YangInstanceIdentifier nodePath,
258 final SchemaContext schemaContext) {
259 DataSchemaContextNode<?> schemaNode = DataSchemaContextTree.from(schemaContext).getRoot();
260 for (PathArgument arg : nodePath.getPathArguments()) {
261 schemaNode = schemaNode.getChild(arg);
262 if (schemaNode == null) {
271 static class SimpleStack<E> {
272 List<E> stack = new LinkedList<>();
274 void push(final E element) {
282 return stack.remove(stack.size() - 1);
290 return stack.get(stack.size() - 1);