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.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.model.api.SchemaContext;
31 * The NormalizedNodePruner removes all nodes from the input NormalizedNode that do not have a corresponding
32 * schema element in the passed in SchemaContext
35 public class NormalizedNodePruner implements NormalizedNodeStreamWriter {
37 public static final URI BASE_NAMESPACE = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0");
38 private final SimpleStack<NormalizedNodeBuilderWrapper> stack = new SimpleStack<>();
39 private NormalizedNode<?,?> normalizedNode;
40 private final Set<URI> validNamespaces;
41 private boolean sealed = false;
43 public NormalizedNodePruner(SchemaContext schemaContext) {
44 this(NormalizedNodePruner.namespaces(schemaContext));
47 public NormalizedNodePruner(Set<URI> validNamespaces) {
48 this.validNamespaces = validNamespaces;
51 @SuppressWarnings("unchecked")
53 public void leafNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, Object o) throws IOException, IllegalArgumentException {
57 if(!isValidNamespace(nodeIdentifier)){
61 NormalizedNodeBuilderWrapper parent = stack.peek();
62 LeafNode<Object> leafNode = Builders.leafBuilder().withNodeIdentifier(nodeIdentifier).withValue(o).build();
64 parent.builder().addChild(leafNode);
66 // If there's no parent node then this is a stand alone LeafNode.
67 this.normalizedNode = leafNode;
73 public void startLeafSet(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
77 addBuilder(Builders.leafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
81 public void startOrderedLeafSet(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
85 addBuilder(Builders.orderedLeafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
88 @SuppressWarnings({ "unchecked" })
90 public void leafSetEntryNode(QName name, Object o) throws IOException, IllegalArgumentException {
93 if(!isValidNamespace(name)){
97 NormalizedNodeBuilderWrapper parent = stack.peek();
99 parent.builder().addChild(Builders.leafSetEntryBuilder().withValue(o).withNodeIdentifier(
100 new YangInstanceIdentifier.NodeWithValue<>(parent.nodeType(), o)).build());
102 // If there's no parent LeafSetNode then this is a stand alone LeafSetEntryNode.
103 this.normalizedNode = Builders.leafSetEntryBuilder().withValue(o).withNodeIdentifier(
104 new YangInstanceIdentifier.NodeWithValue<>(name, o)).build();
110 public void startContainerNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
114 addBuilder(Builders.containerBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
118 public void startYangModeledAnyXmlNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
119 throw new UnsupportedOperationException("Not implemented yet");
123 public void startUnkeyedList(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
127 addBuilder(Builders.unkeyedListBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
131 public void startUnkeyedListItem(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalStateException {
135 addBuilder(Builders.unkeyedListEntryBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
139 public void startMapNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
143 addBuilder(Builders.mapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
147 public void startMapEntryNode(YangInstanceIdentifier.NodeIdentifierWithPredicates nodeIdentifierWithPredicates, int i) throws IOException, IllegalArgumentException {
151 addBuilder(Builders.mapEntryBuilder().withNodeIdentifier(nodeIdentifierWithPredicates), nodeIdentifierWithPredicates);
155 public void startOrderedMapNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
159 addBuilder(Builders.orderedMapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
163 public void startChoiceNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
167 addBuilder(Builders.choiceBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
171 public void startAugmentationNode(YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifier) throws IOException, IllegalArgumentException {
175 addBuilder(Builders.augmentationBuilder().withNodeIdentifier(augmentationIdentifier), augmentationIdentifier);
178 @SuppressWarnings("unchecked")
180 public void anyxmlNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, Object o) throws IOException, IllegalArgumentException {
183 if(!isValidNamespace(nodeIdentifier)){
187 NormalizedNodeBuilderWrapper parent = stack.peek();
188 AnyXmlNode anyXmlNode = Builders.anyXmlBuilder().withNodeIdentifier(nodeIdentifier).
189 withValue((DOMSource) o).build();
191 parent.builder().addChild(anyXmlNode);
193 // If there's no parent node then this is a stand alone AnyXmlNode.
194 this.normalizedNode = anyXmlNode;
200 public void endNode() throws IOException, IllegalStateException {
204 NormalizedNodeBuilderWrapper child = stack.pop();
206 Preconditions.checkState(child != null, "endNode called on an empty stack");
208 if(!isValidNamespace(child.identifier())){
211 NormalizedNode<?,?> normalizedNode = child.builder().build();
213 if(stack.size() > 0){
214 NormalizedNodeBuilderWrapper parent = stack.peek();
215 parent.builder().addChild(normalizedNode);
217 this.normalizedNode = normalizedNode;
223 public void close() throws IOException {
228 public void flush() throws IOException {
232 public NormalizedNode<?,?> normalizedNode(){
233 return normalizedNode;
236 private void checkNotSealed(){
237 Preconditions.checkState(!sealed, "Pruner can be used only once");
240 private boolean isValidNamespace(QName qName){
241 return validNamespaces.contains(qName.getNamespace());
244 private boolean isValidNamespace(YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifier){
245 Set<QName> possibleChildNames = augmentationIdentifier.getPossibleChildNames();
247 for(QName qName : possibleChildNames){
248 if(isValidNamespace(qName)){
256 private boolean isValidNamespace(YangInstanceIdentifier.PathArgument identifier){
257 if(identifier instanceof YangInstanceIdentifier.AugmentationIdentifier){
258 return isValidNamespace((YangInstanceIdentifier.AugmentationIdentifier) identifier);
261 return isValidNamespace(identifier.getNodeType());
264 private NormalizedNodeBuilderWrapper addBuilder(NormalizedNodeContainerBuilder<?,?,?,?> builder, YangInstanceIdentifier.PathArgument identifier){
265 NormalizedNodeBuilderWrapper wrapper = new NormalizedNodeBuilderWrapper(builder, identifier);
271 static class SimpleStack<E> {
272 List<E> stack = new LinkedList<>();
274 void push(E element){
282 return stack.remove(stack.size() - 1);
290 return stack.get(stack.size() - 1);
299 SimpleStack<NormalizedNodeBuilderWrapper> stack(){
303 public static Set<URI> namespaces(SchemaContext schemaContext){
304 Set<URI> namespaces = new HashSet<>(schemaContext.getModules().size());
305 namespaces.add(BASE_NAMESPACE);
306 for(org.opendaylight.yangtools.yang.model.api.Module module : schemaContext.getModules()){
307 namespaces.add(module.getNamespace());