1 /*
2 *
3 * The DbUnit Database Testing Framework
4 * Copyright (C)2002-2004, DbUnit.org
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22 package org.dbunit.dataset.xml;
23
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27 import org.dbunit.dataset.CachedDataSet;
28 import org.dbunit.dataset.DataSetException;
29 import org.dbunit.dataset.IDataSet;
30
31 import org.xml.sax.InputSource;
32
33 import java.io.File;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.OutputStream;
37 import java.io.Reader;
38 import java.io.Writer;
39 import java.net.URL;
40
41 /**
42 * Reads and writes flat XML dataset document. Each XML element corresponds to a table row.
43 * Each XML element name corresponds to a table name. The XML attributes
44 * correspond to table columns.
45 * <p>
46 * Flat XML dataset document sample:
47 * <p>
48 * <pre>
49 * <!DOCTYPE dataset SYSTEM "my-dataset.dtd">
50 * <dataset>
51 * <TEST_TABLE COL0="row 0 col 0"
52 * COL1="row 0 col 1"
53 * COL2="row 0 col 2"/>
54 * <TEST_TABLE COL1="row 1 col 1"/>
55 * <SECOND_TABLE COL0="row 0 col 0"
56 * COL1="row 0 col 1" />
57 * <EMPTY_TABLE/>
58 * </dataset></pre>
59 * <p>
60 * To specify null values, omit corresponding attribute.
61 * In the above example, missing COL0 and COL2 attributes of TEST_TABLE second row represents null values.
62 * <p>
63 * Table metadata is deduced from the first row of each table by default.
64 * <b>Beware that DbUnit may think a table misses some columns if the first row of that table has one or more null values.</b>
65 * You can do one of the following things to avoid this:
66 * <ul>
67 * <li>Use a DTD. DbUnit will use the columns declared in the DTD as table metadata.
68 * DbUnit only supports external system URI. The URI can be absolute or relative.
69 * </li>
70 * <li>Since DBUnit 2.3.0 there is a functionality called "column sensing" which basically
71 * reads in the whole XML into a buffer and dynamically adds new columns as they appear.
72 * It can be used as demonstrated in the following example:
73 * <pre>
74 * // since dbunit 2.4.7
75 * FlatXmlDataSetBuilder builder = new FlatXmlDataSetBuilder();
76 * builder.setInputSource(new File("src/xml/flatXmlTableTest.xml"));
77 * builder.setColumnSensing(true);
78 * IDataSet dataSet = builder.build();
79 *
80 * // or dbunit release <= 2.4.6:
81 * boolean enableColumnSensing = true;
82 * IDataSet dataSet = new FlatXmlDataSet(
83 * new File("src/xml/flatXmlTableTest.xml"), false, enableColumnSensing);
84 * </pre>
85 * </li>
86 * </ul>
87 * </p>
88 *
89 * @author Manuel Laflamme
90 * @author gommma (gommma AT users.sourceforge.net)
91 * @author Last changed by: $Author: gommma $
92 * @version $Revision: 1048 $ $Date: 2009-09-26 18:21:40 +0200 (sab, 26 set 2009) $
93 * @since 1.0 (Mar 12, 2002)
94 */
95 public class FlatXmlDataSet extends CachedDataSet
96 {
97 /**
98 * Logger for this class
99 */
100 private static final Logger logger = LoggerFactory.getLogger(FlatXmlDataSet.class);
101
102 /**
103 * Creates a new {@link FlatXmlDataSet} with the data of the given producer.
104 * @param flatXmlProducer The producer that provides the {@link FlatXmlDataSet} content
105 * @throws DataSetException
106 * @since 2.4.7
107 */
108 public FlatXmlDataSet(FlatXmlProducer flatXmlProducer) throws DataSetException
109 {
110 super(flatXmlProducer, flatXmlProducer.isCaseSensitiveTableNames());
111 }
112
113 /**
114 * Creates an FlatXmlDataSet object with the specified InputSource.
115 * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
116 */
117 public FlatXmlDataSet(InputSource source) throws IOException, DataSetException
118 {
119 super(new FlatXmlProducer(source));
120 }
121
122 /**
123 * Creates an FlatXmlDataSet object with the specified xml file.
124 * Relative DOCTYPE uri are resolved from the xml file path.
125 *
126 * @param xmlFile the xml file
127 * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
128 */
129 public FlatXmlDataSet(File xmlFile) throws IOException, DataSetException
130 {
131 this(xmlFile, true);
132 }
133
134 /**
135 * Creates an FlatXmlDataSet object with the specified xml file.
136 * Relative DOCTYPE uri are resolved from the xml file path.
137 *
138 * @param xmlFile the xml file
139 * @param dtdMetadata if <code>false</code> do not use DTD as metadata
140 * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
141 */
142 public FlatXmlDataSet(File xmlFile, boolean dtdMetadata)
143 throws IOException, DataSetException
144 {
145 this(xmlFile.toURL(), dtdMetadata);
146 }
147
148 /**
149 * Creates an FlatXmlDataSet object with the specified xml file.
150 * Relative DOCTYPE uri are resolved from the xml file path.
151 *
152 * @param xmlFile the xml file
153 * @param dtdMetadata if <code>false</code> do not use DTD as metadata
154 * @param columnSensing Whether or not the columns should be sensed automatically. Every XML row
155 * is scanned for columns that have not been there in a previous column.
156 * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
157 */
158 public FlatXmlDataSet(File xmlFile, boolean dtdMetadata, boolean columnSensing)
159 throws IOException, DataSetException
160 {
161 this(xmlFile.toURL(), dtdMetadata, columnSensing);
162 }
163
164 /**
165 * Creates an FlatXmlDataSet object with the specified xml file.
166 * Relative DOCTYPE uri are resolved from the xml file path.
167 *
168 * @param xmlFile the xml file
169 * @param dtdMetadata if <code>false</code> do not use DTD as metadata
170 * @param columnSensing Whether or not the columns should be sensed automatically. Every XML row
171 * is scanned for columns that have not been there in a previous column.
172 * @param caseSensitiveTableNames Whether or not this dataset should use case sensitive table names
173 * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
174 */
175 public FlatXmlDataSet(File xmlFile, boolean dtdMetadata, boolean columnSensing, boolean caseSensitiveTableNames)
176 throws IOException, DataSetException
177 {
178 this(xmlFile.toURL(), dtdMetadata, columnSensing, caseSensitiveTableNames);
179 }
180
181 /**
182 * Creates an FlatXmlDataSet object with the specified xml URL.
183 * Relative DOCTYPE uri are resolved from the xml file path.
184 *
185 * @param xmlUrl the xml URL
186 * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
187 */
188 public FlatXmlDataSet(URL xmlUrl) throws IOException, DataSetException
189 {
190 this(xmlUrl, true);
191 }
192
193 /**
194 * Creates an FlatXmlDataSet object with the specified xml URL.
195 * Relative DOCTYPE uri are resolved from the xml file path.
196 *
197 * @param xmlUrl the xml URL
198 * @param dtdMetadata if <code>false</code> do not use DTD as metadata
199 * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
200 */
201 public FlatXmlDataSet(URL xmlUrl, boolean dtdMetadata)
202 throws IOException, DataSetException
203 {
204 this(xmlUrl, dtdMetadata, false);
205 }
206
207
208 /**
209 * Creates an FlatXmlDataSet object with the specified xml URL.
210 * Relative DOCTYPE uri are resolved from the xml file path.
211 *
212 * @param xmlUrl the xml URL
213 * @param dtdMetadata if <code>false</code> do not use DTD as metadata
214 * @param columnSensing Whether or not the columns should be sensed automatically. Every XML row
215 * is scanned for columns that have not been there in a previous column.
216 * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
217 */
218 public FlatXmlDataSet(URL xmlUrl, boolean dtdMetadata, boolean columnSensing)
219 throws IOException, DataSetException
220 {
221 super(new FlatXmlProducer(
222 new InputSource(xmlUrl.toString()), dtdMetadata, columnSensing));
223 }
224
225 /**
226 * Creates an FlatXmlDataSet object with the specified xml file.
227 * Relative DOCTYPE uri are resolved from the xml file path.
228 *
229 * @param xmlUrl the xml file
230 * @param dtdMetadata if <code>false</code> do not use DTD as metadata
231 * @param columnSensing Whether or not the columns should be sensed automatically. Every XML row
232 * is scanned for columns that have not been there in a previous column.
233 * @param caseSensitiveTableNames Whether or not this dataset should use case sensitive table names
234 * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
235 */
236 public FlatXmlDataSet(URL xmlUrl, boolean dtdMetadata, boolean columnSensing, boolean caseSensitiveTableNames)
237 throws IOException, DataSetException
238 {
239 super(new FlatXmlProducer(
240 new InputSource(xmlUrl.toString()), dtdMetadata, columnSensing, caseSensitiveTableNames),
241 caseSensitiveTableNames);
242 }
243
244 /**
245 * Creates an FlatXmlDataSet object with the specified xml reader.
246 * Relative DOCTYPE uri are resolved from the current working directory.
247 *
248 * @param xmlReader the xml reader
249 * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
250 */
251 public FlatXmlDataSet(Reader xmlReader) throws IOException, DataSetException
252 {
253 this(xmlReader, true);
254 }
255
256 /**
257 * Creates an FlatXmlDataSet object with the specified xml reader.
258 * Relative DOCTYPE uri are resolved from the current working directory.
259 *
260 * @param xmlReader the xml reader
261 * @param dtdMetadata if <code>false</code> do not use DTD as metadata
262 * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
263 */
264 public FlatXmlDataSet(Reader xmlReader, boolean dtdMetadata)
265 throws IOException, DataSetException
266 {
267 this(xmlReader, dtdMetadata, false, false);
268 }
269
270 /**
271 * Creates an FlatXmlDataSet object with the specified xml file.
272 * Relative DOCTYPE uri are resolved from the xml file path.
273 *
274 * @param xmlReader the xml reader
275 * @param dtdMetadata if <code>false</code> do not use DTD as metadata
276 * @param columnSensing Whether or not the columns should be sensed automatically. Every XML row
277 * is scanned for columns that have not been there in a previous column.
278 * @param caseSensitiveTableNames Whether or not this dataset should use case sensitive table names
279 * @since 2.4.3
280 * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
281 */
282 public FlatXmlDataSet(Reader xmlReader, boolean dtdMetadata, boolean columnSensing, boolean caseSensitiveTableNames)
283 throws IOException, DataSetException
284 {
285 super(new FlatXmlProducer(new InputSource(xmlReader), dtdMetadata, columnSensing, caseSensitiveTableNames),
286 caseSensitiveTableNames);
287 }
288
289 /**
290 * Creates an FlatXmlDataSet object with the specified xml and dtd readers.
291 *
292 * @param xmlReader the xml reader
293 * @param dtdReader the dtd reader
294 * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
295 */
296 public FlatXmlDataSet(Reader xmlReader, Reader dtdReader)
297 throws IOException, DataSetException
298 {
299 this(xmlReader, new FlatDtdDataSet(dtdReader));
300 }
301
302 /**
303 * Creates an FlatXmlDataSet object with the specified xml reader.
304 *
305 * @param xmlReader the xml reader
306 * @param metaDataSet the dataset used as metadata source.
307 * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
308 */
309 public FlatXmlDataSet(Reader xmlReader, IDataSet metaDataSet)
310 throws IOException, DataSetException
311 {
312 super(new FlatXmlProducer(new InputSource(xmlReader), metaDataSet));
313 }
314
315 /**
316 * Creates an FlatXmlDataSet object with the specified xml input stream.
317 * Relative DOCTYPE uri are resolved from the current working directory.
318 *
319 * @param xmlStream the xml input stream
320 * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
321 */
322 public FlatXmlDataSet(InputStream xmlStream) throws IOException, DataSetException
323 {
324 this(xmlStream, true);
325 }
326
327 /**
328 * Creates an FlatXmlDataSet object with the specified xml input stream.
329 * Relative DOCTYPE uri are resolved from the current working directory.
330 *
331 * @param xmlStream the xml input stream
332 * @param dtdMetadata if <code>false</code> do not use DTD as metadata
333 * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
334 */
335 public FlatXmlDataSet(InputStream xmlStream, boolean dtdMetadata)
336 throws IOException, DataSetException
337 {
338 super(new FlatXmlProducer(new InputSource(xmlStream), dtdMetadata));
339 }
340
341 /**
342 * Creates an FlatXmlDataSet object with the specified xml and dtd input
343 * stream.
344 *
345 * @param xmlStream the xml input stream
346 * @param dtdStream the dtd input stream
347 * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
348 */
349 public FlatXmlDataSet(InputStream xmlStream, InputStream dtdStream)
350 throws IOException, DataSetException
351 {
352 this(xmlStream, new FlatDtdDataSet(dtdStream));
353 }
354
355 /**
356 * Creates an FlatXmlDataSet object with the specified xml input stream.
357 *
358 * @param xmlStream the xml input stream
359 * @param metaDataSet the dataset used as metadata source.
360 * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
361 */
362 public FlatXmlDataSet(InputStream xmlStream, IDataSet metaDataSet)
363 throws IOException, DataSetException
364 {
365 super(new FlatXmlProducer(new InputSource(xmlStream), metaDataSet));
366 }
367
368 /**
369 * Write the specified dataset to the specified output stream as xml.
370 */
371 public static void write(IDataSet dataSet, OutputStream out)
372 throws IOException, DataSetException
373 {
374 logger.debug("write(dataSet={}, out={}) - start", dataSet, out);
375
376 FlatXmlWriter datasetWriter = new FlatXmlWriter(out);
377 datasetWriter.setIncludeEmptyTable(true);
378 datasetWriter.write(dataSet);
379 }
380
381 /**
382 * Write the specified dataset to the specified writer as xml.
383 */
384 public static void write(IDataSet dataSet, Writer writer)
385 throws IOException, DataSetException
386 {
387 logger.debug("write(dataSet={}, writer={}) - start", dataSet, writer);
388 write(dataSet, writer, null);
389 }
390
391 /**
392 * Write the specified dataset to the specified writer as xml.
393 */
394 public static void write(IDataSet dataSet, Writer writer, String encoding)
395 throws IOException, DataSetException
396 {
397 if (logger.isDebugEnabled())
398 {
399 logger.debug("write(dataSet={}, writer={}, encoding={}) - start",
400 new Object[]{ dataSet, writer, encoding });
401 }
402
403 FlatXmlWriter datasetWriter = new FlatXmlWriter(writer, encoding);
404 datasetWriter.setIncludeEmptyTable(true);
405 datasetWriter.write(dataSet);
406 }
407
408 /**
409 * Write a DTD for the specified dataset to the specified output.
410 * @deprecated use {@link FlatDtdDataSet#write}
411 */
412 public static void writeDtd(IDataSet dataSet, OutputStream out)
413 throws IOException, DataSetException
414 {
415 logger.debug("writeDtd(dataSet={}, out={}) - start", dataSet, out);
416 FlatDtdDataSet.write(dataSet, out);
417 }
418 }
419
420
421
422
423
424
425
426
427
428
429
430