View Javadoc
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   * Writer implementation using StAX.
25   *
26   * @author Erik van Zijst
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       * Creates a new StAX document with the default namespace set to the specified
39       * uri.
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 }