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.binding.data.codec.impl;
10 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;
17 import java.util.Map.Entry;
19 import org.opendaylight.yangtools.concepts.Delegator;
20 import org.opendaylight.yangtools.yang.binding.Augmentation;
21 import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
22 import org.opendaylight.yangtools.yang.binding.DataContainer;
23 import org.opendaylight.yangtools.yang.binding.DataObject;
24 import org.opendaylight.yangtools.yang.binding.Identifiable;
25 import org.opendaylight.yangtools.yang.binding.Identifier;
26 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
29 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
30 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
32 class BindingToNormalizedStreamWriter implements BindingStreamEventWriter, Delegator<NormalizedNodeStreamWriter> {
34 private final NormalizedNodeStreamWriter delegate;
35 private final Deque<NodeCodecContext> schema = new ArrayDeque<>();
36 private final NodeCodecContext rootNodeSchema;
38 public BindingToNormalizedStreamWriter(final NodeCodecContext schema, final NormalizedNodeStreamWriter delegate) {
39 this.delegate = Preconditions.checkNotNull(delegate, "Delegate must not be null");
40 this.rootNodeSchema = Preconditions.checkNotNull(schema);
44 private NodeCodecContext current() {
48 private NodeIdentifier duplicateSchemaEnter() {
49 final NodeCodecContext next;
50 if (current() == null) {
51 // Entry of first node
52 next = rootNodeSchema;
56 this.schema.push(next);
57 return (NodeIdentifier) current().getDomPathArgument();
60 private <T extends YangInstanceIdentifier.PathArgument> T enter(final Class<?> name, final Class<T> identifier) {
61 final NodeCodecContext next;
62 if (current() == null) {
63 // Entry of first node
64 next = rootNodeSchema;
66 Preconditions.checkArgument((current() instanceof DataContainerCodecContext), "Could not start node %s",
68 next = ((DataContainerCodecContext<?>) current()).getStreamChild(name);
70 this.schema.push(next);
71 @SuppressWarnings("unchecked")
72 T arg = (T) next.getDomPathArgument();
76 private <T extends YangInstanceIdentifier.PathArgument> T enter(final String localName, final Class<T> identifier) {
77 NodeCodecContext current = current();
78 NodeCodecContext next = ((DataObjectCodecContext<?>) current).getLeafChild(localName);
79 this.schema.push(next);
80 @SuppressWarnings("unchecked")
81 T arg = (T) next.getDomPathArgument();
86 public void endNode() throws IOException {
87 NodeCodecContext left = schema.pop();
88 // NormalizedNode writer does not have entry into case, but into choice
89 // so for leaving case, we do not emit endNode.
90 if (!(left instanceof CaseNodeCodecContext)) {
91 getDelegate().endNode();
96 public NormalizedNodeStreamWriter getDelegate() {
100 private Map.Entry<NodeIdentifier, Object> serializeLeaf(final String localName, final Object value) {
101 Preconditions.checkArgument(current() instanceof DataObjectCodecContext<?>);
103 DataObjectCodecContext<?> currentCasted = (DataObjectCodecContext<?>) current();
104 LeafNodeCodecContext leafContext = currentCasted.getLeafChild(localName);
106 NodeIdentifier domArg = (NodeIdentifier) leafContext.getDomPathArgument();
107 Object domValue = leafContext.getValueCodec().serialize(value);
108 return new AbstractMap.SimpleEntry<>(domArg, domValue);
112 public void leafNode(final String localName, final Object value) throws IOException, IllegalArgumentException {
113 Entry<NodeIdentifier, Object> dom = serializeLeaf(localName, value);
114 getDelegate().leafNode(dom.getKey(), dom.getValue());
118 public void anyxmlNode(final String name, final Object value) throws IOException, IllegalArgumentException {
119 Entry<NodeIdentifier, Object> dom = serializeLeaf(name, value);
120 getDelegate().anyxmlNode(dom.getKey(), dom.getValue());
124 public void leafSetEntryNode(final Object value) throws IOException, IllegalArgumentException {
125 LeafNodeCodecContext ctx = (LeafNodeCodecContext) current();
126 getDelegate().leafSetEntryNode(ctx.getValueCodec().serialize(value));
130 public void startAugmentationNode(final Class<? extends Augmentation<?>> augmentationType)
131 throws IOException, IllegalArgumentException {
132 getDelegate().startAugmentationNode(enter(augmentationType, AugmentationIdentifier.class));
136 public void startCase(final Class<? extends DataObject> caze, final int childSizeHint)
137 throws IllegalArgumentException {
138 enter(caze, NodeIdentifier.class);
142 public void startChoiceNode(final Class<? extends DataContainer> type, final int childSizeHint)
143 throws IOException, IllegalArgumentException {
144 getDelegate().startChoiceNode(enter(type, NodeIdentifier.class), childSizeHint);
148 public void startContainerNode(final Class<? extends DataObject> object, final int childSizeHint)
149 throws IOException, IllegalArgumentException {
150 getDelegate().startContainerNode(enter(object, NodeIdentifier.class), childSizeHint);
154 public void startLeafSet(final String localName, final int childSizeHint) throws IOException, IllegalArgumentException {
155 getDelegate().startLeafSet(enter(localName, NodeIdentifier.class), childSizeHint);
159 public void startMapEntryNode(final Identifier<?> key, final int childSizeHint) throws IOException, IllegalArgumentException {
160 duplicateSchemaEnter();
161 NodeIdentifierWithPredicates identifier = ((ListNodeCodecContext) current()).serialize(key);
162 getDelegate().startMapEntryNode(identifier, childSizeHint);
166 public <T extends DataObject & Identifiable<?>> void startMapNode(final Class<T> mapEntryType,
167 final int childSizeHint) throws IOException, IllegalArgumentException {
168 getDelegate().startMapNode(enter(mapEntryType, NodeIdentifier.class), childSizeHint);
172 public <T extends DataObject & Identifiable<?>> void startOrderedMapNode(final Class<T> mapEntryType,
173 final int childSizeHint) throws IOException, IllegalArgumentException {
174 getDelegate().startOrderedMapNode(enter(mapEntryType, NodeIdentifier.class), childSizeHint);
178 public void startUnkeyedList(final Class<? extends DataObject> obj, final int childSizeHint)
179 throws IOException, IllegalArgumentException {
180 getDelegate().startUnkeyedList(enter(obj, NodeIdentifier.class), childSizeHint);
184 public void startUnkeyedListItem(final int childSizeHint) throws IllegalStateException, IOException {
185 getDelegate().startUnkeyedListItem(duplicateSchemaEnter(), childSizeHint);
189 public void flush() throws IOException {
190 getDelegate().flush();
194 public void close() throws IOException {
195 getDelegate().close();