/*
* Copyright (C) 2004 Anthony Smith
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* ----------------------------------------------------------------------------
* TITLE $Id$
* ---------------------------------------------------------------------------
*
* --------------------------------------------------------------------------*/
package opendbcopy.plugin.dump;
import opendbcopy.config.APM;
import opendbcopy.config.XMLTags;
import opendbcopy.connection.DBConnection;
import opendbcopy.connection.exception.CloseConnectionException;
import opendbcopy.controller.MainController;
import opendbcopy.plugin.model.DynamicPluginThread;
import opendbcopy.plugin.model.Model;
import opendbcopy.plugin.model.database.DatabaseModel;
import opendbcopy.plugin.model.exception.PluginException;
import opendbcopy.sql.Helper;
import opendbcopy.util.InputOutputHelper;
import org.jdom.Element;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* class description
*
* @author Anthony Smith
* @version $Revision$
*/
public class DumpDataToFileDelimitedPlugin extends DynamicPluginThread {
private DatabaseModel model;
private Connection connSource = null;
private Statement stmSource = null;
private ResultSet rs = null;
private StringBuffer recordBuffer = new StringBuffer(); // to hold records contents
private int counterRecords = 0;
private int counterTables = 0;
private int append_file_after_records = 0;
private String delimiter;
private String fileType = "";
private boolean show_header = false;
private boolean show_null_values = false;
List processTables = null;
private File outputPath = null;
/**
* Creates a new CopyMappingPlugin object.
*
* @param controller DOCUMENT ME!
* @param baseModel DOCUMENT ME!
*
* @throws PluginException DOCUMENT ME!
*/
public DumpDataToFileDelimitedPlugin(MainController controller,
Model baseModel) throws PluginException {
super(controller, baseModel);
this.model = (DatabaseModel) baseModel;
}
/**
* DOCUMENT ME!
*
* @throws PluginException DOCUMENT ME!
*/
protected final void setUp() throws PluginException {
// read the plugins configuration
Element conf = model.getConf();
try {
outputPath = new File(conf.getChild(XMLTags.DIR).getAttributeValue(XMLTags.VALUE));
if (!outputPath.exists()) {
boolean mkDirOk = outputPath.mkdir();
if (!mkDirOk) {
throw new PluginException("Could not create " + outputPath.getAbsolutePath());
}
}
fileType = conf.getChild(XMLTags.FILE_TYPE).getAttributeValue(XMLTags.VALUE);
show_header = Boolean.valueOf(conf.getChild(XMLTags.SHOW_HEADER).getAttributeValue(XMLTags.VALUE)).booleanValue();
show_null_values = Boolean.valueOf(conf.getChild("show_null_values").getAttributeValue(XMLTags.VALUE)).booleanValue();
append_file_after_records = Integer.parseInt(conf.getChild(XMLTags.APPEND_FILE_AFTER_RECORDS).getAttributeValue(XMLTags.VALUE));
delimiter = conf.getChild(XMLTags.DELIMITER).getAttributeValue(XMLTags.VALUE);
// transform \t for tabulator into unicode representation
if (delimiter.compareToIgnoreCase("\\t") == 0) {
delimiter = "\u0009";
}
// get connection
connSource = DBConnection.getConnection(model.getSourceConnection());
// extract the tables to dump
processTables = model.getSourceTablesToProcessOrdered();
} catch (Exception e) {
throw new PluginException(e);
}
// now set the number of tables that need to be copied
model.setLengthProgressTable(processTables.size());
}
/**
* DOCUMENT ME!
*
* @throws PluginException DOCUMENT ME!
*/
public void execute() throws PluginException {
try {
stmSource = connSource.createStatement();
String stmSelect = "";
ArrayList generatedFiles = new ArrayList();
Iterator itProcessTables = processTables.iterator();
while (itProcessTables.hasNext() && !isInterrupted()) {
Element tableProcess = (Element) itProcessTables.next();
String sourceTableName = tableProcess.getAttributeValue(XMLTags.NAME);
File file = new File(outputPath.getAbsolutePath() + APM.FILE_SEP + getFileName(sourceTableName));
counterRecords = 0;
List processColumns = model.getSourceColumnsToProcess(sourceTableName);
if (show_header) {
initHeader(processColumns);
} else {
recordBuffer = new StringBuffer();
}
// setting record counter to minimum of progress bar
model.setCurrentProgressRecord(0);
model.setCurrentProgressTable(0);
// Reading number of records for progress bar
model.setLengthProgressRecord(Helper.getNumberOfRecordsFiltered(stmSource, model, XMLTags.SOURCE_DB, sourceTableName));
// get Select Statement
stmSelect = Helper.getSelectStatement(model, sourceTableName, XMLTags.NAME, processColumns);
model.setCurrentProgressTable(counterTables);
// Execute SELECT
rs = stmSource.executeQuery(stmSelect);
model.setProgressMessage("Reading " + sourceTableName + " ...");
logger.info("Reading " + sourceTableName + " ...");
// open file writer
OutputStreamWriter fileWriter = new OutputStreamWriter(new FileOutputStream(file), MainController.getEncoding());
while (rs.next()) {
model.setCurrentProgressRecord(++counterRecords);
// process columns
for (int colCounter = 1; colCounter < (processColumns.size() + 1); colCounter++) {
String input = rs.getString(colCounter);
if (!rs.wasNull()) {
recordBuffer.append(input + delimiter);
} else {
if (show_null_values) {
recordBuffer.append("null" + delimiter);
} else {
recordBuffer.append("" + delimiter);
}
}
}
recordBuffer.append(APM.LINE_SEP);
if ((counterRecords % append_file_after_records) == 0) {
fileWriter.write(recordBuffer.toString());
recordBuffer = new StringBuffer();
}
}
// append rest and close file
if (recordBuffer.length() > 0) {
fileWriter.write(recordBuffer.toString());
fileWriter.close();
}
rs.close();
generatedFiles.add(file);
logger.info(counterRecords + " records written to file " + file.getAbsolutePath());
counterRecords = 0;
// required in case of last table that had to be copied
model.setCurrentProgressTable(++counterTables);
// set processed
tableProcess.setAttribute(XMLTags.PROCESSED, "true");
}
stmSource.close();
DBConnection.closeConnection(connSource);
if (!isInterrupted()) {
logger.info(counterTables + " table(s) processed");
File[] outputFiles = new File[generatedFiles.size()];
outputFiles = (File[]) generatedFiles.toArray(outputFiles);
Element outputConf = model.getConf().getChild(XMLTags.OUTPUT);
model.appendToOutput(InputOutputHelper.createFileListElement(outputFiles, outputConf.getChild(XMLTags.FILELIST).getAttributeValue(XMLTags.VALUE)));
}
} catch (SQLException sqle) {
throw new PluginException(sqle);
} catch (Exception e1) {
// clean up
try {
DBConnection.closeConnection(connSource);
} catch (CloseConnectionException e2) {
// bad luck ... don't worry
}
throw new PluginException(e1);
}
}
/**
* DOCUMENT ME!
*
* @param processColumns DOCUMENT ME!
*
* @throws IllegalArgumentException DOCUMENT ME!
*/
private void initHeader(List processColumns) throws IllegalArgumentException {
if (processColumns == null) {
throw new IllegalArgumentException("Missing processColumns");
}
recordBuffer = new StringBuffer();
Iterator itProcessColumns = processColumns.iterator();
// set the column headings
while (itProcessColumns.hasNext()) {
recordBuffer.append(((Element) itProcessColumns.next()).getAttributeValue(XMLTags.NAME) + delimiter);
}
recordBuffer.append(APM.LINE_SEP);
}
/**
* DOCUMENT ME!
*
* @param tableName DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws IllegalArgumentException DOCUMENT ME!
*/
private String getFileName(String tableName) throws IllegalArgumentException {
if (tableName == null) {
throw new IllegalArgumentException("Missing tableName");
}
return tableName + "." + fileType;
}
}