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.Preconditions;
13 import java.io.IOException;
15 import java.util.HashSet;
16 import java.util.LinkedList;
17 import java.util.List;
19 import javax.xml.transform.dom.DOMSource;
20 import org.opendaylight.yangtools.yang.common.QName;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
22 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
23 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
24 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
25 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
26 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
29 * The NormalizedNodePruner removes all nodes from the input NormalizedNode that do not have a corresponding
30 * schema element in the passed in SchemaContext
33 public class NormalizedNodePruner implements NormalizedNodeStreamWriter {
35 private final SimpleStack<NormalizedNodeBuilderWrapper> stack = new SimpleStack<>();
36 private NormalizedNode<?,?> normalizedNode;
37 private final Set<URI> validNamespaces;
38 private boolean sealed = false;
40 public NormalizedNodePruner(SchemaContext schemaContext) {
41 validNamespaces = new HashSet<>(schemaContext.getModules().size());
42 for(org.opendaylight.yangtools.yang.model.api.Module module : schemaContext.getModules()){
43 validNamespaces.add(module.getNamespace());
47 public void leafNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, Object o) throws IOException, IllegalArgumentException {
51 if(!isValidNamespace(nodeIdentifier)){
54 NormalizedNodeBuilderWrapper parent = stack.peek();
55 Preconditions.checkState(parent != null, "leafNode has no parent");
57 .addChild(Builders.leafBuilder()
58 .withNodeIdentifier(nodeIdentifier)
64 public void startLeafSet(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
68 addBuilder(Builders.leafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
72 public void leafSetEntryNode(Object o) throws IOException, IllegalArgumentException {
76 NormalizedNodeBuilderWrapper parent = stack.peek();
77 Preconditions.checkState(parent != null, "leafSetEntryNode has no parent");
78 if(!isValidNamespace(parent.identifier())){
83 .addChild(Builders.leafSetEntryBuilder()
85 .withNodeIdentifier(new YangInstanceIdentifier.NodeWithValue(parent.nodeType(), o))
90 public void startContainerNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
94 addBuilder(Builders.containerBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
98 public void startUnkeyedList(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
102 addBuilder(Builders.unkeyedListBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
106 public void startUnkeyedListItem(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalStateException {
110 addBuilder(Builders.unkeyedListEntryBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
114 public void startMapNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
118 addBuilder(Builders.mapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
122 public void startMapEntryNode(YangInstanceIdentifier.NodeIdentifierWithPredicates nodeIdentifierWithPredicates, int i) throws IOException, IllegalArgumentException {
126 addBuilder(Builders.mapEntryBuilder().withNodeIdentifier(nodeIdentifierWithPredicates), nodeIdentifierWithPredicates);
130 public void startOrderedMapNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
134 addBuilder(Builders.orderedMapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
138 public void startChoiceNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
142 addBuilder(Builders.choiceBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
146 public void startAugmentationNode(YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifier) throws IOException, IllegalArgumentException {
150 addBuilder(Builders.augmentationBuilder().withNodeIdentifier(augmentationIdentifier), augmentationIdentifier);
154 public void anyxmlNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, Object o) throws IOException, IllegalArgumentException {
158 if(!isValidNamespace(nodeIdentifier)){
161 NormalizedNodeBuilderWrapper parent = stack.peek();
162 Preconditions.checkState(parent != null, "anyxmlNode has no parent");
163 parent.builder().addChild(Builders.anyXmlBuilder().withNodeIdentifier(nodeIdentifier).withValue((DOMSource) o).build());
167 public void endNode() throws IOException, IllegalStateException {
171 NormalizedNodeBuilderWrapper child = stack.pop();
173 Preconditions.checkState(child != null, "endNode called on an empty stack");
175 if(!isValidNamespace(child.identifier())){
178 NormalizedNode<?,?> normalizedNode = child.builder().build();
180 if(stack.size() > 0){
181 NormalizedNodeBuilderWrapper parent = stack.peek();
182 parent.builder().addChild(normalizedNode);
184 this.normalizedNode = normalizedNode;
190 public void close() throws IOException {
195 public void flush() throws IOException {
199 public NormalizedNode<?,?> normalizedNode(){
200 return normalizedNode;
203 private void checkNotSealed(){
204 Preconditions.checkState(!sealed, "Pruner can be used only once");
207 private boolean isValidNamespace(QName qName){
208 return validNamespaces.contains(qName.getNamespace());
211 private boolean isValidNamespace(YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifier){
212 Set<QName> possibleChildNames = augmentationIdentifier.getPossibleChildNames();
214 for(QName qName : possibleChildNames){
215 if(isValidNamespace(qName)){
223 private boolean isValidNamespace(YangInstanceIdentifier.PathArgument identifier){
224 if(identifier instanceof YangInstanceIdentifier.AugmentationIdentifier){
225 return isValidNamespace((YangInstanceIdentifier.AugmentationIdentifier) identifier);
228 return isValidNamespace(identifier.getNodeType());
231 private NormalizedNodeBuilderWrapper addBuilder(NormalizedNodeContainerBuilder<?,?,?,?> builder, YangInstanceIdentifier.PathArgument identifier){
232 NormalizedNodeBuilderWrapper wrapper = new NormalizedNodeBuilderWrapper(builder, identifier);
238 static class SimpleStack<E> {
239 List<E> stack = new LinkedList<>();
241 void push(E element){
249 return stack.remove(stack.size() - 1);
257 return stack.get(stack.size() - 1);
266 SimpleStack<NormalizedNodeBuilderWrapper> stack(){