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.base.Optional;
14 import java.util.ArrayDeque;
15 import java.util.Deque;
16 import java.util.NoSuchElementException;
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 Deque<NormalizedNodeBuilderWrapper> stack = new ArrayDeque<>();
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 final NormalizedNodeBuilderWrapper child;
197 } catch (NoSuchElementException e) {
198 throw new IllegalStateException("endNode called on an empty stack", e);
201 if (!child.getSchema().isPresent()) {
202 LOG.debug("Schema not found for {}", child.identifier());
206 NormalizedNode<?, ?> newNode = child.builder().build();
207 if (stack.size() > 0) {
208 NormalizedNodeBuilderWrapper parent = stack.peek();
209 parent.builder().addChild(newNode);
211 this.normalizedNode = newNode;
217 public void close() {
222 public void flush() {
226 public NormalizedNode<?, ?> normalizedNode() {
227 return normalizedNode;
230 private void checkNotSealed() {
231 checkState(!sealed, "Pruner can be used only once");
234 private static boolean hasValidSchema(final QName name, final NormalizedNodeBuilderWrapper parent) {
235 boolean valid = parent.getSchema().isPresent() && parent.getSchema().get().getChild(name) != null;
237 LOG.debug("Schema not found for {}", name);
243 private NormalizedNodeBuilderWrapper addBuilder(final NormalizedNodeContainerBuilder<?, ?, ?, ?> builder,
244 final PathArgument identifier) {
245 final Optional<DataSchemaContextNode<?>> schemaNode;
246 NormalizedNodeBuilderWrapper parent = stack.peek();
247 if (parent == null) {
248 schemaNode = Optional.fromNullable(nodePathSchemaNode);
249 } else if (parent.getSchema().isPresent()) {
250 schemaNode = Optional.fromNullable(parent.getSchema().get().getChild(identifier));
252 schemaNode = Optional.absent();
255 NormalizedNodeBuilderWrapper wrapper = new NormalizedNodeBuilderWrapper(builder, identifier, schemaNode);
260 private static DataSchemaContextNode<?> findSchemaNodeForNodePath(final YangInstanceIdentifier nodePath,
261 final SchemaContext schemaContext) {
262 DataSchemaContextNode<?> schemaNode = DataSchemaContextTree.from(schemaContext).getRoot();
263 for (PathArgument arg : nodePath.getPathArguments()) {
264 schemaNode = schemaNode.getChild(arg);
265 if (schemaNode == null) {