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;
14 import java.io.IOException;
16 import java.util.HashSet;
17 import java.util.LinkedList;
18 import java.util.List;
21 import javax.xml.transform.dom.DOMSource;
23 import org.opendaylight.yangtools.yang.common.QName;
24 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
25 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
27 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
28 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
29 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
32 * The NormalizedNodePruner removes all nodes from the input NormalizedNode that do not have a corresponding
33 * schema element in the passed in SchemaContext
36 public class NormalizedNodePruner implements NormalizedNodeStreamWriter {
38 public static final URI BASE_NAMESPACE = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0");
39 private final SimpleStack<NormalizedNodeBuilderWrapper> stack = new SimpleStack<>();
40 private NormalizedNode<?,?> normalizedNode;
41 private final Set<URI> validNamespaces;
42 private boolean sealed = false;
44 public NormalizedNodePruner(SchemaContext schemaContext) {
45 this(NormalizedNodePruner.namespaces(schemaContext));
48 public NormalizedNodePruner(Set<URI> validNamespaces) {
49 this.validNamespaces = validNamespaces;
53 public void leafNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, Object o) throws IOException, IllegalArgumentException {
57 if(!isValidNamespace(nodeIdentifier)){
60 NormalizedNodeBuilderWrapper parent = stack.peek();
61 Preconditions.checkState(parent != null, "leafNode has no parent");
63 .addChild(Builders.leafBuilder()
64 .withNodeIdentifier(nodeIdentifier)
70 public void startLeafSet(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
74 addBuilder(Builders.leafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
78 public void startOrderedLeafSet(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
82 addBuilder(Builders.orderedLeafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
86 public void leafSetEntryNode(Object o) throws IOException, IllegalArgumentException {
90 NormalizedNodeBuilderWrapper parent = stack.peek();
91 Preconditions.checkState(parent != null, "leafSetEntryNode has no parent");
92 if(!isValidNamespace(parent.identifier())){
97 .addChild(Builders.leafSetEntryBuilder()
99 .withNodeIdentifier(new YangInstanceIdentifier.NodeWithValue(parent.nodeType(), o))
104 public void startContainerNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
108 addBuilder(Builders.containerBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
112 public void startYangModeledAnyXmlNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
113 throw new UnsupportedOperationException("Not implemented yet");
117 public void startUnkeyedList(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
121 addBuilder(Builders.unkeyedListBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
125 public void startUnkeyedListItem(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalStateException {
129 addBuilder(Builders.unkeyedListEntryBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
133 public void startMapNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
137 addBuilder(Builders.mapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
141 public void startMapEntryNode(YangInstanceIdentifier.NodeIdentifierWithPredicates nodeIdentifierWithPredicates, int i) throws IOException, IllegalArgumentException {
145 addBuilder(Builders.mapEntryBuilder().withNodeIdentifier(nodeIdentifierWithPredicates), nodeIdentifierWithPredicates);
149 public void startOrderedMapNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
153 addBuilder(Builders.orderedMapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
157 public void startChoiceNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
161 addBuilder(Builders.choiceBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
165 public void startAugmentationNode(YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifier) throws IOException, IllegalArgumentException {
169 addBuilder(Builders.augmentationBuilder().withNodeIdentifier(augmentationIdentifier), augmentationIdentifier);
173 public void anyxmlNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, Object o) throws IOException, IllegalArgumentException {
177 if(!isValidNamespace(nodeIdentifier)){
180 NormalizedNodeBuilderWrapper parent = stack.peek();
181 Preconditions.checkState(parent != null, "anyxmlNode has no parent");
182 parent.builder().addChild(Builders.anyXmlBuilder().withNodeIdentifier(nodeIdentifier).withValue((DOMSource) o).build());
186 public void endNode() throws IOException, IllegalStateException {
190 NormalizedNodeBuilderWrapper child = stack.pop();
192 Preconditions.checkState(child != null, "endNode called on an empty stack");
194 if(!isValidNamespace(child.identifier())){
197 NormalizedNode<?,?> normalizedNode = child.builder().build();
199 if(stack.size() > 0){
200 NormalizedNodeBuilderWrapper parent = stack.peek();
201 parent.builder().addChild(normalizedNode);
203 this.normalizedNode = normalizedNode;
209 public void close() throws IOException {
214 public void flush() throws IOException {
218 public NormalizedNode<?,?> normalizedNode(){
219 return normalizedNode;
222 private void checkNotSealed(){
223 Preconditions.checkState(!sealed, "Pruner can be used only once");
226 private boolean isValidNamespace(QName qName){
227 return validNamespaces.contains(qName.getNamespace());
230 private boolean isValidNamespace(YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifier){
231 Set<QName> possibleChildNames = augmentationIdentifier.getPossibleChildNames();
233 for(QName qName : possibleChildNames){
234 if(isValidNamespace(qName)){
242 private boolean isValidNamespace(YangInstanceIdentifier.PathArgument identifier){
243 if(identifier instanceof YangInstanceIdentifier.AugmentationIdentifier){
244 return isValidNamespace((YangInstanceIdentifier.AugmentationIdentifier) identifier);
247 return isValidNamespace(identifier.getNodeType());
250 private NormalizedNodeBuilderWrapper addBuilder(NormalizedNodeContainerBuilder<?,?,?,?> builder, YangInstanceIdentifier.PathArgument identifier){
251 NormalizedNodeBuilderWrapper wrapper = new NormalizedNodeBuilderWrapper(builder, identifier);
257 static class SimpleStack<E> {
258 List<E> stack = new LinkedList<>();
260 void push(E element){
268 return stack.remove(stack.size() - 1);
276 return stack.get(stack.size() - 1);
285 SimpleStack<NormalizedNodeBuilderWrapper> stack(){
289 public static Set<URI> namespaces(SchemaContext schemaContext){
290 Set<URI> namespaces = new HashSet<>(schemaContext.getModules().size());
291 namespaces.add(BASE_NAMESPACE);
292 for(org.opendaylight.yangtools.yang.model.api.Module module : schemaContext.getModules()){
293 namespaces.add(module.getNamespace());