You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ddlutils-dev@db.apache.org by to...@apache.org on 2006/12/15 08:30:53 UTC

svn commit: r487473 - in /db/ddlutils/trunk/src: java/org/apache/ddlutils/ java/org/apache/ddlutils/io/ java/org/apache/ddlutils/platform/ java/org/apache/ddlutils/task/ test/org/apache/ddlutils/ test/org/apache/ddlutils/io/

Author: tomdz
Date: Thu Dec 14 23:30:52 2006
New Revision: 487473

URL: http://svn.apache.org/viewvc?view=rev&rev=487473
Log:
Added convenience class to read and write data from/to the database
Added ability to turn identity override on/off
Fixed bug in jdbc model reader which did not called initialize
Added tests for reading and writing data via XML

Added:
    db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DatabaseDataIO.java
    db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestMisc.java
Modified:
    db/ddlutils/trunk/src/java/org/apache/ddlutils/Platform.java
    db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataReader.java
    db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataSink.java
    db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataToDatabaseSink.java
    db/ddlutils/trunk/src/java/org/apache/ddlutils/io/Identity.java
    db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java
    db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java
    db/ddlutils/trunk/src/java/org/apache/ddlutils/task/ConvertingDatabaseCommand.java
    db/ddlutils/trunk/src/java/org/apache/ddlutils/task/WriteDataToDatabaseCommand.java
    db/ddlutils/trunk/src/java/org/apache/ddlutils/task/WriteDataToFileCommand.java
    db/ddlutils/trunk/src/test/org/apache/ddlutils/RunAllTests.java
    db/ddlutils/trunk/src/test/org/apache/ddlutils/TestDatabaseWriterBase.java
    db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDataReaderAndWriter.java
    db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDatatypes.java

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/Platform.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/Platform.java?view=diff&rev=487473&r1=487472&r2=487473
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/Platform.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/Platform.java Thu Dec 14 23:30:52 2006
@@ -164,6 +164,26 @@
     public void setSqlCommentsOn(boolean sqlCommentsOn);
 
     /**
+     * Determines whether SQL insert statements can specify values for identity columns.
+     * This setting is only relevant if the database supports it
+     * ({@link PlatformInfo#isIdentityOverrideAllowed()). If this is off, then the
+     * <code>insert</code> methods will ignore values for identity columns. 
+     *  
+     * @return <code>true</code> if identity override is enabled (the default)
+     */
+    public boolean isIdentityOverrideOn();
+
+    /**
+     * Specifies whether SQL insert statements can specify values for identity columns.
+     * This setting is only relevant if the database supports it
+     * ({@link PlatformInfo#isIdentityOverrideAllowed()). If this is off, then the
+     * <code>insert</code> methods will ignore values for identity columns. 
+     *  
+     * @param identityOverrideOn <code>true</code> if identity override is enabled (the default)
+     */
+    public void setIdentityOverrideOn(boolean identityOverrideOn);
+
+    /**
      * Determines whether foreign keys of a table read from a live database
      * are alphabetically sorted.
      *

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataReader.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataReader.java?view=diff&rev=487473&r1=487472&r2=487473
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataReader.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataReader.java Thu Dec 14 23:30:52 2006
@@ -24,10 +24,11 @@
 import org.apache.ddlutils.model.Column;
 import org.apache.ddlutils.model.Database;
 import org.apache.ddlutils.model.Table;
-import org.xml.sax.SAXException;
 
 /**
- * Reads data XML into dyna beans matching a specified database model.
+ * Reads data XML into dyna beans matching a specified database model. Note that
+ * the data sink won't be started or ended by the data reader, this has to be done
+ * in the code that uses the data reader. 
  * 
  * @version $Revision: 289996 $
  */
@@ -156,23 +157,5 @@
             _needsConfiguration = false;
         }
         super.configure();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void endDocument() throws SAXException
-    {
-        super.endDocument();
-        _sink.end();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void startDocument() throws SAXException
-    {
-        _sink.start();
-        super.startDocument();
     }
 }

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataSink.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataSink.java?view=diff&rev=487473&r1=487472&r2=487473
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataSink.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataSink.java Thu Dec 14 23:30:52 2006
@@ -43,5 +43,5 @@
     /**
      * Notifies the sink that all beans have been added.
      */
-    public void end()  throws DataSinkException;
+    public void end() throws DataSinkException;
 }

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataToDatabaseSink.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataToDatabaseSink.java?view=diff&rev=487473&r1=487472&r2=487473
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataToDatabaseSink.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DataToDatabaseSink.java Thu Dec 14 23:30:52 2006
@@ -66,8 +66,10 @@
     private ArrayList _batchQueue = new ArrayList();
     /** The number of beans to insert in one batch. */
     private int _batchSize = 1024;
-    /** Stores the already-processed identities per table name. */
-    private HashMap _processedIdentities = new HashMap();
+    /** Stores the tables that are target of a foreign key. */
+    private HashSet _fkTables = new HashSet();
+    /** Maps original to processed identities. */
+    private HashMap _identityMap = new HashMap();
     /** Stores the objects that are waiting for other objects to be inserted. */
     private ArrayList _waitingObjects = new ArrayList();
 
@@ -196,9 +198,7 @@
      */
     public void start() throws DataSinkException
     {
-        // we're determining all tables referenced by foreignkeys, and initialize the
-        // lists of already-processed identities for these tables
-        _processedIdentities.clear();
+        _fkTables.clear();
         _waitingObjects.clear();
         if (_ensureFkOrder)
         {
@@ -210,10 +210,7 @@
                 {
                     ForeignKey curFk = table.getForeignKey(fkIdx);
     
-                    if (!_processedIdentities.containsKey(curFk.getForeignTableName()))
-                    {
-                        _processedIdentities.put(curFk.getForeignTableName(), new HashSet());
-                    }
+                    _fkTables.add(curFk.getForeignTable());
                 }
             }
         }
@@ -245,9 +242,13 @@
 
                 if (fkIdentity != null)
                 {
-                    HashSet identitiesForTable = (HashSet)_processedIdentities.get(fk.getForeignTableName());
+                    Identity processedIdentity = (Identity)_identityMap.get(fkIdentity);
     
-                    if (!identitiesForTable.contains(fkIdentity))
+                    if (processedIdentity != null)
+                    {
+                        updateFKColumns(bean, fkIdentity.getForeignKeyName(), processedIdentity);
+                    }
+                    else
                     {
                         waitingObj.addPendingFK(fkIdentity);
                     }
@@ -258,6 +259,7 @@
                 if (_log.isDebugEnabled())
                 {
                     StringBuffer msg = new StringBuffer();
+
                     msg.append("Defering insertion of bean ");
                     msg.append(buildIdentityFromPKs(table, bean).toString());
                     msg.append(" because it is waiting for:");
@@ -272,18 +274,21 @@
                 return;
             }
         }
+
+        Identity origIdentity = buildIdentityFromPKs(table, bean);
+
         insertBeanIntoDatabase(table, bean);
-        if (_ensureFkOrder && _processedIdentities.containsKey(table.getName()))
+
+        if (_ensureFkOrder && _fkTables.contains(table))
         {
-            Identity  identity           = buildIdentityFromPKs(table, bean);
-            HashSet   identitiesForTable = (HashSet)_processedIdentities.get(table.getName());
-            ArrayList finishedObjs       = new ArrayList();
+            Identity  newIdentity  = buildIdentityFromPKs(table, bean);
+            ArrayList finishedObjs = new ArrayList();
 
-            identitiesForTable.add(identity);
+            _identityMap.put(origIdentity, newIdentity);
             for (Iterator waitingObjIt = _waitingObjects.iterator(); waitingObjIt.hasNext();)
             {
                 WaitingObject waitingObj = (WaitingObject)waitingObjIt.next();
-                Identity      fkIdentity = waitingObj.removePendingFK(identity);
+                Identity      fkIdentity = waitingObj.removePendingFK(origIdentity);
 
                 if (!waitingObj.hasPendingFKs())
                 {
@@ -291,7 +296,7 @@
                     // the object was only waiting for this one, so store it now
                     // prior to that we also update the fk fields in case one of the pk
                     // columns of the target object is auto-incremented by the database
-                    updateFKColumns(waitingObj.getObject(), bean, fkIdentity.getForeignKeyName());
+                    updateFKColumns(waitingObj.getObject(), fkIdentity.getForeignKeyName(), newIdentity);
                     // we defer handling of the finished objects to avoid concurrent modification exceptions
                     finishedObjs.add(waitingObj.getObject());
                 }
@@ -453,12 +458,12 @@
      */
     private Identity buildIdentityFromPKs(Table table, DynaBean bean)
     {
-        Identity identity  = new Identity(table.getName());
+        Identity identity  = new Identity(table);
         Column[] pkColumns = table.getPrimaryKeyColumns();
 
         for (int idx = 0; idx < pkColumns.length; idx++)
         {
-            identity.setIdentityColumn(pkColumns[idx].getName(), bean.get(pkColumns[idx].getName()));
+            identity.setColumnValue(pkColumns[idx].getName(), bean.get(pkColumns[idx].getName()));
         }
         return identity;
     }
@@ -474,7 +479,7 @@
      */
     private Identity buildIdentityFromFK(Table owningTable, ForeignKey fk, DynaBean bean)
     {
-        Identity identity = new Identity(fk.getForeignTableName(), getFKName(owningTable, fk));
+        Identity identity = new Identity(fk.getForeignTable(), getFKName(owningTable, fk));
 
         for (int idx = 0; idx < fk.getReferenceCount(); idx++)
         {
@@ -485,23 +490,23 @@
             {
                 return null;
             }
-            identity.setIdentityColumn(reference.getForeignColumnName(), value);
+            identity.setColumnValue(reference.getForeignColumnName(), value);
         }
         return identity;
     }
 
     /**
-     * Updates the values of the columns constituting the foreign key between the two given beans to
-     * the current values of the primary key columns of the referenced bean.
+     * Updates the values of the columns constituting the indicated foreign key with the values
+     * of the given identity.
      * 
-     * @param referencingBean The referencing bean whose foreign key columns shall be updated
-     * @param referencedBean  The referenced bean whose primary key column values will be used
-     * @param fkName          The name of the foreign key
+     * @param bean     The bean whose columns shall be updated
+     * @param fkName   The name of the foreign key
+     * @param identity The target identity
      */
-    private void updateFKColumns(DynaBean referencingBean, DynaBean referencedBean, String fkName)
+    private void updateFKColumns(DynaBean bean, String fkName, Identity identity)
     {
-        Table      sourceTable = ((SqlDynaClass)referencingBean.getDynaClass()).getTable();
-        Table      targetTable = ((SqlDynaClass)referencedBean.getDynaClass()).getTable();
+        Table      sourceTable = ((SqlDynaClass)bean.getDynaClass()).getTable();
+        Table      targetTable = identity.getTable();
         ForeignKey fk          = null;
 
         for (int idx = 0; idx < sourceTable.getForeignKeyCount(); idx++)
@@ -522,10 +527,10 @@
             for (int idx = 0; idx < fk.getReferenceCount(); idx++)
             {
                 Reference curRef       = fk.getReference(idx);
-                Column    sourceColumn = sourceTable.findColumn(curRef.getLocalColumnName());
-                Column    targetColumn = targetTable.findColumn(curRef.getForeignColumnName());
+                Column    sourceColumn = curRef.getLocalColumn();
+                Column    targetColumn = curRef.getForeignColumn();
 
-                referencingBean.set(sourceColumn.getName(), referencedBean.get(targetColumn.getName()));
+                bean.set(sourceColumn.getName(), identity.getColumnValue(targetColumn.getName()));
             }
         }
     }

Added: db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DatabaseDataIO.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DatabaseDataIO.java?view=auto&rev=487473
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DatabaseDataIO.java (added)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/io/DatabaseDataIO.java Thu Dec 14 23:30:52 2006
@@ -0,0 +1,621 @@
+package org.apache.ddlutils.io;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.apache.ddlutils.DdlUtilsException;
+import org.apache.ddlutils.Platform;
+import org.apache.ddlutils.model.Column;
+import org.apache.ddlutils.model.Database;
+import org.apache.ddlutils.model.Table;
+
+/**
+ * Provides basic live database data <-> XML functionality.
+ * 
+ * @version $Revision: $
+ */
+public class DatabaseDataIO
+{
+    /** The converters to use for converting between data and its XML representation. */
+    private ArrayList _converters = new ArrayList();
+    /** Whether we should continue when an error was detected. */
+    private boolean _failOnError = true;
+    /** Whether foreign key order shall be followed when inserting data into the database. */
+    private boolean _ensureFKOrder = true;
+    /** Whether we should use batch mode. */
+    private boolean _useBatchMode;
+    /** The maximum number of objects to insert in one batch. */
+    private Integer _batchSize;
+
+    /**
+     * Registers a converter.
+     * 
+     * @param converterRegistration The registration info
+     */
+    public void registerConverter(DataConverterRegistration converterRegistration)
+    {
+        _converters.add(converterRegistration);
+    }
+
+    /**
+     * Determines whether data io is stopped when an error happens.
+     *  
+     * @return Whether io is stopped when an error was detected (true by default)
+     */
+    public boolean isFailOnError()
+    {
+        return _failOnError;
+    }
+
+    /**
+     * Specifies whether data io shall be stopped when an error happens.
+     *  
+     * @param failOnError Whether io should stop when an error was detected
+     */
+    public void setFailOnError(boolean failOnError)
+    {
+        _failOnError = failOnError;
+    }
+
+    /**
+     * Determines whether batch mode is used for inserting data into the database.
+     * 
+     * @return <code>true</code> if batch mode is used
+     */
+    public boolean getUseBatchMode()
+    {
+        return _useBatchMode;
+    }
+
+    /**
+     * Specifies whether batch mode should be used for inserting data into the database.
+     * 
+     * @param useBatchMode <code>true</code> if batch mode shall be used
+     */
+    public void setUseBatchMode(boolean useBatchMode)
+    {
+        _useBatchMode = useBatchMode;
+    }
+
+    /**
+     * Returns the batch size override.
+     * 
+     * @return The batch size if different from the default, <code>null</code> otherwise
+     */
+    public Integer getBatchSize()
+    {
+        return _batchSize;
+    }
+
+    /**
+     * Sets the batch size to be used by this object.
+     * 
+     * @param batchSize The batch size if different from the default, or <code>null</code> if
+     *                  the default shall be used
+     */
+    public void setBatchSize(Integer batchSize)
+    {
+        _batchSize = batchSize;
+    }
+
+    /**
+     * Determines whether the sink delays the insertion of beans so that the beans referenced by it
+     * via foreignkeys are already inserted into the database.
+     *
+     * @return <code>true</code> if beans are inserted after its foreignkey-references
+     */
+    public boolean isEnsureFKOrder()
+    {
+        return _ensureFKOrder;
+    }
+
+    /**
+     * Specifies whether the sink shall delay the insertion of beans so that the beans referenced by it
+     * via foreignkeys are already inserted into the database.<br/>
+     * Note that you should careful with setting <code>haltOnErrors</code> to false as this might
+     * result in beans not inserted at all. The sink will then throw an appropriate exception at the end
+     * of the insertion process (method {@link #end()}).
+     *
+     * @param ensureFkOrder <code>true</code> if beans shall be inserted after its foreignkey-references
+     */
+    public void setEnsureFKOrder(boolean ensureFKOrder)
+    {
+        _ensureFKOrder = ensureFKOrder;
+    }
+
+    /**
+     * Registers the converters at the given configuration.
+     * 
+     * @param converterConf The converter configuration
+     */
+    private void registerConverters(ConverterConfiguration converterConf) throws DdlUtilsException
+    {
+        for (Iterator it = _converters.iterator(); it.hasNext();)
+        {
+            DataConverterRegistration registrationInfo = (DataConverterRegistration)it.next();
+
+            if (registrationInfo.getTypeCode() != Integer.MIN_VALUE)
+            {
+                converterConf.registerConverter(registrationInfo.getTypeCode(),
+                                                registrationInfo.getConverter());
+            }
+            else
+            {
+                if ((registrationInfo.getTable() == null) || (registrationInfo.getColumn() == null)) 
+                {
+                    throw new DdlUtilsException("Please specify either the jdbc type or a table/column pair for which the converter shall be defined");
+                }
+                converterConf.registerConverter(registrationInfo.getTable(),
+                                                registrationInfo.getColumn(),
+                                                registrationInfo.getConverter());
+            }
+        }
+    }
+
+    /**
+     * Returns a data writer instance configured to write to the indicated file
+     * in the specified encoding.
+     * 
+     * @param path        The path to the output XML data file
+     * @param xmlEncoding The encoding to use for writing the XML
+     * @return The writer
+     */
+    public DataWriter getConfiguredDataWriter(String path, String xmlEncoding) throws DdlUtilsException
+    {
+        try
+        {
+            DataWriter writer = new DataWriter(new FileOutputStream(path), xmlEncoding);
+            
+            registerConverters(writer.getConverterConfiguration());
+            return writer;
+        }
+        catch (IOException ex)
+        {
+            throw new DdlUtilsException(ex);
+        }
+    }
+
+    /**
+     * Returns a data writer instance configured to write to the given output stream
+     * in the specified encoding.
+     * 
+     * @param output      The output stream
+     * @param xmlEncoding The encoding to use for writing the XML
+     * @return The writer
+     */
+    public DataWriter getConfiguredDataWriter(OutputStream output, String xmlEncoding) throws DdlUtilsException
+    {
+        DataWriter writer = new DataWriter(output, xmlEncoding);
+        
+        registerConverters(writer.getConverterConfiguration());
+        return writer;
+    }
+
+    /**
+     * Returns a data writer instance configured to write to the given output writer
+     * in the specified encoding.
+     * 
+     * @param output      The output writer; needs to be configured with the specified encoding
+     * @param xmlEncoding The encoding to use for writing the XML
+     * @return The writer
+     */
+    public DataWriter getConfiguredDataWriter(Writer output, String xmlEncoding) throws DdlUtilsException
+    {
+        DataWriter writer = new DataWriter(output, xmlEncoding);
+        
+        registerConverters(writer.getConverterConfiguration());
+        return writer;
+    }
+
+    /**
+     * Writes the data contained in the database to which the given platform is connected, as XML
+     * to the given output stream (which won't be closed by this method).
+     *  
+     * @param platform    The platform; needs to be connected to a live database
+     * @param path        The path of the output file
+     * @param xmlEncoding The encoding to use for the XML
+     */
+    public void writeDataToXML(Platform platform, String path, String xmlEncoding) throws DdlUtilsException
+    {
+        writeDataToXML(platform, getConfiguredDataWriter(path, xmlEncoding));
+    }
+
+    /**
+     * Writes the data contained in the database to which the given platform is connected, as XML
+     * to the given output stream (which won't be closed by this method).
+     *  
+     * @param platform    The platform; needs to be connected to a live database
+     * @param model       The model for which to retrieve and write the data
+     * @param path        The path of the output file
+     * @param xmlEncoding The encoding to use for the XML
+     */
+    public void writeDataToXML(Platform platform, Database model, String path, String xmlEncoding)
+    {
+        writeDataToXML(platform, model, getConfiguredDataWriter(path, xmlEncoding));
+    }
+
+    /**
+     * Writes the data contained in the database to which the given platform is connected, as XML
+     * to the given output stream (which won't be closed by this method).
+     *  
+     * @param platform    The platform; needs to be connected to a live database
+     * @param output      The output stream
+     * @param xmlEncoding The encoding to use for the XML
+     */
+    public void writeDataToXML(Platform platform, OutputStream output, String xmlEncoding)
+    {
+        writeDataToXML(platform, getConfiguredDataWriter(output, xmlEncoding));
+    }
+
+    /**
+     * Writes the data contained in the database to which the given platform is connected, as XML
+     * to the given output stream (which won't be closed by this method).
+     *  
+     * @param platform    The platform; needs to be connected to a live database
+     * @param model       The model for which to retrieve and write the data
+     * @param output      The output stream
+     * @param xmlEncoding The encoding to use for the XML
+     */
+    public void writeDataToXML(Platform platform, Database model, OutputStream output, String xmlEncoding)
+    {
+        writeDataToXML(platform, model, getConfiguredDataWriter(output, xmlEncoding));
+    }
+
+    /**
+     * Writes the data contained in the database to which the given platform is connected, as XML
+     * to the given output writer (which won't be closed by this method).
+     *  
+     * @param platform    The platform; needs to be connected to a live database
+     * @param output      The output writer (which needs to be openend with the specified encoding)
+     * @param xmlEncoding The encoding to use for the XML
+     */
+    public void writeDataToXML(Platform platform, Writer output, String xmlEncoding)
+    {
+        writeDataToXML(platform, getConfiguredDataWriter(output, xmlEncoding));
+    }
+
+    /**
+     * Writes the data contained in the database to which the given platform is connected, as XML
+     * to the given output writer (which won't be closed by this method).
+     *  
+     * @param platform    The platform; needs to be connected to a live database
+     * @param model       The model for which to retrieve and write the data
+     * @param output      The output writer (which needs to be openend with the specified encoding)
+     * @param xmlEncoding The encoding to use for the XML
+     */
+    public void writeDataToXML(Platform platform, Database model, Writer output, String xmlEncoding)
+    {
+        writeDataToXML(platform, model, getConfiguredDataWriter(output, xmlEncoding));
+    }
+
+    /**
+     * Writes the data contained in the database to which the given platform is connected, as XML
+     * to the given data writer.
+     *  
+     * @param platform The platform; needs to be connected to a live database
+     * @param writer   The data writer
+     */
+    public void writeDataToXML(Platform platform, DataWriter writer)
+    {
+        writeDataToXML(platform, platform.readModelFromDatabase("unnamed"), writer);
+    }
+
+    /**
+     * Writes the data contained in the database to which the given platform is connected, as XML
+     * to the given data writer.
+     *  
+     * @param platform The platform; needs to be connected to a live database
+     * @param model    The model for which to retrieve and write the data
+     * @param writer   The data writer
+     */
+    public void writeDataToXML(Platform platform, Database model, DataWriter writer)
+    {
+        Table[] tables = new Table[1];
+        
+        registerConverters(writer.getConverterConfiguration());
+
+        // TODO: An advanced algorithm could be employed here that writes objects
+        //       related by foreign keys, in the correct order
+        StringBuffer query = new StringBuffer();
+
+        writer.writeDocumentStart();
+        for (int tableIdx = 0; tableIdx < model.getTableCount(); tableIdx++)
+        {
+            tables[0] = (Table)model.getTable(tableIdx);
+            query.setLength(0);
+            query.append("SELECT ");
+
+            Column[] columns = tables[0].getColumns();
+
+            for (int columnIdx = 0; columnIdx < columns.length; columnIdx++)
+            {
+                if (columnIdx > 0)
+                {
+                    query.append(",");
+                }
+                if (platform.isDelimitedIdentifierModeOn())
+                {
+                    query.append(platform.getPlatformInfo().getDelimiterToken());
+                }
+                query.append(columns[columnIdx].getName());
+                if (platform.isDelimitedIdentifierModeOn())
+                {
+                    query.append(platform.getPlatformInfo().getDelimiterToken());
+                }
+            }
+            query.append(" FROM ");
+            if (platform.isDelimitedIdentifierModeOn())
+            {
+                query.append(platform.getPlatformInfo().getDelimiterToken());
+            }
+            query.append(tables[0].getName());
+            if (platform.isDelimitedIdentifierModeOn())
+            {
+                query.append(platform.getPlatformInfo().getDelimiterToken());
+            }
+
+            writer.write(platform.query(model, query.toString(), tables));
+        }
+        writer.writeDocumentEnd();
+    }
+
+    /**
+     * Returns a data reader instance configured for the given platform (which needs to
+     * be connected to a live database) and model.
+     * 
+     * @param platform The database
+     * @param model    The model
+     * @return The data reader
+     */
+    public DataReader getConfiguredDataReader(Platform platform, Database model) throws DdlUtilsException
+    {
+        DataToDatabaseSink sink     = new DataToDatabaseSink(platform, model);
+        DataReader         reader   = new DataReader();
+
+        sink.setHaltOnErrors(_failOnError);
+        sink.setEnsureForeignKeyOrder(_ensureFKOrder);
+        sink.setUseBatchMode(_useBatchMode);
+        if (_batchSize != null)
+        {
+            sink.setBatchSize(_batchSize.intValue());
+        }
+        
+        reader.setModel(model);
+        reader.setSink(sink);
+        registerConverters(reader.getConverterConfiguration());
+        return reader;
+    }
+
+    /**
+     * Reads the data from the specified files and writes it to the database to which the given
+     * platform is connected.
+     * 
+     * @param platform The platform, must be connected to a live database
+     * @param files    The XML data files
+     */
+    public void writeDataToDatabase(Platform platform, String[] files) throws DdlUtilsException
+    {
+        writeDataToDatabase(platform, platform.readModelFromDatabase("unnamed"), files); 
+    }
+
+    /**
+     * Reads the data from the given input streams and writes it to the database to which the given
+     * platform is connected.
+     * 
+     * @param platform The platform, must be connected to a live database
+     * @param input    The input streams for the XML data
+     */
+    public void writeDataToDatabase(Platform platform, InputStream[] inputs) throws DdlUtilsException
+    {
+        writeDataToDatabase(platform, platform.readModelFromDatabase("unnamed"), inputs); 
+    }
+
+    /**
+     * Reads the data from the given input readers and writes it to the database to which the given
+     * platform is connected.
+     * 
+     * @param platform The platform, must be connected to a live database
+     * @param input    The input readers for the XML data
+     */
+    public void writeDataToDatabase(Platform platform, Reader[] inputs) throws DdlUtilsException
+    {
+        writeDataToDatabase(platform, platform.readModelFromDatabase("unnamed"), inputs); 
+    }
+
+    /**
+     * Reads the data from the indicated files and writes it to the database to which the given
+     * platform is connected. Only data that matches the given model will be written.
+     * 
+     * @param platform The platform, must be connected to a live database
+     * @param model    The model to which to constrain the written data
+     * @param files    The XML data files
+     */
+    public void writeDataToDatabase(Platform platform, Database model, String[] files) throws DdlUtilsException
+    {
+        DataReader dataReader = getConfiguredDataReader(platform, model); 
+
+        dataReader.getSink().start();
+        for (int idx = 0; (files != null) && (idx < files.length); idx++)
+        {
+            writeDataToDatabase(dataReader, files[idx]);
+        }
+        dataReader.getSink().end();
+    }
+
+    /**
+     * Reads the data from the given input streams and writes it to the database to which the given
+     * platform is connected. Only data that matches the given model will be written.
+     * 
+     * @param platform The platform, must be connected to a live database
+     * @param model    The model to which to constrain the written data
+     * @param input    The input streams for the XML data
+     */
+    public void writeDataToDatabase(Platform platform, Database model, InputStream[] inputs) throws DdlUtilsException
+    {
+        DataReader dataReader = getConfiguredDataReader(platform, model); 
+
+        dataReader.getSink().start();
+        for (int idx = 0; (inputs != null) && (idx < inputs.length); idx++)
+        {
+            writeDataToDatabase(dataReader, inputs[idx]);
+        }
+        dataReader.getSink().end();
+    }
+
+    /**
+     * Reads the data from the given input readers and writes it to the database to which the given
+     * platform is connected. Only data that matches the given model will be written.
+     * 
+     * @param platform The platform, must be connected to a live database
+     * @param model    The model to which to constrain the written data
+     * @param input    The input readers for the XML data
+     */
+    public void writeDataToDatabase(Platform platform, Database model, Reader[] inputs) throws DdlUtilsException
+    {
+        DataReader dataReader = getConfiguredDataReader(platform, model); 
+
+        dataReader.getSink().start();
+        for (int idx = 0; (inputs != null) && (idx < inputs.length); idx++)
+        {
+            writeDataToDatabase(dataReader, inputs[idx]);
+        }
+        dataReader.getSink().end();
+    }
+
+    /**
+     * Reads the data from the specified files and writes it to the database via the given data reader.
+     * Note that the sink that the data reader is configured with, won't be started or ended by
+     * this method. This has to be done by the code using this method.
+     * 
+     * @param dataReader The data reader
+     * @param files      The XML data files
+     */
+    public void writeDataToDatabase(DataReader dataReader, String[] files) throws DdlUtilsException
+    {
+        for (int idx = 0; (files != null) && (idx < files.length); idx++)
+        {
+            writeDataToDatabase(dataReader, files[idx]);
+        }
+    }
+
+    /**
+     * Reads the data from the given input stream and writes it to the database via the given data reader.
+     * Note that the input stream won't be closed by this method. Note also that the sink that the data
+     * reader is configured with, won't be started or ended by this method. This has to be done by the
+     * code using this method.
+     * 
+     * @param dataReader The data reader
+     * @param input      The input streams for the XML data
+     */
+    public void writeDataToDatabase(DataReader dataReader, InputStream[] inputs) throws DdlUtilsException
+    {
+        for (int idx = 0; (inputs != null) && (idx < inputs.length); idx++)
+        {
+            writeDataToDatabase(dataReader, inputs[idx]);
+        }
+    }
+
+    /**
+     * Reads the data from the given input stream and writes it to the database via the given data reader.
+     * Note that the input stream won't be closed by this method. Note also that the sink that the data
+     * reader is configured with, won't be started or ended by this method. This has to be done by the
+     * code using this method.
+     * 
+     * @param dataReader The data reader
+     * @param input      The input readers for the XML data
+     */
+    public void writeDataToDatabase(DataReader dataReader, Reader[] inputs) throws DdlUtilsException
+    {
+        for (int idx = 0; (inputs != null) && (idx < inputs.length); idx++)
+        {
+            writeDataToDatabase(dataReader, inputs[idx]);
+        }
+    }
+
+    /**
+     * Reads the data from the indicated XML file and writes it to the database via the given data reader.
+     * Note that the sink that the data reader is configured with, won't be started or ended by this method.
+     * This has to be done by the code using this method.
+     * 
+     * @param dataReader The data reader
+     * @param path       The path to the XML data file
+     */
+    public void writeDataToDatabase(DataReader dataReader, String path) throws DdlUtilsException
+    {
+        try
+        {
+            dataReader.parse(path);
+        }
+        catch (Exception ex)
+        {
+            throw new DdlUtilsException(ex);
+        }
+    }
+
+    /**
+     * Reads the data from the given input stream and writes it to the database via the given data reader.
+     * Note that the input stream won't be closed by this method. Note also that the sink that the data
+     * reader is configured with, won't be started or ended by this method. This has to be done by the
+     * code using this method.
+     * 
+     * @param dataReader The data reader
+     * @param input      The input stream for the XML data
+     */
+    public void writeDataToDatabase(DataReader dataReader, InputStream input) throws DdlUtilsException
+    {
+        try
+        {
+            dataReader.parse(input);
+        }
+        catch (Exception ex)
+        {
+            throw new DdlUtilsException(ex);
+        }
+    }
+
+    /**
+     * Reads the data from the given input stream and writes it to the database via the given data reader.
+     * Note that the input stream won't be closed by this method. Note also that the sink that the data
+     * reader is configured with, won't be started or ended by this method. This has to be done by the
+     * code using this method.
+     * 
+     * @param dataReader The data reader
+     * @param input      The input reader for the XML data
+     */
+    public void writeDataToDatabase(DataReader dataReader, Reader input) throws DdlUtilsException
+    {
+        try
+        {
+            dataReader.parse(input);
+        }
+        catch (Exception ex)
+        {
+            throw new DdlUtilsException(ex);
+        }
+    }
+}

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/io/Identity.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/io/Identity.java?view=diff&rev=487473&r1=487472&r2=487473
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/io/Identity.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/io/Identity.java Thu Dec 14 23:30:52 2006
@@ -23,6 +23,8 @@
 import java.util.Iterator;
 import java.util.Map;
 
+import org.apache.ddlutils.model.Table;
+
 /**
  * Stores the identity of an database object as defined by its primary keys. Is used
  * by {@link org.apache.ddlutils.io.DataToDatabaseSink} class for inserting objects
@@ -32,33 +34,43 @@
  */
 public class Identity
 {
-    /** The name of the table. */
-    private String _tableName;
+    /** The table. */
+    private Table _table;
     /** The optional foreign key name whose referenced object this identity represents. */
     private String _fkName;
     /** The identity columns and their values. */
     private HashMap _columnValues = new HashMap();
 
     /**
-     * Creates a new identity object for the indicated table.
+     * Creates a new identity object for the given table.
+     * 
+     * @param table The name of the table
+     */
+    public Identity(Table table)
+    {
+        _table = table;
+    }
+
+    /**
+     * Creates a new identity object for the given table.
      * 
-     * @param tableName The name of the table
+     * @param table  The table
+     * @param fkName The name of the foreign key whose referenced object this identity represents
      */
-    public Identity(String tableName)
+    public Identity(Table table, String fkName)
     {
-        _tableName = tableName;
+        _table  = table;
+        _fkName = fkName;
     }
 
     /**
-     * Creates a new identity object for the indicated table.
+     * Returns the table that this identity is for.
      * 
-     * @param tableName The name of the table
-     * @param fkName    The name of the foreign key whose referenced object this identity represents
+     * @return The table
      */
-    public Identity(String tableName, String fkName)
+    public Table getTable()
     {
-        _tableName = tableName;
-        _fkName    = fkName;
+        return _table;
     }
 
     /**
@@ -74,17 +86,28 @@
     }
     
     /**
-     * Specifies the value for one of the identity columns.
+     * Specifies the value of the indicated identity columns.
      * 
      * @param name  The column name
      * @param value The value for the column
      */
-    public void setIdentityColumn(String name, Object value)
+    public void setColumnValue(String name, Object value)
     {
         _columnValues.put(name, value);
     }
 
     /**
+     * Returns the value of the indicated identity columns.
+     * 
+     * @param name  The column name
+     * @return The column's value
+     */
+    public Object getColumnValue(String name)
+    {
+        return _columnValues.get(name);
+    }
+
+    /**
      * {@inheritDoc}
      */
     public boolean equals(Object obj)
@@ -96,7 +119,7 @@
 
         Identity otherIdentity = (Identity)obj;
 
-        if (!_tableName.equals(otherIdentity._tableName))
+        if (!_table.equals(otherIdentity._table))
         {
             return false;
         }
@@ -143,7 +166,7 @@
     {
         StringBuffer buffer = new StringBuffer();
 
-        buffer.append(_tableName);
+        buffer.append(_table.getName());
         buffer.append(":");
         for (Iterator it = _columnValues.entrySet().iterator(); it.hasNext();)
         {

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java?view=diff&rev=487473&r1=487472&r2=487473
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java Thu Dec 14 23:30:52 2006
@@ -481,6 +481,7 @@
         {
             _connection = null;
         }
+        db.initialize();
         return db;
     }
 

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java?view=diff&rev=487473&r1=487472&r2=487473
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java Thu Dec 14 23:30:52 2006
@@ -85,6 +85,8 @@
     private boolean _sqlCommentsOn = true;
     /** Whether delimited identifiers are used or not. */
     private boolean _delimitedIdentifierModeOn;
+    /** Whether identity override is enabled. */
+    private boolean _identityOverrideOn = true;
     /** Whether read foreign keys shall be sorted alphabetically. */
     private boolean _foreignKeysSorted;
 
@@ -195,6 +197,22 @@
     /**
      * {@inheritDoc}
      */
+    public boolean isIdentityOverrideOn()
+    {
+        return _identityOverrideOn;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setIdentityOverrideOn(boolean identityOverrideOn)
+    {
+        _identityOverrideOn = identityOverrideOn;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
     public boolean isForeignKeysSorted()
     {
         return _foreignKeysSorted;
@@ -1152,16 +1170,19 @@
                 if (bean.get(prop.getName()) != null)
                 {
                     // we ignore properties for which a value is present in the bean
-                    // only if they are auto-increment and the platform does not allow
-                    // the override of the auto-increment specification
-                    return getPlatformInfo().isIdentityOverrideAllowed() || !prop.getColumn().isAutoIncrement();
+                    // only if they are identity and identity override is off or
+                    // the platform does not allow the override of the auto-increment
+                    // specification
+                    return !prop.getColumn().isAutoIncrement() ||
+                           (isIdentityOverrideOn() && getPlatformInfo().isIdentityOverrideAllowed());
                 }
                 else
                 {
                     // we also return properties without a value in the bean
                     // if they ain't auto-increment and don't have a default value
                     // in this case, a NULL is inserted
-                    return !prop.getColumn().isAutoIncrement() && (prop.getColumn().getDefaultValue() == null);
+                    return !prop.getColumn().isAutoIncrement() &&
+                           (prop.getColumn().getDefaultValue() == null);
                 }
             }
         });
@@ -1191,7 +1212,7 @@
                 // in INSERT/UPDATE statements, then we need to filter the corresponding
                 // columns out
                 return prop.getColumn().isAutoIncrement() &&
-                       (!getPlatformInfo().isIdentityOverrideAllowed() || (bean.get(prop.getName()) == null));
+                       (!isIdentityOverrideOn() || !getPlatformInfo().isIdentityOverrideAllowed() || (bean.get(prop.getName()) == null));
             }
         });
 
@@ -1269,7 +1290,7 @@
         }
         catch (SQLException ex)
         {
-            throw new DatabaseOperationException("Error while inserting into the database", ex);
+            throw new DatabaseOperationException("Error while inserting into the database: " + ex.getMessage(), ex);
         }
         finally
         {

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/task/ConvertingDatabaseCommand.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/task/ConvertingDatabaseCommand.java?view=diff&rev=487473&r1=487472&r2=487473
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/task/ConvertingDatabaseCommand.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/task/ConvertingDatabaseCommand.java Thu Dec 14 23:30:52 2006
@@ -19,12 +19,8 @@
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.Iterator;
-
-import org.apache.ddlutils.io.ConverterConfiguration;
 import org.apache.ddlutils.io.DataConverterRegistration;
-import org.apache.tools.ant.BuildException;
+import org.apache.ddlutils.io.DatabaseDataIO;
 
 /**
  * Base type for database commands that use converters.
@@ -34,45 +30,26 @@
  */
 public abstract class ConvertingDatabaseCommand extends DatabaseCommand
 {
-    /** The converters. */
-    private ArrayList _converters = new ArrayList();
+    /** The database data io object. */
+    private DatabaseDataIO _dataIO = new DatabaseDataIO();
 
     /**
-     * Registers a converter.
+     * Returns the database data io object.
      * 
-     * @param converterRegistration The registration info
+     * @return The data io object
      */
-    public void addConfiguredConverter(DataConverterRegistration converterRegistration)
+    protected DatabaseDataIO getDataIO()
     {
-        _converters.add(converterRegistration);
+        return _dataIO;
     }
 
     /**
-     * Registers the converters at the given configuration.
+     * Registers a converter.
      * 
-     * @param converterConf The converter configuration
+     * @param converterRegistration The registration info
      */
-    protected void registerConverters(ConverterConfiguration converterConf) throws BuildException
+    public void addConfiguredConverter(DataConverterRegistration converterRegistration)
     {
-        for (Iterator it = _converters.iterator(); it.hasNext();)
-        {
-            DataConverterRegistration registrationInfo = (DataConverterRegistration)it.next();
-
-            if (registrationInfo.getTypeCode() != Integer.MIN_VALUE)
-            {
-                converterConf.registerConverter(registrationInfo.getTypeCode(),
-                                                registrationInfo.getConverter());
-            }
-            else
-            {
-                if ((registrationInfo.getTable() == null) || (registrationInfo.getColumn() == null)) 
-                {
-                    throw new BuildException("Please specify either the jdbc type or a table/column pair for which the converter shall be defined");
-                }
-                converterConf.registerConverter(registrationInfo.getTable(),
-                                                registrationInfo.getColumn(),
-                                                registrationInfo.getConverter());
-            }
-        }
+        _dataIO.registerConverter(converterRegistration);
     }
 }

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/task/WriteDataToDatabaseCommand.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/task/WriteDataToDatabaseCommand.java?view=diff&rev=487473&r1=487472&r2=487473
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/task/WriteDataToDatabaseCommand.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/task/WriteDataToDatabaseCommand.java Thu Dec 14 23:30:52 2006
@@ -24,9 +24,7 @@
 import java.util.Iterator;
 
 import org.apache.commons.lang.exception.ExceptionUtils;
-import org.apache.ddlutils.Platform;
 import org.apache.ddlutils.io.DataReader;
-import org.apache.ddlutils.io.DataToDatabaseSink;
 import org.apache.ddlutils.model.Database;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.DirectoryScanner;
@@ -56,12 +54,6 @@
     private File      _singleDataFile = null;
     /** The input files. */
     private ArrayList _fileSets = new ArrayList();
-    /** Whether foreign key order shall be followed when inserting data into the database. */
-    private boolean _ensureFKOrder = true;
-    /** Whether we should use batch mode. */
-    private Boolean _useBatchMode;
-    /** The maximum number of objects to insert in one batch. */
-    private Integer _batchSize;
     
     /**
      * Adds a fileset.
@@ -94,7 +86,7 @@
      */
     public void setBatchSize(int batchSize)
     {
-        _batchSize = new Integer(batchSize);
+        getDataIO().setBatchSize(new Integer(batchSize));
     }
 
     /**
@@ -110,7 +102,7 @@
      */
     public void setUseBatchMode(boolean useBatchMode)
     {
-        _useBatchMode = Boolean.valueOf(useBatchMode);
+        getDataIO().setUseBatchMode(useBatchMode);
     }
 
     /**
@@ -125,7 +117,7 @@
      */
     public void setEnsureForeignKeyOrder(boolean ensureFKOrder)
     {
-        _ensureFKOrder = ensureFKOrder;
+        getDataIO().setEnsureFKOrder(ensureFKOrder);
     }
 
     /**
@@ -133,32 +125,20 @@
      */
     public void execute(Task task, Database model) throws BuildException
     {
-        try
+        if ((_singleDataFile != null) && !_fileSets.isEmpty())
         {
-            Platform           platform = getPlatform();
-            DataToDatabaseSink sink     = new DataToDatabaseSink(platform, model);
-            DataReader         reader   = new DataReader();
+            throw new BuildException("Please use either the datafile attribute or the sub fileset element, but not both");
+        }
 
-            sink.setEnsureForeignKeyOrder(_ensureFKOrder);
-            if (_useBatchMode != null)
-            {
-                sink.setUseBatchMode(_useBatchMode.booleanValue());
-                if (_batchSize != null)
-                {
-                    sink.setBatchSize(_batchSize.intValue());
-                }
-            }
-            
-            reader.setModel(model);
-            reader.setSink(sink);
-            registerConverters(reader.getConverterConfiguration());
-            if ((_singleDataFile != null) && !_fileSets.isEmpty())
-            {
-                throw new BuildException("Please use either the datafile attribute or the sub fileset element, but not both");
-            }
+        DataReader dataReader = null;
+
+        try
+        {
+            dataReader = getDataIO().getConfiguredDataReader(getPlatform(), model);
+            dataReader.getSink().start();
             if (_singleDataFile != null)
             {
-                readSingleDataFile(task, reader, _singleDataFile);
+                readSingleDataFile(task, dataReader, _singleDataFile);
             }
             else
             {
@@ -171,7 +151,7 @@
     
                     for (int idx = 0; (files != null) && (idx < files.length); idx++)
                     {
-                        readSingleDataFile(task, reader, new File(fileSetDir, files[idx]));
+                        readSingleDataFile(task, dataReader, new File(fileSetDir, files[idx]));
                     }
                 }
             }
@@ -187,6 +167,13 @@
                 throw new BuildException(ex);
             }
         }
+        finally
+        {
+            if (dataReader != null)
+            {
+                dataReader.getSink().end();
+            }
+        }
     }
 
     /**
@@ -214,7 +201,7 @@
         {
             try
             {
-                reader.parse(dataFile);
+                getDataIO().writeDataToDatabase(reader, dataFile.getAbsolutePath());
                 task.log("Written data file "+dataFile.getAbsolutePath() + " to database", Project.MSG_INFO);
             }
             catch (Exception ex)

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/task/WriteDataToFileCommand.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/task/WriteDataToFileCommand.java?view=diff&rev=487473&r1=487472&r2=487473
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/task/WriteDataToFileCommand.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/task/WriteDataToFileCommand.java Thu Dec 14 23:30:52 2006
@@ -22,10 +22,7 @@
 import java.io.File;
 import java.io.FileOutputStream;
 
-import org.apache.ddlutils.Platform;
-import org.apache.ddlutils.io.DataWriter;
 import org.apache.ddlutils.model.Database;
-import org.apache.ddlutils.model.Table;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Task;
 
@@ -72,22 +69,8 @@
     {
         try
         {
-            Platform   platform = getPlatform();
-            DataWriter writer   = new DataWriter(new FileOutputStream(_outputFile), _encoding);
-            Table[]    tables   = new Table[1];
-            
-            registerConverters(writer.getConverterConfiguration());
-
-            // TODO: An advanced algorithm could be employed here that writes objects
-            //       related by foreign keys, in the correct order
-            writer.writeDocumentStart();
-            for (int idx = 0; idx < model.getTableCount(); idx++)
-            {
-                tables[0] = (Table)model.getTable(idx);
-
-                writer.write(platform.query(model, "select * from "+tables[0].getName(), tables));
-            }
-            writer.writeDocumentEnd();
+            getDataIO().writeDataToXML(getPlatform(),
+                                       new FileOutputStream(_outputFile), _encoding);
         }
         catch (Exception ex)
         {

Modified: db/ddlutils/trunk/src/test/org/apache/ddlutils/RunAllTests.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/test/org/apache/ddlutils/RunAllTests.java?view=diff&rev=487473&r1=487472&r2=487473
==============================================================================
--- db/ddlutils/trunk/src/test/org/apache/ddlutils/RunAllTests.java (original)
+++ db/ddlutils/trunk/src/test/org/apache/ddlutils/RunAllTests.java Thu Dec 14 23:30:52 2006
@@ -27,6 +27,7 @@
 import org.apache.ddlutils.io.TestDataReaderAndWriter;
 import org.apache.ddlutils.io.TestDatabaseIO;
 import org.apache.ddlutils.io.TestDatatypes;
+import org.apache.ddlutils.io.TestMisc;
 import org.apache.ddlutils.io.converters.TestDateConverter;
 import org.apache.ddlutils.io.converters.TestTimeConverter;
 import org.apache.ddlutils.model.TestArrayAccessAtTable;
@@ -125,6 +126,7 @@
             suite.addTestSuite(TestDatatypes.class);
             suite.addTestSuite(TestConstraints.class);
             suite.addTestSuite(TestAlteration.class);
+            suite.addTestSuite(TestMisc.class);
         }
 
         return suite;

Modified: db/ddlutils/trunk/src/test/org/apache/ddlutils/TestDatabaseWriterBase.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/test/org/apache/ddlutils/TestDatabaseWriterBase.java?view=diff&rev=487473&r1=487472&r2=487473
==============================================================================
--- db/ddlutils/trunk/src/test/org/apache/ddlutils/TestDatabaseWriterBase.java (original)
+++ db/ddlutils/trunk/src/test/org/apache/ddlutils/TestDatabaseWriterBase.java Thu Dec 14 23:30:52 2006
@@ -293,7 +293,9 @@
 
             dataReader.setModel(_model);
             dataReader.setSink(new DataToDatabaseSink(getPlatform(), _model));
+            dataReader.getSink().start();
             dataReader.parse(new StringReader(dataXml));
+            dataReader.getSink().end();
             return _model;
         }
         catch (Exception ex)

Modified: db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDataReaderAndWriter.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDataReaderAndWriter.java?view=diff&rev=487473&r1=487472&r2=487473
==============================================================================
--- db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDataReaderAndWriter.java (original)
+++ db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDataReaderAndWriter.java Thu Dec 14 23:30:52 2006
@@ -106,6 +106,7 @@
             public void end() throws DataSinkException
             {}
         });
+        // no need to call start/end as the don't do anything anyways
         dataReader.parse(new StringReader(testDataXml));
 
         assertEquals(5, readObjects.size());
@@ -215,6 +216,7 @@
             public void end() throws DataSinkException
             {}
         });
+        // no need to call start/end as the don't do anything anyways
         dataReader.parse(new StringReader(dataXml));
 
         assertEquals(1, readObjects.size());

Modified: db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDatatypes.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDatatypes.java?view=diff&rev=487473&r1=487472&r2=487473
==============================================================================
--- db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDatatypes.java (original)
+++ db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestDatatypes.java Thu Dec 14 23:30:52 2006
@@ -145,6 +145,7 @@
         sink.setUseBatchMode(false);
         reader.setModel(getModel());
         reader.setSink(sink);
+        sink.start();
         try
         {
             reader.parse(new StringReader(dataSql));
@@ -152,6 +153,10 @@
         catch (Exception ex)
         {
             throw new RuntimeException(ex);
+        }
+        finally
+        {
+            sink.end();
         }
 
         beans = getRows("roundtrip");

Added: db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestMisc.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestMisc.java?view=auto&rev=487473
==============================================================================
--- db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestMisc.java (added)
+++ db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestMisc.java Thu Dec 14 23:30:52 2006
@@ -0,0 +1,257 @@
+package org.apache.ddlutils.io;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.List;
+
+import junit.framework.Test;
+
+import org.dom4j.Document;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+import org.xml.sax.InputSource;
+
+/**
+ * Contains misc tests.
+ * 
+ * @version $Revision: $
+ */
+public class TestMisc extends RoundtripTestBase
+{
+    /**
+     * Parameterized test case pattern.
+     * 
+     * @return The tests
+     */
+    public static Test suite() throws Exception
+    {
+        return getTests(TestMisc.class);
+    }
+
+    /**
+     * Tests the backup of restore of a table with an identity column and a foreign key to
+     * it when identity override is turned on.
+     */
+    public void testIdentityOverrideOn() throws Exception
+    {
+        if (!getPlatformInfo().isIdentityOverrideAllowed())
+        {
+            // TODO: for testing these platforms, we need deleteRows
+            return;
+        }
+        final String modelXml = 
+            "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+
+            "<database name='roundtriptest'>\n"+
+            "  <table name='misc1'>\n"+
+            "    <column name='pk' type='INTEGER' primaryKey='true' required='true' autoIncrement='true'/>\n"+
+            "    <column name='avalue' type='INTEGER' required='false'/>\n"+
+            "  </table>\n"+
+            "  <table name='misc2'>\n"+
+            "    <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+
+            "    <column name='fk' type='INTEGER' required='false'/>\n"+
+            "    <foreign-key name='test' foreignTable='misc1'>\n"+
+            "      <reference local='fk' foreign='pk'/>\n"+
+            "    </foreign-key>\n"+
+            "  </table>\n"+
+            "</database>";
+
+        createDatabase(modelXml);
+
+        insertRow("misc1", new Object[] { new Integer(10), new Integer(1) });
+        insertRow("misc1", new Object[] { new Integer(12), new Integer(2) });
+        insertRow("misc1", new Object[] { new Integer(13), new Integer(3) });
+        insertRow("misc2", new Object[] { new Integer(1), new Integer(10) });
+        insertRow("misc2", new Object[] { new Integer(2), new Integer(13) });
+
+        StringWriter   stringWriter = new StringWriter();
+        DatabaseDataIO dataIO       = new DatabaseDataIO();
+
+        dataIO.writeDataToXML(getPlatform(), stringWriter, "UTF-8");
+
+        String    dataAsXml = stringWriter.toString();
+        SAXReader reader    = new SAXReader();
+        Document  testDoc   = reader.read(new InputSource(new StringReader(dataAsXml)));
+
+        if (getPlatform().isDelimitedIdentifierModeOn())
+        {
+            List misc1Rows = testDoc.selectNodes("//misc1");
+            List misc2Rows = testDoc.selectNodes("//misc2");
+
+            assertEquals(3, misc1Rows.size());
+            assertEquals("10", ((Element)misc1Rows.get(0)).attributeValue("pk"));
+            assertEquals("1",  ((Element)misc1Rows.get(0)).attributeValue("avalue"));
+            assertEquals("12", ((Element)misc1Rows.get(1)).attributeValue("pk"));
+            assertEquals("2",  ((Element)misc1Rows.get(1)).attributeValue("avalue"));
+            assertEquals("13", ((Element)misc1Rows.get(2)).attributeValue("pk"));
+            assertEquals("3",  ((Element)misc1Rows.get(2)).attributeValue("avalue"));
+            assertEquals(2, misc2Rows.size());
+            assertEquals("1",  ((Element)misc2Rows.get(0)).attributeValue("pk"));
+            assertEquals("10", ((Element)misc2Rows.get(0)).attributeValue("fk"));
+            assertEquals("2",  ((Element)misc2Rows.get(1)).attributeValue("pk"));
+            assertEquals("13", ((Element)misc2Rows.get(1)).attributeValue("fk"));
+        }
+        else
+        {
+            List misc1Rows = testDoc.selectNodes("//MISC1");
+            List misc2Rows = testDoc.selectNodes("//MISC2");
+
+            assertEquals(3, misc1Rows.size());
+            assertEquals("10", ((Element)misc1Rows.get(0)).attributeValue("PK"));
+            assertEquals("1",  ((Element)misc1Rows.get(0)).attributeValue("AVALUE"));
+            assertEquals("12", ((Element)misc1Rows.get(1)).attributeValue("PK"));
+            assertEquals("2",  ((Element)misc1Rows.get(1)).attributeValue("AVALUE"));
+            assertEquals("13", ((Element)misc1Rows.get(2)).attributeValue("PK"));
+            assertEquals("3",  ((Element)misc1Rows.get(2)).attributeValue("AVALUE"));
+            assertEquals(2, misc2Rows.size());
+            assertEquals("1",  ((Element)misc2Rows.get(0)).attributeValue("PK"));
+            assertEquals("10", ((Element)misc2Rows.get(0)).attributeValue("FK"));
+            assertEquals("2",  ((Element)misc2Rows.get(1)).attributeValue("PK"));
+            assertEquals("13", ((Element)misc2Rows.get(1)).attributeValue("FK"));
+        }
+
+        dropDatabase();
+        createDatabase(modelXml);
+
+        StringReader stringReader = new StringReader(dataAsXml);
+
+        dataIO.writeDataToDatabase(getPlatform(), new Reader[] { stringReader });
+
+        List beans = getRows("misc1");
+
+        assertEquals(new Integer(10), beans.get(0), "pk");
+        assertEquals(new Integer(1),  beans.get(0), "avalue");
+        assertEquals(new Integer(12), beans.get(1), "pk");
+        assertEquals(new Integer(2),  beans.get(1), "avalue");
+        assertEquals(new Integer(13), beans.get(2), "pk");
+        assertEquals(new Integer(3),  beans.get(2), "avalue");
+
+        beans = getRows("misc2");
+
+        assertEquals(new Integer(1),  beans.get(0), "pk");
+        assertEquals(new Integer(10), beans.get(0), "fk");
+        assertEquals(new Integer(2),  beans.get(1), "pk");
+        assertEquals(new Integer(13), beans.get(1), "fk");
+    }
+
+    /**
+     * Tests the backup of restore of a table with an identity column and a foreign key to
+     * it when identity override is turned off.
+     */
+    public void testIdentityOverrideOff() throws Exception
+    {
+        final String modelXml = 
+            "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+
+            "<database name='roundtriptest'>\n"+
+            "  <table name='misc1'>\n"+
+            "    <column name='pk' type='INTEGER' primaryKey='true' required='true' autoIncrement='true'/>\n"+
+            "    <column name='avalue' type='INTEGER' required='false'/>\n"+
+            "  </table>\n"+
+            "  <table name='misc2'>\n"+
+            "    <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+
+            "    <column name='fk' type='INTEGER' required='false'/>\n"+
+            "    <foreign-key name='test' foreignTable='misc1'>\n"+
+            "      <reference local='fk' foreign='pk'/>\n"+
+            "    </foreign-key>\n"+
+            "  </table>\n"+
+            "</database>";
+
+        createDatabase(modelXml);
+
+        insertRow("misc1", new Object[] { new Integer(10), new Integer(1) });
+        insertRow("misc1", new Object[] { new Integer(12), new Integer(2) });
+        insertRow("misc1", new Object[] { new Integer(13), new Integer(3) });
+        insertRow("misc2", new Object[] { new Integer(1), new Integer(10) });
+        insertRow("misc2", new Object[] { new Integer(2), new Integer(13) });
+
+        StringWriter   stringWriter = new StringWriter();
+        DatabaseDataIO dataIO       = new DatabaseDataIO();
+
+        dataIO.writeDataToXML(getPlatform(), stringWriter, "UTF-8");
+
+        String    dataAsXml = stringWriter.toString();
+        SAXReader reader    = new SAXReader();
+        Document  testDoc   = reader.read(new InputSource(new StringReader(dataAsXml)));
+
+        if (getPlatform().isDelimitedIdentifierModeOn())
+        {
+            List misc1Rows = testDoc.selectNodes("//misc1");
+            List misc2Rows = testDoc.selectNodes("//misc2");
+
+            assertEquals(3, misc1Rows.size());
+            assertEquals("10", ((Element)misc1Rows.get(0)).attributeValue("pk"));
+            assertEquals("1",  ((Element)misc1Rows.get(0)).attributeValue("avalue"));
+            assertEquals("12", ((Element)misc1Rows.get(1)).attributeValue("pk"));
+            assertEquals("2",  ((Element)misc1Rows.get(1)).attributeValue("avalue"));
+            assertEquals("13", ((Element)misc1Rows.get(2)).attributeValue("pk"));
+            assertEquals("3",  ((Element)misc1Rows.get(2)).attributeValue("avalue"));
+            assertEquals(2, misc2Rows.size());
+            assertEquals("1",  ((Element)misc2Rows.get(0)).attributeValue("pk"));
+            assertEquals("10", ((Element)misc2Rows.get(0)).attributeValue("fk"));
+            assertEquals("2",  ((Element)misc2Rows.get(1)).attributeValue("pk"));
+            assertEquals("13", ((Element)misc2Rows.get(1)).attributeValue("fk"));
+        }
+        else
+        {
+            List misc1Rows = testDoc.selectNodes("//MISC1");
+            List misc2Rows = testDoc.selectNodes("//MISC2");
+
+            assertEquals(3, misc1Rows.size());
+            assertEquals("10", ((Element)misc1Rows.get(0)).attributeValue("PK"));
+            assertEquals("1",  ((Element)misc1Rows.get(0)).attributeValue("AVALUE"));
+            assertEquals("12", ((Element)misc1Rows.get(1)).attributeValue("PK"));
+            assertEquals("2",  ((Element)misc1Rows.get(1)).attributeValue("AVALUE"));
+            assertEquals("13", ((Element)misc1Rows.get(2)).attributeValue("PK"));
+            assertEquals("3",  ((Element)misc1Rows.get(2)).attributeValue("AVALUE"));
+            assertEquals(2, misc2Rows.size());
+            assertEquals("1",  ((Element)misc2Rows.get(0)).attributeValue("PK"));
+            assertEquals("10", ((Element)misc2Rows.get(0)).attributeValue("FK"));
+            assertEquals("2",  ((Element)misc2Rows.get(1)).attributeValue("PK"));
+            assertEquals("13", ((Element)misc2Rows.get(1)).attributeValue("FK"));
+        }
+
+        dropDatabase();
+        createDatabase(modelXml);
+
+        getPlatform().setIdentityOverrideOn(false);
+
+        StringReader stringReader = new StringReader(dataAsXml);
+
+        dataIO.writeDataToDatabase(getPlatform(), new Reader[] { stringReader });
+
+        List beans = getRows("misc1");
+
+        assertEquals(new Integer(1), beans.get(0), "pk");
+        assertEquals(new Integer(1), beans.get(0), "avalue");
+        assertEquals(new Integer(2), beans.get(1), "pk");
+        assertEquals(new Integer(2), beans.get(1), "avalue");
+        assertEquals(new Integer(3), beans.get(2), "pk");
+        assertEquals(new Integer(3), beans.get(2), "avalue");
+
+        beans = getRows("misc2");
+
+        assertEquals(new Integer(1), beans.get(0), "pk");
+        assertEquals(new Integer(1), beans.get(0), "fk");
+        assertEquals(new Integer(2), beans.get(1), "pk");
+        assertEquals(new Integer(3), beans.get(1), "fk");
+    }
+}