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.ReusableImmutableNormalizedNodeStreamWriter;
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.DataSchemaNode;
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 {
47 private interface WriterMethod<T extends PathArgument> {
49 void apply(ReusableImmutableNormalizedNodeStreamWriter writer, T name) throws IOException;
53 private interface SizedWriterMethod<T extends PathArgument> {
55 void apply(ReusableImmutableNormalizedNodeStreamWriter writer, T name, int childSizeHint) throws IOException;
58 private static final Logger LOG = LoggerFactory.getLogger(AbstractNormalizedNodePruner.class);
60 private final Deque<DataSchemaContextNode<?>> stack = new ArrayDeque<>();
61 private final ReusableImmutableNormalizedNodeStreamWriter delegate =
62 ReusableImmutableNormalizedNodeStreamWriter.create();
63 private final DataSchemaContextTree tree;
65 private DataSchemaContextNode<?> nodePathSchemaNode;
66 private State state = State.UNITIALIZED;
69 // FIXME: package-private to support unguarded NormalizedNodePruner access
70 NormalizedNode<?, ?> normalizedNode;
72 AbstractNormalizedNodePruner(final DataSchemaContextTree tree) {
73 this.tree = requireNonNull(tree);
76 AbstractNormalizedNodePruner(final SchemaContext schemaContext) {
77 this(DataSchemaContextTree.from(schemaContext));
80 final DataSchemaContextTree getTree() {
84 final void initialize(final YangInstanceIdentifier nodePath) {
85 nodePathSchemaNode = tree.findChild(nodePath).orElse(null);
87 normalizedNode = null;
94 public void startLeafNode(final NodeIdentifier name) throws IOException {
95 enter(ReusableImmutableNormalizedNodeStreamWriter::startLeafNode, name);
99 public void startLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
100 enter(ReusableImmutableNormalizedNodeStreamWriter::startLeafSet, name, childSizeHint);
104 public void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
105 enter(ReusableImmutableNormalizedNodeStreamWriter::startOrderedLeafSet, name, childSizeHint);
109 public void startLeafSetEntryNode(final NodeWithValue<?> name) throws IOException {
110 enter(ReusableImmutableNormalizedNodeStreamWriter::startLeafSetEntryNode, name);
114 public void startContainerNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
115 enter(ReusableImmutableNormalizedNodeStreamWriter::startContainerNode, name, childSizeHint);
119 public void startYangModeledAnyXmlNode(final NodeIdentifier nodeIdentifier, final int count) {
120 // FIXME: implement this
121 throw new UnsupportedOperationException("Not implemented yet");
125 public void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) throws IOException {
126 enter(ReusableImmutableNormalizedNodeStreamWriter::startUnkeyedList, name, childSizeHint);
130 public void startUnkeyedListItem(final NodeIdentifier name, final int childSizeHint) throws IOException {
131 enter(ReusableImmutableNormalizedNodeStreamWriter::startUnkeyedListItem, name, childSizeHint);
135 public void startMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
136 enter(ReusableImmutableNormalizedNodeStreamWriter::startMapNode, name, childSizeHint);
140 public void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint)
142 enter(ReusableImmutableNormalizedNodeStreamWriter::startMapEntryNode, identifier, childSizeHint);
146 public void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
147 enter(ReusableImmutableNormalizedNodeStreamWriter::startOrderedMapNode, name, childSizeHint);
151 public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
152 enter(ReusableImmutableNormalizedNodeStreamWriter::startChoiceNode, name, childSizeHint);
156 public void startAugmentationNode(final AugmentationIdentifier identifier) throws IOException {
157 enter(ReusableImmutableNormalizedNodeStreamWriter::startAugmentationNode, identifier);
161 public void startAnyxmlNode(final NodeIdentifier name) throws IOException {
162 enter(ReusableImmutableNormalizedNodeStreamWriter::startAnyxmlNode, name);
166 public void domSourceValue(final DOMSource value) throws IOException {
169 delegate.domSourceValue(value);
174 public void scalarValue(final Object value) throws IOException {
177 delegate.scalarValue(value);
182 public void endNode() throws IOException {
188 } catch (NoSuchElementException e) {
189 throw new IllegalStateException("endNode called on an empty stack", e);
195 // Still at unknown, do not attempt to create result
200 if (stack.isEmpty()) {
201 normalizedNode = delegate.getResult();
202 state = State.CLOSED;
207 public void close() throws IOException {
208 state = State.CLOSED;
214 public void flush() throws IOException {
219 * Return the resulting normalized node.
221 * @return Resulting node for the path, if it was not pruned
222 * @throws IllegalStateException if this pruner has not been closed
224 public final Optional<NormalizedNode<?, ?>> getResult() {
225 checkState(state == State.CLOSED, "Cannot get result in state %s", state);
226 return Optional.ofNullable(normalizedNode);
229 private void checkNotSealed() {
230 checkState(state == State.OPEN, "Illegal operation in state %s", state);
233 private boolean enter(final PathArgument name) {
237 LOG.debug("Skipping child {} in unknown subtree", name);
242 final DataSchemaContextNode<?> schema;
243 final DataSchemaContextNode<?> parent = stack.peek();
244 if (parent != null) {
245 schema = parent.getChild(name);
247 schema = nodePathSchemaNode;
250 if (schema == null) {
251 LOG.debug("Schema not found for {}", name);
257 final DataSchemaNode dataSchema = schema.getDataSchemaNode();
258 if (dataSchema != null) {
259 delegate.nextDataSchemaNode(dataSchema);
264 private <A extends PathArgument> void enter(final WriterMethod<A> method, final A name) throws IOException {
266 method.apply(delegate, name);
270 private <A extends PathArgument> void enter(final SizedWriterMethod<A> method, final A name, final int size)
273 method.apply(delegate, name, size);