adams.data.io.output.AbstractSpreadSheetWriter.java Source code

Java tutorial

Introduction

Here is the source code for adams.data.io.output.AbstractSpreadSheetWriter.java

Source

/*
 *   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 3 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, see <http://www.gnu.org/licenses/>.
 */

/*
 * AbstractSpreadSheetWriter.java
 * Copyright (C) 2010-2017 University of Waikato, Hamilton, New Zealand
 */
package adams.data.io.output;

import adams.core.AdditionalInformationHandler;
import adams.core.ClassLister;
import adams.core.Utils;
import adams.core.base.BaseCharset;
import adams.core.io.EncodingSupporter;
import adams.core.io.FileUtils;
import adams.core.option.AbstractOptionHandler;
import adams.data.spreadsheet.SpreadSheet;
import org.apache.commons.io.output.WriterOutputStream;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.zip.GZIPOutputStream;

/**
 * Ancestor for classes that can write spreadsheet objects.
 *
 * @author  fracpete (fracpete at waikato dot ac dot nz)
 * @version $Revision$
 */
public abstract class AbstractSpreadSheetWriter extends AbstractOptionHandler
        implements SpreadSheetWriter, EncodingSupporter, AdditionalInformationHandler {

    /** for serialization. */
    private static final long serialVersionUID = -3547064795252689769L;

    /**
     * How to write the data.
     *
     * @author  fracpete (fracpete at waikato dot ac dot nz)
     * @version $Revision$
     */
    public enum OutputType {
        /** write to a file. */
        FILE,
        /** write using a writer. */
        WRITER,
        /** write to a stream. */
        STREAM
    }

    /** whether the read process was stopped through an external source. */
    protected boolean m_Stopped;

    /** the encoding to use. */
    protected BaseCharset m_Encoding;

    /**
     * Initializes the members.
     */
    @Override
    protected void initialize() {
        super.initialize();

        m_Encoding = new BaseCharset();
    }

    /**
     * Resets the writer.
     */
    @Override
    public void reset() {
        super.reset();
    }

    /**
     * Returns a string describing the format (used in the file chooser).
     *
     * @return          a description suitable for displaying in the
     *             file chooser
     */
    @Override
    public abstract String getFormatDescription();

    /**
     * Returns the extension(s) of the format.
     *
     * @return          the extension (without the dot!)
     */
    @Override
    public abstract String[] getFormatExtensions();

    /**
     * Returns the default extension of the format.
     *
     * @return          the default extension (without the dot!)
     */
    public String getDefaultFormatExtension() {
        return getFormatExtensions()[0];
    }

    /**
     * Returns the additional information.
     *
     * @return      the additional information, null or 0-length string for no information
     */
    public String getAdditionalInformation() {
        StringBuilder result;

        result = new StringBuilder();

        result.append("Supported file extensions: " + Utils.flatten(getFormatExtensions(), ", "));
        result.append("\n");
        result.append("Default file extension: " + getDefaultFormatExtension());

        return result.toString();
    }

    /**
     * Sets the encoding to use.
     *
     * @param value   the encoding, e.g. "UTF-8" or "UTF-16", empty string for default
     */
    @Override
    public void setEncoding(BaseCharset value) {
        m_Encoding = value;
        reset();
    }

    /**
     * Returns the encoding to use.
     *
     * @return      the encoding, e.g. "UTF-8" or "UTF-16", empty string for default
     */
    @Override
    public BaseCharset getEncoding() {
        return m_Encoding;
    }

    /**
     * Returns the tip text for this property.
     *
     * @return       tip text for this property suitable for
     *          displaying in the GUI or for listing the options.
     */
    @Override
    public String encodingTipText() {
        return "The type of encoding to use when writing using a writer, use empty string for default.";
    }

    /**
     * Returns how the data is written.
     *
     * @return      the type
     */
    protected abstract OutputType getOutputType();

    /**
     * Returns whether to automatically compress.
     * <br><br>
     * Default implementation returns false.
     *
     * @return      true if to automatically decompress
     */
    protected boolean supportsCompressedOutput() {
        return false;
    }

    /**
     * Returns whether the file should get compressed, i.e.,
     * {@link #supportsCompressedOutput()} returns true and the filename ends
     * with ".gz".
     *
     * @param filename   the filename to check
     * @return      true if decompression should occur
     */
    protected boolean canCompress(String filename) {
        return supportsCompressedOutput() && filename.toLowerCase().endsWith(".gz");
    }

    /**
     * Hook method before writing to a file.
     * <br>
     * Default implementation does nothing.
     *
     * @param filename   the filename to check
     */
    protected void preWriteFile(String filename) {
    }

    /**
     * Writes the given content to the specified file.
     * Handles compression automatically, if the filename ends with ".gz",
     * {@link #supportsCompressedOutput()} returns true and file is not
     * being appended.
     *
     * @param content   the content to write
     * @param file   the file to write to
     * @return      true if successfully written
     * @see      #supportsCompressedOutput()
     * @see      AppendableSpreadSheetWriter
     */
    @Override
    public boolean write(SpreadSheet content, File file) {
        return write(content, file.getAbsolutePath());
    }

    /**
     * Writes the spreadsheet in CSV format to the given file.
     * Handles compression automatically, if the filename ends with ".gz",
     * {@link #supportsCompressedOutput()} returns true and file is not
     * being appended.
     *
     * @param content   the spreadsheet to write
     * @param filename   the file to write the spreadsheet to
     * @return      true if successfully written
     * @see      #supportsCompressedOutput()
     * @see      AppendableSpreadSheetWriter
     */
    @Override
    public boolean write(SpreadSheet content, String filename) {
        boolean result;
        BufferedWriter writer;
        OutputStream output;
        boolean append;
        AppendableSpreadSheetWriter appendable;

        result = true;

        preWriteFile(filename);

        append = false;
        if (this instanceof AppendableSpreadSheetWriter) {
            appendable = (AppendableSpreadSheetWriter) this;
            append = appendable.isAppending();
            if (append) {
                appendable.setFileExists(new File(filename).exists());
                append = appendable.canAppend(content);
            }
        }

        writer = null;
        output = null;
        try {
            switch (getOutputType()) {
            case FILE:
                result = doWrite(content, filename);
                break;
            case STREAM:
                output = new FileOutputStream(filename, append);
                if (!append && canCompress(filename))
                    output = new GZIPOutputStream(output);
                result = doWrite(content, output);
                output.flush();
                break;
            case WRITER:
                output = new FileOutputStream(filename, append);
                if (!append && canCompress(filename))
                    output = new GZIPOutputStream(output);
                if (m_Encoding != null)
                    writer = new BufferedWriter(new OutputStreamWriter(output, m_Encoding.charsetValue()));
                else
                    writer = new BufferedWriter(new OutputStreamWriter(output));
                result = doWrite(content, writer);
                writer.flush();
                break;
            default:
                throw new IllegalStateException("Unhandled output type: " + getOutputType());
            }
        } catch (Exception e) {
            result = false;
            e.printStackTrace();
        } finally {
            FileUtils.closeQuietly(writer);
            FileUtils.closeQuietly(output);
        }

        return result;
    }

    /**
     * Writes the spreadsheet in CSV format to the given output stream. The caller
     * must ensure that the stream gets closed.
     *
     * @param content   the spreadsheet to write
     * @param stream   the output stream to write the spreadsheet to
     * @return      true if successfully written
     */
    @Override
    public boolean write(SpreadSheet content, OutputStream stream) {
        switch (getOutputType()) {
        case FILE:
            throw new IllegalStateException("Only supports writing to files, not output streams!");
        case STREAM:
            return doWrite(content, stream);
        case WRITER:
            return doWrite(content, new OutputStreamWriter(stream));
        default:
            throw new IllegalStateException("Unhandled output type: " + getOutputType());
        }
    }

    /**
     * Writes the spreadsheet in CSV format to the given writer. The caller
     * must ensure that the writer gets closed.
     *
     * @param content   the spreadsheet to write
     * @param writer   the writer to write the spreadsheet to
     * @return      true if successfully written
     */
    @Override
    public boolean write(SpreadSheet content, Writer writer) {
        switch (getOutputType()) {
        case FILE:
            throw new IllegalStateException("Only supports writing to files, not output streams!");
        case STREAM:
            return doWrite(content, new WriterOutputStream(writer));
        case WRITER:
            return doWrite(content, writer);
        default:
            throw new IllegalStateException("Unhandled output type: " + getOutputType());
        }
    }

    /**
     * Performs the actual writing.
     * <br><br>
     * Default implementation returns always false.
     *
     * @param content   the spreadsheet to write
     * @param filename   the file to write the spreadsheet to
     * @return      true if successfully written
     */
    protected boolean doWrite(SpreadSheet content, String filename) {
        return false;
    }

    /**
     * Performs the actual writing. The caller must ensure that the writer gets
     * closed.
     * <br><br>
     * Default implementation returns always false.
     *
     * @param content   the spreadsheet to write
     * @param writer   the writer to write the spreadsheet to
     * @return      true if successfully written
     */
    protected boolean doWrite(SpreadSheet content, Writer writer) {
        return false;
    }

    /**
     * Performs the actual writing. The caller must ensure that the output stream
     * gets closed.
     * <br><br>
     * Default implementation returns always false.
     *
     * @param content   the spreadsheet to write
     * @param out      the output stream to write the spreadsheet to
     * @return      true if successfully written
     */
    protected boolean doWrite(SpreadSheet content, OutputStream out) {
        return false;
    }

    /**
     * Stops the reading (might not be immediate, depending on reader).
     */
    public void stopExecution() {
        m_Stopped = true;
    }

    /**
     * Returns whether the reading was stopped.
     *
     * @return      true if stopped
     */
    public boolean isStopped() {
        return m_Stopped;
    }

    /**
     * Returns a list with classnames of writers.
     *
     * @return      the writer classnames
     */
    public static String[] getWriters() {
        return ClassLister.getSingleton().getClassnames(SpreadSheetWriter.class);
    }
}