ff21106cd3d5f946a6a67e3389ddca791dab1163
[yangtools.git] / codec / 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         ANYDATA,
35     }
36
37     private final Deque<NodeType> nodeTypeStack = new ArrayDeque<>();
38
39     SchemalessXMLStreamNormalizedNodeStreamWriter(final XMLStreamWriter writer) {
40         super(writer);
41     }
42
43     @Override
44     public void startLeafNode(final NodeIdentifier name) throws IOException {
45         nodeTypeStack.push(NodeType.SCALAR);
46         startElement(name.getNodeType());
47     }
48
49     @Override
50     public void startLeafSetEntryNode(final NodeWithValue<?> name) throws IOException {
51         nodeTypeStack.push(NodeType.SCALAR);
52         startElement(name.getNodeType());
53     }
54
55     @Override
56     public void startLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
57         nodeTypeStack.push(NodeType.LEAF_SET);
58     }
59
60     @Override
61     public void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
62         nodeTypeStack.push(NodeType.LEAF_SET);
63     }
64
65     @Override
66     public void startContainerNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
67         nodeTypeStack.push(NodeType.CONTAINER);
68         startElement(name.getNodeType());
69     }
70
71     @Override
72     public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
73         nodeTypeStack.push(NodeType.CHOICE);
74     }
75
76     @Override
77     public void startAugmentationNode(final AugmentationIdentifier identifier) throws IOException {
78         nodeTypeStack.push(NodeType.AUGMENTATION);
79     }
80
81     @Override
82     public boolean startAnyxmlNode(final NodeIdentifier name, final Class<?> objectModel) throws IOException {
83         if (DOMSource.class.isAssignableFrom(objectModel)) {
84             nodeTypeStack.push(NodeType.ANY_XML);
85             startElement(name.getNodeType());
86             return true;
87         }
88         return false;
89     }
90
91     @Override
92     String encodeValue(final ValueWriter xmlWriter, final Object value, final Object context) {
93         return value.toString();
94     }
95
96     @Override
97     String encodeAnnotationValue(final ValueWriter xmlWriter, final QName qname, final Object value) {
98         return value.toString();
99     }
100
101     @Override
102     void startList(final NodeIdentifier name) {
103         nodeTypeStack.push(NodeType.LIST);
104     }
105
106     @Override
107     void startListItem(final PathArgument name) throws IOException {
108         nodeTypeStack.push(NodeType.LIST_ITEM);
109         startElement(name.getNodeType());
110     }
111
112     @Override
113     public void scalarValue(final Object value) throws IOException {
114         final NodeType type = nodeTypeStack.peek();
115         if (type == NodeType.SCALAR) {
116             writeValue(value, null);
117         } else if (type == NodeType.ANYDATA) {
118             anydataValue(value);
119         } else {
120             throw new IllegalStateException("Unexpected scalar " + value + " in type " + type);
121         }
122     }
123
124     @Override
125     public void domSourceValue(final DOMSource value) throws IOException {
126         final NodeType type = nodeTypeStack.peek();
127         checkState(type == NodeType.ANY_XML, "Unexpected DOMSource %s in %s", value, type);
128         anyxmlValue(value);
129     }
130
131     @Override
132     public void endNode() throws IOException {
133         NodeType type = nodeTypeStack.pop();
134         switch (type) {
135             case CONTAINER:
136             case LIST_ITEM:
137             case SCALAR:
138             case ANY_XML:
139             case ANYDATA:
140                 endElement();
141                 break;
142             default:
143                 break;
144         }
145     }
146
147     @Override
148     void startAnydata(final NodeIdentifier name) {
149         nodeTypeStack.push(NodeType.ANYDATA);
150     }
151 }