Fix odlparent-3.0.0 checkstyle issues
[mdsal.git] / binding / mdsal-binding-dom-codec / src / main / java / org / opendaylight / mdsal / binding / dom / codec / impl / BindingToNormalizedStreamWriter.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. 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.dom.codec.impl;
9
10 import com.google.common.base.Preconditions;
11 import java.io.IOException;
12 import java.util.AbstractMap;
13 import java.util.ArrayDeque;
14 import java.util.Deque;
15 import java.util.Map;
16 import java.util.Map.Entry;
17 import org.opendaylight.yangtools.concepts.Delegator;
18 import org.opendaylight.yangtools.yang.binding.Augmentation;
19 import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
20 import org.opendaylight.yangtools.yang.binding.DataContainer;
21 import org.opendaylight.yangtools.yang.binding.DataObject;
22 import org.opendaylight.yangtools.yang.binding.Identifiable;
23 import org.opendaylight.yangtools.yang.binding.Identifier;
24 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
25 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
26 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
28 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
29 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
30
31 final class BindingToNormalizedStreamWriter implements BindingStreamEventWriter, Delegator<NormalizedNodeStreamWriter> {
32     private final Deque<NodeCodecContext<?>> schema = new ArrayDeque<>();
33     private final NormalizedNodeStreamWriter delegate;
34     private final NodeCodecContext<?> rootNodeSchema;
35
36     BindingToNormalizedStreamWriter(final NodeCodecContext<?> rootNodeSchema,
37             final NormalizedNodeStreamWriter delegate) {
38         this.rootNodeSchema = Preconditions.checkNotNull(rootNodeSchema);
39         this.delegate = Preconditions.checkNotNull(delegate);
40     }
41
42     static BindingToNormalizedStreamWriter create(final NodeCodecContext<?> schema,
43             final NormalizedNodeStreamWriter delegate) {
44         return new BindingToNormalizedStreamWriter(schema, delegate);
45     }
46
47     private void emitSchema(final Object schemaNode) {
48         delegate.nextDataSchemaNode((DataSchemaNode) schemaNode);
49     }
50
51     NodeCodecContext<?> current() {
52         return schema.peek();
53     }
54
55     private NodeIdentifier duplicateSchemaEnter() {
56         final NodeCodecContext<?> next;
57         if (current() == null) {
58             // Entry of first node
59             next = rootNodeSchema;
60         } else {
61             next = current();
62         }
63         this.schema.push(next);
64         return (NodeIdentifier) current().getDomPathArgument();
65     }
66
67     @SuppressWarnings({"unchecked", "rawtypes"})
68     private <T extends YangInstanceIdentifier.PathArgument> T enter(final Class<?> name, final Class<T> identifier) {
69         final NodeCodecContext<?> next;
70         if (current() == null) {
71             // Entry of first node
72             next = rootNodeSchema;
73         } else {
74             Preconditions.checkArgument(current() instanceof DataContainerCodecContext, "Could not start node %s",
75                     name);
76             next = ((DataContainerCodecContext<?,?>) current()).streamChild((Class) name);
77         }
78         this.schema.push(next);
79         T arg = (T) next.getDomPathArgument();
80         return arg;
81     }
82
83     private <T extends YangInstanceIdentifier.PathArgument> T enter(final String localName, final Class<T> identifier) {
84         NodeCodecContext<?> current = current();
85         NodeCodecContext<?> next = ((DataObjectCodecContext<?,?>) current).getLeafChild(localName);
86         this.schema.push(next);
87         @SuppressWarnings("unchecked")
88         T arg = (T) next.getDomPathArgument();
89         return arg;
90     }
91
92     @Override
93     public NormalizedNodeStreamWriter getDelegate() {
94         return delegate;
95     }
96
97     @Override
98     public void endNode() throws IOException {
99         NodeCodecContext<?> left = schema.pop();
100         // NormalizedNode writer does not have entry into case, but into choice
101         // so for leaving case, we do not emit endNode.
102         if (!(left instanceof CaseNodeCodecContext)) {
103             getDelegate().endNode();
104         }
105     }
106
107     private Map.Entry<NodeIdentifier, Object> serializeLeaf(final String localName, final Object value) {
108         Preconditions.checkArgument(current() instanceof DataObjectCodecContext);
109
110         DataObjectCodecContext<?,?> currentCasted = (DataObjectCodecContext<?,?>) current();
111         LeafNodeCodecContext<?> leafContext = currentCasted.getLeafChild(localName);
112
113         NodeIdentifier domArg = (NodeIdentifier) leafContext.getDomPathArgument();
114         Object domValue = leafContext.getValueCodec().serialize(value);
115         emitSchema(leafContext.getSchema());
116         return new AbstractMap.SimpleEntry<>(domArg, domValue);
117     }
118
119     @Override
120     public void leafNode(final String localName, final Object value) throws IOException {
121         Entry<NodeIdentifier, Object> dom = serializeLeaf(localName, value);
122         getDelegate().leafNode(dom.getKey(), dom.getValue());
123     }
124
125     @Override
126     public void anyxmlNode(final String name, final Object value) throws IOException {
127         Entry<NodeIdentifier, Object> dom = serializeLeaf(name, value);
128         getDelegate().anyxmlNode(dom.getKey(), dom.getValue());
129     }
130
131     @Override
132     public void leafSetEntryNode(final Object value) throws IOException {
133         LeafNodeCodecContext<?> ctx = (LeafNodeCodecContext<?>) current();
134         getDelegate().leafSetEntryNode(ctx.getSchema().getQName(),
135             ctx.getValueCodec().serialize(value));
136     }
137
138     @Override
139     public void startAugmentationNode(final Class<? extends Augmentation<?>> augmentationType)
140             throws IOException {
141         getDelegate().startAugmentationNode(enter(augmentationType, AugmentationIdentifier.class));
142     }
143
144     @Override
145     public void startCase(final Class<? extends DataObject> caze, final int childSizeHint) {
146         enter(caze, NodeIdentifier.class);
147     }
148
149     @Override
150     public void startChoiceNode(final Class<? extends DataContainer> type, final int childSizeHint)
151             throws IOException {
152         getDelegate().startChoiceNode(enter(type, NodeIdentifier.class), childSizeHint);
153     }
154
155     @Override
156     public void startContainerNode(final Class<? extends DataObject> object, final int childSizeHint)
157             throws IOException {
158         getDelegate().startContainerNode(enter(object, NodeIdentifier.class), childSizeHint);
159     }
160
161     @Override
162     public void startLeafSet(final String localName, final int childSizeHint) throws IOException {
163         final NodeIdentifier id = enter(localName, NodeIdentifier.class);
164         emitSchema(current().getSchema());
165         getDelegate().startLeafSet(id, childSizeHint);
166     }
167
168     @Override
169     public void startOrderedLeafSet(final String localName, final int childSizeHint) throws IOException {
170         getDelegate().startOrderedLeafSet(enter(localName, NodeIdentifier.class), childSizeHint);
171     }
172
173     @Override
174     public void startMapEntryNode(final Identifier<?> key, final int childSizeHint) throws IOException {
175         duplicateSchemaEnter();
176         NodeIdentifierWithPredicates identifier = ((KeyedListNodeCodecContext<?>) current()).serialize(key);
177         getDelegate().startMapEntryNode(identifier, childSizeHint);
178     }
179
180     @Override
181     public <T extends DataObject & Identifiable<?>> void startMapNode(final Class<T> mapEntryType,
182             final int childSizeHint) throws IOException {
183         getDelegate().startMapNode(enter(mapEntryType, NodeIdentifier.class), childSizeHint);
184     }
185
186     @Override
187     public <T extends DataObject & Identifiable<?>> void startOrderedMapNode(final Class<T> mapEntryType,
188             final int childSizeHint) throws IOException {
189         getDelegate().startOrderedMapNode(enter(mapEntryType, NodeIdentifier.class), childSizeHint);
190     }
191
192     @Override
193     public void startUnkeyedList(final Class<? extends DataObject> obj, final int childSizeHint) throws IOException {
194         getDelegate().startUnkeyedList(enter(obj, NodeIdentifier.class), childSizeHint);
195     }
196
197     @Override
198     public void startUnkeyedListItem(final int childSizeHint) throws IOException {
199         getDelegate().startUnkeyedListItem(duplicateSchemaEnter(), childSizeHint);
200     }
201
202     @Override
203     public void flush() throws IOException {
204         getDelegate().flush();
205     }
206
207     @Override
208     public void close() throws IOException {
209         getDelegate().close();
210     }
211 }