diff --git a/README.adoc b/README.adoc
index 38329f9..263a9ff 100644
--- a/README.adoc
+++ b/README.adoc
@@ -2,8 +2,8 @@
:toclevels: 2
= Poiji
-:version: v4.4.0
-:branch: 4.4.0
+:version: v4.5.0
+:branch: 4.5.0
image:https://github.com/ozlerhakan/poiji/actions/workflows/maven.yml/badge.svg["Build Status"] image:https://app.codacy.com/project/badge/Grade/64f7e2cb9e604807b62334a4cfc3952d["Codacy code quality",link="https://www.codacy.com/gh/ozlerhakan/poiji/dashboard?utm_source=github.com&utm_medium=referral&utm_content=ozlerhakan/poiji&utm_campaign=Badge_Grade"]
image:https://codecov.io/gh/ozlerhakan/poiji/branch/{branch}/graph/badge.svg?token=MN6V6xOWBq["Codecov",link="https://codecov.io/gh/ozlerhakan/poiji"] image:https://img.shields.io/badge/apache.poi-5.2.3-brightgreen.svg[] image:https://app.fossa.com/api/projects/git%2Bgithub.com%2Fozlerhakan%2Fpoiji.svg?type=shield["FOSSA Status",link="https://app.fossa.com/projects/git%2Bgithub.com%2Fozlerhakan%2Fpoiji?ref=badge_shield"]
@@ -25,7 +25,7 @@ In your Maven/Gradle project, first add the corresponding dependency:
com.github.ozlerhakan
poiji
- 4.4.0
+ 4.5.0
----
@@ -710,7 +710,7 @@ The `mandatoryHeader` field is compatible with XLS and XLSX files.
[NOTE]
====
-The `mandatoryCell` field works **only** with XLS files.
+The `mandatoryCell` field works **only** with XLS files and `Sheet` instances. XLS workbooks are opened with `RETURN_BLANK_AS_NULL` missing cell policy. If passing a `Sheet` instance it is up for the caller to make sure the missing cell policy of the parent workbook is set accordingly.
====
=== Debug Cells Formats
diff --git a/pom.xml b/pom.xml
index b9992b7..23a8140 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
com.github.ozlerhakan
poiji
- 4.4.0
+ 4.5.0
jar
poiji
diff --git a/src/main/java/com/poiji/bind/mapping/HSSFUnmarshallerFile.java b/src/main/java/com/poiji/bind/mapping/HSSFUnmarshallerFile.java
index 077eb8e..a30777d 100644
--- a/src/main/java/com/poiji/bind/mapping/HSSFUnmarshallerFile.java
+++ b/src/main/java/com/poiji/bind/mapping/HSSFUnmarshallerFile.java
@@ -3,6 +3,7 @@
import com.poiji.bind.PoijiFile;
import com.poiji.exception.PoijiException;
import com.poiji.option.PoijiOptions;
+import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
@@ -24,7 +25,9 @@ final class HSSFUnmarshallerFile extends HSSFUnmarshaller {
@Override
protected Workbook workbook() {
try {
- return WorkbookFactory.create(poijiFile.file(), options.getPassword(), true);
+ Workbook workbook = WorkbookFactory.create(poijiFile.file(), options.getPassword(), true);
+ workbook.setMissingCellPolicy(Row.MissingCellPolicy.RETURN_BLANK_AS_NULL);
+ return workbook;
} catch (IOException e) {
throw new PoijiException("Problem occurred while creating HSSFWorkbook", e);
}
diff --git a/src/main/java/com/poiji/bind/mapping/HSSFUnmarshallerStream.java b/src/main/java/com/poiji/bind/mapping/HSSFUnmarshallerStream.java
index 9683d7e..3ed33c7 100644
--- a/src/main/java/com/poiji/bind/mapping/HSSFUnmarshallerStream.java
+++ b/src/main/java/com/poiji/bind/mapping/HSSFUnmarshallerStream.java
@@ -3,6 +3,7 @@
import com.poiji.bind.PoijiInputStream;
import com.poiji.exception.PoijiException;
import com.poiji.option.PoijiOptions;
+import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
@@ -23,12 +24,14 @@ final class HSSFUnmarshallerStream extends HSSFUnmarshaller {
@Override
protected Workbook workbook() {
try {
-
+ Workbook workbook;
if (options.getPassword() != null) {
- return WorkbookFactory.create(poijiInputStream.stream(), options.getPassword());
+ workbook = WorkbookFactory.create(poijiInputStream.stream(), options.getPassword());
+ } else {
+ workbook = WorkbookFactory.create(poijiInputStream.stream());
}
-
- return WorkbookFactory.create(poijiInputStream.stream());
+ workbook.setMissingCellPolicy(Row.MissingCellPolicy.RETURN_BLANK_AS_NULL);
+ return workbook;
} catch (IOException e) {
throw new PoijiException("Problem occurred while creating HSSFWorkbook", e);
}
diff --git a/src/test/java/com/poiji/deserialize/MandatoryCellsExceptionTest.java b/src/test/java/com/poiji/deserialize/MandatoryCellsExceptionTest.java
index 0571b9f..14be6e1 100644
--- a/src/test/java/com/poiji/deserialize/MandatoryCellsExceptionTest.java
+++ b/src/test/java/com/poiji/deserialize/MandatoryCellsExceptionTest.java
@@ -2,18 +2,20 @@
import com.poiji.bind.Poiji;
import com.poiji.deserialize.model.byname.MandatoryMissingCells;
+import com.poiji.exception.PoijiExcelType;
import com.poiji.exception.PoijiMultiRowException;
import com.poiji.exception.PoijiMultiRowException.PoijiRowSpecificException;
import com.poiji.option.PoijiOptions;
-
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;
-import java.io.IOException;
+import java.io.*;
import java.util.List;
import static org.junit.Assert.assertEquals;
@@ -22,7 +24,7 @@
public class MandatoryCellsExceptionTest {
@Test
- public void testExcelMandatoryColumn() {
+ public void shouldThrowExceptionForMissingCell() {
try {
Poiji.fromExcel(createDummyExcel(), MandatoryMissingCells.class, PoijiOptions.PoijiOptionsBuilder
.settings()
@@ -38,6 +40,58 @@ public void testExcelMandatoryColumn() {
fail("Expected exception: " + PoijiMultiRowException.class.getName());
}
+ @Test
+ public void shouldThrowExceptionForBlankCellInSheet() throws IOException {
+ try (InputStream stream = new FileInputStream("src/test/resources/blank-cell.xlsx");
+ XSSFWorkbook workbook = new XSSFWorkbook(stream)) {
+ workbook.setMissingCellPolicy(Row.MissingCellPolicy.RETURN_BLANK_AS_NULL);
+ XSSFSheet sheet = workbook.getSheetAt(0);
+ Poiji.fromExcel(sheet, MandatoryMissingCells.class, PoijiOptions.PoijiOptionsBuilder
+ .settings()
+ .build());
+ } catch (PoijiMultiRowException e) {
+ List errors = e.getErrors();
+ assertEquals(1, errors.size());
+ assertEquals("Address", errors.get(0).getColumnName());
+ assertEquals("address", errors.get(0).getFieldName());
+ assertEquals((Integer) 1, errors.get(0).getRowNum());
+ return;
+ }
+ fail("Expected exception: " + PoijiMultiRowException.class.getName());
+ }
+
+ @Test
+ public void shouldThrowExceptionForBlankCellInFile() {
+ try {
+ Poiji.fromExcel(new File("src/test/resources/blank-cell.xls"), MandatoryMissingCells.class,
+ PoijiOptions.PoijiOptionsBuilder.settings().build());
+ } catch (PoijiMultiRowException e) {
+ List errors = e.getErrors();
+ assertEquals(1, errors.size());
+ assertEquals("Address", errors.get(0).getColumnName());
+ assertEquals("address", errors.get(0).getFieldName());
+ assertEquals((Integer) 1, errors.get(0).getRowNum());
+ return;
+ }
+ fail("Expected exception: " + PoijiMultiRowException.class.getName());
+ }
+
+ @Test
+ public void shouldThrowExceptionForBlankCellInStream() throws IOException {
+ try (InputStream stream = new FileInputStream("src/test/resources/blank-cell.xls")) {
+ Poiji.fromExcel(stream, PoijiExcelType.XLS, MandatoryMissingCells.class,
+ PoijiOptions.PoijiOptionsBuilder.settings().build());
+ } catch (PoijiMultiRowException e) {
+ List errors = e.getErrors();
+ assertEquals(1, errors.size());
+ assertEquals("Address", errors.get(0).getColumnName());
+ assertEquals("address", errors.get(0).getFieldName());
+ assertEquals((Integer) 1, errors.get(0).getRowNum());
+ return;
+ }
+ fail("Expected exception: " + PoijiMultiRowException.class.getName());
+ }
+
private Sheet createDummyExcel() {
Workbook workbook = new HSSFWorkbook();
diff --git a/src/test/java/com/poiji/parser/NumberParserTest.java b/src/test/java/com/poiji/parser/NumberParserTest.java
new file mode 100644
index 0000000..5508786
--- /dev/null
+++ b/src/test/java/com/poiji/parser/NumberParserTest.java
@@ -0,0 +1,27 @@
+package com.poiji.parser;
+
+import org.junit.Test;
+
+import com.poiji.option.PoijiOptions;
+import com.poiji.option.PoijiOptions.PoijiOptionsBuilder;
+
+import static org.junit.Assert.assertEquals;
+
+import java.text.NumberFormat;
+
+public class NumberParserTest {
+ @Test
+ public void parseNumber() {
+ PoijiOptions options = PoijiOptionsBuilder.settings().build();
+ NumberParser numParser = new NumberParser(NumberFormat.getInstance(options.getLocale()));
+ Number expectedNumber = numParser.parse("1").doubleValue();
+ assertEquals(expectedNumber.doubleValue(), 1.0, 0);
+ }
+
+ @Test(expected = NumberFormatException.class)
+ public void parseNullNumber() {
+ PoijiOptions options = PoijiOptionsBuilder.settings().build();
+ NumberParser numParser = new NumberParser(NumberFormat.getInstance(options.getLocale()));
+ numParser.parse(null).doubleValue();
+ }
+}
diff --git a/src/test/java/com/poiji/util/DefaultCastingTest.java b/src/test/java/com/poiji/util/DefaultCastingTest.java
index ccf4fab..07c76c8 100644
--- a/src/test/java/com/poiji/util/DefaultCastingTest.java
+++ b/src/test/java/com/poiji/util/DefaultCastingTest.java
@@ -266,6 +266,12 @@ public void castBigDecimal() {
assertEquals(BigDecimal.valueOf(81.56891), testVal);
}
+ @Test
+ public void castEmptyString() {
+ Object testVal = casting.castValue(String.class, "", options);
+ assertEquals("", testVal);
+ }
+
static class MyConfig extends DefaultCasting {
Object castValue(Class> fieldType, String value, PoijiOptions options) {
return getValueObject(null, -1, -1, options, value, fieldType);
diff --git a/src/test/resources/blank-cell.xls b/src/test/resources/blank-cell.xls
new file mode 100644
index 0000000..b11c0b3
Binary files /dev/null and b/src/test/resources/blank-cell.xls differ
diff --git a/src/test/resources/blank-cell.xlsx b/src/test/resources/blank-cell.xlsx
new file mode 100644
index 0000000..d89082f
Binary files /dev/null and b/src/test/resources/blank-cell.xlsx differ