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;
11 import static java.util.Objects.requireNonNull;
13 import java.io.IOException;
14 import java.util.ArrayDeque;
15 import java.util.Deque;
16 import java.util.NoSuchElementException;
17 import java.util.Optional;
18 import javax.xml.transform.dom.DOMSource;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
24 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
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.NormalizedNodeBuilder;
29 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
30 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
31 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
36 * The NormalizedNodePruner removes all nodes from the input NormalizedNode that do not have a corresponding
37 * schema element in the passed in SchemaContext.
39 abstract class AbstractNormalizedNodePruner implements NormalizedNodeStreamWriter {
46 private static final Logger LOG = LoggerFactory.getLogger(AbstractNormalizedNodePruner.class);
48 private final Deque<NormalizedNodeBuilderWrapper> stack = new ArrayDeque<>();
49 private final DataSchemaContextTree tree;
51 private DataSchemaContextNode<?> nodePathSchemaNode;
52 private State state = State.UNITIALIZED;
54 // FIXME: package-private to support unguarded NormalizedNodePruner access
55 NormalizedNode<?, ?> normalizedNode;
57 AbstractNormalizedNodePruner(final DataSchemaContextTree tree) {
58 this.tree = requireNonNull(tree);
61 AbstractNormalizedNodePruner(final SchemaContext schemaContext) {
62 this(DataSchemaContextTree.from(schemaContext));
65 final DataSchemaContextTree getTree() {
69 final void initialize(final YangInstanceIdentifier nodePath) {
70 nodePathSchemaNode = tree.findChild(nodePath).orElse(null);
71 normalizedNode = null;
77 public void startLeafNode(final NodeIdentifier name) {
78 addBuilder(Builders.leafBuilder().withNodeIdentifier(name), name);
82 public void startLeafSet(final NodeIdentifier nodeIdentifier, final int count) {
83 addBuilder(Builders.leafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
87 public void startOrderedLeafSet(final NodeIdentifier nodeIdentifier, final int str) {
88 addBuilder(Builders.orderedLeafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
92 public void startLeafSetEntryNode(final NodeWithValue<?> name) throws IOException {
93 addBuilder(Builders.leafSetEntryBuilder().withNodeIdentifier(name), name);
97 public void startContainerNode(final NodeIdentifier nodeIdentifier, final int count) {
98 addBuilder(Builders.containerBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
102 public void startYangModeledAnyXmlNode(final NodeIdentifier nodeIdentifier, final int count) {
103 throw new UnsupportedOperationException("Not implemented yet");
107 public void startUnkeyedList(final NodeIdentifier nodeIdentifier, final int count) {
108 addBuilder(Builders.unkeyedListBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
112 public void startUnkeyedListItem(final NodeIdentifier nodeIdentifier, final int count) {
113 addBuilder(Builders.unkeyedListEntryBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
117 public void startMapNode(final NodeIdentifier nodeIdentifier, final int count) {
118 addBuilder(Builders.mapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
122 public void startMapEntryNode(final NodeIdentifierWithPredicates nodeIdentifierWithPredicates, final int count) {
123 addBuilder(Builders.mapEntryBuilder().withNodeIdentifier(nodeIdentifierWithPredicates),
124 nodeIdentifierWithPredicates);
128 public void startOrderedMapNode(final NodeIdentifier nodeIdentifier, final int count) {
129 addBuilder(Builders.orderedMapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
133 public void startChoiceNode(final NodeIdentifier nodeIdentifier, final int count) {
134 addBuilder(Builders.choiceBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
138 public void startAugmentationNode(final AugmentationIdentifier augmentationIdentifier) {
139 addBuilder(Builders.augmentationBuilder().withNodeIdentifier(augmentationIdentifier), augmentationIdentifier);
143 public void startAnyxmlNode(final NodeIdentifier name) {
144 addBuilder(Builders.anyXmlBuilder().withNodeIdentifier(name), name);
148 public void domSourceValue(final DOMSource value) {
153 public void scalarValue(final Object value) {
158 public void endNode() {
161 final NormalizedNodeBuilderWrapper child;
164 } catch (NoSuchElementException e) {
165 throw new IllegalStateException("endNode called on an empty stack", e);
168 if (child.getSchema() == null) {
169 LOG.debug("Schema not found for {}", child.identifier());
170 if (stack.isEmpty()) {
171 normalizedNode = null;
172 state = State.CLOSED;
177 final NormalizedNode<?, ?> newNode = child.build();
178 final NormalizedNodeBuilderWrapper parent = stack.peek();
179 if (parent == null) {
180 normalizedNode = newNode;
181 state = State.CLOSED;
183 parent.addChild(newNode);
188 public void close() {
189 state = State.CLOSED;
194 public void flush() {
199 * Return the resulting normalized node.
201 * @return Resulting node for the path, if it was not pruned
202 * @throws IllegalStateException if this pruner has not been closed
204 public final Optional<NormalizedNode<?, ?>> getResult() {
205 checkState(state == State.CLOSED, "Cannot get result in state %s", state);
206 return Optional.ofNullable(normalizedNode);
209 private void checkNotSealed() {
210 checkState(state == State.OPEN, "Illegal operation in state %s", state);
213 private void setValue(final Object value) {
215 final NormalizedNodeBuilderWrapper current = stack.peek();
216 checkState(current != null, "Attempted to set value %s while no node is open", value);
217 current.setValue(value);
220 private <T extends NormalizedNodeBuilder<?, ?, ?>> NormalizedNodeBuilderWrapper addBuilder(final T builder,
221 final PathArgument identifier) {
224 final DataSchemaContextNode<?> schemaNode;
225 final NormalizedNodeBuilderWrapper parent = stack.peek();
226 if (parent != null) {
227 schemaNode = parent.childSchema(identifier);
229 schemaNode = nodePathSchemaNode;
232 NormalizedNodeBuilderWrapper wrapper = new NormalizedNodeBuilderWrapper(builder, identifier, schemaNode);