package matrix.implementations.csv; import java.io.File; import java.util.ArrayList; import java.util.List; import matrix.AbstractDataMatrixInstance; import matrix.general.DataMatrixHandler; import matrix.implementations.memory.MemoryDataMatrixInstance; import org.apache.log4j.Logger; import org.molgenis.core.MolgenisFile; import org.molgenis.data.Data; import org.molgenis.framework.db.Database; import org.molgenis.matrix.MatrixException; import org.molgenis.util.CsvFileReader; import org.molgenis.util.CsvReader; import org.molgenis.util.Tuple; public class CSVDataMatrixInstance extends AbstractDataMatrixInstance<Object> { Logger logger = Logger.getLogger(getClass().getSimpleName()); private CsvReader reader; Data dataDescription; File src; public CSVDataMatrixInstance(Database db, MolgenisFile mf) throws Exception { DataMatrixHandler dmh = new DataMatrixHandler(db); new CSVDataMatrixInstance(dmh.findData(mf, db), dmh.getFile(mf, db)); } public CSVDataMatrixInstance(Data data, File file) throws Exception { src = file; reader = new CsvFileReader(file); this.setData(data); // put the rownames and colnames in parent this.setRowNames(reader.rownames()); this.setColNames(reader.colnames().subList(1, reader.colnames().size())); this.setNumberOfCols(this.getColNames().size()); this.setNumberOfRows(this.getRowNames().size()); } @Override public Object[] getCol(int colIndex) throws Exception { final int finalColIndex = colIndex; final Object[] result = new Object[getNumberOfRows()]; reader.reset(); int line_number = 1; for (Tuple tuple : reader) { result[line_number - 1] = tuple.getObject(finalColIndex + 1); line_number++; } return result; } @Override public Object getElement(int rowIndex, int colIndex) throws Exception { final int finalColIndex = colIndex; final int finalRowIndex = rowIndex; // naive implementation final finalObject finalResult = new finalObject(); reader.reset(); int row = 0; for (Tuple tuple : reader) { if (row == rowIndex) finalResult.set(tuple.getObject(finalColIndex + 1)); row++; } return finalResult.get(); } @Override public Object[][] getElements() throws MatrixException { try { final Object[][] result = new Object[getNumberOfRows()][getNumberOfCols()]; reader.reset(); int line_number = 1; for (Tuple tuple : reader) { for (int col = 0; col < tuple.size() - 1; col++) { result[line_number - 1][col] = tuple.getObject(col + 1); } line_number++; } return result; } catch (Exception e) { throw new MatrixException(e); } } @Override public Object[] getRow(int rowIndex) throws Exception { final int finalRowIndex = rowIndex; final Object[] result = new Object[getNumberOfCols()]; reader.reset(); int row = 0; for (Tuple tuple : reader) { if (row == rowIndex) { for (int col = 0; col < tuple.size() - 1; col++) { result[col] = tuple.getObject(col + 1); } } row++; } return result; } @Override public AbstractDataMatrixInstance<Object> getSubMatrix(int[] rowIndices, int[] colIndices) throws MatrixException { try { // the optimized way: find out of indices form a single block // if so, used offset retrieval instead boolean offsetAble = true; for (int i = 0; i < rowIndices.length - 1; i++) { if (rowIndices[i] != (rowIndices[i + 1] + 1)) { offsetAble = false; break; } } if (offsetAble) { for (int i = 0; i < colIndices.length - 1; i++) { if (colIndices[i] != (colIndices[i + 1] + 1)) { offsetAble = false; break; } } } if (offsetAble) { return getSubMatrixByOffset(rowIndices[0], rowIndices.length, colIndices[0], colIndices.length); } // optimalization: sort ascending in primitive array, then dont use // contains on list (slow) but smart counter // TODO: probably broken!! assign elements[line_number - 1][col] is // wrong.. // use: // HashMap<Integer, Integer> rowIndexPositions = new // HashMap<Integer, // Integer>(); // HashMap<Integer, Integer> colIndexPositions = new // HashMap<Integer, // Integer>(); AbstractDataMatrixInstance<Object> result = null; final Object[][] elements = new Object[rowIndices.length][colIndices.length]; final ArrayList<Integer> rowIndicesList = new ArrayList<Integer>(rowIndices.length); for (int i : rowIndices) { rowIndicesList.add(i); } final ArrayList<Integer> colIndicesList = new ArrayList<Integer>(colIndices.length); for (int i : colIndices) { colIndicesList.add(i); } // final finalObject finalResult = new finalObject(); reader.reset(); int row = 0; for (Tuple tuple : reader) { if (rowIndicesList.contains(row)) { for (int col = 1; col <= tuple.size(); col++) { if (colIndicesList.contains(col - 1)) { elements[row][col - 1] = tuple.getObject(col); } } } row++; } List<String> rowNames = new ArrayList<String>(); List<String> colNames = new ArrayList<String>(); for (int rowIndex : rowIndices) { rowNames.add(this.getRowNames().get(rowIndex).toString()); } for (int colIndex : colIndices) { colNames.add(this.getColNames().get(colIndex).toString()); } result = new MemoryDataMatrixInstance<Object>(rowNames, colNames, elements, this.getData()); return result; } catch (Exception e) { throw new MatrixException(e); } } @Override public AbstractDataMatrixInstance<Object> getSubMatrixByOffset(int startRow, int numRows, int startCol, int numCols) throws Exception { ; AbstractDataMatrixInstance<Object> result = null; final Object[][] elements = new Object[numRows][numCols]; // final finalObject finalResult = new finalObject(); reader.reset(); int row = 0; int rowCount = 0; int colCount = 0; for (Tuple tuple : reader) { if (row >= startRow && row < startRow + numRows) { colCount = 0; for (int col = 0; col < tuple.size() - 1; col++) { if (col >= startCol && col < startCol + numCols) { elements[rowCount][colCount] = tuple.getObject(col + 1); colCount++; } } rowCount++; } row++; } List<String> rowNames = getRowNames().subList(startRow, startRow + numRows); List<String> colNames = getColNames().subList(startCol, startCol + numCols); result = new MemoryDataMatrixInstance<Object>(rowNames, colNames, elements, this.getData()); return result; } public File getAsFile() throws Exception { return src; } @Override public void addColumn() throws Exception { throw new Exception("Action not possible"); } @Override public void addRow() throws Exception { throw new Exception("Action not possible"); } @Override public void updateElement() throws Exception { throw new Exception("Action not possible"); } } class finalObject { Object obj; Object get() { return obj; } void set(Object obj) { this.obj = obj; } }