Skip to content
Snippets Groups Projects
Commit 0eb14cc3 authored by Georg Graßnick's avatar Georg Graßnick :thinking:
Browse files

Add own XAlignedCategories parser

parent 5212f359
No related branches found
No related tags found
1 merge request!11Feat/csv data importer overhaul
...@@ -11,8 +11,8 @@ import de.tudresden.inf.mci.brailleplot.configparser.Printer; ...@@ -11,8 +11,8 @@ import de.tudresden.inf.mci.brailleplot.configparser.Printer;
import de.tudresden.inf.mci.brailleplot.csvparser.CsvOrientation; import de.tudresden.inf.mci.brailleplot.csvparser.CsvOrientation;
import de.tudresden.inf.mci.brailleplot.csvparser.CsvParser; import de.tudresden.inf.mci.brailleplot.csvparser.CsvParser;
import de.tudresden.inf.mci.brailleplot.csvparser.CsvType; import de.tudresden.inf.mci.brailleplot.csvparser.CsvType;
import de.tudresden.inf.mci.brailleplot.datacontainers.CategoricalPointListContainer;
import de.tudresden.inf.mci.brailleplot.datacontainers.PointList; import de.tudresden.inf.mci.brailleplot.datacontainers.PointList;
import de.tudresden.inf.mci.brailleplot.datacontainers.PointListContainer;
import de.tudresden.inf.mci.brailleplot.diagrams.BarChart; import de.tudresden.inf.mci.brailleplot.diagrams.BarChart;
import de.tudresden.inf.mci.brailleplot.printabledata.SimpleMatrixDataImpl; import de.tudresden.inf.mci.brailleplot.printabledata.SimpleMatrixDataImpl;
import de.tudresden.inf.mci.brailleplot.rendering.MasterRenderer; import de.tudresden.inf.mci.brailleplot.rendering.MasterRenderer;
...@@ -151,11 +151,11 @@ public final class App { ...@@ -151,11 +151,11 @@ public final class App {
// Parse csv data // Parse csv data
ClassLoader classloader = Thread.currentThread().getContextClassLoader(); ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream csvStream = classloader.getResourceAsStream("examples/csv/0_bar_chart.csv"); InputStream csvStream = classloader.getResourceAsStream("examples/csv/0_bar_chart_categorical_vertical.csv");
Reader csvReader = new BufferedReader(new InputStreamReader(csvStream)); Reader csvReader = new BufferedReader(new InputStreamReader(csvStream));
CsvParser csvParser = new CsvParser(csvReader, ',', '\"'); CsvParser csvParser = new CsvParser(csvReader, ',', '\"');
PointListContainer<PointList> container = csvParser.parse(CsvType.X_ALIGNED, CsvOrientation.VERTICAL); CategoricalPointListContainer<PointList> container = csvParser.parse(CsvType.X_ALIGNED_CATEGORIES, CsvOrientation.VERTICAL);
mLogger.debug("Internal data representation:\n {}", container.toString()); mLogger.debug("Internal data representation:\n {}", container.toString());
BarChart barChart = new BarChart(container); BarChart barChart = new BarChart(container);
......
...@@ -16,7 +16,7 @@ import java.util.Objects; ...@@ -16,7 +16,7 @@ import java.util.Objects;
* @author SVGPlott-Team, Georg Graßnick * @author SVGPlott-Team, Georg Graßnick
* @version 2019.07.29 * @version 2019.07.29
*/ */
public class CsvDotParser extends CsvParseAlgorithm { public class CsvDotParser extends CsvParseAlgorithm<PointListContainer<PointList>> {
/** /**
* Parses scattered point data in horizontal data sets, alternating mX and mY. The * Parses scattered point data in horizontal data sets, alternating mX and mY. The
......
...@@ -14,10 +14,11 @@ import java.util.Objects; ...@@ -14,10 +14,11 @@ import java.util.Objects;
/** /**
* An algorithm for parsing CSV data. Contains implementations for two * An algorithm for parsing CSV data. Contains implementations for two
* orientations of the data in the file. * orientations of the data in the file.
* @param <T> The type of PointContainer, that is parsed to.
* @author SVGPlott-Team, Georg Graßnick * @author SVGPlott-Team, Georg Graßnick
* @version 2019.07.29 * @version 2019.07.29
*/ */
public abstract class CsvParseAlgorithm { public abstract class CsvParseAlgorithm<T extends PointListContainer<PointList>> {
protected final Logger mLogger = LoggerFactory.getLogger(getClass()); protected final Logger mLogger = LoggerFactory.getLogger(getClass());
...@@ -27,7 +28,7 @@ public abstract class CsvParseAlgorithm { ...@@ -27,7 +28,7 @@ public abstract class CsvParseAlgorithm {
* @param csvData The parsed input String. * @param csvData The parsed input String.
* @return A {@link PointListContainer}{@literal <PointList>} representing the data. * @return A {@link PointListContainer}{@literal <PointList>} representing the data.
*/ */
public abstract PointListContainer<PointList> parseAsHorizontalDataSets(List<? extends List<String>> csvData); public abstract T parseAsHorizontalDataSets(List<? extends List<String>> csvData);
/** /**
* If the data sets are oriented horizontally, i.e. in rows, parse the rows into * If the data sets are oriented horizontally, i.e. in rows, parse the rows into
...@@ -35,7 +36,7 @@ public abstract class CsvParseAlgorithm { ...@@ -35,7 +36,7 @@ public abstract class CsvParseAlgorithm {
* @param csvData The parsed input String. * @param csvData The parsed input String.
* @return A {@link PointListContainer}{@literal <}{@link PointList}{@literal >} representing the data. * @return A {@link PointListContainer}{@literal <}{@link PointList}{@literal >} representing the data.
*/ */
public abstract PointListContainer<PointList> parseAsVerticalDataSets(List<? extends List<String>> csvData); public abstract T parseAsVerticalDataSets(List<? extends List<String>> csvData);
/** /**
* Adds a {@link Point2DDouble} to a {@link PointList} in a {@link PointListContainer}{@literal <}{@link PointList}{@literal >}, * Adds a {@link Point2DDouble} to a {@link PointList} in a {@link PointListContainer}{@literal <}{@link PointList}{@literal >},
......
...@@ -8,7 +8,6 @@ import de.tudresden.inf.mci.brailleplot.datacontainers.PointListContainer; ...@@ -8,7 +8,6 @@ import de.tudresden.inf.mci.brailleplot.datacontainers.PointListContainer;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -20,7 +19,7 @@ import java.util.Objects; ...@@ -20,7 +19,7 @@ import java.util.Objects;
* @author SVGPlott-Team, Georg Graßnick * @author SVGPlott-Team, Georg Graßnick
* @version 2019.07.29 * @version 2019.07.29
*/ */
public class CsvParser { public final class CsvParser {
private final Logger mLogger = LoggerFactory.getLogger(CsvParser.class); private final Logger mLogger = LoggerFactory.getLogger(CsvParser.class);
...@@ -56,27 +55,29 @@ public class CsvParser { ...@@ -56,27 +55,29 @@ public class CsvParser {
/** /**
* Chooses the right parsing algorithm. * Chooses the right parsing algorithm.
* Casting in this method is not guaranteed to be safe, so use at your own risk.
* @param csvType CsvType * @param csvType CsvType
* @param csvOrientation CsvOrientation * @param csvOrientation CsvOrientation
* @return PointListList * @return PointListList
*/ */
public PointListContainer<PointList> parse(final CsvType csvType, final CsvOrientation csvOrientation) { @SuppressWarnings("unchecked")
CsvParseAlgorithm csvParseAlgorithm; public <T extends PointListContainer<PointList>> T parse(final CsvType csvType, final CsvOrientation csvOrientation) {
CsvParseAlgorithm<T> csvParseAlgorithm;
mLogger.debug("Parsing data as \"{}\", orientation \"{}\"", csvType, csvOrientation); mLogger.debug("Parsing data as \"{}\", orientation \"{}\"", csvType, csvOrientation);
switch (csvType) { switch (csvType) {
case DOTS: case DOTS:
csvParseAlgorithm = new CsvDotParser(); csvParseAlgorithm = ((CsvParseAlgorithm<T>) new CsvDotParser());
break; break;
case X_ALIGNED: case X_ALIGNED:
csvParseAlgorithm = new CsvXAlignedParser(); csvParseAlgorithm = ((CsvParseAlgorithm<T>) new CsvXAlignedParser());
break; break;
case X_ALIGNED_CATEGORIES: case X_ALIGNED_CATEGORIES:
csvParseAlgorithm = new CsvXAlignedCategoriesParser(); csvParseAlgorithm = ((CsvParseAlgorithm<T>) new CsvXAlignedCategoriesParser());
break; break;
default: default:
return null; throw new UnsupportedOperationException();
} }
switch (csvOrientation) { switch (csvOrientation) {
...@@ -85,7 +86,7 @@ public class CsvParser { ...@@ -85,7 +86,7 @@ public class CsvParser {
case VERTICAL: case VERTICAL:
return csvParseAlgorithm.parseAsVerticalDataSets(mCsvData); return csvParseAlgorithm.parseAsVerticalDataSets(mCsvData);
default: default:
return null; throw new UnsupportedOperationException();
} }
} }
} }
package de.tudresden.inf.mci.brailleplot.csvparser; package de.tudresden.inf.mci.brailleplot.csvparser;
import de.tudresden.inf.mci.brailleplot.datacontainers.CategoricalPointListContainer;
import de.tudresden.inf.mci.brailleplot.datacontainers.PointList; import de.tudresden.inf.mci.brailleplot.datacontainers.PointList;
import de.tudresden.inf.mci.brailleplot.datacontainers.PointListContainer; import de.tudresden.inf.mci.brailleplot.datacontainers.SimpleCategoricalPointListContainerImpl;
import de.tudresden.inf.mci.brailleplot.datacontainers.SimplePointListContainerImpl;
import de.tudresden.inf.mci.brailleplot.datacontainers.SimplePointListImpl; import de.tudresden.inf.mci.brailleplot.datacontainers.SimplePointListImpl;
import de.tudresden.inf.mci.brailleplot.point.Point2DDouble; import de.tudresden.inf.mci.brailleplot.point.Point2DDouble;
...@@ -17,13 +17,13 @@ import java.util.Objects; ...@@ -17,13 +17,13 @@ import java.util.Objects;
* @author SVGPlott-Team, Georg Graßnick * @author SVGPlott-Team, Georg Graßnick
* @version 2019.07.29 * @version 2019.07.29
*/ */
public class CsvXAlignedCategoriesParser extends CsvParseAlgorithm { public class CsvXAlignedCategoriesParser extends CsvParseAlgorithm<CategoricalPointListContainer<PointList>> {
@Override @Override
public PointListContainer<PointList> parseAsHorizontalDataSets(final List<? extends List<String>> csvData) { public CategoricalPointListContainer<PointList> parseAsHorizontalDataSets(final List<? extends List<String>> csvData) {
Objects.requireNonNull(csvData); Objects.requireNonNull(csvData);
PointListContainer<PointList> container = new SimplePointListContainerImpl(); CategoricalPointListContainer<PointList> container = new SimpleCategoricalPointListContainerImpl();
Iterator<? extends List<String>> rowIterator = csvData.iterator(); Iterator<? extends List<String>> rowIterator = csvData.iterator();
...@@ -33,6 +33,12 @@ public class CsvXAlignedCategoriesParser extends CsvParseAlgorithm { ...@@ -33,6 +33,12 @@ public class CsvXAlignedCategoriesParser extends CsvParseAlgorithm {
Iterator<String> lineIterator = rowIterator.next().iterator(); Iterator<String> lineIterator = rowIterator.next().iterator();
// Move the iterator to the first category name
if (!lineIterator.hasNext()) {
return container;
}
lineIterator.next();
if (!lineIterator.hasNext()) { if (!lineIterator.hasNext()) {
return container; return container;
...@@ -53,11 +59,6 @@ public class CsvXAlignedCategoriesParser extends CsvParseAlgorithm { ...@@ -53,11 +59,6 @@ public class CsvXAlignedCategoriesParser extends CsvParseAlgorithm {
if (!lineIterator.hasNext()) { if (!lineIterator.hasNext()) {
continue; continue;
} }
if (!categoriesIt.hasNext()) {
continue;
}
String category = categoriesIt.next(); String category = categoriesIt.next();
PointList pointList = new SimplePointListImpl(category); PointList pointList = new SimplePointListImpl(category);
container.pushBack(pointList); container.pushBack(pointList);
...@@ -90,73 +91,50 @@ public class CsvXAlignedCategoriesParser extends CsvParseAlgorithm { ...@@ -90,73 +91,50 @@ public class CsvXAlignedCategoriesParser extends CsvParseAlgorithm {
} }
@Override @Override
public PointListContainer<PointList> parseAsVerticalDataSets(final List<? extends List<String>> csvData) { public CategoricalPointListContainer<PointList> parseAsVerticalDataSets(final List<? extends List<String>> csvData) {
Objects.requireNonNull(csvData); Objects.requireNonNull(csvData);
PointListContainer<PointList> container = new SimplePointListContainerImpl(); CategoricalPointListContainer<PointList> container = new SimpleCategoricalPointListContainerImpl();
Iterator<? extends List<String>> rowIterator = csvData.iterator(); Iterator<? extends List<String>> rowIt = 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()) { int rowNum = 0; // Keep track of the row number, so that we can include the erroneous row number in the exception.
return container; while (rowIt.hasNext()) {
} Iterator<String> lineIt = rowIt.next().iterator();
rowNum++;
// Add a PointList for each title // Check if we are in the first line, were all the categories are defined ...
while (lineIterator.hasNext()) { if (rowNum == 1) {
PointList pointList = new SimplePointListImpl(); while (lineIt.hasNext()) {
pointList.setName(lineIterator.next()); container.pushBackCategory(lineIt.next());
container.pushBack(pointList);
}
// Add the data
Iterator<PointList> it = container.iterator();
int categoryCounter = 0;
while (rowIterator.hasNext()) {
lineIterator = rowIterator.next().iterator();
if (!lineIterator.hasNext()) {
categoryCounter++;
continue;
}
// Find out the category title
String currentCategory = lineIterator.next();
if (it.hasNext()) {
it.next().setName(currentCategory);
}
// 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;
} }
// ... or if we are in a row, were the actual data sets are defined
Point2DDouble newPoint = new Point2DDouble(categoryCounter, yValue.doubleValue()); } else {
addPointToPointListList(container, currentDataSet, newPoint); // Get the name for the values of a data set
currentDataSet++; if (!lineIt.hasNext()) {
throw new MalformedCsvException("Line: " + rowNum + ": Data set must contain a name");
}
String name = lineIt.next().trim();
PointList pl = new SimplePointListImpl(name);
// Parse all values
// Set the x value of each Point to the index of the category, they belong to
int columnNum = 0;
while (lineIt.hasNext()) {
columnNum++;
String value = lineIt.next().trim();
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(columnNum, val.doubleValue());
pl.pushBack(p);
}
container.pushBack(pl);
} }
categoryCounter++;
} }
// 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; return container;
} }
......
...@@ -17,7 +17,7 @@ import java.util.Objects; ...@@ -17,7 +17,7 @@ import java.util.Objects;
* @author SVGPlott-Team, Georg Graßnick * @author SVGPlott-Team, Georg Graßnick
* @version 2019.07.29 * @version 2019.07.29
*/ */
public class CsvXAlignedParser extends CsvParseAlgorithm { public class CsvXAlignedParser extends CsvParseAlgorithm<PointListContainer<PointList>> {
@Override @Override
public PointListContainer<PointList> parseAsHorizontalDataSets(final List<? extends List<String>> csvData) { public PointListContainer<PointList> parseAsHorizontalDataSets(final List<? extends List<String>> csvData) {
......
...@@ -51,4 +51,15 @@ public class SimpleCategoricalPointListContainerImpl extends SimplePointListCont ...@@ -51,4 +51,15 @@ public class SimpleCategoricalPointListContainerImpl extends SimplePointListCont
} }
return mCategories.get(index); return mCategories.get(index);
} }
@Override
protected String toRecursiveString(final int depth) {
StringBuilder sb = new StringBuilder();
sb.append("Categories:\n");
for (String s : mCategories) {
sb.append(s).append("\n");
}
sb.append(super.toRecursiveString(depth));
return sb.toString();
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment