package railo.runtime.text.csv;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import railo.runtime.exp.PageException;
import railo.runtime.type.Array;
import railo.runtime.type.ArrayImpl;
import railo.runtime.type.Query;
import railo.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();
if ( numRows == 0 )
throw new CSVParserException( "No data found in CSV string" );
List<String> row = allRows.get( 0 );
int numCols = row.size();
int curRow = 0;
if ( firstRowIsHeaders ) { // set first line to header
curRow++;
if ( headers == null )
headers = makeUnique( row.toArray( new String[ numCols ] ) );
}
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;
}
}