001    /**
002     * ========================================
003     * JFreeReport : a free Java report library
004     * ========================================
005     *
006     * Project Info:  http://reporting.pentaho.org/
007     *
008     * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors.
009     *
010     * This library is free software; you can redistribute it and/or modify it under the terms
011     * of the GNU Lesser General Public License as published by the Free Software Foundation;
012     * either version 2.1 of the License, or (at your option) any later version.
013     *
014     * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015     * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016     * See the GNU Lesser General Public License for more details.
017     *
018     * You should have received a copy of the GNU Lesser General Public License along with this
019     * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020     * Boston, MA 02111-1307, USA.
021     *
022     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023     * in the United States and other countries.]
024     *
025     * ------------
026     * $Id: CSVTableModelProducer.java 2725 2007-04-01 18:49:29Z taqua $
027     * ------------
028     * (C) Copyright 2000-2005, by Object Refinery Limited.
029     * (C) Copyright 2005-2007, by Pentaho Corporation.
030     */
031    
032    package org.jfree.report.modules.misc.tablemodel;
033    
034    import java.io.BufferedReader;
035    import java.io.FileNotFoundException;
036    import java.io.FileReader;
037    import java.io.IOException;
038    import java.io.InputStream;
039    import java.io.InputStreamReader;
040    import java.util.ArrayList;
041    import javax.swing.table.TableModel;
042    
043    import org.jfree.report.util.CSVTokenizer;
044    
045    /**
046     * Creates a <code>TableModel</code> using a file formated in CSV for input. The
047     * separation can be what ever you want (as it is an understandable regexp). The default
048     * separator is a <code>,</code>.
049     *
050     * @author Mimil
051     */
052    public class CSVTableModelProducer
053    {
054      private BufferedReader reader;
055      private String separator;
056      private CSVTableModel tableModel;
057      private boolean columnNameFirst;
058    
059      public CSVTableModelProducer (final InputStream in)
060      {
061        this(new BufferedReader(new InputStreamReader(in)));
062      }
063    
064      public CSVTableModelProducer (final String filename)
065              throws FileNotFoundException
066      {
067        this(new BufferedReader(new FileReader(filename)));
068      }
069    
070      public CSVTableModelProducer (final BufferedReader r)
071      {
072        if (r == null)
073        {
074          throw new NullPointerException("The input stream must not be null");
075        }
076        this.reader = r;
077        this.separator = ",";
078      }
079    
080      public void close ()
081              throws IOException
082      {
083        this.reader.close();
084      }
085    
086      /**
087       * Parses the input and stores data in a TableModel.
088       *
089       * @see this.getTableModel()
090       */
091      public synchronized TableModel parse ()
092              throws IOException
093      {
094        if (tableModel != null)
095        {
096          return tableModel;
097        }
098    
099    
100        this.tableModel = new CSVTableModel();
101    
102        if (this.columnNameFirst == true)
103        {   //read the fisrt line
104          final String first = this.reader.readLine();
105    
106          if (first == null)
107          {
108            // after the end of the file it makes no sense to read anything.
109            // so we can safely return ..
110            return tableModel;
111          }
112          this.tableModel.setColumnNames(splitLine(first));
113        }
114    
115        final ArrayList data = new ArrayList();
116        String line;
117        int maxLength = 0;
118        while ((line = this.reader.readLine()) != null)
119        {
120          final String[] o = splitLine(line);
121          if (o.length > maxLength)
122          {
123            maxLength = o.length;
124          }
125          data.add(o);
126        }
127    
128        close();
129    
130        final Object[][] array = new Object[data.size()][];
131        data.toArray(array);
132        this.tableModel.setData(array);
133        return tableModel;
134      }
135    
136      private String[] splitLine (final String line)
137      {
138        final ArrayList row = new ArrayList();
139        final CSVTokenizer tokenizer = new CSVTokenizer(line, getSeparator());
140        while (tokenizer.hasMoreElements())
141        {
142          row.add(tokenizer.nextElement());
143        }
144        return (String[]) row.toArray(new String[row.size()]);
145      }
146    
147      /**
148       * Returns the current separator used to parse the input.
149       *
150       * @return a regexp
151       */
152      public String getSeparator ()
153      {
154        return separator;
155      }
156    
157      /**
158       * Sets the separator for parsing the input. It can be a regexp as we use the function
159       * <code>String.split()</code>. The default separator is a <code>;</code>.
160       *
161       * @param separator a regexp
162       */
163      public void setSeparator (final String separator)
164      {
165        this.separator = separator;
166      }
167    
168      /**
169       * Creates the corrspondant TableModel of the input.
170       *
171       * @return the new TableModel
172       */
173      public TableModel getTableModel ()
174              throws IOException
175      {
176        return this.parse();
177      }
178    
179      /**
180       * Tells if the first line of the input was column names.
181       *
182       * @return boolean
183       */
184      public boolean isColumnNameFirstLine ()
185      {
186        return columnNameFirst;
187      }
188    
189      /**
190       * Set if the first line of the input is column names or not.
191       *
192       * @param columnNameFirst boolean
193       */
194      public void setColumnNameFirstLine (final boolean columnNameFirst)
195      {
196        this.columnNameFirst = columnNameFirst;
197      }
198    
199    }