2 * Copyright (c) 2014 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.yangtools.yang.data.impl.schema;
10 import com.google.common.base.Preconditions;
11 import java.util.ArrayDeque;
12 import java.util.Deque;
13 import java.util.List;
14 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
15 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
16 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
18 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
19 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
20 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
21 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
22 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
23 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
24 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
25 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder;
26 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
27 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
28 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
29 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListNodeBuilder;
33 * Implementation of {@link NormalizedNodeStreamWriter}, which constructs
34 * immutable instances of {@link NormalizedNode}s.
36 * This writer supports two modes of behaviour one is using {@link #from(NormalizedNodeResult)}
37 * where resulting NormalizedNode will be stored in supplied result object.
39 * Other mode of operation is using {@link #from(NormalizedNodeContainerBuilder)},
40 * where all created nodes will be written to this builder.
44 public class ImmutableNormalizedNodeStreamWriter implements NormalizedNodeStreamWriter {
48 @SuppressWarnings("rawtypes")
49 private final Deque<NormalizedNodeContainerBuilder> builders;
52 @SuppressWarnings("rawtypes")
53 private ImmutableNormalizedNodeStreamWriter( final NormalizedNodeContainerBuilder topLevelBuilder) {
54 builders = new ArrayDeque<>();
55 builders.push(topLevelBuilder);
59 * Creates a {@link NormalizedNodeStreamWriter} which creates instances of supplied
60 * {@link NormalizedNode}s and writes them to supplied builder as child nodes.
62 * Type of supplied {@link NormalizedNodeContainerBuilder} affects,
63 * which events could be emitted in order to ensure proper construction of
66 * @param builder Builder to which data will be written.
67 * @return {@link NormalizedNodeStreamWriter} which writes data
69 public static final NormalizedNodeStreamWriter from(final NormalizedNodeContainerBuilder<?, ?, ?, ?> builder) {
70 return new ImmutableNormalizedNodeStreamWriter(builder);
75 * Creates a {@link NormalizedNodeStreamWriter} which creates one instance of top
76 * level {@link NormalizedNode} (type of NormalizedNode) is determined by first
79 * Result is built when {@link #endNode()} associated with that start event
82 * Writer properly creates also nested {@link NormalizedNode} instances,
83 * if their are supported inside the scope of first event.
85 * This method is useful for clients, which knows there will be one
86 * top level node written, but does not know which type of {@link NormalizedNode}
90 * @param result {@link NormalizedNodeResult} object which will hold result value.
91 * @return {@link NormalizedNodeStreamWriter} whcih will write item to supplied result holder.
93 public static final NormalizedNodeStreamWriter from(final NormalizedNodeResult result) {
94 return new ImmutableNormalizedNodeStreamWriter(new NormalizedNodeResultBuilder(result));
98 @SuppressWarnings("rawtypes")
99 private NormalizedNodeContainerBuilder getCurrent() {
100 return builders.peek();
103 @SuppressWarnings("rawtypes")
104 private void enter(final NormalizedNodeContainerBuilder next) {
108 @SuppressWarnings("unchecked")
109 private void writeChild(final NormalizedNode<?, ?> child) {
110 getCurrent().addChild(child);
114 @SuppressWarnings({"rawtypes","unchecked"})
115 public void endNode() {
116 final NormalizedNodeContainerBuilder finishedBuilder = builders.poll();
117 Preconditions.checkState(finishedBuilder != null, "Node which should be closed does not exists.");
118 NormalizedNodeContainerBuilder current = getCurrent();
119 Preconditions.checkState(current != null, "Reached top level node, which could not be closed in this writer.");
120 NormalizedNode<PathArgument, ?> product = finishedBuilder.build();
121 current.addChild(product);
125 public void leafNode(final NodeIdentifier name, final Object value) throws IllegalArgumentException {
126 checkDataNodeContainer();
127 writeChild(ImmutableNodes.leafNode(name, value));
131 public void startLeafSet(final NodeIdentifier name,final int childSizeHint) throws IllegalArgumentException {
132 checkDataNodeContainer();
133 ListNodeBuilder<Object, LeafSetEntryNode<Object>> builder = Builders.leafSetBuilder();
134 builder.withNodeIdentifier(name);
139 public void leafSetEntryNode(final Object value) throws IllegalArgumentException {
140 Preconditions.checkArgument(getCurrent() instanceof ImmutableLeafSetNodeBuilder<?>);
141 @SuppressWarnings("unchecked")
142 ListNodeBuilder<Object, LeafSetEntryNode<Object>> builder = ((ImmutableLeafSetNodeBuilder<Object>) getCurrent());
143 builder.withChildValue(value);
147 public void anyxmlNode(final NodeIdentifier name, final Object value) throws IllegalArgumentException {
148 checkDataNodeContainer();
154 public void startContainerNode(final NodeIdentifier name,final int childSizeHint) throws IllegalArgumentException {
155 checkDataNodeContainer();
156 enter(Builders.containerBuilder().withNodeIdentifier(name));
160 public void startUnkeyedList(final NodeIdentifier name,final int childSizeHint) throws IllegalArgumentException {
161 checkDataNodeContainer();
162 enter(Builders.unkeyedListBuilder().withNodeIdentifier(name));
166 public void startUnkeyedListItem(final NodeIdentifier name,final int childSizeHint) throws IllegalStateException {
167 Preconditions.checkArgument(getCurrent() instanceof ImmutableUnkeyedListNodeBuilder);
168 enter(Builders.unkeyedListEntryBuilder().withNodeIdentifier(name));
172 public void startMapNode(final NodeIdentifier name,final int childSizeHint) throws IllegalArgumentException {
173 checkDataNodeContainer();
174 enter(Builders.mapBuilder().withNodeIdentifier(name));
178 public void startMapEntryNode(final NodeIdentifierWithPredicates identifier,final int childSizeHint) throws IllegalArgumentException {
179 if(!(getCurrent() instanceof NormalizedNodeResultBuilder)) {
180 Preconditions.checkArgument(getCurrent() instanceof ImmutableMapNodeBuilder);
182 enter(Builders.mapEntryBuilder().withNodeIdentifier(identifier));
186 public void startOrderedMapNode(final NodeIdentifier name,final int childSizeHint) throws IllegalArgumentException {
187 if(!(getCurrent() instanceof NormalizedNodeResultBuilder)) {
188 Preconditions.checkArgument(getCurrent() instanceof ImmutableOrderedMapNodeBuilder);
190 enter(Builders.mapBuilder().withNodeIdentifier(name));
194 public void startChoiceNode(final NodeIdentifier name,final int childSizeHint) throws IllegalArgumentException {
195 checkDataNodeContainer();
196 enter(Builders.choiceBuilder().withNodeIdentifier(name));
199 public void startAugmentationNode(final AugmentationIdentifier identifier) throws IllegalArgumentException {
200 checkDataNodeContainer();
201 Preconditions.checkArgument(!(getCurrent() instanceof ImmutableAugmentationNodeBuilder));
202 enter(Builders.augmentationBuilder().withNodeIdentifier(identifier));
205 private void checkDataNodeContainer() {
206 @SuppressWarnings("rawtypes")
207 NormalizedNodeContainerBuilder current = getCurrent();
208 if(!(current instanceof NormalizedNodeResultBuilder)) {
209 Preconditions.checkArgument(current instanceof DataContainerNodeBuilder<?, ?>, "Invalid nesting of data.");
213 @SuppressWarnings("rawtypes")
214 private static final class NormalizedNodeResultBuilder implements NormalizedNodeContainerBuilder {
216 private final NormalizedNodeResult result;
218 public NormalizedNodeResultBuilder(final NormalizedNodeResult result) {
219 this.result = result;
223 public NormalizedNodeBuilder withValue(final Object value) {
224 throw new UnsupportedOperationException();
228 public NormalizedNode build() {
229 throw new IllegalStateException("Can not close NormalizedNodeResult");
233 public NormalizedNodeContainerBuilder withNodeIdentifier(final PathArgument nodeIdentifier) {
234 throw new UnsupportedOperationException();
238 public NormalizedNodeContainerBuilder withValue(final List value) {
239 throw new UnsupportedOperationException();
243 public NormalizedNodeContainerBuilder addChild(final NormalizedNode child) {
244 result.setResult(child);
249 public NormalizedNodeContainerBuilder removeChild(final PathArgument key) {
250 throw new UnsupportedOperationException();