com.healthmarketscience.jackcess.ExportUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.healthmarketscience.jackcess.ExportUtil.java

Source

/*
Copyright (c) 2007 Health Market Science, Inc.
    
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
    
This library 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
Lesser General Public License for more details.
    
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
USA
    
You can contact Health Market Science at info@healthmarketscience.com
or at the following address:
    
Health Market Science
2700 Horizon Drive
Suite 200
King of Prussia, PA 19406
*/

package com.healthmarketscience.jackcess;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 
 * @author Frank Gerbig
 */
public class ExportUtil {

    private static final Log LOG = LogFactory.getLog(ExportUtil.class);

    public static final String DEFAULT_DELIMITER = ",";
    public static final char DEFAULT_QUOTE_CHAR = '"';
    public static final String DEFAULT_FILE_EXT = "csv";

    private ExportUtil() {
    }

    /**
     * Copy all tables into new delimited text files <br>
     * Equivalent to: {@code exportAll(db, dir, "csv");}
     * 
     * @param db
     *          Database the table to export belongs to
     * @param dir
     *          The directory where the new files will be created
     * 
     * @see #exportAll(Database,File,String)
     * @see Builder
     */
    public static void exportAll(Database db, File dir) throws IOException {
        exportAll(db, dir, DEFAULT_FILE_EXT);
    }

    /**
     * Copy all tables into new delimited text files <br>
     * Equivalent to: {@code exportFile(db, name, f, false, null, '"',
     * SimpleExportFilter.INSTANCE);}
     * 
     * @param db
     *          Database the table to export belongs to
     * @param dir
     *          The directory where the new files will be created
     * @param ext
     *          The file extension of the new files
     * 
     * @see #exportFile(Database,String,File,boolean,String,char,ExportFilter)
     * @see Builder
     */
    public static void exportAll(Database db, File dir, String ext) throws IOException {
        for (String tableName : db.getTableNames()) {
            exportFile(db, tableName, new File(dir, tableName + "." + ext), false, DEFAULT_DELIMITER,
                    DEFAULT_QUOTE_CHAR, SimpleExportFilter.INSTANCE);
        }
    }

    /**
     * Copy all tables into new delimited text files <br>
     * Equivalent to: {@code exportFile(db, name, f, false, null, '"',
     * SimpleExportFilter.INSTANCE);}
     * 
     * @param db
     *          Database the table to export belongs to
     * @param dir
     *          The directory where the new files will be created
     * @param ext
     *          The file extension of the new files
     * @param header
     *          If <code>true</code> the first line contains the column names
     * 
     * @see #exportFile(Database,String,File,boolean,String,char,ExportFilter)
     * @see Builder
     */
    public static void exportAll(Database db, File dir, String ext, boolean header) throws IOException {
        for (String tableName : db.getTableNames()) {
            exportFile(db, tableName, new File(dir, tableName + "." + ext), header, DEFAULT_DELIMITER,
                    DEFAULT_QUOTE_CHAR, SimpleExportFilter.INSTANCE);
        }
    }

    /**
     * Copy all tables into new delimited text files <br>
     * Equivalent to: {@code exportFile(db, name, f, false, null, '"',
     * SimpleExportFilter.INSTANCE);}
     * 
     * @param db
     *          Database the table to export belongs to
     * @param dir
     *          The directory where the new files will be created
     * @param ext
     *          The file extension of the new files
     * @param header
     *          If <code>true</code> the first line contains the column names
     * @param delim
     *          The column delimiter, <code>null</code> for default (comma)
     * @param quote
     *          The quote character
     * @param filter
     *          valid export filter
     * 
     * @see #exportFile(Database,String,File,boolean,String,char,ExportFilter)
     * @see Builder
     */
    public static void exportAll(Database db, File dir, String ext, boolean header, String delim, char quote,
            ExportFilter filter) throws IOException {
        for (String tableName : db.getTableNames()) {
            exportFile(db, tableName, new File(dir, tableName + "." + ext), header, delim, quote, filter);
        }
    }

    /**
     * Copy a table into a new delimited text file <br>
     * Equivalent to: {@code exportFile(db, name, f, false, null, '"',
     * SimpleExportFilter.INSTANCE);}
     * 
     * @param db
     *          Database the table to export belongs to
     * @param tableName
     *          Name of the table to export
     * @param f
     *          New file to create
     * 
     * @see #exportFile(Database,String,File,boolean,String,char,ExportFilter)
     * @see Builder
     */
    public static void exportFile(Database db, String tableName, File f) throws IOException {
        exportFile(db, tableName, f, false, DEFAULT_DELIMITER, DEFAULT_QUOTE_CHAR, SimpleExportFilter.INSTANCE);
    }

    /**
     * Copy a table into a new delimited text file <br>
     * Nearly equivalent to: {@code exportWriter(db, name, new BufferedWriter(f),
     * header, delim, quote, filter);}
     * 
     * @param db
     *          Database the table to export belongs to
     * @param tableName
     *          Name of the table to export
     * @param f
     *          New file to create
     * @param header
     *          If <code>true</code> the first line contains the column names
     * @param delim
     *          The column delimiter, <code>null</code> for default (comma)
     * @param quote
     *          The quote character
     * @param filter
     *          valid export filter
     * 
     * @see #exportWriter(Database,String,BufferedWriter,boolean,String,char,ExportFilter)
     * @see Builder
     */
    public static void exportFile(Database db, String tableName, File f, boolean header, String delim, char quote,
            ExportFilter filter) throws IOException {
        BufferedWriter out = null;
        try {
            out = new BufferedWriter(new FileWriter(f));
            exportWriter(db, tableName, out, header, delim, quote, filter);
            out.close();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (Exception ex) {
                    LOG.warn("Could not close file " + f.getAbsolutePath(), ex);
                }
            }
        }
    }

    /**
     * Copy a table in this database into a new delimited text file <br>
     * Equivalent to: {@code exportWriter(db, name, out, false, null, '"',
     * SimpleExportFilter.INSTANCE);}
     * 
     * @param db
     *          Database the table to export belongs to
     * @param tableName
     *          Name of the table to export
     * @param out
     *          Writer to export to
     * 
     * @see #exportWriter(Database,String,BufferedWriter,boolean,String,char,ExportFilter)
     * @see Builder
     */
    public static void exportWriter(Database db, String tableName, BufferedWriter out) throws IOException {
        exportWriter(db, tableName, out, false, DEFAULT_DELIMITER, DEFAULT_QUOTE_CHAR, SimpleExportFilter.INSTANCE);
    }

    /**
     * Copy a table in this database into a new delimited text file. <br>
     * Equivalent to: {@code exportWriter(Cursor.createCursor(db.getTable(tableName)), out, header, delim, quote, filter);}
     * 
     * @param db
     *          Database the table to export belongs to
     * @param tableName
     *          Name of the table to export
     * @param out
     *          Writer to export to
     * @param header
     *          If <code>true</code> the first line contains the column names
     * @param delim
     *          The column delimiter, <code>null</code> for default (comma)
     * @param quote
     *          The quote character
     * @param filter
     *          valid export filter
     * 
     * @see #exportWriter(Cursor,BufferedWriter,boolean,String,char,ExportFilter)
     * @see Builder
     */
    public static void exportWriter(Database db, String tableName, BufferedWriter out, boolean header, String delim,
            char quote, ExportFilter filter) throws IOException {
        exportWriter(Cursor.createCursor(db.getTable(tableName)), out, header, delim, quote, filter);
    }

    /**
     * Copy a table in this database into a new delimited text file.
     * 
     * @param cursor
     *          Cursor to export
     * @param out
     *          Writer to export to
     * @param header
     *          If <code>true</code> the first line contains the column names
     * @param delim
     *          The column delimiter, <code>null</code> for default (comma)
     * @param quote
     *          The quote character
     * @param filter
     *          valid export filter
     *
     * @see Builder
     */
    public static void exportWriter(Cursor cursor, BufferedWriter out, boolean header, String delim, char quote,
            ExportFilter filter) throws IOException {
        String delimiter = (delim == null) ? DEFAULT_DELIMITER : delim;

        // create pattern which will indicate whether or not a value needs to be
        // quoted or not (contains delimiter, separator, or newline)
        Pattern needsQuotePattern = Pattern.compile("(?:" + "x" + ")|(?:" + "x" + ")|(?:[\n\r])");
        //Pattern needsQuotePattern = Pattern.compile(
        //"(?:" + Pattern.quote(delimiter) + ")|(?:" + 
        //Pattern.quote("" + quote) + ")|(?:[\n\r])");

        List<Column> origCols = cursor.getTable().getColumns();
        List<Column> columns = new ArrayList<Column>(origCols);
        columns = filter.filterColumns(columns);

        Collection<String> columnNames = null;
        if (!origCols.equals(columns)) {

            // columns have been filtered
            columnNames = new HashSet<String>();
            for (Column c : columns) {
                columnNames.add(c.getName());
            }
        }

        // print the header row (if desired)
        if (header) {
            for (Iterator<Column> iter = columns.iterator(); iter.hasNext();) {

                writeValue(out, iter.next().getName(), quote, needsQuotePattern);

                if (iter.hasNext()) {
                    out.write(delimiter);
                }
            }
            out.newLine();
        }

        // print the data rows
        Map<String, Object> row;
        Object[] unfilteredRowData = new Object[columns.size()];
        while ((row = cursor.getNextRow(columnNames)) != null) {

            // fill raw row data in array
            for (int i = 0; i < columns.size(); i++) {
                unfilteredRowData[i] = columns.get(i).getRowValue(row);
            }

            // apply filter
            Object[] rowData = filter.filterRow(unfilteredRowData);
            if (rowData == null) {
                continue;
            }

            // print row
            for (int i = 0; i < columns.size(); i++) {

                Object obj = rowData[i];
                if (obj != null) {

                    String value = null;
                    if (obj instanceof byte[]) {

                        value = ByteUtil.toHexString((byte[]) obj);

                    } else {

                        value = String.valueOf(rowData[i]);
                    }

                    writeValue(out, value, quote, needsQuotePattern);
                }

                if (i < columns.size() - 1) {
                    out.write(delimiter);
                }
            }

            out.newLine();
        }

        out.flush();
    }

    private static void writeValue(BufferedWriter out, String value, char quote, Pattern needsQuotePattern)
            throws IOException {
        if (!needsQuotePattern.matcher(value).find()) {

            // no quotes necessary
            out.write(value);
            return;
        }

        // wrap the value in quotes and handle internal quotes
        out.write(quote);
        for (int i = 0; i < value.length(); ++i) {
            char c = value.charAt(i);

            if (c == quote) {
                out.write(quote);
            }
            out.write(c);
        }
        out.write(quote);
    }

    /**
     * Builder which simplifies configuration of an export operation.
     */
    public static class Builder {
        private Database _db;
        private String _tableName;
        private String _ext = DEFAULT_FILE_EXT;
        private Cursor _cursor;
        private String _delim = DEFAULT_DELIMITER;
        private char _quote = DEFAULT_QUOTE_CHAR;
        private ExportFilter _filter = SimpleExportFilter.INSTANCE;
        private boolean _header;

        public Builder(Database db) {
            this(db, null);
        }

        public Builder(Database db, String tableName) {
            _db = db;
            _tableName = tableName;
        }

        public Builder(Cursor cursor) {
            _cursor = cursor;
        }

        public Builder setDatabase(Database db) {
            _db = db;
            return this;
        }

        public Builder setTableName(String tableName) {
            _tableName = tableName;
            return this;
        }

        public Builder setCursor(Cursor cursor) {
            _cursor = cursor;
            return this;
        }

        public Builder setDelimiter(String delim) {
            _delim = delim;
            return this;
        }

        public Builder setQuote(char quote) {
            _quote = quote;
            return this;
        }

        public Builder setFilter(ExportFilter filter) {
            _filter = filter;
            return this;
        }

        public Builder setHeader(boolean header) {
            _header = header;
            return this;
        }

        public Builder setFileNameExtension(String ext) {
            _ext = ext;
            return this;
        }

        /**
         * @see ExportUtil#exportAll(Database,File,String,boolean,String,char,ExportFilter)
         */
        public void exportAll(File dir) throws IOException {
            ExportUtil.exportAll(_db, dir, _ext, _header, _delim, _quote, _filter);
        }

        /**
         * @see ExportUtil#exportFile(Database,String,File,boolean,String,char,ExportFilter)
         */
        public void exportFile(File f) throws IOException {
            ExportUtil.exportFile(_db, _tableName, f, _header, _delim, _quote, _filter);
        }

        /**
         * @see ExportUtil#exportWriter(Database,String,BufferedWriter,boolean,String,char,ExportFilter)
         * @see ExportUtil#exportWriter(Cursor,BufferedWriter,boolean,String,char,ExportFilter)
         */
        public void exportWriter(BufferedWriter writer) throws IOException {
            if (_cursor != null) {
                ExportUtil.exportWriter(_cursor, writer, _header, _delim, _quote, _filter);
            } else {
                ExportUtil.exportWriter(_db, _tableName, writer, _header, _delim, _quote, _filter);
            }
        }
    }

}