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.mdsal.binding.dom.codec.impl;
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;
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;
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;
36 BindingToNormalizedStreamWriter(final NodeCodecContext<?> rootNodeSchema,
37 final NormalizedNodeStreamWriter delegate) {
38 this.rootNodeSchema = Preconditions.checkNotNull(rootNodeSchema);
39 this.delegate = Preconditions.checkNotNull(delegate);
42 static BindingToNormalizedStreamWriter create(final NodeCodecContext<?> schema,
43 final NormalizedNodeStreamWriter delegate) {
44 return new BindingToNormalizedStreamWriter(schema, delegate);
47 private void emitSchema(final Object schemaNode) {
48 delegate.nextDataSchemaNode((DataSchemaNode) schemaNode);
51 NodeCodecContext<?> current() {
55 private NodeIdentifier duplicateSchemaEnter() {
56 final NodeCodecContext<?> next;
57 if (current() == null) {
58 // Entry of first node
59 next = rootNodeSchema;
63 this.schema.push(next);
64 return (NodeIdentifier) current().getDomPathArgument();
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;
74 Preconditions.checkArgument(current() instanceof DataContainerCodecContext, "Could not start node %s",
76 next = ((DataContainerCodecContext<?,?>) current()).streamChild((Class) name);
78 this.schema.push(next);
79 T arg = (T) next.getDomPathArgument();
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();
93 public NormalizedNodeStreamWriter getDelegate() {
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();
107 private Map.Entry<NodeIdentifier, Object> serializeLeaf(final String localName, final Object value) {
108 Preconditions.checkArgument(current() instanceof DataObjectCodecContext);
110 DataObjectCodecContext<?,?> currentCasted = (DataObjectCodecContext<?,?>) current();
111 LeafNodeCodecContext<?> leafContext = currentCasted.getLeafChild(localName);
113 NodeIdentifier domArg = (NodeIdentifier) leafContext.getDomPathArgument();
114 Object domValue = leafContext.getValueCodec().serialize(value);
115 emitSchema(leafContext.getSchema());
116 return new AbstractMap.SimpleEntry<>(domArg, domValue);
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());
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());
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));
139 public void startAugmentationNode(final Class<? extends Augmentation<?>> augmentationType)
141 getDelegate().startAugmentationNode(enter(augmentationType, AugmentationIdentifier.class));
145 public void startCase(final Class<? extends DataObject> caze, final int childSizeHint) {
146 enter(caze, NodeIdentifier.class);
150 public void startChoiceNode(final Class<? extends DataContainer> type, final int childSizeHint)
152 getDelegate().startChoiceNode(enter(type, NodeIdentifier.class), childSizeHint);
156 public void startContainerNode(final Class<? extends DataObject> object, final int childSizeHint)
158 getDelegate().startContainerNode(enter(object, NodeIdentifier.class), childSizeHint);
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);
169 public void startOrderedLeafSet(final String localName, final int childSizeHint) throws IOException {
170 getDelegate().startOrderedLeafSet(enter(localName, NodeIdentifier.class), childSizeHint);
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);
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);
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);
193 public void startUnkeyedList(final Class<? extends DataObject> obj, final int childSizeHint) throws IOException {
194 getDelegate().startUnkeyedList(enter(obj, NodeIdentifier.class), childSizeHint);
198 public void startUnkeyedListItem(final int childSizeHint) throws IOException {
199 getDelegate().startUnkeyedListItem(duplicateSchemaEnter(), childSizeHint);
203 public void flush() throws IOException {
204 getDelegate().flush();
208 public void close() throws IOException {
209 getDelegate().close();