Propagate @Nonnull and @Nullable annotations
[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 com.google.common.base.Strings;
11 import java.io.IOException;
12 import java.util.ArrayDeque;
13 import java.util.Collections;
14 import java.util.Deque;
15 import java.util.Map;
16 import java.util.Map.Entry;
17 import javax.annotation.Nonnull;
18 import javax.xml.stream.XMLStreamException;
19 import javax.xml.stream.XMLStreamWriter;
20 import org.opendaylight.yangtools.yang.common.QName;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
24 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
25
26 class SchemalessXMLStreamNormalizedNodeStreamWriter extends XMLStreamNormalizedNodeStreamWriter<Object> {
27     private enum ContainerType {
28         CONTAINER,
29         LEAF_SET,
30         LIST,
31         LIST_ITEM,
32         ANY_XML,
33         CHOICE,
34         AUGMENTATION
35     }
36
37     private final Deque<ContainerType> containerTypeStack = new ArrayDeque<>();
38     private final RandomPrefix randomPrefix;
39
40     private SchemalessXMLStreamNormalizedNodeStreamWriter(XMLStreamWriter writer) {
41         super(writer);
42         randomPrefix = new RandomPrefix();
43     }
44
45     static NormalizedNodeStreamWriter newInstance(XMLStreamWriter writer) {
46         return new SchemalessXMLStreamNormalizedNodeStreamWriter(writer);
47     }
48
49     @Override
50     public void leafNode(NodeIdentifier name, Object value, Map<QName, String> attributes) throws IOException {
51         writeElement(name.getNodeType(), value, attributes, null);
52     }
53
54     @Override
55     public void leafSetEntryNode(QName name, Object value, Map<QName, String> attributes) throws IOException {
56         writeElement(name, value, attributes, null);
57     }
58
59     @Override
60     public void leafNode(NodeIdentifier name, Object value) throws IOException {
61         writeElement(name.getNodeType(), value, Collections.emptyMap(), null);
62     }
63
64     @Override
65     public void leafSetEntryNode(QName name, Object value) throws IOException {
66         writeElement(name, value, Collections.emptyMap(), null);
67     }
68
69     @Override
70     public void startLeafSet(NodeIdentifier name, int childSizeHint) throws IOException {
71         containerTypeStack.push(ContainerType.LEAF_SET);
72     }
73
74     @Override
75     public void startOrderedLeafSet(NodeIdentifier name, int childSizeHint)
76             throws IOException, IllegalArgumentException {
77         containerTypeStack.push(ContainerType.LEAF_SET);
78     }
79
80     @Override
81     public void startContainerNode(NodeIdentifier name, int childSizeHint) throws IOException {
82         containerTypeStack.push(ContainerType.CONTAINER);
83         startElement(name.getNodeType());
84     }
85
86     @Override
87     public void startChoiceNode(NodeIdentifier name, int childSizeHint) throws IOException {
88         containerTypeStack.push(ContainerType.CHOICE);
89     }
90
91     @Override
92     public void startAugmentationNode(AugmentationIdentifier identifier) throws IOException {
93         containerTypeStack.push(ContainerType.AUGMENTATION);
94     }
95
96     @Override
97     public void anyxmlNode(NodeIdentifier name, Object value) throws IOException {
98         anyxmlNode(name.getNodeType(), value);
99     }
100
101     @Override
102     public void startYangModeledAnyXmlNode(NodeIdentifier name, int childSizeHint) throws IOException {
103         containerTypeStack.push(ContainerType.ANY_XML);
104         startElement(name.getNodeType());
105     }
106
107     @Override
108     protected void writeAttributes(@Nonnull final Map<QName, String> attributes) throws IOException {
109         for (final Entry<QName, String> qNameStringEntry : attributes.entrySet()) {
110             try {
111                 final String namespace = qNameStringEntry.getKey().getNamespace().toString();
112
113                 if (Strings.isNullOrEmpty(namespace)) {
114                     writer.writeAttribute(qNameStringEntry.getKey().getLocalName(), qNameStringEntry.getValue());
115                 } else {
116                     final String prefix = randomPrefix.encodePrefix(qNameStringEntry.getKey().getNamespace());
117                     writer.writeAttribute(prefix, namespace, qNameStringEntry.getKey().getLocalName(), qNameStringEntry
118                             .getValue());
119                 }
120             } catch (final XMLStreamException e) {
121                 throw new IOException("Unable to emit attribute " + qNameStringEntry, e);
122             }
123         }
124     }
125
126     @Override
127     protected void writeValue(XMLStreamWriter xmlWriter, QName qname, @Nonnull Object value, Object context)
128             throws XMLStreamException {
129         xmlWriter.writeCharacters(value.toString());
130     }
131
132     @Override
133     protected void startList(NodeIdentifier name) {
134         containerTypeStack.push(ContainerType.LIST);
135     }
136
137     @Override
138     protected void startListItem(PathArgument name) throws IOException {
139         containerTypeStack.push(ContainerType.LIST_ITEM);
140         startElement(name.getNodeType());
141     }
142
143     @Override
144     protected void endNode(XMLStreamWriter xmlWriter) throws IOException, XMLStreamException {
145         ContainerType type = containerTypeStack.pop();
146         switch (type) {
147         case CONTAINER:
148         case LIST_ITEM:
149         case ANY_XML:
150             xmlWriter.writeEndElement();
151             break;
152         default:
153             break;
154         }
155     }
156 }