1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package com.rapiddweller.platform.xml;
28
29 import com.rapiddweller.benerator.consumer.AbstractConsumer;
30 import com.rapiddweller.benerator.consumer.FileExporter;
31 import com.rapiddweller.common.ConfigurationError;
32 import com.rapiddweller.common.IOUtil;
33 import com.rapiddweller.common.StringUtil;
34 import com.rapiddweller.common.SystemInfo;
35 import com.rapiddweller.common.converter.ToStringConverter;
36 import com.rapiddweller.model.data.ComplexTypeDescriptor;
37 import com.rapiddweller.model.data.Entity;
38 import org.apache.logging.log4j.LogManager;
39 import org.apache.logging.log4j.Logger;
40 import org.xml.sax.SAXException;
41 import org.xml.sax.helpers.AttributesImpl;
42
43 import javax.xml.transform.OutputKeys;
44 import javax.xml.transform.Transformer;
45 import javax.xml.transform.TransformerConfigurationException;
46 import javax.xml.transform.sax.SAXTransformerFactory;
47 import javax.xml.transform.sax.TransformerHandler;
48 import javax.xml.transform.stream.StreamResult;
49 import java.io.FileNotFoundException;
50 import java.io.FileOutputStream;
51 import java.io.OutputStream;
52 import java.util.Map;
53
54
55
56
57
58
59
60
61 public class XMLEntityExporter extends AbstractConsumer implements FileExporter {
62
63 private static final Logger LOGGER = LogManager.getLogger(XMLEntityExporter.class);
64
65
66
67 private static final String DEFAULT_ENCODING = SystemInfo.getFileEncoding();
68 private static final String DEFAULT_URI = "export.xml";
69
70 private static final ToStringConverter converter = new ToStringConverter("", "yyyy-MM-dd", "yyyy-MM-dd'T'hh:mm:ss.SSS");
71
72
73
74 private String uri;
75 private String encoding;
76
77 private OutputStream out;
78 private TransformerHandler handler;
79
80
81
82
83
84
85 public XMLEntityExporter() {
86 this(DEFAULT_URI);
87 }
88
89
90
91
92
93
94 public XMLEntityExporter(String uri) {
95 this(uri, DEFAULT_ENCODING);
96 }
97
98
99
100
101
102
103
104 public XMLEntityExporter(String uri, String encoding) {
105 this.uri = uri;
106 this.encoding = encoding;
107 }
108
109
110
111 private static boolean hasSimpleType(Object value) {
112 return (!value.getClass().isArray() && !(value instanceof Entity));
113 }
114
115 @Override
116 public String getUri() {
117 return uri;
118 }
119
120
121
122
123
124
125 public void setUri(String uri) {
126 this.uri = uri;
127 }
128
129
130
131
132
133
134
135
136 public void setEncoding(String encoding) {
137 this.encoding = encoding;
138 }
139
140 @Override
141 public void startProductConsumption(Object object) {
142 LOGGER.debug("startConsuming({})", object);
143 if (out == null) {
144 initHandler();
145 }
146 Entity../../../../com/rapiddweller/model/data/Entity.html#Entity">Entity entity = (Entity) object;
147 renderElementStart(entity);
148 }
149
150 @Override
151 public void finishProductConsumption(Object object) {
152 LOGGER.debug("finishConsuming({})", object);
153 Entity../../../../com/rapiddweller/model/data/Entity.html#Entity">Entity entity = (Entity) object;
154 try {
155 handler.endElement("", "", entity.type());
156 } catch (SAXException e) {
157 throw new ConfigurationError("Error in processing element: " + entity, e);
158 }
159 }
160
161 @Override
162 public void flush() {
163 IOUtil.flush(out);
164 }
165
166
167
168 @Override
169 public void close() {
170 if (out != null) {
171 try {
172 if (handler != null) {
173 handler.endDocument();
174 handler = null;
175 }
176 } catch (SAXException e) {
177 throw new ConfigurationError("Error closing XML file.", e);
178 } finally {
179 IOUtil.close(out);
180 }
181 }
182 }
183
184 private void renderSimpleType(Object value) throws SAXException {
185 String s = converter.convert(value);
186 char[] cc = StringUtil.getChars(s);
187 handler.characters(cc, 0, cc.length);
188 }
189
190 private void renderElementStart(Entity entity) {
191 try {
192 AttributesImpl atts = new AttributesImpl();
193 for (Map.Entry<String, Object> entry : entity.getComponents().entrySet()) {
194 String key = entry.getKey();
195 Object value = entry.getValue();
196 if (value == null) {
197 continue;
198 }
199 if (key != null && !ComplexTypeDescriptor.__SIMPLE_CONTENT.equals(key) && hasSimpleType(value)) {
200 atts.addAttribute("", "", entry.getKey(), "CDATA", converter.convert(value));
201 }
202 }
203 handler.startElement("", "", entity.type(), atts);
204 Object content = entity.getComponent(ComplexTypeDescriptor.__SIMPLE_CONTENT);
205 if (content != null) {
206 renderSimpleType(content);
207 }
208 } catch (SAXException e) {
209 throw new ConfigurationError("Error in processing element: " + entity, e);
210 }
211 }
212
213 private void initHandler() {
214 LOGGER.debug("Initializing {}", uri);
215
216 try {
217
218 SAXTransformerFactory tf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
219 handler = tf.newTransformerHandler();
220
221 Transformer transformer = handler.getTransformer();
222 transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
223 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
224 transformer.setOutputProperty("{http://xml.apache.org/xslt}" + "indent-amount", "2");
225
226 out = new FileOutputStream(uri);
227 handler.setResult(new StreamResult(out));
228 handler.startDocument();
229 } catch (TransformerConfigurationException e) {
230 throw new ConfigurationError(e);
231 } catch (SAXException e) {
232 throw new ConfigurationError("Error in initializing XML file", e);
233 } catch (FileNotFoundException e) {
234 throw new RuntimeException("Error writing file " + uri, e);
235 }
236 }
237
238
239
240 @Override
241 public String toString() {
242 return getClass().getSimpleName() + '[' + uri + ']';
243 }
244
245 }