Add support for opaque anydata XML output
[yangtools.git] / yang / yang-data-codec-xml / src / main / java / org / opendaylight / yangtools / yang / data / codec / xml / SchemalessXMLStreamNormalizedNodeStreamWriter.java
1 /*
2  * Copyright (c) 2016 Brocade Communications 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.yangtools.yang.data.codec.xml;
9
10 import static com.google.common.base.Preconditions.checkState;
11
12 import java.io.IOException;
13 import java.util.ArrayDeque;
14 import java.util.Deque;
15 import javax.xml.stream.XMLStreamWriter;
16 import javax.xml.transform.dom.DOMSource;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
22
23 final class SchemalessXMLStreamNormalizedNodeStreamWriter extends XMLStreamNormalizedNodeStreamWriter<Object> {
24     private enum NodeType {
25         CONTAINER,
26         LEAF_SET,
27         LIST,
28         LIST_ITEM,
29         YANG_MODELED_ANY_XML,
30         CHOICE,
31         AUGMENTATION,
32         SCALAR,
33         ANY_XML,
34     }
35
36     private final Deque<NodeType> nodeTypeStack = new ArrayDeque<>();
37
38     SchemalessXMLStreamNormalizedNodeStreamWriter(final XMLStreamWriter writer) {
39         super(writer);
40     }
41
42     @Override
43     public void startLeafNode(final NodeIdentifier name) throws IOException {
44         nodeTypeStack.push(NodeType.SCALAR);
45         startElement(name.getNodeType());
46     }
47
48     @Override
49     public void startLeafSetEntryNode(final NodeWithValue<?> name) throws IOException {
50         nodeTypeStack.push(NodeType.SCALAR);
51         startElement(name.getNodeType());
52     }
53
54     @Override
55     public void startLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
56         nodeTypeStack.push(NodeType.LEAF_SET);
57     }
58
59     @Override
60     public void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
61         nodeTypeStack.push(NodeType.LEAF_SET);
62     }
63
64     @Override
65     public void startContainerNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
66         nodeTypeStack.push(NodeType.CONTAINER);
67         startElement(name.getNodeType());
68     }
69
70     @Override
71     public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
72         nodeTypeStack.push(NodeType.CHOICE);
73     }
74
75     @Override
76     public void startAugmentationNode(final AugmentationIdentifier identifier) throws IOException {
77         nodeTypeStack.push(NodeType.AUGMENTATION);
78     }
79
80     @Override
81     public void startAnyxmlNode(final NodeIdentifier name) throws IOException {
82         nodeTypeStack.push(NodeType.ANY_XML);
83         startElement(name.getNodeType());
84     }
85
86     @Override
87     public void startYangModeledAnyXmlNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
88         nodeTypeStack.push(NodeType.YANG_MODELED_ANY_XML);
89         startElement(name.getNodeType());
90     }
91
92     @Override
93     String encodeValue(final ValueWriter xmlWriter, final Object value, final Object context) {
94         return value.toString();
95     }
96
97     @Override
98     String encodeAnnotationValue(final ValueWriter xmlWriter, final QName qname, final Object value) {
99         return value.toString();
100     }
101
102     @Override
103     void startList(final NodeIdentifier name) {
104         nodeTypeStack.push(NodeType.LIST);
105     }
106
107     @Override
108     void startListItem(final PathArgument name) throws IOException {
109         nodeTypeStack.push(NodeType.LIST_ITEM);
110         startElement(name.getNodeType());
111     }
112
113     @Override
114     public void scalarValue(final Object value) throws IOException {
115         final NodeType type = nodeTypeStack.peek();
116         checkState(type == NodeType.SCALAR, "Unexpected scalar %s in %s", value, type);
117         writeValue(value, null);
118     }
119
120     @Override
121     public void domSourceValue(final DOMSource value) throws IOException {
122         final NodeType type = nodeTypeStack.peek();
123         checkState(type == NodeType.ANY_XML, "Unexpected DOMSource %s in %s", value, type);
124         anyxmlValue(value);
125     }
126
127     @Override
128     public void endNode() throws IOException {
129         NodeType type = nodeTypeStack.pop();
130         switch (type) {
131             case CONTAINER:
132             case LIST_ITEM:
133             case SCALAR:
134             case ANY_XML:
135                 endElement();
136                 break;
137             default:
138                 break;
139         }
140     }
141
142     @Override
143     Object startAnydata(final NodeIdentifier name) {
144         nodeTypeStack.push(NodeType.ANY_XML);
145         return null;
146     }
147 }