Skip to content

Commit

Permalink
Merge pull request #81 from passedbylove/1.18.0
Browse files Browse the repository at this point in the history
1.18.0 a new feature, support stream-based cell mapping
  • Loading branch information
ozlerhakan committed Apr 26, 2019
2 parents edddc2f + 003a5c8 commit bad6055
Show file tree
Hide file tree
Showing 11 changed files with 455 additions and 17 deletions.
65 changes: 62 additions & 3 deletions src/main/java/com/poiji/bind/Poiji.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
package com.poiji.bind;

import com.poiji.bind.mapping.UnmarshallerHelper;
import com.poiji.exception.IllegalCastException;

import com.poiji.exception.InvalidExcelFileExtension;
import com.poiji.exception.PoijiExcelType;
import com.poiji.exception.IllegalCastException;
import com.poiji.exception.PoijiException;
import com.poiji.exception.InvalidExcelStreamException;
import com.poiji.exception.PoijiExcelType;
import com.poiji.option.PoijiOptions;
import com.poiji.option.PoijiOptions.PoijiOptionsBuilder;
import com.poiji.util.Files;
import org.apache.poi.hssf.OldExcelFormatException;
import org.apache.poi.poifs.filesystem.FileMagic;
import org.apache.poi.util.IOUtils;

import java.io.File;
import java.io.InputStream;
import java.io.File;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
Expand Down Expand Up @@ -192,6 +200,15 @@ public static synchronized <T> List<T> fromExcel(final InputStream inputStream,
return list;
}

public static synchronized <T> List<T> fromExcel(final InputStream inputStream,
final Class<T> type,
final PoijiOptions options){
final ArrayList<T> list = new ArrayList<>();
final Unmarshaller unmarshaller = deserializer(inputStream, options);
unmarshaller.unmarshal(type, list::add);
return list;
}

/**
* converts excel rows into a list of objects
*
Expand Down Expand Up @@ -233,6 +250,48 @@ private static Unmarshaller deserializer(final File file, final PoijiOptions opt
}
}

private static Unmarshaller deserializer(final InputStream inputStream, final PoijiOptions options){
try {
byte[] buff = new byte[4096];

int bytesRead = 0;

ByteArrayOutputStream bao = new ByteArrayOutputStream();

while((bytesRead = inputStream.read(buff)) != -1) {
bao.write(buff, 0, bytesRead);
}

byte[] data = bao.toByteArray();

ByteArrayInputStream byteStream = new ByteArrayInputStream(data);

final PoijiInputStream poijiInputStream = new PoijiInputStream<>(byteStream);

// Ensure that there is at least some data there
byte[] header8 = IOUtils.peekFirst8Bytes(byteStream);

if (FileMagic.valueOf(header8) == FileMagic.OLE2) {

return UnmarshallerHelper.HSSFInstance(poijiInputStream, options);

} else if (FileMagic.valueOf(header8) == FileMagic.OOXML) {

return UnmarshallerHelper.XSSFInstance(poijiInputStream, options);

}else if (FileMagic.valueOf(header8) == FileMagic.BIFF2
||FileMagic.valueOf(header8) == FileMagic.BIFF3
||FileMagic.valueOf(header8) == FileMagic.BIFF4
) {
throw new OldExcelFormatException("found old Excel file,not supported");
}
throw new InvalidExcelStreamException("invalid or unsupported Excel stream");
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}

@SuppressWarnings("unchecked")
private static Unmarshaller deserializer(final InputStream inputStream, PoijiExcelType excelType, final PoijiOptions options) {
final PoijiInputStream poijiInputStream = new PoijiInputStream<>(inputStream);
Expand Down
6 changes: 5 additions & 1 deletion src/main/java/com/poiji/bind/mapping/PoijiHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,11 @@ public void cell(String cellReference, String formattedValue, XSSFComment commen
int column = cellAddress.getColumn();

if (row == 0) {
titles.put(formattedValue, column);
if(options.trimTagName()) {
formattedValue = formattedValue.trim();
}

titles.put(formattedValue, column);
}

if (row + 1 <= options.skip()) {
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/poiji/exception/InvalidExcelStreamException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.poiji.exception;

/**
* Created by passedbylove on 2019-04-18.
*/
public final class InvalidExcelStreamException extends PoijiException {

public InvalidExcelStreamException(String message) {
super(message);
}

}
37 changes: 31 additions & 6 deletions src/main/java/com/poiji/option/PoijiOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ public final class PoijiOptions {
private int sheetIndex;
private String password;
private String dateRegex;
private String datePattern;
private String[] datePattern;
private boolean dateLenient;
private boolean trimTagName;
private boolean trimCellValue;
private boolean ignoreHiddenSheets;
private boolean preferNullOverDefault;
Expand All @@ -32,7 +33,7 @@ private PoijiOptions setSkip(int skip) {
return this;
}

private PoijiOptions setDatePattern(String datePattern) {
private PoijiOptions setDatePattern(String[] datePattern) {
this.datePattern = datePattern;
return this;
}
Expand All @@ -56,7 +57,7 @@ private PoijiOptions setPassword(String password) {
return this;
}

public String datePattern() {
public String[] datePattern() {
return datePattern;
}

Expand Down Expand Up @@ -86,7 +87,17 @@ private PoijiOptions setIgnoreHiddenSheets(boolean ignoreHiddenSheets) {
return this;
}

public boolean trimCellValue() {

public boolean trimTagName() {
return trimTagName;
}

public PoijiOptions setTrimTagName(boolean trimTagName) {
this.trimTagName = trimTagName;
return this;
}

public boolean trimCellValue() {
return trimCellValue;
}

Expand Down Expand Up @@ -129,10 +140,11 @@ public static class PoijiOptionsBuilder {
private String password;
private String dateRegex;
private boolean dateLenient;
private boolean trimTagName;
private boolean trimCellValue;
private boolean ignoreHiddenSheets;
private boolean preferNullOverDefault;
private String datePattern = DEFAULT_DATE_PATTERN;
private String[] datePattern = DEFAULT_DATE_PATTERN;
private DateTimeFormatter dateTimeFormatter = DEFAULT_DATE_TIME_FORMATTER;

private PoijiOptionsBuilder() {
Expand All @@ -151,6 +163,7 @@ public PoijiOptions build() {
.setDateTimeFormatter(dateTimeFormatter)
.setSheetIndex(sheetIndex)
.setIgnoreHiddenSheets(ignoreHiddenSheets)
.setTrimTagName(trimTagName)
.setTrimCellValue(trimCellValue)
.setDateRegex(dateRegex)
.setDateLenient(dateLenient);
Expand Down Expand Up @@ -179,7 +192,7 @@ public PoijiOptionsBuilder dateTimeFormatter(DateTimeFormatter dateTimeFormatter
* @param datePattern date time formatter
* @return this
*/
public PoijiOptionsBuilder datePattern(String datePattern) {
public PoijiOptionsBuilder datePattern(String ...datePattern) {
this.datePattern = datePattern;
return this;
}
Expand Down Expand Up @@ -254,7 +267,19 @@ public PoijiOptionsBuilder ignoreHiddenSheets(boolean ignoreHiddenSheets) {
return this;
}


/**
*
* Trim tag name
* @param trimTagName trim the tag name
* @return this
*/
public PoijiOptionsBuilder trimTagName(boolean trimTagName){
this.trimTagName = trimTagName;
return this;
}

/**Name
* Trim cell value
*
* @param trimCellValue trim the cell value before processing work book.
Expand Down
23 changes: 17 additions & 6 deletions src/main/java/com/poiji/util/Casting.java
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,24 @@ private Date dateValue(String value, PoijiOptions options) {
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);
String[] patterns = options.datePattern();
Date parsed = defaultDate(options);
for(String pattern:patterns) {
try {
final SimpleDateFormat sdf = new SimpleDateFormat(pattern);
//bug
if(patterns.length==1) {
sdf.setLenient(options.getDateLenient());
}else
{
sdf.setLenient(false);
}
return sdf.parse(value);
} catch (ParseException e) {
continue;
}
}
return parsed;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/poiji/util/PoijiConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/
public final class PoijiConstants {

public static final String DEFAULT_DATE_PATTERN = "dd/M/yyyy";
public static final String[] DEFAULT_DATE_PATTERN = {"dd/M/yyyy","yyyy-MM-dd","yyyy/MM/dd"};
public static final DateTimeFormatter DEFAULT_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("dd/M/yyyy");
public static final String XLS_EXTENSION = ".xls";
public static final String XLSX_EXTENSION = ".xlsx";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.poiji.deserialize;


import com.poiji.bind.Poiji;
import com.poiji.deserialize.model.byid.Employee;
import com.poiji.deserialize.model.byid.Employee2;
import com.poiji.deserialize.model.byname.EmployeeByName;
import com.poiji.deserialize.model.byname.EmployeeByName2;
import com.poiji.option.PoijiOptions;
import com.poiji.option.PoijiOptions.PoijiOptionsBuilder;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;

import static com.poiji.util.Data.unmarshallingDeserialize;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;

/**
* Created by passedbylove@gmail.com on 2018-11-15.
*/
@RunWith(Parameterized.class)
public class DeserializersByNameTagWithWhiteSpaceTest {

private String path;

public DeserializersByNameTagWithWhiteSpaceTest(String path) {
this.path = path;

}

@Parameterized.Parameters(name = "{index}: ({0})={1}")
public static Iterable<Object[]> queries() {
return Arrays.asList(new Object[][]{
{"src/test/resources/employees-tagwithwhitespace.xlsx"},
});
}

@Test
public void shouldMapExcelToJava() {
PoijiOptions options = PoijiOptionsBuilder.settings().datePattern("dd/MM/yyyy","yyyy-MM-dd","yyyy/MM/dd","yyyy年MM月dd日","yyyy\\MM\\dd").trimCellValue(true).trimTagName(true).build();
try {
List<EmployeeByName2> actualEmployees = Poiji.fromExcel(new FileInputStream(new File(path)), EmployeeByName2.class, options);
assertThat(actualEmployees.size(),is(4));
} catch (IOException e) {
e.printStackTrace();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.poiji.deserialize;

import com.poiji.bind.Poiji;
import com.poiji.deserialize.model.byid.Sample;
import com.poiji.option.PoijiOptions;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;

import static com.poiji.util.Data.unmarshallingSamples;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;

@RunWith(Parameterized.class)
public class DeserializersSheetViaStreamTest {
private String path;
private boolean preferNullOverDefault;
private List<Sample> expectedSamples;
private Class<?> expectedException;

public DeserializersSheetViaStreamTest(String path,
List<Sample> expectedSamples,
boolean preferNullOverDefault,
Class<?> expectedException) {
this.path = path;
this.expectedSamples = expectedSamples;
this.preferNullOverDefault = preferNullOverDefault;
this.expectedException = expectedException;
}

@Parameterized.Parameters(name = "{index}: ({0})={1}")
public static Iterable<Object[]> queries() {
return Arrays.asList(new Object[][]{
{"src/test/resources/sample.xlsx", unmarshallingSamples(), false, null},
{"src/test/resources/sample.xls", unmarshallingSamples(), true, null},
});
}

@Test
public void readeFromStream() {

try {

PoijiOptions poijiOptions = PoijiOptions.PoijiOptionsBuilder.settings().preferNullOverDefault(this.preferNullOverDefault).build();
InputStream is = new FileInputStream(new File(path));
List<Sample> samples = Poiji.fromExcel(is, Sample.class, poijiOptions);

assertThat(samples, notNullValue());
assertThat(samples.size(), not(0));
assertThat(samples.size(), is(expectedSamples.size()));

Sample actualSample1 = samples.get(0);
Sample actualSample2 = samples.get(1);

Sample expectedSample1 = expectedSamples.get(0);
Sample expectedSample2 = expectedSamples.get(1);

assertThat(actualSample1.toString(), is(expectedSample1.toString()));
assertThat(actualSample2.toString(), is(expectedSample2.toString()));

} catch (Exception e) {
if (expectedException == null) {
fail(e.getMessage());
} else {
assertThat(e, instanceOf(expectedException));
}
}
}
}
Loading

0 comments on commit bad6055

Please sign in to comment.