diff --git a/core/src/main/java/tech/tablesaw/api/DateColumn.java b/core/src/main/java/tech/tablesaw/api/DateColumn.java index 11f25d407..abaf74dfd 100644 --- a/core/src/main/java/tech/tablesaw/api/DateColumn.java +++ b/core/src/main/java/tech/tablesaw/api/DateColumn.java @@ -34,6 +34,7 @@ import java.util.function.Consumer; import java.util.function.Supplier; import java.util.stream.Stream; +import javax.annotation.Nonnull; import tech.tablesaw.columns.AbstractColumn; import tech.tablesaw.columns.AbstractColumnParser; import tech.tablesaw.columns.Column; @@ -135,17 +136,32 @@ public DateColumn set(int index, LocalDate value) { return value == null ? setMissing(index) : set(index, PackedLocalDate.pack(value)); } + /** + * Creates and sets a printFormatter based-on the given DateTimeFormatter. Missing values will be + * printed as the given missingValueString. Non missing values will be handled by the + * dateTimeFormatter + */ public void setPrintFormatter(DateTimeFormatter dateTimeFormatter, String missingValueString) { Preconditions.checkNotNull(dateTimeFormatter); Preconditions.checkNotNull(missingValueString); this.printFormatter = new DateColumnFormatter(dateTimeFormatter, missingValueString); } + /** + * Creates and sets a printFormatter based-on the given DateTimeFormatter. Missing values will be + * printed as empty strings. Non missing values will be handled by the dateTimeFormatter + */ public void setPrintFormatter(DateTimeFormatter dateTimeFormatter) { Preconditions.checkNotNull(dateTimeFormatter); this.printFormatter = new DateColumnFormatter(dateTimeFormatter); } + /** Sets the print formatter to the argument */ + public void setPrintFormatter(@Nonnull DateColumnFormatter dateColumnFormatter) { + Preconditions.checkNotNull(dateColumnFormatter); + this.printFormatter = dateColumnFormatter; + } + @Override public String getString(int row) { return printFormatter.format(getPackedDate(row)); diff --git a/core/src/main/java/tech/tablesaw/api/TextColumn.java b/core/src/main/java/tech/tablesaw/api/TextColumn.java index 8c9778e86..0de50ad86 100644 --- a/core/src/main/java/tech/tablesaw/api/TextColumn.java +++ b/core/src/main/java/tech/tablesaw/api/TextColumn.java @@ -292,7 +292,8 @@ public TextColumn appendCell(String object) { @Override public TextColumn appendCell(String object, AbstractColumnParser parser) { - return appendObj(parser.parse(object)); + values.add(String.valueOf(parser.parse(object))); + return this; } @Override diff --git a/core/src/main/java/tech/tablesaw/columns/AbstractColumnParser.java b/core/src/main/java/tech/tablesaw/columns/AbstractColumnParser.java index 07e5e1520..d281461ee 100644 --- a/core/src/main/java/tech/tablesaw/columns/AbstractColumnParser.java +++ b/core/src/main/java/tech/tablesaw/columns/AbstractColumnParser.java @@ -83,4 +83,8 @@ protected static String remove(final String str, final char remove) { } return new String(chars, 0, pos); } + + public void setMissingValueStrings(List missingValueStrings) { + this.missingValueStrings = missingValueStrings; + } } diff --git a/core/src/main/java/tech/tablesaw/columns/ColumnFormatter.java b/core/src/main/java/tech/tablesaw/columns/ColumnFormatter.java new file mode 100644 index 000000000..6712f80d1 --- /dev/null +++ b/core/src/main/java/tech/tablesaw/columns/ColumnFormatter.java @@ -0,0 +1,22 @@ +package tech.tablesaw.columns; + +/** + * Abstract class for Column Formatters Every column type has a specialized print formatter that is + * used for formatting output for both table printing via, for example, table.printAll(). It is also + * used for writing text files using table.write().csv() + */ +public abstract class ColumnFormatter { + + // The string to use for missing values + private final String missingString; + + /** Constructs a new Formatter with the given missing value string. */ + protected ColumnFormatter(String missingString) { + this.missingString = missingString; + } + + /** Returns the string to be used in place of any missing values in the column */ + public String getMissingString() { + return missingString; + } +} diff --git a/core/src/main/java/tech/tablesaw/columns/TemporalColumnFormatter.java b/core/src/main/java/tech/tablesaw/columns/TemporalColumnFormatter.java new file mode 100644 index 000000000..220a62ea2 --- /dev/null +++ b/core/src/main/java/tech/tablesaw/columns/TemporalColumnFormatter.java @@ -0,0 +1,36 @@ +package tech.tablesaw.columns; + +import java.time.format.DateTimeFormatter; + +/** + * Abstract class for Column Formatters for temporal columns Date, DateTime, Time, and Instant Every + * column type has a specialized print formatter that is used for formatting output for both table + * printing via, for example, table.printAll(). It is also used for writing text files using + * table.write().csv() + */ +public abstract class TemporalColumnFormatter extends ColumnFormatter { + + private final DateTimeFormatter format; + + /** Constructs a new Formatter with the given formatter and an empty missing value string. */ + protected TemporalColumnFormatter(DateTimeFormatter format) { + super(""); + this.format = format; + } + + /** Constructs a new Formatter with the given formatter and missing value string. */ + protected TemporalColumnFormatter(DateTimeFormatter format, String missingValueString) { + super(missingValueString); + this.format = format; + } + + /** Constructs a new default Formatter. This produces unformatted output. */ + protected TemporalColumnFormatter() { + super(""); + this.format = null; + } + + public DateTimeFormatter getFormat() { + return format; + } +} diff --git a/core/src/main/java/tech/tablesaw/columns/booleans/BooleanFormatter.java b/core/src/main/java/tech/tablesaw/columns/booleans/BooleanFormatter.java index 1da18b34c..a965f557a 100644 --- a/core/src/main/java/tech/tablesaw/columns/booleans/BooleanFormatter.java +++ b/core/src/main/java/tech/tablesaw/columns/booleans/BooleanFormatter.java @@ -1,30 +1,30 @@ package tech.tablesaw.columns.booleans; -public class BooleanFormatter { +import tech.tablesaw.columns.ColumnFormatter; + +public class BooleanFormatter extends ColumnFormatter { private String trueString = "true"; private String falseString = "false"; - private String missingString = ""; - public BooleanFormatter(String trueString, String falseString, String missingString) { + super(missingString); this.trueString = trueString; this.falseString = falseString; - this.missingString = missingString; } public BooleanFormatter(String trueString, String falseString) { + super(""); this.trueString = trueString; this.falseString = falseString; - this.missingString = ""; } public BooleanFormatter(String missingString) { - this.missingString = missingString; + super(missingString); } public String format(Boolean value) { if (value == null) { - return missingString; + return getMissingString(); } if (value) { return trueString; @@ -34,7 +34,7 @@ public String format(Boolean value) { public String format(byte value) { if (value == BooleanColumnType.MISSING_VALUE) { - return missingString; + return getMissingString(); } if (value == (byte) 1) { return trueString; @@ -52,7 +52,7 @@ public String toString() { + falseString + '\'' + ", missingString='" - + missingString + + getMissingString() + '\'' + '}'; } diff --git a/core/src/main/java/tech/tablesaw/columns/dates/DateColumnFormatter.java b/core/src/main/java/tech/tablesaw/columns/dates/DateColumnFormatter.java index 7b93efb47..5b7558857 100644 --- a/core/src/main/java/tech/tablesaw/columns/dates/DateColumnFormatter.java +++ b/core/src/main/java/tech/tablesaw/columns/dates/DateColumnFormatter.java @@ -6,47 +6,44 @@ import java.time.LocalDate; import java.time.format.DateTimeFormatter; import javax.annotation.concurrent.Immutable; +import tech.tablesaw.columns.TemporalColumnFormatter; @Immutable -public class DateColumnFormatter { +public class DateColumnFormatter extends TemporalColumnFormatter { - private final DateTimeFormatter format; - private String missingString = ""; - - public DateColumnFormatter() { - this.format = null; + public DateColumnFormatter(DateTimeFormatter format) { + super(format); } - public DateColumnFormatter(DateTimeFormatter format) { - this.format = format; + public DateColumnFormatter() { + super(); } - public DateColumnFormatter(DateTimeFormatter format, String missingString) { - this.format = format; - this.missingString = missingString; + public DateColumnFormatter(DateTimeFormatter format, String missingValueString) { + super(format, missingValueString); } public String format(int value) { if (value == DateColumnType.missingValueIndicator()) { - return missingString; + return getMissingString(); } - if (format == null) { + if (getFormat() == null) { return toDateString(value); } LocalDate date = asLocalDate(value); if (date == null) { return ""; } - return format.format(date); + return getFormat().format(date); } @Override public String toString() { return "DateColumnFormatter{" + "format=" - + format + + getFormat() + ", missingString='" - + missingString + + getMissingString() + '\'' + '}'; } diff --git a/core/src/main/java/tech/tablesaw/columns/instant/InstantColumnFormatter.java b/core/src/main/java/tech/tablesaw/columns/instant/InstantColumnFormatter.java index 2bf7f2e67..e76f582de 100644 --- a/core/src/main/java/tech/tablesaw/columns/instant/InstantColumnFormatter.java +++ b/core/src/main/java/tech/tablesaw/columns/instant/InstantColumnFormatter.java @@ -1,73 +1,71 @@ package tech.tablesaw.columns.instant; +import java.time.Instant; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import javax.annotation.concurrent.Immutable; -import tech.tablesaw.columns.times.TimeColumnType; +import tech.tablesaw.columns.TemporalColumnFormatter; @Immutable -public class InstantColumnFormatter { +public class InstantColumnFormatter extends TemporalColumnFormatter { - private final DateTimeFormatter format; private final ZoneId zoneId; - private String missingValueString = ""; public InstantColumnFormatter() { - this.format = null; + super(null); this.zoneId = ZoneOffset.UTC; } public InstantColumnFormatter(ZoneId zoneId) { - this.format = null; + super(null); this.zoneId = zoneId; } public InstantColumnFormatter(DateTimeFormatter format) { - this.format = format; + super(format); this.zoneId = ZoneOffset.UTC; } public InstantColumnFormatter(DateTimeFormatter format, ZoneId zoneId) { - this.format = format; + super(format); this.zoneId = zoneId; } public InstantColumnFormatter(DateTimeFormatter format, String missingValueString) { - this.format = format; - this.missingValueString = missingValueString; + super(format, missingValueString); this.zoneId = ZoneOffset.UTC; } public InstantColumnFormatter( DateTimeFormatter format, ZoneId zoneId, String missingValueString) { - this.format = format; - this.missingValueString = missingValueString; + super(format, missingValueString); this.zoneId = zoneId; } public String format(long value) { - if (value == TimeColumnType.missingValueIndicator()) { - return missingValueString; + if (value == InstantColumnType.missingValueIndicator()) { + return getMissingString(); } - if (format == null) { + if (getFormat() == null) { return PackedInstant.toString(value); } - ZonedDateTime time = PackedInstant.asInstant(value).atZone(zoneId); - if (time == null) { + Instant instant = PackedInstant.asInstant(value); + if (instant == null) { return ""; } - return format.format(time); + ZonedDateTime time = instant.atZone(zoneId); + return getFormat().format(time); } @Override public String toString() { return "InstantColumnFormatter{" + "format=" - + format + + getFormat() + ", missingValueString='" - + missingValueString + + getMissingString() + '\'' + '}'; } diff --git a/core/src/main/java/tech/tablesaw/columns/numbers/NumberColumnFormatter.java b/core/src/main/java/tech/tablesaw/columns/numbers/NumberColumnFormatter.java index f0e5a3a9f..45877691f 100644 --- a/core/src/main/java/tech/tablesaw/columns/numbers/NumberColumnFormatter.java +++ b/core/src/main/java/tech/tablesaw/columns/numbers/NumberColumnFormatter.java @@ -4,11 +4,11 @@ import java.text.DecimalFormatSymbols; import java.text.NumberFormat; import java.util.Locale; +import tech.tablesaw.columns.ColumnFormatter; -public class NumberColumnFormatter { +public class NumberColumnFormatter extends ColumnFormatter { private final NumberFormat format; - private String missingString = ""; public static NumberColumnFormatter percent(int fractionalDigits) { NumberFormat format = NumberFormat.getPercentInstance(); @@ -63,26 +63,28 @@ public static NumberColumnFormatter currency(String language, String country) { } public NumberColumnFormatter() { + super(""); this.format = null; } public NumberColumnFormatter(NumberFormat format) { + super(""); this.format = format; } public NumberColumnFormatter(NumberFormat format, String missingString) { + super(missingString); this.format = format; - this.missingString = missingString; } public NumberColumnFormatter(String missingString) { + super(missingString); this.format = null; - this.missingString = missingString; } public String format(long value) { if (isMissingValue(value)) { - return missingString; + return getMissingString(); } if (format == null) { return String.valueOf(value); @@ -92,7 +94,7 @@ public String format(long value) { public String format(double value) { if (isMissingValue(value)) { - return missingString; + return getMissingString(); } if (format == null) { return String.valueOf(value); @@ -106,7 +108,7 @@ public String toString() { + "format=" + format + ", missingString='" - + missingString + + getMissingString() + '\'' + '}'; } diff --git a/core/src/main/java/tech/tablesaw/columns/strings/StringColumnFormatter.java b/core/src/main/java/tech/tablesaw/columns/strings/StringColumnFormatter.java index f801966d6..b73fa4fe1 100644 --- a/core/src/main/java/tech/tablesaw/columns/strings/StringColumnFormatter.java +++ b/core/src/main/java/tech/tablesaw/columns/strings/StringColumnFormatter.java @@ -1,29 +1,31 @@ package tech.tablesaw.columns.strings; import java.util.function.Function; +import tech.tablesaw.columns.ColumnFormatter; -public class StringColumnFormatter { +public class StringColumnFormatter extends ColumnFormatter { private final Function formatter; - private String missingString = ""; public StringColumnFormatter() { + super(""); this.formatter = null; } public StringColumnFormatter(Function formatFunction) { + super(""); this.formatter = formatFunction; } public StringColumnFormatter(Function formatFunction, String missingString) { + super(missingString); this.formatter = formatFunction; - this.missingString = missingString; } public String format(String value) { if (StringColumnType.missingValueIndicator().equals(value)) { - return missingString; + return getMissingString(); } if (formatter == null) { return value; @@ -37,7 +39,7 @@ public String toString() { + "format=" + formatter + ", missingString='" - + missingString + + getMissingString() + '\'' + '}'; } diff --git a/core/src/main/java/tech/tablesaw/columns/times/TimeColumnFormatter.java b/core/src/main/java/tech/tablesaw/columns/times/TimeColumnFormatter.java index e1f8b6d63..5cabce9d2 100644 --- a/core/src/main/java/tech/tablesaw/columns/times/TimeColumnFormatter.java +++ b/core/src/main/java/tech/tablesaw/columns/times/TimeColumnFormatter.java @@ -6,29 +6,27 @@ import java.time.LocalTime; import java.time.format.DateTimeFormatter; import javax.annotation.concurrent.Immutable; +import tech.tablesaw.columns.TemporalColumnFormatter; @Immutable -public class TimeColumnFormatter { +public class TimeColumnFormatter extends TemporalColumnFormatter { - private final DateTimeFormatter format; - private String missingString = ""; - - public TimeColumnFormatter() { - this.format = null; + public TimeColumnFormatter(DateTimeFormatter format) { + super(format); } - public TimeColumnFormatter(DateTimeFormatter format) { - this.format = format; + public TimeColumnFormatter() { + super(); } - public TimeColumnFormatter(DateTimeFormatter format, String missingString) { - this.format = format; - this.missingString = missingString; + public TimeColumnFormatter(DateTimeFormatter format, String missingValueString) { + super(format, missingValueString); } public String format(int value) { + DateTimeFormatter format = getFormat(); if (value == TimeColumnType.missingValueIndicator()) { - return missingString; + return getMissingString(); } if (format == null) { return toShortTimeString(value); @@ -44,9 +42,9 @@ public String format(int value) { public String toString() { return "TimeColumnFormatter{" + "format=" - + format + + getFormat() + ", missingString='" - + missingString + + getMissingString() + '\'' + '}'; } diff --git a/core/src/main/java/tech/tablesaw/io/csv/CsvWriteOptions.java b/core/src/main/java/tech/tablesaw/io/csv/CsvWriteOptions.java index 2a497c9f9..ac18ecb7c 100644 --- a/core/src/main/java/tech/tablesaw/io/csv/CsvWriteOptions.java +++ b/core/src/main/java/tech/tablesaw/io/csv/CsvWriteOptions.java @@ -16,6 +16,7 @@ public class CsvWriteOptions extends WriteOptions { private final boolean header; private final boolean ignoreLeadingWhitespaces; private final boolean ignoreTrailingWhitespaces; + private final boolean usePrintFormatter; private final Character separator; private final Character quoteChar; private final Character escapeChar; @@ -38,6 +39,7 @@ private CsvWriteOptions(Builder builder) { this.dateFormatter = builder.dateFormatter; this.dateTimeFormatter = builder.dateTimeFormatter; this.columnNameMap = builder.columnNameMap; + this.usePrintFormatter = builder.usePrintFormatters; } public boolean header() { @@ -64,6 +66,10 @@ public boolean quoteAllFields() { return quoteAllFields; } + public boolean usePrintFormatters() { + return usePrintFormatter; + } + public Map columnNameMap() { return columnNameMap; } @@ -110,6 +116,7 @@ public static class Builder extends WriteOptions.Builder { private boolean ignoreLeadingWhitespaces = true; private boolean ignoreTrailingWhitespaces = true; private boolean quoteAllFields = false; + private boolean usePrintFormatters = false; private Character separator; private String lineEnd = System.lineSeparator(); private Character escapeChar; @@ -159,16 +166,37 @@ public CsvWriteOptions.Builder quoteChar(char quoteChar) { return this; } + /** + * Writes date column output using the given DateFormatter + * + * @deprecated + */ + @Deprecated public CsvWriteOptions.Builder dateFormatter(DateTimeFormatter dateFormatter) { this.dateFormatter = dateFormatter; return this; } + /** + * Writes DateTime column output using the given DateFormatter + * + * @deprecated + */ + @Deprecated public CsvWriteOptions.Builder dateTimeFormatter(DateTimeFormatter dateTimeFormatter) { this.dateTimeFormatter = dateTimeFormatter; return this; } + /** + * Sets the usePrintFormatters option @link{tech.tablesaw.columns.ColumnFormatter} When true, + * printFormatters will be used in writing the output text for any column that has one. + */ + public CsvWriteOptions.Builder usePrintFormatters(boolean useFormatter) { + this.usePrintFormatters = useFormatter; + return this; + } + /** * Causes all data exported as a CSV file to be enclosed in quotes. Note that this includes the * headers, and all columns regardless of type diff --git a/core/src/main/java/tech/tablesaw/io/csv/CsvWriter.java b/core/src/main/java/tech/tablesaw/io/csv/CsvWriter.java index 4a3052c1c..c2cbfc5b9 100644 --- a/core/src/main/java/tech/tablesaw/io/csv/CsvWriter.java +++ b/core/src/main/java/tech/tablesaw/io/csv/CsvWriter.java @@ -50,30 +50,11 @@ public void write(Table table, CsvWriteOptions options) { csvWriter = new com.univocity.parsers.csv.CsvWriter(options.destination().createWriter(), settings); - if (options.header()) { - String[] header = new String[table.columnCount()]; - for (int c = 0; c < table.columnCount(); c++) { - String name = table.column(c).name(); - header[c] = options.columnNameMap().getOrDefault(name, name); - } - csvWriter.writeHeaders(header); - } + writeHeader(table, options, csvWriter); for (int r = 0; r < table.rowCount(); r++) { String[] entries = new String[table.columnCount()]; for (int c = 0; c < table.columnCount(); c++) { - table.get(r, c); - DateTimeFormatter dateFormatter = options.dateFormatter(); - DateTimeFormatter dateTimeFormatter = options.dateTimeFormatter(); - ColumnType columnType = table.column(c).type(); - if (dateFormatter != null && columnType.equals(ColumnType.LOCAL_DATE)) { - DateColumn dc = (DateColumn) table.column(c); - entries[c] = options.dateFormatter().format(dc.get(r)); - } else if (dateTimeFormatter != null && columnType.equals(ColumnType.LOCAL_DATE_TIME)) { - DateTimeColumn dc = (DateTimeColumn) table.column(c); - entries[c] = options.dateTimeFormatter().format(dc.get(r)); - } else { - entries[c] = table.getUnformatted(r, c); - } + writeValues(table, options, r, entries, c); } csvWriter.writeRow(entries); } @@ -85,6 +66,37 @@ public void write(Table table, CsvWriteOptions options) { } } + private void writeValues(Table table, CsvWriteOptions options, int r, String[] entries, int c) { + DateTimeFormatter dateFormatter = options.dateFormatter(); + DateTimeFormatter dateTimeFormatter = options.dateTimeFormatter(); + ColumnType columnType = table.column(c).type(); + if (dateFormatter != null && columnType.equals(ColumnType.LOCAL_DATE)) { + DateColumn dc = (DateColumn) table.column(c); + entries[c] = options.dateFormatter().format(dc.get(r)); + } else if (dateTimeFormatter != null && columnType.equals(ColumnType.LOCAL_DATE_TIME)) { + DateTimeColumn dc = (DateTimeColumn) table.column(c); + entries[c] = options.dateTimeFormatter().format(dc.get(r)); + } else { + if (options.usePrintFormatters()) { + entries[c] = table.getString(r, c); + } else { + entries[c] = table.getUnformatted(r, c); + } + } + } + + private void writeHeader( + Table table, CsvWriteOptions options, com.univocity.parsers.csv.CsvWriter csvWriter) { + if (options.header()) { + String[] header = new String[table.columnCount()]; + for (int c = 0; c < table.columnCount(); c++) { + String name = table.column(c).name(); + header[c] = options.columnNameMap().getOrDefault(name, name); + } + csvWriter.writeHeaders(header); + } + } + protected static CsvWriterSettings createSettings(CsvWriteOptions options) { CsvWriterSettings settings = new CsvWriterSettings(); // Sets the character sequence to write for the values that are null. diff --git a/core/src/main/java/tech/tablesaw/joining/DataFrameJoiner.java b/core/src/main/java/tech/tablesaw/joining/DataFrameJoiner.java index fd043cdac..174f4c8a3 100644 --- a/core/src/main/java/tech/tablesaw/joining/DataFrameJoiner.java +++ b/core/src/main/java/tech/tablesaw/joining/DataFrameJoiner.java @@ -14,22 +14,11 @@ import tech.tablesaw.columns.dates.DateColumnType; import tech.tablesaw.columns.datetimes.DateTimeColumnType; import tech.tablesaw.columns.instant.InstantColumnType; -import tech.tablesaw.columns.numbers.DoubleColumnType; -import tech.tablesaw.columns.numbers.FloatColumnType; -import tech.tablesaw.columns.numbers.IntColumnType; -import tech.tablesaw.columns.numbers.LongColumnType; -import tech.tablesaw.columns.numbers.ShortColumnType; +import tech.tablesaw.columns.numbers.*; import tech.tablesaw.columns.strings.StringColumnType; import tech.tablesaw.columns.strings.TextColumnType; import tech.tablesaw.columns.times.TimeColumnType; -import tech.tablesaw.index.ByteIndex; -import tech.tablesaw.index.DoubleIndex; -import tech.tablesaw.index.FloatIndex; -import tech.tablesaw.index.Index; -import tech.tablesaw.index.IntIndex; -import tech.tablesaw.index.LongIndex; -import tech.tablesaw.index.ShortIndex; -import tech.tablesaw.index.StringIndex; +import tech.tablesaw.index.*; import tech.tablesaw.selection.Selection; public class DataFrameJoiner { @@ -442,7 +431,9 @@ public Table leftOuter(Table... tables) { public Table leftOuter(boolean allowDuplicateColumnNames, Table... tables) { Table joined = table; for (Table table2 : tables) { - joined = leftOuter(table2, allowDuplicateColumnNames, joinColumnNames); + joined = + joinInternal( + joined, table2, JoinType.LEFT_OUTER, allowDuplicateColumnNames, joinColumnNames); } return joined; } diff --git a/core/src/test/java/tech/tablesaw/analytic/AnalyticQueryTest.java b/core/src/test/java/tech/tablesaw/analytic/AnalyticQueryTest.java index 2353c26c2..05c62907f 100644 --- a/core/src/test/java/tech/tablesaw/analytic/AnalyticQueryTest.java +++ b/core/src/test/java/tech/tablesaw/analytic/AnalyticQueryTest.java @@ -13,6 +13,8 @@ class AnalyticQueryTest { + private static final String LINE_END = System.lineSeparator(); + @Test public void testToSqlString() { Table table = Table.create("table1", IntColumn.create("sales")); @@ -31,17 +33,17 @@ public void testToSqlString() { String expected = "SELECT" - + System.lineSeparator() + + LINE_END + "SUM(sales) OVER w1 AS sumSales" - + System.lineSeparator() + + LINE_END + "FROM table1" - + System.lineSeparator() + + LINE_END + "Window w1 AS (" - + System.lineSeparator() + + LINE_END + "PARTITION BY product, region" - + System.lineSeparator() + + LINE_END + "ORDER BY sales ASC" - + System.lineSeparator() + + LINE_END + "ROWS BETWEEN UNBOUNDED_PRECEDING AND UNBOUNDED_FOLLOWING);"; assertEquals(expected, query.toSqlLikeString()); @@ -60,10 +62,14 @@ public void toSqlStringQuick() { .build(); String expectd = - "SELECT\n" - + "MAX(sales) OVER w1 AS salesSum\n" - + "FROM sales\n" - + "Window w1 AS (\n" + "SELECT" + + LINE_END + + "MAX(sales) OVER w1 AS salesSum" + + LINE_END + + "FROM sales" + + LINE_END + + "Window w1 AS (" + + LINE_END + "ROWS BETWEEN CURRENT_ROW AND 1 FOLLOWING);"; assertEquals(expectd, query.toSqlLikeString()); @@ -81,10 +87,14 @@ public void toSqlStringNumbering() { .build(); String expectd = - "SELECT\n" - + "RANK() OVER w1 AS myRank\n" - + "FROM myTable\n" - + "Window w1 AS (\n" + "SELECT" + + LINE_END + + "RANK() OVER w1 AS myRank" + + LINE_END + + "FROM myTable" + + LINE_END + + "Window w1 AS (" + + LINE_END + "ORDER BY date ASC, region ASC);"; assertEquals(expectd, query.toSqlLikeString()); diff --git a/core/src/test/java/tech/tablesaw/api/StringColumnTest.java b/core/src/test/java/tech/tablesaw/api/StringColumnTest.java index 7f1e22d5d..aaacf51a6 100644 --- a/core/src/test/java/tech/tablesaw/api/StringColumnTest.java +++ b/core/src/test/java/tech/tablesaw/api/StringColumnTest.java @@ -21,6 +21,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static tech.tablesaw.columns.strings.StringPredicates.isEqualToIgnoringCase; +import com.google.common.collect.Lists; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; @@ -29,6 +31,7 @@ import org.junit.jupiter.api.Test; import tech.tablesaw.TestDataUtil; import tech.tablesaw.columns.strings.StringColumnFormatter; +import tech.tablesaw.columns.strings.StringParser; import tech.tablesaw.selection.Selection; class StringColumnTest { @@ -63,6 +66,21 @@ void testAppendObj2() { assertArrayEquals(sc.asList().toArray(), sc.asObjectArray()); } + @Test + void appendAsterisk() { + final StringColumn sc = StringColumn.create("sc"); + sc.append("*"); + assertEquals(0, sc.countMissing()); + StringParser parser = new StringParser(ColumnType.TEXT); + parser.setMissingValueStrings(new ArrayList<>()); + sc.appendCell("*", parser); + assertEquals(0, sc.countMissing()); + StringParser parser2 = new StringParser(ColumnType.TEXT); + parser2.setMissingValueStrings(Lists.newArrayList("45")); + sc.appendCell("45", parser2); + assertEquals(1, sc.countMissing()); + } + @Test void testForNulls() { String[] array1 = {"1", "2", "3", "4", null}; diff --git a/core/src/test/java/tech/tablesaw/api/TableTest.java b/core/src/test/java/tech/tablesaw/api/TableTest.java index c4234f07f..6b1a5843c 100644 --- a/core/src/test/java/tech/tablesaw/api/TableTest.java +++ b/core/src/test/java/tech/tablesaw/api/TableTest.java @@ -351,8 +351,10 @@ void stepWithRows() throws Exception { void melt() throws Exception { boolean dropMissing = false; String df = - "subject, time, age, weight, height\n" - + "John Smith, 1, 33, 90, 1.87\n" + "subject, time, age, weight, height" + + LINE_END + + "John Smith, 1, 33, 90, 1.87" + + LINE_END + "Mary Smith, 1, NA, NA, 1.54"; StringReader reader = new StringReader(df); Table t = Table.read().csv(reader); @@ -362,14 +364,22 @@ void melt() throws Exception { Table melted = t.melt(ids, measures, dropMissing); assertEquals( - " \n" - + " subject | time | variable | value |\n" - + "----------------------------------------------\n" - + " John Smith | 1 | age | 33 |\n" - + " John Smith | 1 | weight | 90 |\n" - + " John Smith | 1 | height | 1.87 |\n" - + " Mary Smith | 1 | age | |\n" - + " Mary Smith | 1 | weight | |\n" + " " + + LINE_END + + " subject | time | variable | value |" + + LINE_END + + "----------------------------------------------" + + LINE_END + + " John Smith | 1 | age | 33 |" + + LINE_END + + " John Smith | 1 | weight | 90 |" + + LINE_END + + " John Smith | 1 | height | 1.87 |" + + LINE_END + + " Mary Smith | 1 | age | |" + + LINE_END + + " Mary Smith | 1 | weight | |" + + LINE_END + " Mary Smith | 1 | height | 1.54 |", melted.toString()); } @@ -378,8 +388,10 @@ void melt() throws Exception { void meltAndDropMissing() throws Exception { boolean dropMissing = true; String df = - "subject, time, age, weight, height\n" - + "John Smith, 1, 33, 90, 1.87\n" + "subject, time, age, weight, height" + + LINE_END + + "John Smith, 1, 33, 90, 1.87" + + LINE_END + "Mary Smith, 1, NA, NA, 1.54"; StringReader reader = new StringReader(df); Table t = Table.read().csv(reader); @@ -390,12 +402,18 @@ void meltAndDropMissing() throws Exception { Table melted = t.melt(ids, measures, dropMissing); melted.write().csv("../data/molten_smiths_drop_missing.csv"); assertEquals( - " \n" - + " subject | time | variable | value |\n" - + "----------------------------------------------\n" - + " John Smith | 1 | age | 33 |\n" - + " John Smith | 1 | weight | 90 |\n" - + " John Smith | 1 | height | 1.87 |\n" + " " + + LINE_END + + " subject | time | variable | value |" + + LINE_END + + "----------------------------------------------" + + LINE_END + + " John Smith | 1 | age | 33 |" + + LINE_END + + " John Smith | 1 | weight | 90 |" + + LINE_END + + " John Smith | 1 | height | 1.87 |" + + LINE_END + " Mary Smith | 1 | height | 1.54 |", melted.toString()); } @@ -408,9 +426,12 @@ void cast() throws IOException { cast.write().csv(writer); String writeString = writer.toString(); assertEquals( - "subject,time,weight,age,height\n" - + "John Smith,1,90.0,33.0,1.87\n" - + "Mary Smith,1,,,1.54\n", + "subject,time,weight,age,height" + + LINE_END + + "John Smith,1,90.0,33.0,1.87" + + LINE_END + + "Mary Smith,1,,,1.54" + + LINE_END, writeString); } @@ -422,9 +443,12 @@ void castWithDropMissing() throws IOException { cast.write().csv(writer); String writeString = writer.toString(); assertEquals( - "subject,time,weight,age,height\n" - + "John Smith,1,90.0,33.0,1.87\n" - + "Mary Smith,1,,,1.54\n", + "subject,time,weight,age,height" + + LINE_END + + "John Smith,1,90.0,33.0,1.87" + + LINE_END + + "Mary Smith,1,,,1.54" + + LINE_END, writeString); } diff --git a/core/src/test/java/tech/tablesaw/api/TextColumnTest.java b/core/src/test/java/tech/tablesaw/api/TextColumnTest.java index a30bb1425..9d327e922 100644 --- a/core/src/test/java/tech/tablesaw/api/TextColumnTest.java +++ b/core/src/test/java/tech/tablesaw/api/TextColumnTest.java @@ -21,6 +21,7 @@ import com.google.common.base.Joiner; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.function.Function; @@ -28,6 +29,7 @@ import org.junit.jupiter.api.Test; import tech.tablesaw.TestDataUtil; import tech.tablesaw.columns.strings.StringColumnFormatter; +import tech.tablesaw.columns.strings.StringParser; import tech.tablesaw.io.csv.CsvReadOptions; import tech.tablesaw.selection.Selection; @@ -109,6 +111,15 @@ public void joinTablesWithStringColumnsSuccess() throws IOException { assertEquals(3, joined.columnCount()); } + @Test + void appendAsterisk() { + final TextColumn sc = TextColumn.create("sc"); + StringParser parser = new StringParser(ColumnType.TEXT); + parser.setMissingValueStrings(new ArrayList<>()); + sc.appendCell("*", parser); + assertEquals(0, sc.countMissing()); + } + @Test public void lead() { TextColumn c1 = column.lead(1); diff --git a/core/src/test/java/tech/tablesaw/io/DataFrameReaderTest.java b/core/src/test/java/tech/tablesaw/io/DataFrameReaderTest.java index 1da7e46e3..374b11af2 100644 --- a/core/src/test/java/tech/tablesaw/io/DataFrameReaderTest.java +++ b/core/src/test/java/tech/tablesaw/io/DataFrameReaderTest.java @@ -26,7 +26,8 @@ void setUp() { } private URL mockUrlHelper(String url, List content) throws Exception { - Path path = mockFileHelper(url, content); + // Remove http:// part to be able to save to a local filesystem file + Path path = mockFileHelper(url.replace("http://", ""), content); return path.toUri().toURL(); } @@ -40,7 +41,7 @@ private Path mockFileHelper(String path, List content) throws IOExceptio @Test public void csv() throws IOException { - Path path = mockFileHelper("/data/file.csv", ImmutableList.of("region", "canada", "us")); + Path path = mockFileHelper("data/file.csv", ImmutableList.of("region", "canada", "us")); Table expected = Table.create(StringColumn.create("region", new String[] {"canada", "us"})); Table actual = Table.read().csv(Files.newInputStream(path)); assertEquals(expected.columnNames(), actual.columnNames()); diff --git a/core/src/test/java/tech/tablesaw/io/csv/CsvWriterTest.java b/core/src/test/java/tech/tablesaw/io/csv/CsvWriterTest.java index 509a44aa5..0792e02c5 100644 --- a/core/src/test/java/tech/tablesaw/io/csv/CsvWriterTest.java +++ b/core/src/test/java/tech/tablesaw/io/csv/CsvWriterTest.java @@ -6,18 +6,23 @@ import com.google.common.collect.ImmutableMap; import java.io.IOException; import java.io.StringWriter; +import java.text.DecimalFormat; +import java.time.Instant; +import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Map; import org.junit.jupiter.api.Test; -import tech.tablesaw.api.DateTimeColumn; -import tech.tablesaw.api.StringColumn; -import tech.tablesaw.api.Table; +import tech.tablesaw.api.*; +import tech.tablesaw.columns.booleans.BooleanFormatter; +import tech.tablesaw.columns.instant.InstantColumnFormatter; +import tech.tablesaw.columns.numbers.NumberColumnFormatter; +import tech.tablesaw.columns.strings.StringColumnFormatter; public class CsvWriterTest { @Test - public void toWriterWithExtension() throws IOException { + void toWriterWithExtension() throws IOException { StringColumn colA = StringColumn.create("colA", ImmutableList.of("a", "b")); StringColumn colB = StringColumn.create("colB", ImmutableList.of("1", "2")); Table table = Table.create("testTable", colA, colB); @@ -27,7 +32,7 @@ public void toWriterWithExtension() throws IOException { } @Test - public void quoteAll() throws IOException { + void quoteAll() throws IOException { StringColumn colA = StringColumn.create("colA", ImmutableList.of("a", "b")); StringColumn colB = StringColumn.create("colB", ImmutableList.of("1", "2")); Table table = Table.create("testTable", colA, colB); @@ -39,7 +44,7 @@ public void quoteAll() throws IOException { } @Test - public void dateFormatter() throws IOException { + void dateFormatter() throws IOException { Table table = Table.read().csv("../data/bush.csv").rows(1); StringWriter writer = new StringWriter(); table @@ -54,7 +59,156 @@ public void dateFormatter() throws IOException { } @Test - public void dateTimeFormatter() throws IOException { + void printFormatter_double() throws IOException { + Table table = Table.create("", DoubleColumn.create("percents")); + table.doubleColumn("percents").setPrintFormatter(NumberColumnFormatter.percent(2)); + table.doubleColumn("percents").append(0.323).append(0.1192).append(1.0); + StringWriter writer = new StringWriter(); + table.write().usingOptions(CsvWriteOptions.builder(writer).usePrintFormatters(true).build()); + assertEquals( + "percents\n" + "32.30%\n" + "11.92%\n" + "100.00%\n", + writer.toString().replaceAll("\\r\\n", "\n")); + } + + @Test + void printFormatter_date() throws IOException { + Table table = Table.create("", DateColumn.create("dates")); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-dd-MMM"); + table.dateColumn("dates").setPrintFormatter(formatter, "WHAT?"); + table + .dateColumn("dates") + .append(LocalDate.of(2021, 11, 3)) + .appendObj(null) + .append(LocalDate.of(2021, 3, 11)); + StringWriter writer = new StringWriter(); + table.write().usingOptions(CsvWriteOptions.builder(writer).usePrintFormatters(true).build()); + assertEquals( + "dates\n" + "2021-03-Nov\n" + "WHAT?\n" + "2021-11-Mar\n", + writer.toString().replaceAll("\\r\\n", "\n")); + } + + @Test + void printFormatter_int() throws IOException { + Table table = Table.create("", IntColumn.create("ints")); + table.intColumn("ints").setPrintFormatter(NumberColumnFormatter.intsWithGrouping()); + table.intColumn("ints").append(102_123).append(2).append(-1_232_132); + StringWriter writer = new StringWriter(); + table.write().usingOptions(CsvWriteOptions.builder(writer).usePrintFormatters(true).build()); + assertEquals( + "ints\n" + "\"102,123\"\n" + "2\n" + "\"-1,232,132\"\n", + writer.toString().replaceAll("\\r\\n", "\n")); + } + + @Test + void printFormatter_float() throws IOException { + Table table = Table.create("", FloatColumn.create("floats")); + table.floatColumn("floats").setPrintFormatter(NumberColumnFormatter.fixedWithGrouping(2)); + table.floatColumn("floats").append(032.3f).append(0.1192f).appendObj(null).append(1001.0f); + StringWriter writer = new StringWriter(); + table.write().usingOptions(CsvWriteOptions.builder(writer).usePrintFormatters(true).build()); + assertEquals( + "floats\n" + "32.30\n" + "0.12\n" + "\n" + "\"1,001.00\"\n", + writer.toString().replaceAll("\\r\\n", "\n")); + } + + @Test + void printFormatter_datetime() throws IOException { + Table table = Table.create("", DateTimeColumn.create("dates")); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM d, yyyy - hh:mm"); + table.dateTimeColumn("dates").setPrintFormatter(formatter, "WHAT?"); + table.dateTimeColumn("dates").append(LocalDateTime.of(2011, 1, 1, 4, 30)); + StringWriter writer = new StringWriter(); + table.write().usingOptions(CsvWriteOptions.builder(writer).usePrintFormatters(true).build()); + assertEquals( + "dates\n" + "\"Jan 1, 2011 - 04:30\"\n", writer.toString().replaceAll("\\r\\n", "\n")); + } + + @Test + void printFormatter_boolean() throws IOException { + Table table = Table.create("", BooleanColumn.create("bools")); + BooleanFormatter formatter = new BooleanFormatter("Yes", "No", "IDK"); + table.booleanColumn("bools").setPrintFormatter(formatter); + table.booleanColumn("bools").append(true).append(false).appendMissing(); + StringWriter writer = new StringWriter(); + table.write().usingOptions(CsvWriteOptions.builder(writer).usePrintFormatters(true).build()); + assertEquals( + "bools\n" + "Yes\n" + "No\n" + "IDK\n", writer.toString().replaceAll("\\r\\n", "\n")); + } + + @Test + void printFormatter_string() throws IOException { + Table table = Table.create("", StringColumn.create("strings")); + StringColumnFormatter formatter = new StringColumnFormatter(s -> "[" + s + "]", "N/A"); + table.stringColumn("strings").setPrintFormatter(formatter); + table.stringColumn("strings").append("hey").append("you").appendMissing(); + StringWriter writer = new StringWriter(); + table.write().usingOptions(CsvWriteOptions.builder(writer).usePrintFormatters(true).build()); + assertEquals( + "strings\n" + "[hey]\n" + "[you]\n" + "N/A\n", + writer.toString().replaceAll("\\r\\n", "\n")); + } + + @Test + void printFormatter_text() throws IOException { + Table table = Table.create("", TextColumn.create("strings")); + StringColumnFormatter formatter = new StringColumnFormatter(s -> "[" + s + "]", "N/A"); + table.textColumn("strings").setPrintFormatter(formatter); + table.textColumn("strings").append("hey").append("you").appendMissing(); + StringWriter writer = new StringWriter(); + table.write().usingOptions(CsvWriteOptions.builder(writer).usePrintFormatters(true).build()); + assertEquals( + "strings\n" + "[hey]\n" + "[you]\n" + "N/A\n", + writer.toString().replaceAll("\\r\\n", "\n")); + } + + @Test + void printFormatter_short() throws IOException { + Table table = Table.create("", ShortColumn.create("ints")); + table.shortColumn("ints").setPrintFormatter(NumberColumnFormatter.intsWithGrouping()); + table.shortColumn("ints").append((short) 102).append((short) 12_132).append((short) -1_234); + StringWriter writer = new StringWriter(); + table.write().usingOptions(CsvWriteOptions.builder(writer).usePrintFormatters(true).build()); + assertEquals( + "ints\n" + "102\n" + "\"12,132\"\n" + "\"-1,234\"\n", + writer.toString().replaceAll("\\r\\n", "\n")); + } + + @Test + void printFormatter_instant() throws IOException { + Table table = Table.create("", InstantColumn.create("dates")); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM d, yyyy - hh:mm"); + table.instantColumn("dates").setPrintFormatter(new InstantColumnFormatter(formatter, "WHAT?")); + table.instantColumn("dates").append(Instant.parse("2007-12-03T10:15:30.00Z")).appendMissing(); + StringWriter writer = new StringWriter(); + table.write().usingOptions(CsvWriteOptions.builder(writer).usePrintFormatters(true).build()); + assertEquals( + "dates\n" + "\"Dec 3, 2007 - 10:15\"\n" + "WHAT?\n", + writer.toString().replaceAll("\\r\\n", "\n")); + } + + /** Test preventing scientific notation */ + @Test + void printFormatter_scientific_notation() throws IOException { + Table table = Table.create("", DoubleColumn.create("doubles")); + DecimalFormat df = new DecimalFormat("0.#"); + df.setMaximumFractionDigits(11); + NumberColumnFormatter formatter = new NumberColumnFormatter(df); + table.doubleColumn("doubles").setPrintFormatter(formatter); + table + .doubleColumn("doubles") + .append(32.32342489123) + .append(0.1192342224) + .appendObj(null) + .append(1001.0); + StringWriter writer = new StringWriter(); + table.write().usingOptions(CsvWriteOptions.builder(writer).usePrintFormatters(true).build()); + assertEquals( + "doubles\n" + "32.32342489123\n" + "0.1192342224\n" + "\n" + "1001\n", + writer.toString().replaceAll("\\r\\n", "\n")); + } + + @Test + void dateTimeFormatter() throws IOException { Table table = Table.create("test", DateTimeColumn.create("dt")); table.dateTimeColumn(0).append(LocalDateTime.of(2011, 1, 1, 4, 30)); StringWriter writer = new StringWriter(); diff --git a/core/src/test/java/tech/tablesaw/io/csv/UnicodeBomHandlingTest.java b/core/src/test/java/tech/tablesaw/io/csv/UnicodeBomHandlingTest.java index 8db30be4e..05703583b 100644 --- a/core/src/test/java/tech/tablesaw/io/csv/UnicodeBomHandlingTest.java +++ b/core/src/test/java/tech/tablesaw/io/csv/UnicodeBomHandlingTest.java @@ -6,6 +6,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import tech.tablesaw.api.Table; @@ -22,6 +23,7 @@ public class UnicodeBomHandlingTest { } @Test + @Disabled public void javaBehaviour() throws IOException { Table t = diff --git a/core/src/test/java/tech/tablesaw/joining/DataFrameJoinerTest.java b/core/src/test/java/tech/tablesaw/joining/DataFrameJoinerTest.java index 0d7f678ff..90d74ffe7 100644 --- a/core/src/test/java/tech/tablesaw/joining/DataFrameJoinerTest.java +++ b/core/src/test/java/tech/tablesaw/joining/DataFrameJoinerTest.java @@ -1,6 +1,7 @@ package tech.tablesaw.joining; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import com.google.common.base.Joiner; import java.util.Arrays; @@ -246,6 +247,37 @@ private static Table createINSTRUCTOR() { "Instructor"); } + private static Table createGOODS1() { + return Table.read() + .csv( + Joiner.on(System.lineSeparator()) + .join( + "ID,Name,Price", + "1,Chips,10", + "2,Coca-cola,20", + "3,Bread,30", + "4,Toothbrush,10", + "5,Soap,20", + "6,Towel,30"), + "Goods1"); + } + + private static Table createGOODS2() { + return Table.read() + .csv( + Joiner.on(System.lineSeparator()) + .join("ID,Name,Price", "1,Chips,11", "2,Bread,29", "3,Soap,21", "4,Towel,33"), + "Goods2"); + } + + private static Table createGOODS3() { + return Table.read() + .csv( + Joiner.on(System.lineSeparator()) + .join("ID,Name,Price", "1,Chips,9", "2,Coca-cola,22", "3,Bread,29"), + "Goods3"); + } + private static Table createDEPTHEAD() { return Table.read() .csv( @@ -570,9 +602,16 @@ public void leftOuterJoinWithDoubles3() { public void leftOuterJoinWithDoubles4() { Table joined = DOUBLE_INDEXED_DOGS.joinOn("ID").leftOuter(DOUBLE_INDEXED_PEOPLE, DOUBLE_INDEXED_CATS); - assertEquals(3, joined.columnCount()); - assertEquals(4, joined.rowCount()); + assertTrue( + joined.columnNames().containsAll(Arrays.asList("ID", "Dog Name", "Name", "Cat Name"))); assertEquals(4, joined.column("ID").size()); + assertEquals(4, joined.column("Dog Name").size()); + assertEquals(0, joined.column("Dog Name").countMissing()); + assertEquals(4, joined.column("Name").size()); + assertEquals(1, joined.column("Name").countMissing()); + assertEquals(4, joined.column("Cat Name").size()); + assertEquals(3, joined.column("Cat Name").countMissing()); + assertEquals(4, joined.rowCount()); } @Test @@ -843,6 +882,26 @@ public void leftJoinStudentInstructorOnStateAge() { assertEquals(10, joined.column("Age").size()); } + @Test + public void leftJoinStoreWithMultiTables() { + Table table1 = createGOODS1(); + Table table2 = createGOODS2(); + Table table3 = createGOODS3(); + Table joined = table1.joinOn("Name").leftOuter(true, table2, table3); + assertEquals(7, joined.columnCount()); + assertTrue( + joined + .columnNames() + .containsAll( + Arrays.asList("ID", "Name", "Price", "T2.ID", "T2.Price", "T3.ID", "T3.Price"))); + assertEquals(6, joined.rowCount()); + assertEquals(6, joined.column("Price").size()); + assertEquals(6, joined.column("T2.ID").size()); + assertEquals(2, joined.column("T2.ID").countMissing()); + assertEquals(6, joined.column("T3.ID").size()); + assertEquals(3, joined.column("T3.ID").countMissing()); + } + @Test public void innerJoinHouseBoatOnBedroomsOwner() { Table table1 = createHOUSE(); diff --git a/core/src/test/java/tech/tablesaw/table/TableSummaryTest.java b/core/src/test/java/tech/tablesaw/table/TableSummaryTest.java index 2da8f36d8..cfff68445 100644 --- a/core/src/test/java/tech/tablesaw/table/TableSummaryTest.java +++ b/core/src/test/java/tech/tablesaw/table/TableSummaryTest.java @@ -13,6 +13,8 @@ public class TableSummaryTest { + private static final String LINE_END = System.lineSeparator(); + @Test public void emptyTable() { Table testTable = Table.create("Data"); @@ -29,16 +31,26 @@ public void summaryTestTwoDoubleColumnsStatistics() { DoubleColumn.create("value2", 2.0, 2.1, 2.2)); Table result = testTable.summary(); assertEquals( - " Data \n" - + " Summary | value1 | value2 |\n" - + "-------------------------------------------------------------\n" - + " Count | 3 | 3 |\n" - + " sum | 3.3 | 6.3 |\n" - + " Mean | 1.1 | 2.1 |\n" - + " Min | 1 | 2 |\n" - + " Max | 1.2 | 2.2 |\n" - + " Range | 0.19999999999999996 | 0.20000000000000018 |\n" - + " Variance | 0.009999999999999995 | 0.01000000000000004 |\n" + " Data " + + LINE_END + + " Summary | value1 | value2 |" + + LINE_END + + "-------------------------------------------------------------" + + LINE_END + + " Count | 3 | 3 |" + + LINE_END + + " sum | 3.3 | 6.3 |" + + LINE_END + + " Mean | 1.1 | 2.1 |" + + LINE_END + + " Min | 1 | 2 |" + + LINE_END + + " Max | 1.2 | 2.2 |" + + LINE_END + + " Range | 0.19999999999999996 | 0.20000000000000018 |" + + LINE_END + + " Variance | 0.009999999999999995 | 0.01000000000000004 |" + + LINE_END + " Std. Dev | 0.09999999999999998 | 0.1000000000000002 |", result.print()); } @@ -58,24 +70,42 @@ public void summaryMixedTypes() { })); Table result = testTable.summary(); assertEquals( - " Data \n" - + " Summary | label | value1 | truthy | dates |\n" - + "---------------------------------------------------------------------------\n" - + " Count | 3 | 3 | | 3 |\n" - + " Unique | 2 | | | |\n" - + " Top | yellow | | | |\n" - + " Top Freq. | 2 | | | |\n" - + " sum | | 3.3 | | |\n" - + " Mean | | 1.1 | | |\n" - + " Min | | 1 | | |\n" - + " Max | | 1.2 | | |\n" - + " Range | | 0.19999999999999996 | | |\n" - + " Variance | | 0.009999999999999995 | | |\n" - + " Std. Dev | | 0.09999999999999998 | | |\n" - + " false | | | 1 | |\n" - + " true | | | 2 | |\n" - + " Missing | | | | 0 |\n" - + " Earliest | | | | 2001-01-01 |\n" + " Data " + + LINE_END + + " Summary | label | value1 | truthy | dates |" + + LINE_END + + "---------------------------------------------------------------------------" + + LINE_END + + " Count | 3 | 3 | | 3 |" + + LINE_END + + " Unique | 2 | | | |" + + LINE_END + + " Top | yellow | | | |" + + LINE_END + + " Top Freq. | 2 | | | |" + + LINE_END + + " sum | | 3.3 | | |" + + LINE_END + + " Mean | | 1.1 | | |" + + LINE_END + + " Min | | 1 | | |" + + LINE_END + + " Max | | 1.2 | | |" + + LINE_END + + " Range | | 0.19999999999999996 | | |" + + LINE_END + + " Variance | | 0.009999999999999995 | | |" + + LINE_END + + " Std. Dev | | 0.09999999999999998 | | |" + + LINE_END + + " false | | | 1 | |" + + LINE_END + + " true | | | 2 | |" + + LINE_END + + " Missing | | | | 0 |" + + LINE_END + + " Earliest | | | | 2001-01-01 |" + + LINE_END + " Latest | | | | 2002-01-01 |", result.print()); } diff --git a/html/src/test/java/tech/tablesaw/io/html/HtmlWriterTest.java b/html/src/test/java/tech/tablesaw/io/html/HtmlWriterTest.java index e4f584ccc..ea261fedb 100644 --- a/html/src/test/java/tech/tablesaw/io/html/HtmlWriterTest.java +++ b/html/src/test/java/tech/tablesaw/io/html/HtmlWriterTest.java @@ -29,7 +29,7 @@ public class HtmlWriterTest { - private static final String LINE_END = System.lineSeparator(); + private static final String LINE_END = "\n"; private double[] v1 = {1, 2, NaN}; private double[] v2 = {1, 2, NaN}; diff --git a/jsplot/src/test/java/tech/tablesaw/components/LayoutTest.java b/jsplot/src/test/java/tech/tablesaw/components/LayoutTest.java index 29a72bffa..a9ca6d496 100644 --- a/jsplot/src/test/java/tech/tablesaw/components/LayoutTest.java +++ b/jsplot/src/test/java/tech/tablesaw/components/LayoutTest.java @@ -11,6 +11,8 @@ public class LayoutTest { + private static final String LINE_END = System.lineSeparator(); + // @Test public void asJavascript() { @@ -55,58 +57,62 @@ public void testAutosize() { { Layout layout = Layout.builder().autosize(true).build(); assertEquals( - "var layout = {\n" - + // - " autosize: true,\n" - + // - "\n\n" - + // - "};\n", + "var layout = {" + + LINE_END + + " autosize: true," + + LINE_END + + LINE_END + + LINE_END + + "};" + + LINE_END, layout.asJavascript()); } { Layout layout = Layout.builder().autosize(true).width(800).build(); assertEquals( - "var layout = {\n" - + // - " width: 800,\n" - + // - " autosize: true,\n" - + // - "\n\n" - + // - "};\n", + "var layout = {" + + LINE_END + + " width: 800," + + LINE_END + + " autosize: true," + + LINE_END + + LINE_END + + LINE_END + + "};" + + LINE_END, layout.asJavascript()); } { Layout layout = Layout.builder().autosize(true).height(600).width(800).build(); assertEquals( - "var layout = {\n" - + // - " height: 600,\n" - + // - " width: 800,\n" - + // - " autosize: true,\n" - + // - "\n\n" - + // - "};\n", + "var layout = {" + + LINE_END + + " height: 600," + + LINE_END + + " width: 800," + + LINE_END + + " autosize: true," + + LINE_END + + LINE_END + + LINE_END + + "};" + + LINE_END, layout.asJavascript()); } { // see if 700x450 Layout layout = Layout.builder().autosize(false).height(600).build(); assertEquals( - "var layout = {\n" - + // - " height: 600,\n" - + // - " width: 700,\n" - + // - "\n\n" - + // - "};\n", + "var layout = {" + + LINE_END + + " height: 600," + + LINE_END + + " width: 700," + + LINE_END + + LINE_END + + LINE_END + + "};" + + LINE_END, layout.asJavascript()); } } diff --git a/jsplot/src/test/java/tech/tablesaw/plotly/components/FigureTest.java b/jsplot/src/test/java/tech/tablesaw/plotly/components/FigureTest.java index e9ad6c48e..8fced2023 100644 --- a/jsplot/src/test/java/tech/tablesaw/plotly/components/FigureTest.java +++ b/jsplot/src/test/java/tech/tablesaw/plotly/components/FigureTest.java @@ -8,6 +8,7 @@ class FigureTest { + private static final String LINE_END = System.lineSeparator(); private String divName = "target"; private double[] x = {1, 2, 3, 4, 5}; @@ -20,22 +21,38 @@ void asJavascript() { Figure figure = new Figure(trace); assertEquals( - " \n", + " " + + LINE_END, figure.asJavascript(divName)); } @@ -62,46 +79,86 @@ void asJavascript2() { Figure figure = new Figure(layout, trace); assertEquals( - " \n", + " " + + LINE_END, figure.asJavascript(divName)); } diff --git a/pom.xml b/pom.xml index aa80f382e..7523fc201 100644 --- a/pom.xml +++ b/pom.xml @@ -238,12 +238,11 @@ org.apache.maven.plugins maven-surefire-plugin - -Duser.language=en-US -Duser.region=US false - ${argLine} -Xms256m -Xmx2048m + ${argLine} -Xms256m -Xmx2048m -Duser.language=en-US -Duser.region=US 1 random