/**
*
* Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
*
* 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, see <http://www.gnu.org/licenses/>.
*
**/
package lucee.runtime.text.csv;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import lucee.runtime.exp.PageException;
import lucee.runtime.type.Array;
import lucee.runtime.type.ArrayImpl;
import lucee.runtime.type.Query;
import lucee.runtime.type.QueryImpl;
public class CSVParser {
public static Query toQuery( String csv, char delimiter, char textQualifier, String[] headers, boolean firstRowIsHeaders ) throws CSVParserException, PageException {
List<List<String>> allRows = ( new CSVString( csv, delimiter ).parse() );
int numRows = allRows.size();
// no records
if ( numRows == 0) {
if(firstRowIsHeaders || headers==null)
throw new CSVParserException( "No data found in CSV string");
return new QueryImpl( headers, 0, "query" );
}
List<String> row = allRows.get( 0 );
int numCols = row.size();
int curRow = 0;
// set first line to header
if ( firstRowIsHeaders ) {
curRow++;
if ( headers == null )
headers = makeUnique( row.toArray( new String[ numCols ] ) );
}
// create first line for header
if( headers == null ) {
headers = new String[ numCols ];
for ( int i=0; i < numCols; i++ )
headers[ i ] = "COLUMN_" + ( i + 1 );
}
Array[] arrays = new Array[ numCols ]; // create column Arrays
for( int i=0; i < numCols; i++ )
arrays[ i ] = new ArrayImpl();
while ( curRow < numRows ) {
row = allRows.get( curRow++ );
if ( row.size() != numCols )
throw new CSVParserException( "Invalid CSV line size, expected " + numCols + " columns but found " + row.size() + " instead", row.toString() );
for ( int i=0; i < numCols; i++ ) {
arrays[ i ].append( row.get( i ) );
}
}
return new QueryImpl( headers, arrays, "query" );
}
private static String[] makeUnique( String[] headers ) {
int c = 1;
Set set = new TreeSet( String.CASE_INSENSITIVE_ORDER );
String header, orig;
for (int i=0; i<headers.length; i++) {
orig = header = headers[ i ];
while ( set.contains( header ) )
header = orig + "_" + ++c;
set.add( header );
if ( header != orig ) // ref comparison for performance
headers[ i ] = header;
}
return headers;
}
}