Repository: jtablesaw/tablesaw
Pull request #626 (2019-08-22 16:30:05)

fixes bug #623
but doesn't implement the enhancement.

Empty columns, and columns where all rows sampled have missing values, will get the default type, usually StringColumn or TextColumn, rather than LocalDateTime.

Thanks for contributing.

- [ ] Tick to sign-off your agreement to the [Developer Certificate of Origin (DCO) 1.1](https://developercertificate.org)

## Description

What was changed

## Testing

Did you add a unit test? Yes



Patch:
diff --git a/aggregate/pom.xml b/aggregate/pom.xml
index 319185b3..002585e9 100644
--- a/aggregate/pom.xml
+++ b/aggregate/pom.xml
@@ -29,6 +29,7 @@
           <argLine>${argLine} -Xms256m -Xmx2048m</argLine>
           <forkCount>1</forkCount>
           <runOrder>random</runOrder>
+          <printSummary>false</printSummary>
         </configuration>
       </plugin>
       <plugin>
diff --git a/core/pom.xml b/core/pom.xml
index 815f0a6a..64444fb9 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -96,6 +96,7 @@
                 <artifactId>maven-surefire-plugin</artifactId>
                 <configuration>
                     <argLine>-Duser.language=en-US -Duser.region=US</argLine>
+                    <printSummary>false</printSummary>
                 </configuration>
             </plugin>
         </plugins>
diff --git a/core/src/main/java/tech/tablesaw/api/Row.java b/core/src/main/java/tech/tablesaw/api/Row.java
index 0f6d61b8..1d5fc507 100644
--- a/core/src/main/java/tech/tablesaw/api/Row.java
+++ b/core/src/main/java/tech/tablesaw/api/Row.java
@@ -43,8 +43,8 @@ public class Row implements Iterator<Row> {
     }
 
     /**
-     * Will get thrown when column name is correct, but used the wrong method get/set is called. E.G. the user called
-     * .getLong on an IntColumn.
+     * Will get thrown when column name is correct, but used the wrong method get/set is called.
+     * E.G. the user called .getLong on an IntColumn.
      */
     private void throwWrongTypeError(String columnName) {
       for (int i = 0; i < columnNames.length; i++) {
diff --git a/core/src/main/java/tech/tablesaw/columns/AbstractColumnParser.java b/core/src/main/java/tech/tablesaw/columns/AbstractColumnParser.java
index dc8c72ca..07e5e152 100644
--- a/core/src/main/java/tech/tablesaw/columns/AbstractColumnParser.java
+++ b/core/src/main/java/tech/tablesaw/columns/AbstractColumnParser.java
@@ -33,7 +33,7 @@ public abstract class AbstractColumnParser<T> {
     return columnType;
   }
 
-  protected boolean isMissing(String s) {
+  public boolean isMissing(String s) {
     if (s == null) {
       return true;
     }
diff --git a/core/src/main/java/tech/tablesaw/io/ColumnTypeDetector.java b/core/src/main/java/tech/tablesaw/io/ColumnTypeDetector.java
index 4dfee66d..bf20be51 100644
--- a/core/src/main/java/tech/tablesaw/io/ColumnTypeDetector.java
+++ b/core/src/main/java/tech/tablesaw/io/ColumnTypeDetector.java
@@ -145,15 +145,25 @@ public class ColumnTypeDetector {
 
     CopyOnWriteArrayList<ColumnType> typeCandidates = new CopyOnWriteArrayList<>(typeArray);
 
+    boolean hasNonMissingValues = false;
+
     for (String s : valuesList) {
       for (AbstractColumnParser<?> parser : parsers) {
-        if (!parser.canParse(s)) {
-          typeCandidates.remove(parser.columnType());
-          parsers.remove(parser);
+        if (!parser.isMissing(s)) {
+          hasNonMissingValues = true;
+          if (!parser.canParse(s)) { // we can skip this test if we know the value is missing
+            typeCandidates.remove(parser.columnType());
+            parsers.remove(parser);
+          }
         }
       }
     }
-    return selectType(typeCandidates);
+    if (hasNonMissingValues) {
+      return selectType(typeCandidates);
+    } else {
+      // the last type in the typeArray is the default
+      return typeArray.get(typeArray.size() - 1);
+    }
   }
 
   /**
diff --git a/pom.xml b/pom.xml
index 95595679..9f217e98 100644
--- a/pom.xml
+++ b/pom.xml
@@ -85,6 +85,9 @@
                     <configuration>
                         <detectOfflineLinks>false</detectOfflineLinks>
                         <failOnError>false</failOnError>
+                        <quiet>true</quiet>
+                        <additionalOptions>-Xdoclint:none</additionalOptions>
+                        <additionalJOption>-Xdoclint:none</additionalJOption>
                     </configuration>
                     <executions>
                         <execution>


Test patch:
diff --git a/core/src/test/java/tech/tablesaw/io/ColumnTypeDetectorTest.java b/core/src/test/java/tech/tablesaw/io/ColumnTypeDetectorTest.java
new file mode 100644
index 00000000..fabff033
--- /dev/null
+++ b/core/src/test/java/tech/tablesaw/io/ColumnTypeDetectorTest.java
@@ -0,0 +1,54 @@
+package tech.tablesaw.io;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static tech.tablesaw.api.ColumnType.BOOLEAN;
+import static tech.tablesaw.api.ColumnType.DOUBLE;
+import static tech.tablesaw.api.ColumnType.FLOAT;
+import static tech.tablesaw.api.ColumnType.INTEGER;
+import static tech.tablesaw.api.ColumnType.LOCAL_DATE;
+import static tech.tablesaw.api.ColumnType.LOCAL_DATE_TIME;
+import static tech.tablesaw.api.ColumnType.LOCAL_TIME;
+import static tech.tablesaw.api.ColumnType.LONG;
+import static tech.tablesaw.api.ColumnType.SHORT;
+import static tech.tablesaw.api.ColumnType.STRING;
+import static tech.tablesaw.api.ColumnType.TEXT;
+
+import com.google.common.collect.Lists;
+import java.util.ArrayList;
+import org.junit.jupiter.api.Test;
+import tech.tablesaw.api.ColumnType;
+import tech.tablesaw.columns.dates.DateColumnType;
+import tech.tablesaw.columns.strings.StringColumnType;
+import tech.tablesaw.columns.strings.TextColumnType;
+
+class ColumnTypeDetectorTest {
+
+  @Test
+  void detectColumnTypes() {
+
+    String[][] val = {{"", "2010-05-03", "x"}, {"", "", ""}};
+
+    ArrayList<String[]> dates = Lists.newArrayList(val);
+
+    ColumnTypeDetector detector =
+        new ColumnTypeDetector(
+            Lists.newArrayList(
+                LOCAL_DATE_TIME,
+                LOCAL_TIME,
+                LOCAL_DATE,
+                BOOLEAN,
+                SHORT,
+                INTEGER,
+                LONG,
+                FLOAT,
+                DOUBLE,
+                STRING,
+                TEXT));
+
+    ColumnType[] types =
+        detector.detectColumnTypes(dates.iterator(), new ReadOptions.Builder().build());
+    assertEquals(TextColumnType.instance(), types[0]);
+    assertEquals(DateColumnType.instance(), types[1]);
+    assertEquals(StringColumnType.instance(), types[2]);
+  }
+}