FlatXmlDataSet.java

  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. package org.dbunit.dataset.xml;

  22. import org.slf4j.Logger;
  23. import org.slf4j.LoggerFactory;

  24. import org.dbunit.dataset.CachedDataSet;
  25. import org.dbunit.dataset.DataSetException;
  26. import org.dbunit.dataset.IDataSet;

  27. import org.xml.sax.InputSource;

  28. import java.io.File;
  29. import java.io.IOException;
  30. import java.io.InputStream;
  31. import java.io.OutputStream;
  32. import java.io.Reader;
  33. import java.io.Writer;
  34. import java.net.URL;
  35. import java.nio.charset.Charset;

  36. /**
  37.  * Reads and writes flat XML dataset document. Each XML element corresponds to a table row.
  38.  *       Each XML element name corresponds to a table name. The XML attributes
  39.  *       correspond to table columns.
  40.  * <p>
  41.  * Flat XML dataset document sample:
  42.  * <p>
  43.  * <pre>
  44.  * &lt;!DOCTYPE dataset SYSTEM "my-dataset.dtd"&gt;
  45.  * &lt;dataset&gt;
  46.  *     &lt;TEST_TABLE COL0="row 0 col 0"
  47.  *         COL1="row 0 col 1"
  48.  *         COL2="row 0 col 2"/&gt;
  49.  *     &lt;TEST_TABLE COL1="row 1 col 1"/&gt;
  50.  *     &lt;SECOND_TABLE COL0="row 0 col 0"
  51.  *           COL1="row 0 col 1" /&gt;
  52.  *     &lt;EMPTY_TABLE/&gt;
  53.  * &lt;/dataset&gt;</pre>
  54.  * <p>
  55.  * To specify null values, omit corresponding attribute.
  56.  * In the above example, missing COL0 and COL2 attributes of TEST_TABLE second row represents null values.
  57.  * <p>
  58.  * Table metadata is deduced from the first row of each table by default.
  59.  * <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>
  60.  * You can do one of the following things to avoid this:
  61.  * <ul>
  62.  * <li>Use a DTD. DbUnit will use the columns declared in the DTD as table metadata.
  63.  * DbUnit only supports external system URI. The URI can be absolute or relative.
  64.  * </li>
  65.  * <li>Since DBUnit 2.3.0 there is a functionality called "column sensing" which basically
  66.  * reads in the whole XML into a buffer and dynamically adds new columns as they appear.
  67.  * It can be used as demonstrated in the following example:
  68.  * <pre>
  69.  *   // since dbunit 2.4.7
  70.  *   FlatXmlDataSetBuilder builder = new FlatXmlDataSetBuilder();
  71.  *   builder.setInputSource(new File("src/xml/flatXmlTableTest.xml"));
  72.  *   builder.setColumnSensing(true);
  73.  *   IDataSet dataSet = builder.build();
  74.  *  
  75.  *   // or dbunit release <= 2.4.6:
  76.  *   boolean enableColumnSensing = true;
  77.  *   IDataSet dataSet = new FlatXmlDataSet(
  78.  *            new File("src/xml/flatXmlTableTest.xml"), false, enableColumnSensing);
  79.  * </pre>
  80.  * </li>
  81.  * </ul>
  82.  * </p>
  83.  *
  84.  * @author Manuel Laflamme
  85.  * @author gommma (gommma AT users.sourceforge.net)
  86.  * @author Last changed by: $Author$
  87.  * @version $Revision$ $Date$
  88.  * @since 1.0 (Mar 12, 2002)
  89.  */
  90. public class FlatXmlDataSet extends CachedDataSet
  91. {
  92.     /**
  93.      * Logger for this class
  94.      */
  95.     private static final Logger logger = LoggerFactory.getLogger(FlatXmlDataSet.class);

  96.     /**
  97.      * Creates a new {@link FlatXmlDataSet} with the data of the given producer.
  98.      * @param flatXmlProducer The producer that provides the {@link FlatXmlDataSet} content
  99.      * @throws DataSetException
  100.      * @since 2.4.7
  101.      */
  102.     public FlatXmlDataSet(FlatXmlProducer flatXmlProducer) throws DataSetException
  103.     {
  104.         super(flatXmlProducer, flatXmlProducer.isCaseSensitiveTableNames());
  105.     }
  106.    
  107.     /**
  108.      * Creates an FlatXmlDataSet object with the specified InputSource.
  109.      * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
  110.      */
  111.     public FlatXmlDataSet(InputSource source) throws IOException, DataSetException
  112.     {
  113.         super(new FlatXmlProducer(source));
  114.     }

  115.     /**
  116.      * Creates an FlatXmlDataSet object with the specified xml file.
  117.      * Relative DOCTYPE uri are resolved from the xml file path.
  118.      *
  119.      * @param xmlFile the xml file
  120.      * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
  121.      */
  122.     public FlatXmlDataSet(File xmlFile) throws IOException, DataSetException
  123.     {
  124.         this(xmlFile, true);
  125.     }

  126.     /**
  127.      * Creates an FlatXmlDataSet object with the specified xml file.
  128.      * Relative DOCTYPE uri are resolved from the xml file path.
  129.      *
  130.      * @param xmlFile the xml file
  131.      * @param dtdMetadata if <code>false</code> do not use DTD as metadata
  132.      * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
  133.      */
  134.     public FlatXmlDataSet(File xmlFile, boolean dtdMetadata)
  135.             throws IOException, DataSetException
  136.     {
  137.         this(xmlFile.toURL(), dtdMetadata);
  138.     }

  139.     /**
  140.      * Creates an FlatXmlDataSet object with the specified xml file.
  141.      * Relative DOCTYPE uri are resolved from the xml file path.
  142.      *
  143.      * @param xmlFile the xml file
  144.      * @param dtdMetadata if <code>false</code> do not use DTD as metadata
  145.      * @param columnSensing Whether or not the columns should be sensed automatically. Every XML row
  146.      * is scanned for columns that have not been there in a previous column.
  147.      * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
  148.      */
  149.     public FlatXmlDataSet(File xmlFile, boolean dtdMetadata, boolean columnSensing)
  150.             throws IOException, DataSetException
  151.     {
  152.         this(xmlFile.toURL(), dtdMetadata, columnSensing);
  153.     }

  154.     /**
  155.      * Creates an FlatXmlDataSet object with the specified xml file.
  156.      * Relative DOCTYPE uri are resolved from the xml file path.
  157.      *
  158.      * @param xmlFile the xml file
  159.      * @param dtdMetadata if <code>false</code> do not use DTD as metadata
  160.      * @param columnSensing Whether or not the columns should be sensed automatically. Every XML row
  161.      * is scanned for columns that have not been there in a previous column.
  162.      * @param caseSensitiveTableNames Whether or not this dataset should use case sensitive table names
  163.      * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
  164.      */
  165.     public FlatXmlDataSet(File xmlFile, boolean dtdMetadata, boolean columnSensing, boolean caseSensitiveTableNames)
  166.     throws IOException, DataSetException
  167.     {
  168.         this(xmlFile.toURL(), dtdMetadata, columnSensing, caseSensitiveTableNames);
  169.     }

  170.     /**
  171.      * Creates an FlatXmlDataSet object with the specified xml URL.
  172.      * Relative DOCTYPE uri are resolved from the xml file path.
  173.      *
  174.      * @param xmlUrl the xml URL
  175.      * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
  176.      */
  177.     public FlatXmlDataSet(URL xmlUrl) throws IOException, DataSetException
  178.     {
  179.         this(xmlUrl, true);
  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.      * @param dtdMetadata if <code>false</code> do not use DTD as metadata
  187.      * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
  188.      */
  189.     public FlatXmlDataSet(URL xmlUrl, boolean dtdMetadata)
  190.             throws IOException, DataSetException
  191.     {
  192.         this(xmlUrl, dtdMetadata, false);
  193.     }
  194.    

  195.     /**
  196.      * Creates an FlatXmlDataSet object with the specified xml URL.
  197.      * Relative DOCTYPE uri are resolved from the xml file path.
  198.      *
  199.      * @param xmlUrl the xml URL
  200.      * @param dtdMetadata if <code>false</code> do not use DTD as metadata
  201.      * @param columnSensing Whether or not the columns should be sensed automatically. Every XML row
  202.      * is scanned for columns that have not been there in a previous column.
  203.      * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
  204.      */
  205.     public FlatXmlDataSet(URL xmlUrl, boolean dtdMetadata, boolean columnSensing)
  206.     throws IOException, DataSetException
  207.     {
  208.         super(new FlatXmlProducer(
  209.                 new InputSource(xmlUrl.toString()), dtdMetadata, columnSensing));
  210.     }

  211.     /**
  212.      * Creates an FlatXmlDataSet object with the specified xml file.
  213.      * Relative DOCTYPE uri are resolved from the xml file path.
  214.      *
  215.      * @param xmlUrl the xml file
  216.      * @param dtdMetadata if <code>false</code> do not use DTD as metadata
  217.      * @param columnSensing Whether or not the columns should be sensed automatically. Every XML row
  218.      * is scanned for columns that have not been there in a previous column.
  219.      * @param caseSensitiveTableNames Whether or not this dataset should use case sensitive table names
  220.      * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
  221.      */
  222.     public FlatXmlDataSet(URL xmlUrl, boolean dtdMetadata, boolean columnSensing, boolean caseSensitiveTableNames)
  223.     throws IOException, DataSetException
  224.     {
  225.         super(new FlatXmlProducer(
  226.                   new InputSource(xmlUrl.toString()), dtdMetadata, columnSensing, caseSensitiveTableNames),
  227.               caseSensitiveTableNames);
  228.     }

  229.     /**
  230.      * Creates an FlatXmlDataSet object with the specified xml reader.
  231.      * Relative DOCTYPE uri are resolved from the current working directory.
  232.      *
  233.      * @param xmlReader the xml reader
  234.      * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
  235.      */
  236.     public FlatXmlDataSet(Reader xmlReader) throws IOException, DataSetException
  237.     {
  238.         this(xmlReader, true);
  239.     }

  240.     /**
  241.      * Creates an FlatXmlDataSet object with the specified xml reader.
  242.      * Relative DOCTYPE uri are resolved from the current working directory.
  243.      *
  244.      * @param xmlReader the xml reader
  245.      * @param dtdMetadata if <code>false</code> do not use DTD as metadata
  246.      * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
  247.      */
  248.     public FlatXmlDataSet(Reader xmlReader, boolean dtdMetadata)
  249.             throws IOException, DataSetException
  250.     {
  251.         this(xmlReader, dtdMetadata, false, false);
  252.     }

  253.     /**
  254.      * Creates an FlatXmlDataSet object with the specified xml file.
  255.      * Relative DOCTYPE uri are resolved from the xml file path.
  256.      *
  257.      * @param xmlReader the xml reader
  258.      * @param dtdMetadata if <code>false</code> do not use DTD as metadata
  259.      * @param columnSensing Whether or not the columns should be sensed automatically. Every XML row
  260.      * is scanned for columns that have not been there in a previous column.
  261.      * @param caseSensitiveTableNames Whether or not this dataset should use case sensitive table names
  262.      * @since 2.4.3
  263.      * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
  264.      */
  265.     public FlatXmlDataSet(Reader xmlReader, boolean dtdMetadata, boolean columnSensing, boolean caseSensitiveTableNames)
  266.     throws IOException, DataSetException
  267.     {
  268.         super(new FlatXmlProducer(new InputSource(xmlReader), dtdMetadata, columnSensing, caseSensitiveTableNames),
  269.                 caseSensitiveTableNames);
  270.     }

  271.     /**
  272.      * Creates an FlatXmlDataSet object with the specified xml and dtd readers.
  273.      *
  274.      * @param xmlReader the xml reader
  275.      * @param dtdReader the dtd reader
  276.      * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
  277.      */
  278.     public FlatXmlDataSet(Reader xmlReader, Reader dtdReader)
  279.             throws IOException, DataSetException
  280.     {
  281.         this(xmlReader, new FlatDtdDataSet(dtdReader));
  282.     }

  283.     /**
  284.      * Creates an FlatXmlDataSet object with the specified xml reader.
  285.      *
  286.      * @param xmlReader the xml reader
  287.      * @param metaDataSet the dataset used as metadata source.
  288.      * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
  289.      */
  290.     public FlatXmlDataSet(Reader xmlReader, IDataSet metaDataSet)
  291.             throws IOException, DataSetException
  292.     {
  293.         super(new FlatXmlProducer(new InputSource(xmlReader), metaDataSet));
  294.     }

  295.     /**
  296.      * Creates an FlatXmlDataSet object with the specified xml input stream.
  297.      * Relative DOCTYPE uri are resolved from the current working directory.
  298.      *
  299.      * @param xmlStream the xml input stream
  300.      * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
  301.      */
  302.     public FlatXmlDataSet(InputStream xmlStream) throws IOException, DataSetException
  303.     {
  304.         this(xmlStream, true);
  305.     }

  306.     /**
  307.      * Creates an FlatXmlDataSet object with the specified xml input stream.
  308.      * Relative DOCTYPE uri are resolved from the current working directory.
  309.      *
  310.      * @param xmlStream the xml input stream
  311.      * @param dtdMetadata if <code>false</code> do not use DTD as metadata
  312.      * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
  313.      */
  314.     public FlatXmlDataSet(InputStream xmlStream, boolean dtdMetadata)
  315.             throws IOException, DataSetException
  316.     {
  317.         super(new FlatXmlProducer(new InputSource(xmlStream), dtdMetadata));
  318.     }

  319.     /**
  320.      * Creates an FlatXmlDataSet object with the specified xml and dtd input
  321.      * stream.
  322.      *
  323.      * @param xmlStream the xml input stream
  324.      * @param dtdStream the dtd input stream
  325.      * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
  326.      */
  327.     public FlatXmlDataSet(InputStream xmlStream, InputStream dtdStream)
  328.             throws IOException, DataSetException
  329.     {
  330.         this(xmlStream, new FlatDtdDataSet(dtdStream));
  331.     }

  332.     /**
  333.      * Creates an FlatXmlDataSet object with the specified xml input stream.
  334.      *
  335.      * @param xmlStream the xml input stream
  336.      * @param metaDataSet the dataset used as metadata source.
  337.      * @deprecated since 2.4.7 - use {@link FlatXmlDataSetBuilder} to create a {@link FlatXmlDataSet}
  338.      */
  339.     public FlatXmlDataSet(InputStream xmlStream, IDataSet metaDataSet)
  340.             throws IOException, DataSetException
  341.     {
  342.         super(new FlatXmlProducer(new InputSource(xmlStream), metaDataSet));
  343.     }

  344.     /**
  345.      * Write the specified dataset to the specified output stream as xml.
  346.      */
  347.     public static void write(IDataSet dataSet, OutputStream out)
  348.             throws IOException, DataSetException
  349.     {
  350.         logger.debug("write(dataSet={}, out={}) - start", dataSet, out);

  351.         FlatXmlWriter datasetWriter = new FlatXmlWriter(out);
  352.         datasetWriter.setIncludeEmptyTable(true);
  353.         datasetWriter.write(dataSet);
  354.     }

  355.     /**
  356.      * Write the specified dataset to the specified writer as xml.
  357.      */
  358.     public static void write(IDataSet dataSet, Writer writer)
  359.             throws IOException, DataSetException
  360.     {
  361.         logger.debug("write(dataSet={}, writer={}) - start", dataSet, writer);
  362.         write(dataSet, writer, null);
  363.     }

  364.     /**
  365.      * Write the specified dataset to the specified writer as xml.
  366.      */
  367.     public static void write(IDataSet dataSet, Writer writer, Charset charset)
  368.             throws IOException, DataSetException
  369.     {
  370.         logger.debug("write(dataSet={}, writer={}, charset={}) - start",
  371.                 dataSet, writer, charset);

  372.         final FlatXmlWriter datasetWriter = new FlatXmlWriter(writer, charset);
  373.         datasetWriter.setIncludeEmptyTable(true);
  374.         datasetWriter.write(dataSet);
  375.     }

  376.     /**
  377.      * Write a DTD for the specified dataset to the specified output.
  378.      * @deprecated use {@link FlatDtdDataSet#write}
  379.      */
  380.     public static void writeDtd(IDataSet dataSet, OutputStream out)
  381.             throws IOException, DataSetException
  382.     {
  383.         logger.debug("writeDtd(dataSet={}, out={}) - start", dataSet, out);
  384.         FlatDtdDataSet.write(dataSet, out);
  385.     }
  386. }