From efe80a534c95bdeb70b6f931452b6df42d13351e Mon Sep 17 00:00:00 2001
From: Rob Bygrave
Date: Thu, 25 Aug 2022 22:09:38 +1200
Subject: [PATCH] Extract CsvReader - remove built in date, time, dateTime
parsing - use StringParser instead
Just always use our own StringParser lambda function instead for parsing date, time and dateTime types.
---
.../java/io/ebean/text/StringFormatter.java | 1 +
.../main/java/io/ebean/text/StringParser.java | 1 +
ebean-csv-reader/pom.xml | 2 +
.../java/io/ebean/csv/reader/CsvReader.java | 144 +-----------------
.../io/ebean/csv/reader/CsvReaderTest.java | 12 +-
5 files changed, 17 insertions(+), 143 deletions(-)
diff --git a/ebean-api/src/main/java/io/ebean/text/StringFormatter.java b/ebean-api/src/main/java/io/ebean/text/StringFormatter.java
index a7aa2631b..613e97129 100644
--- a/ebean-api/src/main/java/io/ebean/text/StringFormatter.java
+++ b/ebean-api/src/main/java/io/ebean/text/StringFormatter.java
@@ -6,6 +6,7 @@ package io.ebean.text;
* Basic interface to support CSV, JSON and XML processing.
*
*/
+@FunctionalInterface
public interface StringFormatter {
/**
diff --git a/ebean-api/src/main/java/io/ebean/text/StringParser.java b/ebean-api/src/main/java/io/ebean/text/StringParser.java
index f76421944..4fe51abe8 100644
--- a/ebean-api/src/main/java/io/ebean/text/StringParser.java
+++ b/ebean-api/src/main/java/io/ebean/text/StringParser.java
@@ -5,6 +5,7 @@ package io.ebean.text;
*
* Basic interface to support CSV, JSON and XML processing.
*/
+@FunctionalInterface
public interface StringParser {
/**
diff --git a/ebean-csv-reader/pom.xml b/ebean-csv-reader/pom.xml
index 147b10ea9..d9f69a67c 100644
--- a/ebean-csv-reader/pom.xml
+++ b/ebean-csv-reader/pom.xml
@@ -23,12 +23,14 @@
io.ebean
ebean-api
13.8.2-SNAPSHOT
+ provided
io.ebean
ebean-core
13.8.2-SNAPSHOT
+ test
diff --git a/ebean-csv-reader/src/main/java/io/ebean/csv/reader/CsvReader.java b/ebean-csv-reader/src/main/java/io/ebean/csv/reader/CsvReader.java
index 1e40db770..98193e197 100644
--- a/ebean-csv-reader/src/main/java/io/ebean/csv/reader/CsvReader.java
+++ b/ebean-csv-reader/src/main/java/io/ebean/csv/reader/CsvReader.java
@@ -8,23 +8,15 @@ import io.ebean.text.StringParser;
import io.ebean.text.TextException;
import java.io.Reader;
-import java.sql.Types;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Date;
import java.util.List;
-import java.util.Locale;
/**
* Implementation of the CsvReader
*/
public class CsvReader {
- private static final TimeStringParser TIME_PARSER = new TimeStringParser();
-
private final Database server;
private final BeanType descriptor;
@@ -37,11 +29,6 @@ public class CsvReader {
private int logInfoFrequency = 1000;
- private String defaultTimeFormat = "HH:mm:ss";
- private String defaultDateFormat = "yyyy-MM-dd";
- private String defaultTimestampFormat = "yyyy-MM-dd hh:mm:ss.fffffffff";
- private Locale defaultLocale = Locale.getDefault();
-
/**
* The batch size used for JDBC statement batching.
*/
@@ -54,102 +41,37 @@ public class CsvReader {
this.descriptor = server.pluginApi().beanType(type);
}
- ////@Override
- public void setDefaultLocale(Locale defaultLocale) {
- this.defaultLocale = defaultLocale;
- }
-
- ////@Override
- public void setDefaultTimeFormat(String defaultTimeFormat) {
- this.defaultTimeFormat = defaultTimeFormat;
- }
-
- ////@Override
- public void setDefaultDateFormat(String defaultDateFormat) {
- this.defaultDateFormat = defaultDateFormat;
- }
-
- ////@Override
- public void setDefaultTimestampFormat(String defaultTimestampFormat) {
- this.defaultTimestampFormat = defaultTimestampFormat;
- }
-
- ////@Override
public void setPersistBatchSize(int persistBatchSize) {
this.persistBatchSize = persistBatchSize;
}
- ////@Override
public void setIgnoreHeader() {
setHasHeader(true, false);
}
- ////@Override
public void setAddPropertiesFromHeader() {
setHasHeader(true, true);
}
- //@Override
public void setHasHeader(boolean hasHeader, boolean addPropertiesFromHeader) {
this.hasHeader = hasHeader;
this.addPropertiesFromHeader = addPropertiesFromHeader;
}
- //@Override
public void setLogInfoFrequency(int logInfoFrequency) {
this.logInfoFrequency = logInfoFrequency;
}
- //@Override
public void addIgnore() {
columnList.add(ignoreColumn);
}
- //@Override
public void addProperty(String propertyName) {
addProperty(propertyName, null);
}
- //@Override
- public void addDateTime(String propertyName, String dateTimeFormat) {
- addDateTime(propertyName, dateTimeFormat, Locale.getDefault());
- }
- //@Override
- public void addDateTime(String propertyName, String dateTimeFormat, Locale locale) {
- ExpressionPath elProp = descriptor.expressionPath(propertyName);
- if (dateTimeFormat == null) {
- dateTimeFormat = getDefaultDateTimeFormat(elProp.jdbcType());
- }
-
- if (locale == null) {
- locale = defaultLocale;
- }
-
- SimpleDateFormat sdf = new SimpleDateFormat(dateTimeFormat, locale);
- DateTimeParser parser = new DateTimeParser(sdf, dateTimeFormat, elProp);
-
- CsvColumn column = new CsvColumn(elProp, parser);
- columnList.add(column);
- }
-
- private String getDefaultDateTimeFormat(int jdbcType) {
- switch (jdbcType) {
- case Types.TIME:
- return defaultTimeFormat;
- case Types.DATE:
- return defaultDateFormat;
- case Types.TIMESTAMP:
- return defaultTimestampFormat;
-
- default:
- throw new RuntimeException("Expected java.sql.Types TIME,DATE or TIMESTAMP but got [" + jdbcType + "]");
- }
- }
-
- //@Override
public void addProperty(String propertyName, StringParser parser) {
-
ExpressionPath elProp = descriptor.expressionPath(propertyName);
if (parser == null) {
parser = elProp.stringParser();
@@ -158,15 +80,12 @@ public class CsvReader {
columnList.add(column);
}
- //@Override
public void process(Reader reader) throws Exception {
DefaultCsvCallback callback = new DefaultCsvCallback<>(persistBatchSize, logInfoFrequency);
process(reader, callback);
}
- //@Override
public void process(Reader reader, CsvCallback callback) throws Exception {
-
if (reader == null) {
throw new NullPointerException("reader is null?");
}
@@ -224,43 +143,22 @@ public class CsvReader {
}
private void addPropertiesFromHeader(String[] line) {
- for (String aLine : line) {
- ExpressionPath elProp = descriptor.expressionPath(aLine);
+ for (String headerElement : line) {
+ ExpressionPath elProp = descriptor.expressionPath(headerElement);
if (elProp == null) {
- throw new TextException("Property [" + aLine + "] not found");
- }
-
- if (Types.TIME == elProp.jdbcType()) {
- addProperty(aLine, TIME_PARSER);
-
- } else if (isDateTimeType(elProp.jdbcType())) {
- addDateTime(aLine, null, null);
-
-// } else if (elProp.isAssocProperty()) {
-// BeanPropertyAssocOne> assocOne = (BeanPropertyAssocOne>) elProp.beanProperty();
-// String idProp = assocOne.descriptor().idBinder().getIdProperty();
-// addProperty(aLine + "." + idProp);
- } else {
- addProperty(aLine);
+ throw new TextException("Property [" + headerElement + "] not found");
}
+ addProperty(headerElement);
}
}
- private boolean isDateTimeType(int t) {
- return t == Types.TIMESTAMP || t == Types.DATE || t == Types.TIME;
- }
-
- @SuppressWarnings("unchecked")
protected T buildBeanFromLineContent(int row, String[] line) {
-
try {
T bean = descriptor.createBean();
- EntityBean entityBean = (EntityBean)bean;
-
+ EntityBean entityBean = (EntityBean) bean;
for (int columnPos = 0; columnPos < line.length; columnPos++) {
convertAndSetColumn(columnPos, line[columnPos], entityBean);
}
-
return bean;
} catch (RuntimeException e) {
@@ -270,13 +168,10 @@ public class CsvReader {
}
protected void convertAndSetColumn(int columnPos, String strValue, EntityBean bean) {
-
strValue = strValue.trim();
-
if (strValue.isEmpty()) {
return;
}
-
CsvColumn c = columnList.get(columnPos);
c.convertAndSet(strValue, bean);
}
@@ -309,7 +204,6 @@ public class CsvReader {
* Convert the string to the appropriate value and set it to the bean.
*/
public void convertAndSet(String strValue, EntityBean bean) {
-
if (parser != null && path != null) {
Object value = parser.parse(strValue);
path.pathSet(bean, value);
@@ -317,32 +211,4 @@ public class CsvReader {
}
}
- /**
- * A StringParser for converting custom date/time/datetime strings into
- * appropriate java types (Date, Calendar, SQL Date, Time, Timestamp, JODA
- * etc).
- */
- private static class DateTimeParser implements StringParser {
-
- private final DateFormat dateFormat;
- private final ExpressionPath path;
- private final String format;
-
- DateTimeParser(DateFormat dateFormat, String format, ExpressionPath path) {
- this.dateFormat = dateFormat;
- this.path = path;
- this.format = format;
- }
-
- //@Override
- public Object parse(String value) {
- try {
- Date dt = dateFormat.parse(value);
- return path.parseDateTime(dt.getTime());
- } catch (ParseException e) {
- throw new TextException("Error parsing [{}] using format[" + format + "]", value, e);
- }
- }
-
- }
}
diff --git a/ebean-csv-reader/src/test/java/io/ebean/csv/reader/CsvReaderTest.java b/ebean-csv-reader/src/test/java/io/ebean/csv/reader/CsvReaderTest.java
index 642f453c0..8a871a62d 100644
--- a/ebean-csv-reader/src/test/java/io/ebean/csv/reader/CsvReaderTest.java
+++ b/ebean-csv-reader/src/test/java/io/ebean/csv/reader/CsvReaderTest.java
@@ -9,10 +9,13 @@ import org.junit.jupiter.api.Test;
import java.io.Reader;
import java.net.URL;
-import java.util.Locale;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
class CsvReaderTest {
+ final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy");
+
@Test
void test() throws Exception {
@@ -29,15 +32,16 @@ class CsvReaderTest {
Database database = DB.getDefault();
CsvReader csvReader = new CsvReader<>(database, Customer.class);
- //CsvReader csvReader = DB.getDefault().createCsvReader(Customer.class);
csvReader.setPersistBatchSize(2);
csvReader.addIgnore();
- // csvReader.addProperty("id");
csvReader.addProperty("status");
csvReader.addProperty("name");
- csvReader.addDateTime("anniversary", "dd-MMM-yyyy", Locale.ENGLISH);
+
+ // supplier a StringParser for custom date, time, dateTime formats
+ csvReader.addProperty("anniversary", (String content) -> LocalDate.parse(content, dateFormatter));
+ // OLD WAY: csvReader.addDateTime("anniversary", "dd-MMM-yyyy", Locale.ENGLISH);
csvReader.addProperty("billingAddress.line1");
csvReader.addProperty("billingAddress.city");
csvReader.addProperty("billingAddress.country.code");