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;
13 import java.util.ArrayDeque;
14 import java.util.Deque;
15 import java.util.NoSuchElementException;
16 import javax.xml.transform.dom.DOMSource;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
24 import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
25 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
27 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
28 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
29 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
30 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
31 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
32 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
37 * The NormalizedNodePruner removes all nodes from the input NormalizedNode that do not have a corresponding
38 * schema element in the passed in SchemaContext.
40 public class NormalizedNodePruner implements NormalizedNodeStreamWriter {
41 private static final Logger LOG = LoggerFactory.getLogger(NormalizedNodePruner.class);
43 public static final URI BASE_NAMESPACE = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0");
45 private final Deque<NormalizedNodeBuilderWrapper> stack = new ArrayDeque<>();
46 private final DataSchemaContextNode<?> nodePathSchemaNode;
48 private NormalizedNode<?, ?> normalizedNode;
49 private boolean sealed = false;
51 public NormalizedNodePruner(final YangInstanceIdentifier nodePath, final SchemaContext schemaContext) {
52 nodePathSchemaNode = DataSchemaContextTree.from(schemaContext).findChild(nodePath).orElse(null);
55 @SuppressWarnings("unchecked")
57 public void leafNode(final NodeIdentifier nodeIdentifier, final Object value) {
60 NormalizedNodeBuilderWrapper parent = stack.peek();
61 LeafNode<Object> leafNode = Builders.leafBuilder().withNodeIdentifier(nodeIdentifier).withValue(value).build();
63 if (hasValidSchema(nodeIdentifier.getNodeType(), parent)) {
64 parent.builder().addChild(leafNode);
67 // If there's no parent node then this is a stand alone LeafNode.
68 if (nodePathSchemaNode != null) {
69 this.normalizedNode = leafNode;
77 public void startLeafSet(final NodeIdentifier nodeIdentifier, final int count) {
79 addBuilder(Builders.leafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
83 public void startOrderedLeafSet(final NodeIdentifier nodeIdentifier, final int str) {
85 addBuilder(Builders.orderedLeafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
88 @SuppressWarnings("unchecked")
90 public void leafSetEntryNode(final QName name, final Object value) {
93 NormalizedNodeBuilderWrapper parent = stack.peek();
95 if (hasValidSchema(name, parent)) {
96 parent.builder().addChild(Builders.leafSetEntryBuilder().withValue(value)
97 .withNodeIdentifier(new NodeWithValue<>(parent.nodeType(), value))
101 // If there's no parent LeafSetNode then this is a stand alone
103 if (nodePathSchemaNode != null) {
104 this.normalizedNode = Builders.leafSetEntryBuilder().withValue(value).withNodeIdentifier(
105 new NodeWithValue<>(name, value)).build();
113 public void startContainerNode(final NodeIdentifier nodeIdentifier, final int count) {
115 addBuilder(Builders.containerBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
119 public void startYangModeledAnyXmlNode(final NodeIdentifier nodeIdentifier, final int count) {
120 throw new UnsupportedOperationException("Not implemented yet");
124 public void startUnkeyedList(final NodeIdentifier nodeIdentifier, final int count) {
126 addBuilder(Builders.unkeyedListBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
130 public void startUnkeyedListItem(final NodeIdentifier nodeIdentifier, final int count) {
132 addBuilder(Builders.unkeyedListEntryBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
136 public void startMapNode(final NodeIdentifier nodeIdentifier, final int count) {
138 addBuilder(Builders.mapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
142 public void startMapEntryNode(final NodeIdentifierWithPredicates nodeIdentifierWithPredicates, final int count) {
144 addBuilder(Builders.mapEntryBuilder().withNodeIdentifier(nodeIdentifierWithPredicates),
145 nodeIdentifierWithPredicates);
149 public void startOrderedMapNode(final NodeIdentifier nodeIdentifier, final int count) {
151 addBuilder(Builders.orderedMapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
155 public void startChoiceNode(final NodeIdentifier nodeIdentifier, final int count) {
157 addBuilder(Builders.choiceBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
161 public void startAugmentationNode(final AugmentationIdentifier augmentationIdentifier) {
163 addBuilder(Builders.augmentationBuilder().withNodeIdentifier(augmentationIdentifier), augmentationIdentifier);
166 @SuppressWarnings("unchecked")
168 public void anyxmlNode(final NodeIdentifier nodeIdentifier, final Object value) {
171 NormalizedNodeBuilderWrapper parent = stack.peek();
172 AnyXmlNode anyXmlNode = Builders.anyXmlBuilder().withNodeIdentifier(nodeIdentifier).withValue((DOMSource) value)
174 if (parent != null) {
175 if (hasValidSchema(nodeIdentifier.getNodeType(), parent)) {
176 parent.builder().addChild(anyXmlNode);
179 // If there's no parent node then this is a stand alone AnyXmlNode.
180 if (nodePathSchemaNode != null) {
181 this.normalizedNode = anyXmlNode;
188 @SuppressWarnings("unchecked")
190 public void endNode() {
193 final NormalizedNodeBuilderWrapper child;
196 } catch (NoSuchElementException e) {
197 throw new IllegalStateException("endNode called on an empty stack", e);
200 if (child.getSchema() == null) {
201 LOG.debug("Schema not found for {}", child.identifier());
205 NormalizedNode<?, ?> newNode = child.builder().build();
206 if (stack.size() > 0) {
207 NormalizedNodeBuilderWrapper parent = stack.peek();
208 parent.builder().addChild(newNode);
210 this.normalizedNode = newNode;
216 public void close() {
221 public void flush() {
225 public NormalizedNode<?, ?> normalizedNode() {
226 return normalizedNode;
229 private void checkNotSealed() {
230 checkState(!sealed, "Pruner can be used only once");
233 private static boolean hasValidSchema(final QName name, final NormalizedNodeBuilderWrapper parent) {
234 final DataSchemaContextNode<?> parentSchema = parent.getSchema();
235 final boolean valid = parentSchema != null && parentSchema.getChild(name) != null;
237 LOG.debug("Schema not found for {}", name);
243 private NormalizedNodeBuilderWrapper addBuilder(final NormalizedNodeContainerBuilder<?, ?, ?, ?> builder,
244 final PathArgument identifier) {
245 final DataSchemaContextNode<?> schemaNode;
246 final NormalizedNodeBuilderWrapper parent = stack.peek();
247 if (parent != null) {
248 final DataSchemaContextNode<?> parentSchema = parent.getSchema();
249 schemaNode = parentSchema == null ? null : parentSchema.getChild(identifier);
251 schemaNode = nodePathSchemaNode;
254 NormalizedNodeBuilderWrapper wrapper = new NormalizedNodeBuilderWrapper(builder, identifier, schemaNode);