1 package com.atlassian.dbexporter.node.stax;
2
3 import com.atlassian.dbexporter.ImportExportErrorService;
4 import com.atlassian.dbexporter.node.NodeCreator;
5 import com.atlassian.dbexporter.node.NodeStreamWriter;
6 import javanet.staxutils.IndentingXMLStreamWriter;
7
8 import javax.xml.bind.DatatypeConverter;
9 import javax.xml.stream.XMLStreamException;
10 import javax.xml.stream.XMLStreamWriter;
11 import java.io.Reader;
12 import java.io.Writer;
13 import java.math.BigDecimal;
14 import java.math.BigInteger;
15 import java.nio.charset.Charset;
16 import java.util.Date;
17
18 import static com.atlassian.dbexporter.node.stax.StaxUtils.newDateFormat;
19 import static com.atlassian.dbexporter.node.stax.StaxUtils.newXmlOutputFactory;
20 import static com.atlassian.dbexporter.node.stax.StaxUtils.unicodeEncode;
21 import static com.google.common.base.Preconditions.checkNotNull;
22
23
24
25
26
27
28 public final class StaxStreamWriter implements NodeStreamWriter {
29 private static final String XMLSCHEMA_URI = "http://www.w3.org/2001/XMLSchema-instance";
30
31 private final ImportExportErrorService errorService;
32 private final XMLStreamWriter writer;
33 private final String nameSpaceUri;
34 private final Charset charset;
35 private boolean rootExists = false;
36
37
38
39
40
41 public StaxStreamWriter(ImportExportErrorService errorService, Writer output, Charset charset, String nameSpaceUri) {
42 this.errorService = checkNotNull(errorService);
43 this.writer = new IndentingXMLStreamWriter(checkNotNull(createXmlStreamWriter(output)));
44 this.charset = checkNotNull(charset);
45 this.nameSpaceUri = checkNotNull(nameSpaceUri);
46 }
47
48 private XMLStreamWriter createXmlStreamWriter(Writer writer) {
49 try {
50 return newXmlOutputFactory().createXMLStreamWriter(writer);
51 } catch (XMLStreamException xe) {
52 throw errorService.newParseException(xe);
53 }
54 }
55
56 public NodeCreator addRootNode(String name) {
57 if (rootExists) {
58 throw new IllegalStateException("Root node already created.");
59 } else {
60 try {
61 writer.writeStartDocument(charset.name(), "1.0");
62 rootExists = true;
63
64 NodeCreator nc = new NodeCreator() {
65 private long depth = 0L;
66
67 public NodeCreator addNode(String name) {
68 try {
69 writer.writeStartElement(name);
70 depth++;
71 return this;
72 } catch (XMLStreamException e) {
73 throw errorService.newParseException(e);
74 }
75 }
76
77 public NodeCreator closeEntity() {
78 try {
79 writer.writeEndElement();
80 return --depth == 0L ? null : this;
81 } catch (XMLStreamException e) {
82 throw errorService.newParseException(e);
83 }
84 }
85
86 public NodeCreator setContentAsDate(Date date) {
87 return setContentAsString(date == null ? null : newDateFormat().format(date));
88 }
89
90 @Override
91 public NodeCreator setContentAsBigInteger(BigInteger bigInteger) {
92 return setContentAsString(bigInteger == null ? null : bigInteger.toString());
93 }
94
95 @Override
96 public NodeCreator setContentAsBigDecimal(BigDecimal bigDecimal) {
97 return setContentAsString(bigDecimal == null ? null : bigDecimal.toString());
98 }
99
100 @Override
101 public NodeCreator setContentAsBoolean(Boolean bool) {
102 return setContentAsString(bool == null ? null : Boolean.toString(bool));
103 }
104
105 @Override
106 public NodeCreator setContentAsBinary(byte[] bytes) {
107
108 return setContentAsString(bytes == null ? null : DatatypeConverter.printBase64Binary(bytes));
109 }
110
111 public NodeCreator setContentAsString(String value) {
112 try {
113 if (value == null) {
114 writer.writeAttribute(XMLSCHEMA_URI, "nil", "true");
115 } else {
116 writer.writeCharacters(unicodeEncode(value));
117 }
118 return this;
119 } catch (XMLStreamException e) {
120 throw errorService.newParseException(e);
121 }
122 }
123
124 public NodeCreator setContent(Reader data) {
125 throw new AssertionError("Not implemented");
126 }
127
128 public NodeCreator addAttribute(String key, String value) {
129 try {
130 writer.writeAttribute(key, unicodeEncode(value));
131 return this;
132 } catch (XMLStreamException e) {
133 throw errorService.newParseException(e);
134 }
135 }
136 };
137 NodeCreator nodeCreator = nc.addNode(name);
138 writer.writeDefaultNamespace(nameSpaceUri);
139 writer.writeNamespace("xsi", XMLSCHEMA_URI);
140 return nodeCreator;
141 } catch (XMLStreamException e) {
142 throw errorService.newParseException("Unable to create the root node.", e);
143 }
144 }
145 }
146
147 public void flush() {
148 try {
149 writer.flush();
150 } catch (XMLStreamException e) {
151 throw errorService.newParseException(e);
152 }
153 }
154
155 public void close() {
156 try {
157 writer.close();
158 } catch (XMLStreamException e) {
159 throw errorService.newParseException(e);
160 }
161 }
162 }