package com.baselet.element.elementnew.plot.parser;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.baselet.control.Matrix;
public class DataSet {
private String id;
private Integer nr;
private int lineNr;
private boolean isInverted;
private List<String> titleRow = null;
private List<String> titleCol = null;
private Matrix<Double> valueMatrix;
private Matrix<String> analyseMatrix;
public static final Double VALUE_DEFAULT = 0.0; // used for invalid value fields or missing fields
protected DataSet(String id, int nr, int lineNr) {
this.id = id;
this.nr = nr;
this.lineNr = lineNr;
analyseMatrix = new Matrix<String>();
}
public String getId() {
return id;
}
public Integer getNr() {
return nr;
}
public int getLineNr() {
return lineNr;
}
/**
* @return the row size
*/
public int rows() {
return valueMatrix.rows();
}
/**
* @return the column size
*/
public int cols() {
return valueMatrix.cols();
}
public boolean isEmpty() {
return valueMatrix.isEmpty();
}
/**
* @param index
* the index of the row
* @return a Double[] containing the cells of the row
*/
public Double[] row(int index) {
List<Double> list = valueMatrix.row(index);
return list.toArray(new Double[list.size()]);
}
public Double[][] data() {
if (valueMatrix.isEmpty()) {
throw new ParserException("The dataset (line: " + getLineNr() + ") has no values");
}
Double[][] returnArray = new Double[rows()][];
for (int i = 0; i < rows(); i++) {
returnArray[i] = row(i);
}
return returnArray;
}
/**
* Changed the manual inversion of the dataset. The dataset must only be inverted if the value has changed because
* it is only referenced from plots, therefore the last inversion will be dragged to further plot-calls without a problem
*/
public void setInvert(boolean shouldBeInverted) {
if (isInverted == !shouldBeInverted) {
analyseMatrix.invert();
separateTitleRowColFromContent();
isInverted = shouldBeInverted;
}
}
public String[] titleRow() {
return titleRow.toArray(new String[titleRow.size()]);
}
public String[] titleCol() {
return titleCol.toArray(new String[titleCol.size()]);
}
@Override
public String toString() {
return "Dataset (" + id + ")\n" + analyseMatrix;
}
protected void addLine(String[] line) {
analyseMatrix.addLine(new ArrayList<String>(Arrays.asList(line)));
}
protected void analyseMatrix() {
separateTitleRowColFromContent();
// If the valuematrix has more rows than cols the analyseMatrix must be inverted and analysed again
// if (!valueMatrix.isEmpty() && valueMatrix.hasMoreRowsThanCols()) analyseMatrix.invert();
// separateTitleRowColFromContent();
}
private void separateTitleRowColFromContent() {
if (analyseMatrix.isEmpty()) {
throw new ParserException("The dataset (line: " + getLineNr() + ") has no content");
}
List<String> firstRow = analyseMatrix.row(0);
List<String> firstCol = analyseMatrix.col(0);
boolean hasTitleRow = isTitleLine(firstRow);
boolean hasTitleCol = isTitleLine(firstCol);
if (hasTitleRow && hasTitleCol) {
if (!firstRow.get(0).isEmpty() || !firstCol.get(0).isEmpty()) {
throw new ParserException("If a dataset has a title row and column, the upper left space must be empty");
}
titleRow = firstRow.subList(1, firstRow.size()); // ignore first cell
titleCol = firstCol.subList(1, firstCol.size()); // ignore first cell
}
else if (hasTitleRow && !hasTitleCol) {
titleRow = firstRow;
titleCol = createEmptyList(firstCol.size() - 1);
}
else if (!hasTitleRow && hasTitleCol) {
titleRow = createEmptyList(firstRow.size() - 1);
titleCol = firstCol;
}
else /* if (!hasTitleRow && !hasTitleCol) */ {
titleRow = createEmptyList(firstRow.size());
titleCol = createEmptyList(firstCol.size());
}
valueMatrix = new Matrix<Double>();
for (int r = hasTitleRow ? 1 : 0; r < analyseMatrix.rows(); r++) {
List<String> row = analyseMatrix.row(r);
List<Double> rowDouble = new ArrayList<Double>();
for (int c = hasTitleCol ? 1 : 0; c < row.size(); c++) {
String val = row.get(c);
try {
if (val == null) {
throw new NumberFormatException();
}
else {
rowDouble.add(Double.parseDouble(val));
}
} catch (NumberFormatException ex) {
throw new ParserException("The Dataset (line: " + getLineNr() + ") contains invalid values");
}
}
valueMatrix.addLine(rowDouble);
}
}
private boolean isTitleLine(List<String> row) {
int numbersInRow = 0;
for (String cell : row) {
if (cell == null) {
continue;
}
try {
Double.parseDouble(cell);
numbersInRow++;
} catch (NumberFormatException ex) {/* do nothing */}
}
return row.size() - numbersInRow > numbersInRow;
}
private List<String> createEmptyList(int size) {
List<String> returnList = new ArrayList<String>();
for (int i = 0; i < size; i++) {
returnList.add("");
}
return returnList;
}
}