package com.revo.deployr.client.data.impl; import com.revo.deployr.client.*; import com.revo.deployr.client.data.*; import com.revo.deployr.client.factory.*; import javax.swing.table.*; import java.io.*; import java.util.*; public class RDataTableImpl extends AbstractTableModel implements RDataTable { private List<String> columnNames = new ArrayList<String>(); private List<List> data = new ArrayList<List>(); public RDataTableImpl(List<List> data) { this.data = data; } public RDataTableImpl(RData rData) throws RDataException { if(rData instanceof RNumericVector) { try { data.add(((RNumericVector)rData).getValue()); } catch(Exception ex) { throw new RDataException("Table initialization failed.", ex); } } else if(rData instanceof RStringVector) { try { data.add(((RStringVector)rData).getValue()); } catch(Exception ex) { throw new RDataException("Table initialization failed.", ex); } } else if(rData instanceof RBooleanVector) { try { data.add(((RBooleanVector)rData).getValue()); } catch(Exception ex) { throw new RDataException("Table initialization failed.", ex); } } else if(rData instanceof RDateVector) { try { data.add(((RDateVector)rData).getValue()); } catch(Exception ex) { throw new RDataException("Table initialization failed.", ex); } } else if(rData instanceof RNumericMatrix) { try { for(List colData : ((RNumericMatrix)rData).getValue()) { data.add(colData); } } catch(Exception ex) { throw new RDataException("Table initialization failed.", ex); } } else if(rData instanceof RStringMatrix) { try { for(List colData : ((RStringMatrix)rData).getValue()) { data.add(colData); } } catch(Exception ex) { throw new RDataException("Table initialization failed.", ex); } } else if(rData instanceof RBooleanMatrix) { try { for(List colData : ((RBooleanMatrix)rData).getValue()) { data.add(colData); } } catch(Exception ex) { throw new RDataException("Table initialization failed.", ex); } } else if(rData instanceof RDataFrame) { try { for(RData dfVal : ((RDataFrame)rData).getValue()) { if(dfVal instanceof RNumericVector) { data.add( ((RNumericVector) dfVal).getValue()); } else if(dfVal instanceof RStringVector) { data.add( ((RStringVector) dfVal).getValue()); } else if(dfVal instanceof RBooleanVector) { data.add( ((RBooleanVector) dfVal).getValue()); } else if(dfVal instanceof RDateVector) { data.add( ((RDateVector) dfVal).getValue()); } } } catch(Exception ex) { throw new RDataException("Table initialization " + "failed.", ex); } } else { throw new RDataException("Table initialization, " + "unsupport RData type=" + rData); } } public RDataTableImpl(InputStream is, String delimiter, boolean hasHeader) throws RDataException { this(is, delimiter, hasHeader, false); } public RDataTableImpl(InputStream is, String delimiter, boolean hasHeader, boolean nullMissingData) throws RDataException { try { /* * Column data. */ List<List> columnData = new ArrayList<List>(); List<String> columnNames = new ArrayList<String>(); boolean beyondHeader = hasHeader ? false : true; BufferedReader reader = new BufferedReader(new InputStreamReader(is)); String rowData = null; while((rowData = reader.readLine()) != null) { if(beyondHeader) { /* * Extract data from data-row. */ String[] rowAsStrings = rowData.trim().split(delimiter); if(columnNames.size() == 0) { /* * If no column-headers found on stream, * generate placeholders. */ for(int i=0; i<rowAsStrings.length; i++) { /* * Based on number of data points found * on the first row, initialize generated * columnNames and the columnData lists. */ columnNames.add(Integer.toString(i)); columnData.add(new ArrayList()); } } if(rowAsStrings.length != columnNames.size()) { if(nullMissingData) { if(rowAsStrings.length > columnNames.size()) { /* * If a row is found to have more data * points than expected (determined by the * number of headers or first data row) then * we have no way of knowing what data to drop * so we abort by raising an RDataException. */ throw new RDataException("Delimited file " + "data not consistent, can not be parsed."); } else if(rowAsStrings.length < columnNames.size()) { /* * Each row of data being ingested from the * data file should contain the same number * of data entries in order to build a * symmetrical matrix or dataframe. If row * data is missing and the "nullMissingData" * parameter is enabled then we can try to * inject null values for each missing data * point. */ String[] paddedRow = new String[columnNames.size()]; for(int p=0; p<paddedRow.length; p++) { if(p < rowAsStrings.length) paddedRow[p] = rowAsStrings[p]; else paddedRow[p] = null; } rowAsStrings = paddedRow; } } else { throw new RDataException("Delimited file data " + "not consistent, can not be parsed."); } } /* * Build columnData row-by-row. */ int colIdx = 0; for(String cellData : rowAsStrings) { try { if(cellData == null || cellData.trim().length() == 0) { columnData.get(colIdx).add(null); } else { // Double data found. Double dbl = Double.parseDouble(cellData); columnData.get(colIdx).add(dbl); } } catch(Throwable dex) { // String data found. columnData.get(colIdx).add(cellData); } colIdx++; } } else { /* * Extract column names from header-row. */ String[] headerNames = rowData.trim().split(delimiter); for(String headerName : headerNames) columnNames.add(headerName); beyondHeader = true; /* * Based on number of columns founds, * initialize columnData lists. */ for(int i=0; i<columnNames.size(); i++) { columnData.add(new ArrayList()); } } } this.data = columnData; this.columnNames = columnNames; } catch(RDataException dex) { throw dex; } catch(Exception ex) { throw new RDataException("Table initialization failed.", ex); } } /** * Returns the number of rows in the model. */ public int getRowCount() { return data.get(0).size(); } /** * Returns the number of columns in the model. */ public int getColumnCount() { return data != null ? data.size() : 0; } /** * Returns the value for the cell at col and row. */ public Object getValueAt(int row, int col) { return data.get(row).get(col); } /** * Returns the most specific superclass for all * the cell values in the column. */ public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); } /** * Returns raw data on the instance of RDataTable. */ public List<List> getData() { return data; } /** * Sets raw data on the instance of RDataTable. */ public void setData(List<List> data) { if(data == null) data = new ArrayList<List>(); else this.data = data; } /** * Converts RDataTable data to DeployR-encoded RData data.frame. */ public RData asDataFrame(String name) throws RDataException { try { List<RData> dfVal = new ArrayList<RData>(); if(columnNames.size() == 0) { for(int n=0; n<data.size(); n++) columnNames.add(Integer.toString(n)); } for(int i=0; i<data.size(); i++) { List colVal = data.get(i); if(colVal.get(0) instanceof Double) { RData colData = RDataFactory.createNumericVector( columnNames.get(i), colVal); dfVal.add(colData); } else if(colVal.get(0) instanceof String) { RData colData = RDataFactory.createStringVector( columnNames.get(i), colVal); dfVal.add(colData); } else if(colVal.get(0) instanceof Boolean) { RData colData = RDataFactory.createBooleanVector( columnNames.get(i), colVal); dfVal.add(colData); } else if(colVal.get(0) instanceof Date) { RData colData = RDataFactory.createDateVector( columnNames.get(i), colVal, "yyyy-MM-dd"); dfVal.add(colData); } } return RDataFactory.createDataFrame(name, dfVal); } catch(Exception ex) { throw new RDataException("Table conversion to RDataFrame failed.", ex); } } /** * Converts RDataTable data to DeployR-encoded RData matrix. */ public RData asMatrix(String name) throws RDataException { try { RData matrix = null; List matVal = new ArrayList(); for(List colData : data) matVal.add(colData); if(getValueAt(0,0) instanceof Double) { matrix = RDataFactory.createNumericMatrix(name, matVal); } else if(getValueAt(0,0) instanceof String) { matrix = RDataFactory.createStringMatrix(name, matVal); } else if(getValueAt(0,0) instanceof Boolean) { matrix = RDataFactory.createBooleanMatrix(name, matVal); } return matrix; } catch(Exception ex) { throw new RDataException("Table conversion to RMatrix failed.", ex); } } /** * Converts RDataTable data to DeployR-encoded RData vector. */ public RData asVector(String name) throws RDataException { try { RData vector = null; List vecVal = data.get(0); if(getValueAt(0,0) instanceof Double) { vector = RDataFactory.createNumericVector(name, vecVal); } else if(getValueAt(0,0) instanceof String) { vector = RDataFactory.createStringVector(name, vecVal); } else if(getValueAt(0,0) instanceof Boolean) { vector = RDataFactory.createBooleanVector(name, vecVal); } else if(getValueAt(0,0) instanceof Date) { vector = RDataFactory.createDateVector(name, vecVal, "yyyy-MM-dd"); } return vector; } catch(Exception ex) { throw new RDataException("Table conversion to RVector failed.", ex); } } }