diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/csvparser/CsvParseAlgorithm.java b/src/main/java/de/tudresden/inf/mci/brailleplot/csvparser/CsvParseAlgorithm.java index 8089d799a9ecf93998268babbb6f72b8eb32d571..9ed818674323ca5bbb29c33d15a2dbb1e885955c 100644 --- a/src/main/java/de/tudresden/inf/mci/brailleplot/csvparser/CsvParseAlgorithm.java +++ b/src/main/java/de/tudresden/inf/mci/brailleplot/csvparser/CsvParseAlgorithm.java @@ -4,6 +4,8 @@ import de.tudresden.inf.mci.brailleplot.datacontainers.PointList; import de.tudresden.inf.mci.brailleplot.datacontainers.PointListContainer; import de.tudresden.inf.mci.brailleplot.datacontainers.SimplePointListImpl; import de.tudresden.inf.mci.brailleplot.point.Point2DDouble; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Iterator; import java.util.List; @@ -17,6 +19,8 @@ import java.util.Objects; */ public abstract class CsvParseAlgorithm { + protected final Logger mLogger = LoggerFactory.getLogger(getClass()); + /** * If the data sets are oriented horizontally, i.e. in rows, parse the rows into * {@link PointListContainer}{@literal <}{@link PointList}{@literal >}. diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/csvparser/CsvXAlignedParser.java b/src/main/java/de/tudresden/inf/mci/brailleplot/csvparser/CsvXAlignedParser.java index a44366e4153dab238e1e5cf4a304bbf063930649..1b1b54d724b5f8cdb05cdfa5bdf66ed9a7f4fb18 100644 --- a/src/main/java/de/tudresden/inf/mci/brailleplot/csvparser/CsvXAlignedParser.java +++ b/src/main/java/de/tudresden/inf/mci/brailleplot/csvparser/CsvXAlignedParser.java @@ -100,69 +100,43 @@ public class CsvXAlignedParser extends CsvParseAlgorithm { } @Override + /** + * This method has been implemented from scratch, as there is no documentation about the structure of the CSV files whatsoever. + */ public PointListContainer<PointList> parseAsVerticalDataSets(final List<? extends List<String>> csvData) { Objects.requireNonNull(csvData); PointListContainer<PointList> container = new SimplePointListContainerImpl(); - Iterator<? extends List<String>> rowIterator = csvData.iterator(); - - if (!rowIterator.hasNext()) { - return container; - } - - Iterator<String> lineIterator = rowIterator.next().iterator(); - - // Move the iterator to the first title - if (!lineIterator.hasNext()) { - return container; - } - lineIterator.next(); - if (!lineIterator.hasNext()) { - return container; - } - - // Add a PointList for each title - while (lineIterator.hasNext()) { - PointList pointList = new SimplePointListImpl(); - pointList.setName(lineIterator.next()); - container.pushBack(pointList); - } - - // Add the data - while (rowIterator.hasNext()) { - lineIterator = rowIterator.next().iterator(); - if (!lineIterator.hasNext()) { - continue; + Iterator<? extends List<String>> rowIt = csvData.iterator(); + + int rowNum = 0; // Keep track of the row number, so that we can include the erroneous row number in the exception. + while (rowIt.hasNext()) { + Iterator<String> lineIt = rowIt.next().iterator(); + rowNum++; + if (!lineIt.hasNext()) { + throw new MalformedCsvException("Line: " + rowNum + ": Data set must contain a name for a value"); } - - // Find out the mX value - Number xValue; - try { - xValue = Constants.NUMBER_FORMAT.parse(lineIterator.next()); - } catch (ParseException e) { - continue; + String name = lineIt.next().trim(); + if (!lineIt.hasNext()) { + throw new MalformedCsvException("Line: " + rowNum + ": Data set must contain a name for a value"); } + String value = lineIt.next().trim(); - // Find out the mY values and add the points to the respective lists - int currentDataSet = 0; - while (lineIterator.hasNext()) { - Number yValue; - try { - yValue = Constants.NUMBER_FORMAT.parse(lineIterator.next()); - } catch (ParseException e) { - currentDataSet++; - continue; - } - - Point2DDouble newPoint = new Point2DDouble(xValue.doubleValue(), yValue.doubleValue()); - addPointToPointListList(container, currentDataSet, newPoint); - currentDataSet++; + // Log if there are more inputs that are not parsed + if (lineIt.hasNext()) { + mLogger.debug("Skipping additional column in line {}", rowNum); } - + Number val; + try { + val = Constants.NUMBER_FORMAT.parse(value); + } catch (final ParseException pe) { + throw new MalformedCsvException("Line: " + rowNum + ": Could not parse value", pe); + } + Point2DDouble p = new Point2DDouble(0, val.doubleValue()); + PointList pl = new SimplePointListImpl(name); + pl.pushBack(p); + container.pushBack(pl); } - - // TODO First add points to PointList, then add PointList to PointListContainer, so that there is no need for a calculateExtrema call - container.calculateExtrema(); return container; } diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/csvparser/MalformedCsvException.java b/src/main/java/de/tudresden/inf/mci/brailleplot/csvparser/MalformedCsvException.java new file mode 100644 index 0000000000000000000000000000000000000000..37e3a3bf54e11f09feb2972cff3568248b649613 --- /dev/null +++ b/src/main/java/de/tudresden/inf/mci/brailleplot/csvparser/MalformedCsvException.java @@ -0,0 +1,25 @@ +package de.tudresden.inf.mci.brailleplot.csvparser; + +/** + * Exception class. + * Indicates, that the parsed CSV file was malformed. + * Most likely created by malformed user input. + * @author Georg GraĆnick + * @version 2019.08.08 + */ +public class MalformedCsvException extends RuntimeException { + + public MalformedCsvException() { } + + public MalformedCsvException(final String message) { + super(message); + } + + public MalformedCsvException(final Throwable cause) { + super(cause); + } + + public MalformedCsvException(final String message, final Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/datacontainers/SimplePointListImpl.java b/src/main/java/de/tudresden/inf/mci/brailleplot/datacontainers/SimplePointListImpl.java index f7bc505366a985451aa221eede41cdd1cd926020..278faef9e14388a1f41c95da276661c321ced7a9 100644 --- a/src/main/java/de/tudresden/inf/mci/brailleplot/datacontainers/SimplePointListImpl.java +++ b/src/main/java/de/tudresden/inf/mci/brailleplot/datacontainers/SimplePointListImpl.java @@ -46,4 +46,9 @@ public class SimplePointListImpl extends AbstractPointContainer<Point2DDouble> i Objects.requireNonNull(newName); mName = newName; } + + @Override + protected String toRecursiveString(final int depth) { + return getName() + super.toRecursiveString(depth); + } } diff --git a/src/main/resources/examples/csv/0_bar_chart.csv b/src/main/resources/examples/csv/0_bar_chart.csv index 2dfe16d59a3fd4be9a0aac4ca0bc66275f497563..13d0acc6254a9e82761cac5fd56b2e08ba0b3542 100644 --- a/src/main/resources/examples/csv/0_bar_chart.csv +++ b/src/main/resources/examples/csv/0_bar_chart.csv @@ -1,5 +1,7 @@ -,Reihe a,Reihe b,Reihe c,Reihe d -Kat.1,500,36,357,473 -Kat.2,1,2,3,4 -Kat.3,2,3,4,5 -Kat.4,1,2,3,4 \ No newline at end of file +a, 1 +b, "2,2" +c, 3 +d, "4,4" +e, 5 +f, 6 +g, 7