Skip to content

Commit

Permalink
Merge 82a6091 into 853ab5a
Browse files Browse the repository at this point in the history
  • Loading branch information
NiklasMehner committed Nov 29, 2018
2 parents 853ab5a + 82a6091 commit 39ec663
Show file tree
Hide file tree
Showing 6 changed files with 271 additions and 250 deletions.
4 changes: 2 additions & 2 deletions src/main/java/com/poiji/bind/mapping/HSSFUnmarshaller.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ abstract class HSSFUnmarshaller implements Unmarshaller {

private final DataFormatter dataFormatter;
protected final PoijiOptions options;
private final Casting casting;
private final Casting casting;
private Map<String, Integer> titles;

HSSFUnmarshaller(PoijiOptions options) {
this.options = options;
dataFormatter = new DataFormatter();
titles = new HashMap<>();
casting = Casting.getInstance();
casting = options.getCasting();
}

@Override
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/com/poiji/bind/mapping/PoijiHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ final class PoijiHandler<T> implements SheetContentsHandler {
private Class<T> type;
private PoijiOptions options;

private final Casting casting;
private final Casting casting;
private Map<String, Integer> titles;
// New maps used to speed up computing and handle inner objects
private Map<String, Object> fieldInstances;
Expand All @@ -47,7 +47,7 @@ final class PoijiHandler<T> implements SheetContentsHandler {
this.options = options;
this.consumer = consumer;

casting = Casting.getInstance();
casting = options.getCasting();
titles = new HashMap<String, Integer>();
columnToField = new HashMap<>();
columnToSuperClassField = new HashMap<>();
Expand Down Expand Up @@ -197,7 +197,7 @@ public void startRow(int rowNum) {
public void endRow(int rowNum) {

if (internalCount != rowNum)
return;
return;

if (rowNum + 1 > options.skip()) {
consumer.accept(instance);
Expand Down
33 changes: 28 additions & 5 deletions src/main/java/com/poiji/option/PoijiOptions.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package com.poiji.option;

import com.poiji.exception.PoijiException;

import com.poiji.util.Casting;
import com.poiji.util.DefaultCasting;
import java.time.format.DateTimeFormatter;

import static com.poiji.util.PoijiConstants.DEFAULT_DATE_PATTERN;
Expand All @@ -22,6 +23,7 @@ public final class PoijiOptions {
private boolean ignoreHiddenSheets;
private boolean preferNullOverDefault;
private DateTimeFormatter dateTimeFormatter;
private Casting casting = new DefaultCasting();
private int headerStart;

private PoijiOptions() {
Expand Down Expand Up @@ -96,6 +98,15 @@ public PoijiOptions setTrimCellValue(boolean trimCellValue) {
return this;
}

public PoijiOptions setCasting(Casting casting) {
this.casting = casting;
return this;
}

public Casting getCasting() {
return casting;
}

private PoijiOptions setSheetIndex(int sheetIndex) {
this.sheetIndex = sheetIndex;
return this;
Expand Down Expand Up @@ -143,6 +154,7 @@ public static class PoijiOptionsBuilder {
private boolean preferNullOverDefault;
private String datePattern = DEFAULT_DATE_PATTERN;
private DateTimeFormatter dateTimeFormatter = DEFAULT_DATE_TIME_FORMATTER;
private Casting casting = new DefaultCasting();
private int headerStart = 0;
private int skip = 0;

Expand All @@ -165,11 +177,11 @@ public static PoijiOptionsBuilder settings(int skip) {
}
return new PoijiOptionsBuilder(skip);
}

public static PoijiOptionsBuilder settings() {
return new PoijiOptionsBuilder();
}

/**
* set a date time formatter, default date time formatter is "dd/M/yyyy"
* for java.time.LocalDate
Expand Down Expand Up @@ -218,7 +230,8 @@ public PoijiOptions build() {
.setTrimCellValue(trimCellValue)
.setDateRegex(dateRegex)
.setDateLenient(dateLenient)
.setHeaderStart(headerStart);
.setHeaderStart(headerStart)
.setCasting(casting);
}

/**
Expand Down Expand Up @@ -308,6 +321,17 @@ public PoijiOptionsBuilder dateLenient(boolean dateLenient) {
return this;
}

/**
* Use a custom casting implementation
*
* @param casting custom casting implementation
* @return this
*/
public PoijiOptionsBuilder withCasting(Casting casting) {
this.casting = casting;
return this;
}

/**
* This is to set the row which the unmarshall will
* use to start reading header titles, incase the
Expand All @@ -323,7 +347,6 @@ public PoijiOptionsBuilder headerStart(int headerStart) {
this.headerStart = headerStart;
return this;
}

}

}
239 changes: 2 additions & 237 deletions src/main/java/com/poiji/util/Casting.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,241 +2,6 @@

import com.poiji.option.PoijiOptions;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeParseException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;

/**
* Created by hakan on 22/01/2017.
*/
public final class Casting {

private static final Casting instance = new Casting();

public static Casting getInstance() {
return instance;
}

private Casting() {
}

private int primitiveIntegerValue(String value) {
try {
return new Integer(value);
} catch (NumberFormatException nfe) {
return 0;
}
}

private Integer integerValue(String value, PoijiOptions options) {
try {
return new Integer(value);
} catch (NumberFormatException nfe) {
if (Boolean.TRUE.equals(options.preferNullOverDefault())) {
return null;
}
return 0;
}
}

private long primitiveLongValue(String value) {
try {
return new Long(value);
} catch (NumberFormatException nfe) {
return 0L;
}
}

private Long longValue(String value, PoijiOptions options) {
try {
return new Long(value);
} catch (NumberFormatException nfe) {
if (Boolean.TRUE.equals(options.preferNullOverDefault())) {
return null;
}
return 0L;
}
}

private double primitiveDoubleValue(String value) {
try {
return new Double(value);
} catch (NumberFormatException nfe) {
return 0d;
}
}

private Double doubleValue(String value, PoijiOptions options) {
try {
return new Double(value);
} catch (NumberFormatException nfe) {
if (Boolean.TRUE.equals(options.preferNullOverDefault())) {
return null;
}
return 0d;
}
}

private float primitiveFloatValue(String value) {
try {
return new Float(value);
} catch (NumberFormatException nfe) {
return 0f;
}
}

private Float floatValue(String value, PoijiOptions options) {
try {
return new Float(value);
} catch (NumberFormatException nfe) {
if (Boolean.TRUE.equals(options.preferNullOverDefault())) {
return null;
}
return 0f;
}
}

private Date defaultDate(PoijiOptions options) {
if (Boolean.TRUE.equals(options.preferNullOverDefault())) {
return null;
}
Calendar calendar = Calendar.getInstance();
return calendar.getTime();
}

private LocalDate defaultLocalDate(PoijiOptions options) {
if (Boolean.TRUE.equals(options.preferNullOverDefault())) {
return null;
}
return LocalDate.now();
}

private BigDecimal bigDecimalValue(String value, PoijiOptions options) {
try {
String clean = value != null ? value.replace(",", ".") : "";
return new BigDecimal(clean);
} catch (NumberFormatException nfe) {
if (Boolean.TRUE.equals(options.preferNullOverDefault())) {
return null;
}
return BigDecimal.ZERO;
}
}

private Date dateValue(String value, PoijiOptions options) {

//ISSUE #57
//if a date regex has been specified then it wont be null
//so then make sure the string matches the pattern
//if it doesn't, fall back to default
//else continue to turn string into java date

//the reason for this is sometime Java will manage to parse a string to a date object
//without any exceptions but since the string was not an exact match you get a very strange date
if (options.getDateRegex() != null && !value.matches(options.getDateRegex())) {
return defaultDate(options);
} else {
try {
final SimpleDateFormat sdf = new SimpleDateFormat(options.datePattern());
sdf.setLenient(options.getDateLenient());
return sdf.parse(value);
} catch (ParseException e) {
return defaultDate(options);
}
}
}

private LocalDate localDateValue(String value, PoijiOptions options) {

//ISSUE #57
//if a date regex has been specified then it wont be null
//so then make sure the string matches the pattern
//if it doesn't, fall back to default
//else continue to turn string into java date

//the reason for this is sometime java will manage to parse a string to a date object
//without any exceptions but since the string was not an exact match you get a very strange date
if (options.getDateRegex() != null && !value.matches(options.getDateRegex())) {
return defaultLocalDate(options);
} else {
try {
return LocalDate.parse(value, options.dateTimeFormatter());
} catch (DateTimeParseException e) {
return defaultLocalDate(options);
}
}
}

private Object enumValue(String value, Class type) {
return Arrays
.stream(type.getEnumConstants())
.filter(o -> ((Enum) o).name().equals(value))
.findFirst()
.orElse(null);
}

public Object castValue(Class<?> fieldType, String value, PoijiOptions options) {
Object o = null;

if (options.trimCellValue()) {
value = value.trim();
}

if (fieldType.getName().equals("int")) {
o = primitiveIntegerValue(value);

} else if (fieldType.getName().equals("java.lang.Integer")) {
o = integerValue(value, options);

} else if (fieldType.getName().equals("java.math.BigDecimal")) {
o = bigDecimalValue(value, options);

} else if (fieldType.getName().equals("long")) {
o = primitiveLongValue(value);

} else if (fieldType.getName().equals("java.lang.Long")) {
o = longValue(value, options);

} else if (fieldType.getName().equals("double")) {
o = primitiveDoubleValue(value);

} else if (fieldType.getName().equals("java.lang.Double")) {
o = doubleValue(value, options);

} else if (fieldType.getName().equals("float")) {
o = primitiveFloatValue(value);

} else if (fieldType.getName().equals("java.lang.Float")) {
o = floatValue(value, options);

} else if (fieldType.getName().equals("boolean") || fieldType.getName().equals("java.lang.Boolean")) {
o = Boolean.valueOf(value);

} else if (fieldType.getName().equals("java.util.Date")) {
o = dateValue(value, options);

} else if (fieldType.getName().equals("java.time.LocalDate")) {
o = localDateValue(value, options);

} else if (fieldType.isEnum()) {
o = enumValue(value, fieldType);

} else {
if (value.isEmpty()) {
if (Boolean.TRUE.equals(options.preferNullOverDefault())) {
o = null;
} else {
o = value;
}
} else {
o = value;
}
}
return o;
}
public interface Casting {
Object castValue(Class<?> fieldType, String value, PoijiOptions options);
}
Loading

0 comments on commit 39ec663

Please sign in to comment.