Fix odlparent-3.0.0 checkstyle issues
[mdsal.git] / binding2 / mdsal-binding2-dom-codec / src / main / java / org / opendaylight / mdsal / binding / javav2 / dom / codec / impl / serializer / BindingToNormalizedStreamWriter.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.mdsal.binding.javav2.dom.codec.impl.serializer;
9
10 import com.google.common.annotations.Beta;
11 import com.google.common.base.Preconditions;
12 import java.io.IOException;
13 import java.util.AbstractMap;
14 import java.util.ArrayDeque;
15 import java.util.Deque;
16 import java.util.Map;
17 import java.util.Map.Entry;
18 import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.context.CaseNodeCodecContext;
19 import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.context.KeyedListNodeCodecContext;
20 import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.context.base.DataContainerCodecContext;
21 import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.context.base.LeafNodeCodecContext;
22 import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.context.base.NodeCodecContext;
23 import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.context.base.TreeNodeCodecContext;
24 import org.opendaylight.mdsal.binding.javav2.spec.base.IdentifiableItem;
25 import org.opendaylight.mdsal.binding.javav2.spec.base.Item;
26 import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
27 import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingStreamEventWriter;
28 import org.opendaylight.mdsal.binding.javav2.spec.structural.Augmentation;
29 import org.opendaylight.yangtools.concepts.Delegator;
30 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
31 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
32 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
33 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
34 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
35 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
36
37 /**
38  * Stream event writer of Binding v2 representation.
39  */
40 @Beta
41 public final class BindingToNormalizedStreamWriter
42         implements BindingStreamEventWriter, Delegator<NormalizedNodeStreamWriter> {
43
44     private final Deque<NodeCodecContext<?>> schema = new ArrayDeque<>();
45     private final NormalizedNodeStreamWriter delegate;
46     private final NodeCodecContext<?> rootNodeSchema;
47
48     private BindingToNormalizedStreamWriter(final NodeCodecContext<?> rootNodeSchema,
49             final NormalizedNodeStreamWriter delegate) {
50         this.rootNodeSchema = Preconditions.checkNotNull(rootNodeSchema);
51         this.delegate = Preconditions.checkNotNull(delegate);
52     }
53
54     /**
55      * Create instance of Binding v2 representation writer.
56      *
57      * @param schema
58      *            - codec schema
59      * @param delegate
60      *            - DOM writer delegator
61      * @return instance of binding writer
62      */
63     public static BindingToNormalizedStreamWriter create(final NodeCodecContext<?> schema,
64             final NormalizedNodeStreamWriter delegate) {
65         return new BindingToNormalizedStreamWriter(schema, delegate);
66     }
67
68     private void emitSchema(final Object schemaNode) {
69         delegate.nextDataSchemaNode((DataSchemaNode) schemaNode);
70     }
71
72     /**
73      * Retrieves, but does not remove, the head of the queue represented by node
74      * codec context.
75      *
76      * @return head of queue
77      */
78     NodeCodecContext<?> current() {
79         return schema.peek();
80     }
81
82     private NodeIdentifier duplicateSchemaEnter() {
83         final NodeCodecContext<?> next;
84         if (current() == null) {
85             // Entry of first node
86             next = rootNodeSchema;
87         } else {
88             next = current();
89         }
90         this.schema.push(next);
91         return (NodeIdentifier) current().getDomPathArgument();
92     }
93
94     @SuppressWarnings({ "unchecked", "rawtypes" })
95     private <T extends YangInstanceIdentifier.PathArgument> T enter(final Class<?> name, final Class<T> identifier) {
96         final NodeCodecContext<?> next;
97         if (current() == null) {
98             // Entry of first node
99             next = rootNodeSchema;
100         } else {
101             Preconditions.checkArgument((current() instanceof DataContainerCodecContext), "Could not start node %s",
102                     name);
103             next = ((DataContainerCodecContext) current()).streamChild(name);
104         }
105         this.schema.push(next);
106         return (T) next.getDomPathArgument();
107     }
108
109     @SuppressWarnings("rawtypes")
110     private <T extends YangInstanceIdentifier.PathArgument> T enter(final String localName, final Class<T> identifier) {
111         final NodeCodecContext<?> current = current();
112         final NodeCodecContext<?> next = ((TreeNodeCodecContext) current).getLeafChild(localName);
113         this.schema.push(next);
114         @SuppressWarnings("unchecked")
115         final T arg = (T) next.getDomPathArgument();
116         return arg;
117     }
118
119     @Override
120     public NormalizedNodeStreamWriter getDelegate() {
121         return delegate;
122     }
123
124     @Override
125     public void endNode() throws IOException {
126         final NodeCodecContext<?> left = schema.pop();
127         // NormalizedNode writer does not have entry into case, but into choice
128         // so for leaving case, we do not emit endNode.
129         if (!(left instanceof CaseNodeCodecContext)) {
130             getDelegate().endNode();
131         }
132     }
133
134     private Map.Entry<NodeIdentifier, Object> serializeLeaf(final String localName, final Object value) {
135         Preconditions.checkArgument(current() instanceof TreeNodeCodecContext);
136
137         final TreeNodeCodecContext<?, ?> currentCasted = (TreeNodeCodecContext<?, ?>) current();
138         final LeafNodeCodecContext<?> leafContext = currentCasted.getLeafChild(localName);
139
140         final NodeIdentifier domArg = (NodeIdentifier) leafContext.getDomPathArgument();
141         final Object domValue = leafContext.getValueCodec().serialize(value);
142         emitSchema(leafContext.getSchema());
143         return new AbstractMap.SimpleEntry<>(domArg, domValue);
144     }
145
146     @Override
147     public void leafNode(final String localName, final Object value) throws IOException {
148         final Entry<NodeIdentifier, Object> dom = serializeLeaf(localName, value);
149         getDelegate().leafNode(dom.getKey(), dom.getValue());
150     }
151
152     @Override
153     public void startAnyxmlNode(final String name, final Object value) throws IOException {
154         final Entry<NodeIdentifier, Object> dom = serializeLeaf(name, value);
155         getDelegate().anyxmlNode(dom.getKey(), dom.getValue());
156     }
157
158     @Override
159     public void leafSetEntryNode(final Object value) throws IOException {
160         final LeafNodeCodecContext<?> ctx = (LeafNodeCodecContext<?>) current();
161         getDelegate().leafSetEntryNode(ctx.getSchema().getQName(), ctx.getValueCodec().serialize(value));
162     }
163
164     @Override
165     public void startAugmentationNode(final Class<? extends Augmentation<?>> augmentationType) throws IOException {
166         getDelegate().startAugmentationNode(enter(augmentationType, AugmentationIdentifier.class));
167     }
168
169     @Override
170     public void startCase(final Class<? extends TreeNode> caze, final int childSizeHint) {
171         enter(caze, NodeIdentifier.class);
172     }
173
174     @Override
175     public <T extends TreeNode> void startChoiceNode(final Item<T> choice, final int childSizeHint) throws IOException {
176         getDelegate().startChoiceNode(enter(choice.getType(), NodeIdentifier.class), childSizeHint);
177     }
178
179     @Override
180     public void startContainerNode(final Class<? extends TreeNode> object, final int childSizeHint)
181             throws IOException {
182         getDelegate().startContainerNode(enter(object, NodeIdentifier.class), childSizeHint);
183     }
184
185     @Override
186     public void startLeafSet(final String localName, final int childSizeHint) throws IOException {
187         final NodeIdentifier id = enter(localName, NodeIdentifier.class);
188         emitSchema(current().getSchema());
189         getDelegate().startLeafSet(id, childSizeHint);
190     }
191
192     @Override
193     public void startOrderedLeafSet(final String localName, final int childSizeHint) throws IOException {
194         getDelegate().startOrderedLeafSet(enter(localName, NodeIdentifier.class), childSizeHint);
195     }
196
197     @Override
198     public <I extends TreeNode, T> void startMapEntryNode(final IdentifiableItem<I, T> keyValues,
199             final int childSizeHint) throws IOException {
200         duplicateSchemaEnter();
201         final NodeIdentifierWithPredicates identifier = ((KeyedListNodeCodecContext<?>) current()).serialize(keyValues);
202         getDelegate().startMapEntryNode(identifier, childSizeHint);
203     }
204
205     @Override
206     public <I extends TreeNode, T> void startMapNode(final IdentifiableItem<I, T> mapEntryType, final int childSizeHint)
207             throws IOException {
208         getDelegate().startMapNode(enter(mapEntryType.getType(), NodeIdentifier.class), childSizeHint);
209     }
210
211     @Override
212     public <I extends TreeNode, T> void startOrderedMapNode(final IdentifiableItem<I, T> mapEntryType,
213             final int childSizeHint) throws IOException {
214         getDelegate().startOrderedMapNode(enter(mapEntryType.getType(), NodeIdentifier.class), childSizeHint);
215     }
216
217     @Override
218     public void startUnkeyedList(final Class<? extends TreeNode> localName, final int childSizeHint)
219             throws IOException {
220         getDelegate().startUnkeyedList(enter(localName, NodeIdentifier.class), childSizeHint);
221     }
222
223     @Override
224     public void startUnkeyedListItem(final int childSizeHint) throws IOException {
225         getDelegate().startUnkeyedListItem(duplicateSchemaEnter(), childSizeHint);
226     }
227
228     @Override
229     public void flush() throws IOException {
230         getDelegate().flush();
231     }
232
233     @Override
234     public void close() throws IOException {
235         getDelegate().close();
236     }
237
238     @Override
239     public void startAnydataNode(final String name, final Object value) throws IOException {
240         // TODO will be done when https://bugs.opendaylight.org/show_bug.cgi?id=8516 is completed
241     }
242 }