com.redhat.rhn.common.util.CSVWriter.java Source code

Java tutorial

Introduction

Here is the source code for com.redhat.rhn.common.util.CSVWriter.java

Source

/**
 * Copyright (c) 2009--2014 Red Hat, Inc.
 *
 * This software is licensed to you under the GNU General Public License,
 * version 2 (GPLv2). There is NO WARRANTY for this software, express or
 * implied, including the implied warranties of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
 * along with this software; if not, see
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
 *
 * Red Hat trademarks are not licensed under GPLv2. No permission is
 * granted to use or replicate Red Hat trademarks that are incorporated
 * in this software or its documentation.
 */

package com.redhat.rhn.common.util;

import com.redhat.rhn.common.localization.LocalizationService;
import com.redhat.rhn.frontend.dto.BaseDto;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.NestedNullException;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * CSVWriter - util class for writing objects into CSV
 * @version $Rev$
 */
public class CSVWriter extends BufferedWriter implements ExportWriter {
    private List<String> columns;
    private Writer contents;
    private String headerText;
    private char separatorChar = ',';

    /**
     * Constructor
     * @param out Writer to send CSV to
     */
    public CSVWriter(Writer out) {
        super(out);
        this.contents = out;
        this.headerText = null;
    }

    /**
     * Constructor
     * @param out Writer to send CSV to
     * @param separator Separator character to use
     */
    public CSVWriter(Writer out, char separator) {
        this(out);
        this.separatorChar = separator;
    }

    /**
     * Set columns
     * @param columnsIn List of Strings containing the names of the columns
     */
    public void setColumns(List<String> columnsIn) {
        columns = new LinkedList<String>();
        for (String column : columnsIn) {
            columns.add(column.trim());
        }
    }

    /**
     * Sets an optional header string.
     * @param headerIn This will become the
     * first line of the export CSV contents.
     */
    public void setHeaderText(String headerIn) {
        headerText = headerIn;
    }

    /**
     * @return String Description of exported data with commas appended
     * to correspond to the number of columns being exported.  Needed so
     * it doesn't break applications which will be parsing this data.
     *
     */
    public String getHeaderText() {
        String hdrStr = headerText;
        if (hdrStr != null) {
            for (int i = 0; i < columns.size() - 1; i++) {
                hdrStr += separatorChar;
            }
        }
        return hdrStr;
    }

    /**
     * Write the header to the stream
     */
    public void writeHeader() {
        write(columns);
    }

    /**
     * {@inheritDoc}
     */
    public void write(List listIn) {
        try {
            this.writeList(listIn);
        } catch (IOException e) {
            throw new RuntimeException("IOException caught trying to write the list: " + e);
        }
    }

    /**
     * Write a List to the stream
     * @param values you want to write
     * @throws IOException if there is error
     */
    private void writeList(List values) throws IOException {
        Iterator itr = values.iterator();

        // Write out the column headers
        if (columns != null) {
            Iterator citer = columns.iterator();
            while (citer.hasNext()) {
                String cname = (String) citer.next();
                if (LocalizationService.getInstance().hasMessage("exportcolumn." + cname)) {
                    write(LocalizationService.getInstance().getMessage("exportcolumn." + cname));
                } else {
                    write(LocalizationService.getInstance().getMessage(cname));
                }

                if (citer.hasNext()) {
                    writeSeparator();
                }
            }
            newLine();
        }
        // Iterate over the values
        while (itr.hasNext()) {
            Object value = itr.next();
            // If its a List of Strings
            if (value instanceof String) {
                write((String) value);
                if (itr.hasNext()) {
                    writeSeparator();
                }
            }
            // If its a list of Maps or Dtos
            else if (value instanceof Map || value instanceof BaseDto) {
                if (columns == null || !columns.iterator().hasNext()) {
                    throw new IllegalArgumentException(
                            "Tried to csv export without" + " setting up the list of columns first");
                }
                Iterator citer = columns.iterator();
                while (citer.hasNext()) {
                    String columnKey = (String) citer.next();
                    Object colVal = getObjectValue(value, columnKey);
                    if (colVal != null) {
                        write(colVal.toString());
                    }
                    if (citer.hasNext()) {
                        writeSeparator();
                    }
                }
                if (itr.hasNext()) {
                    newLine();
                }
            } else {
                throw new IllegalArgumentException(
                        "Must pass in a List of Strings, " + "Maps or AbstractDto classes");
            }
        }
        // Its always good to end a file with
        // a newline.
        newLine();
    }

    /**
     * Util function to get the value for the current row/column in the List.
     */
    private Object getObjectValue(Object row, String columnKey) {
        if (row instanceof Map) {
            Map rowmap = (Map) row;
            return rowmap.get(columnKey);
        } else if (row instanceof BaseDto) {
            String ovalue = null;
            try {
                ovalue = BeanUtils.getProperty(row, columnKey);
            } catch (IllegalAccessException e) {
                throw new IllegalArgumentException("Can't access method in DTO: get" + columnKey
                        + "(), IllegalAccessException:" + e.toString());
            } catch (InvocationTargetException e) {
                throw new IllegalArgumentException("Can't access method in DTO: get" + columnKey
                        + "(),  InvocationTargetException:" + e.toString());
            } catch (NoSuchMethodException e) {
                throw new IllegalArgumentException("Can't call method in DTO class: " + row.getClass().getName()
                        + "." + "get" + columnKey + "(), NoSuchMethodException: " + e.toString());
            } catch (NestedNullException e) {
                return null;
            }
            return ovalue;
        }
        return null;
    }

    /**
     * Write a string to the Writer
     * {@inheritDoc}
     */
    public void write(String s) throws IOException {
        // If the string does not contain a comma, just write it out
        if (s.indexOf(separatorChar) == -1 && s.indexOf('"') == -1) {
            super.write(s);
            return;
        }

        // If the string does have a comma, then write it out
        // surrounded by quotation marks.  Any quotation mark in the
        // string must be doubled.
        super.write("\"");
        int from = 0;
        for (;;) {
            int to = s.indexOf('"', from);
            if (to == -1) {
                super.write(s, from, s.length() - from);
                break;
            }

            super.write(s, from, to - from);
            super.write("\"\"");

            from = to + 1;
        }
        super.write("\"");
    }

    /**
     * Write the separator to the Writer
     * @throws IOException if there is a Writer error
     */
    public void writeSeparator() throws IOException {
        super.write(separatorChar);
    }

    /**
     * {@inheritDoc}
     */
    public String getContents() {
        try {
            this.flush();
        } catch (IOException e) {
            throw new IllegalStateException(
                    "Caught IOException while " + "trying to flush contents for output: " + e);
        }
        if (headerText != null) {
            return getHeaderText() + System.getProperty("line.separator") + this.contents.toString();
        }
        return this.contents.toString();
    }

    /**
     * {@inheritDoc}
     */
    public String getMimeType() {
        return "text/csv";
    }

    /**
     * {@inheritDoc}
     */
    public String getFileExtension() {
        return "csv";
    }
}