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;
14 import java.io.IOException;
16 import java.util.LinkedList;
17 import java.util.List;
18 import javax.xml.transform.dom.DOMSource;
19 import org.opendaylight.yangtools.yang.common.QName;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
22 import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
23 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
24 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
25 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
26 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
27 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
28 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
29 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
30 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
35 * The NormalizedNodePruner removes all nodes from the input NormalizedNode that do not have a corresponding
36 * schema element in the passed in SchemaContext
39 public class NormalizedNodePruner implements NormalizedNodeStreamWriter {
40 private static final Logger LOG = LoggerFactory.getLogger(NormalizedNodePruner.class);
42 public static final URI BASE_NAMESPACE = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0");
43 private final SimpleStack<NormalizedNodeBuilderWrapper> stack = new SimpleStack<>();
44 private NormalizedNode<?,?> normalizedNode;
45 private final DataSchemaContextNode<?> nodePathSchemaNode;
46 private boolean sealed = false;
48 public NormalizedNodePruner(YangInstanceIdentifier nodePath, SchemaContext schemaContext) {
49 nodePathSchemaNode = findSchemaNodeForNodePath(nodePath, schemaContext);
52 @SuppressWarnings("unchecked")
54 public void leafNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, Object o) throws IOException, IllegalArgumentException {
58 NormalizedNodeBuilderWrapper parent = stack.peek();
59 LeafNode<Object> leafNode = Builders.leafBuilder().withNodeIdentifier(nodeIdentifier).withValue(o).build();
61 if(hasValidSchema(nodeIdentifier.getNodeType(), parent)) {
62 parent.builder().addChild(leafNode);
65 // If there's no parent node then this is a stand alone LeafNode.
66 if(nodePathSchemaNode != null) {
67 this.normalizedNode = leafNode;
75 public void startLeafSet(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
79 addBuilder(Builders.leafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
83 public void startOrderedLeafSet(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
87 addBuilder(Builders.orderedLeafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
90 @SuppressWarnings({ "unchecked" })
92 public void leafSetEntryNode(QName name, Object o) throws IOException, IllegalArgumentException {
95 NormalizedNodeBuilderWrapper parent = stack.peek();
97 if(hasValidSchema(name, parent)) {
98 parent.builder().addChild(Builders.leafSetEntryBuilder().withValue(o).withNodeIdentifier(
99 new YangInstanceIdentifier.NodeWithValue<>(parent.nodeType(), o)).build());
102 // If there's no parent LeafSetNode then this is a stand alone LeafSetEntryNode.
103 if(nodePathSchemaNode != null) {
104 this.normalizedNode = Builders.leafSetEntryBuilder().withValue(o).withNodeIdentifier(
105 new YangInstanceIdentifier.NodeWithValue<>(name, o)).build();
113 public void startContainerNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
117 addBuilder(Builders.containerBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
121 public void startYangModeledAnyXmlNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
122 throw new UnsupportedOperationException("Not implemented yet");
126 public void startUnkeyedList(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
130 addBuilder(Builders.unkeyedListBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
134 public void startUnkeyedListItem(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalStateException {
138 addBuilder(Builders.unkeyedListEntryBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
142 public void startMapNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
146 addBuilder(Builders.mapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
150 public void startMapEntryNode(YangInstanceIdentifier.NodeIdentifierWithPredicates nodeIdentifierWithPredicates, int i) throws IOException, IllegalArgumentException {
154 addBuilder(Builders.mapEntryBuilder().withNodeIdentifier(nodeIdentifierWithPredicates), nodeIdentifierWithPredicates);
158 public void startOrderedMapNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
162 addBuilder(Builders.orderedMapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
166 public void startChoiceNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
170 addBuilder(Builders.choiceBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
174 public void startAugmentationNode(YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifier) throws IOException, IllegalArgumentException {
178 addBuilder(Builders.augmentationBuilder().withNodeIdentifier(augmentationIdentifier), augmentationIdentifier);
181 @SuppressWarnings("unchecked")
183 public void anyxmlNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, Object o) throws IOException, IllegalArgumentException {
186 NormalizedNodeBuilderWrapper parent = stack.peek();
187 AnyXmlNode anyXmlNode = Builders.anyXmlBuilder().withNodeIdentifier(nodeIdentifier).
188 withValue((DOMSource) o).build();
190 if(hasValidSchema(nodeIdentifier.getNodeType(), parent)) {
191 parent.builder().addChild(anyXmlNode);
194 // If there's no parent node then this is a stand alone AnyXmlNode.
195 if(nodePathSchemaNode != null) {
196 this.normalizedNode = anyXmlNode;
204 public void endNode() throws IOException, IllegalStateException {
208 NormalizedNodeBuilderWrapper child = stack.pop();
210 Preconditions.checkState(child != null, "endNode called on an empty stack");
212 if(!child.getSchema().isPresent()) {
213 LOG.debug("Schema not found for {}", child.identifier());
217 NormalizedNode<?,?> normalizedNode = child.builder().build();
219 if(stack.size() > 0) {
220 NormalizedNodeBuilderWrapper parent = stack.peek();
221 parent.builder().addChild(normalizedNode);
223 this.normalizedNode = normalizedNode;
229 public void close() throws IOException {
234 public void flush() throws IOException {
238 public NormalizedNode<?,?> normalizedNode(){
239 return normalizedNode;
242 private void checkNotSealed(){
243 Preconditions.checkState(!sealed, "Pruner can be used only once");
246 private static boolean hasValidSchema(QName name, NormalizedNodeBuilderWrapper parent) {
247 boolean valid = parent.getSchema().isPresent() && parent.getSchema().get().getChild(name) != null;
249 LOG.debug("Schema not found for {}", name);
255 private NormalizedNodeBuilderWrapper addBuilder(NormalizedNodeContainerBuilder<?,?,?,?> builder,
256 PathArgument identifier){
257 final Optional<DataSchemaContextNode<?>> schemaNode;
258 NormalizedNodeBuilderWrapper parent = stack.peek();
260 schemaNode = Optional.fromNullable(nodePathSchemaNode);
261 } else if(parent.getSchema().isPresent()) {
262 schemaNode = Optional.fromNullable(parent.getSchema().get().getChild(identifier));
264 schemaNode = Optional.absent();
267 NormalizedNodeBuilderWrapper wrapper = new NormalizedNodeBuilderWrapper(builder, identifier, schemaNode);
272 private static DataSchemaContextNode<?> findSchemaNodeForNodePath(YangInstanceIdentifier nodePath,
273 SchemaContext schemaContext) {
274 DataSchemaContextNode<?> schemaNode = DataSchemaContextTree.from(schemaContext).getRoot();
275 for(PathArgument arg : nodePath.getPathArguments()) {
276 schemaNode = schemaNode.getChild(arg);
277 if(schemaNode == null) {
286 static class SimpleStack<E> {
287 List<E> stack = new LinkedList<>();
289 void push(E element){
297 return stack.remove(stack.size() - 1);
305 return stack.get(stack.size() - 1);