Index: pom.xml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/pom.xml b/pom.xml
--- a/pom.xml (revision 65a9395cd55cf65436ad114a07b65357079685c4)
+++ b/pom.xml (revision eae239508e48579f286db2c29880864fa5f51db1)
@@ -6,7 +6,7 @@
com.github.ozlerhakan
poiji
- 3.1.7
+ 3.1.8-SNAPSHOT
jar
poiji
Index: src/main/java/com/poiji/bind/mapping/HSSFUnmarshaller.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/com/poiji/bind/mapping/HSSFUnmarshaller.java b/src/main/java/com/poiji/bind/mapping/HSSFUnmarshaller.java
--- a/src/main/java/com/poiji/bind/mapping/HSSFUnmarshaller.java (revision 65a9395cd55cf65436ad114a07b65357079685c4)
+++ b/src/main/java/com/poiji/bind/mapping/HSSFUnmarshaller.java (revision eae239508e48579f286db2c29880864fa5f51db1)
@@ -10,6 +10,8 @@
import com.poiji.config.Casting;
import com.poiji.config.Formatting;
import com.poiji.exception.IllegalCastException;
+import com.poiji.exception.PoijiMultiRowException;
+import com.poiji.exception.PoijiMultiRowException.PoijiRowSpecificException;
import com.poiji.option.PoijiOptions;
import com.poiji.util.AnnotationUtil;
import com.poiji.util.ReflectUtil;
@@ -79,6 +81,7 @@
void processRowsToObjects(Sheet sheet, Class type, Consumer super T> consumer) {
int skip = options.skip();
int maxPhysicalNumberOfRows = sheet.getPhysicalNumberOfRows() + 1 - skip;
+ List errors = new ArrayList<>();
loadColumnTitles(sheet, maxPhysicalNumberOfRows);
AnnotationUtil.validateMandatoryNameColumns(options, formatting, type, titleToIndex, indexToTitle);
@@ -90,9 +93,19 @@
if (limit != 0 && internalCount > limit)
return;
- T instance = deserializeRowToInstance(currentRow, type);
- consumer.accept(instance);
+ try {
+ T instance = deserializeRowToInstance(currentRow, type);
+ consumer.accept(instance);
+ } catch (PoijiMultiRowException poijiRowException) {
+ errors.add(poijiRowException);
+ }
}
+ }
+ if (!errors.isEmpty()) {
+ List allErrors = errors.stream()
+ .flatMap((PoijiMultiRowException e) -> e.getErrors().stream())
+ .collect(Collectors.toList());
+ throw new PoijiMultiRowException("Problem(s) occurred while reading data", allErrors);
}
}
@@ -163,6 +176,7 @@
private T tailSetFieldValue(Row currentRow, Class super T> type, T instance) {
List mappedColumnIndices = new ArrayList<>();
List unknownCells = new ArrayList<>();
+ List errors = new ArrayList<>();
for (Field field : type.getDeclaredFields()) {
if (field.getAnnotation(ExcelRow.class) != null) {
@@ -174,15 +188,29 @@
Class> fieldType = field.getType();
Object fieldInstance = ReflectUtil.newInstanceOf(fieldType);
for (Field fieldField : fieldType.getDeclaredFields()) {
- mappedColumnIndices.add(tailSetFieldValue(currentRow, fieldInstance, fieldField));
+ try {
+ mappedColumnIndices.add(
+ tailSetFieldValue(currentRow, fieldInstance, fieldField)
+ );
+ } catch (PoijiRowSpecificException poijiRowException) {
+ errors.add(poijiRowException);
+ }
}
setFieldData(instance, field, fieldInstance);
} else if (field.getAnnotation(ExcelUnknownCells.class) != null) {
unknownCells.add(field);
} else {
- mappedColumnIndices.add(tailSetFieldValue(currentRow, instance, field));
+ try {
+ mappedColumnIndices.add(tailSetFieldValue(currentRow, instance, field));
+ } catch (PoijiRowSpecificException poijiRowException) {
+ errors.add(poijiRowException);
+ }
}
}
+
+ if (!errors.isEmpty()) {
+ throw new PoijiMultiRowException("Problem(s) occurred while reading data", errors);
+ }
Map excelUnknownCellsMap = StreamSupport
.stream(Spliterators.spliteratorUnknownSize(currentRow.cellIterator(), Spliterator.ORDERED), false)
@@ -216,10 +244,19 @@
annotationDetail.setDisabledCellFormat(disableCellFormat.value());
}
+ ExcelCellName excelCellName = field.getAnnotation(ExcelCellName.class);
+ ExcelCell excelCell = field.getAnnotation(ExcelCell.class);
+ if (options.isMandatoryColumnsApplyToCellValues()) {
+ if (excelCellName != null) {
+ annotationDetail.setMandatoryCell(excelCellName.mandatory());
+ annotationDetail.setColumnName(excelCellName.value());
+ } else if (excelCell != null) {
+ annotationDetail.setMandatoryCell(excelCell.mandatory());
+ }
+ }
if (index != null) {
annotationDetail.setColumn(index.value());
} else {
- ExcelCellName excelCellName = field.getAnnotation(ExcelCellName.class);
if (excelCellName != null) {
final String titleName = formatting.transform(options, excelCellName.value());
Integer column = titleToIndex.get(titleName);
@@ -244,6 +281,12 @@
}
Object data = casting.castValue(field, value, currentRow.getRowNum(), annotationDetail.getColumn(), options);
setFieldData(instance, field, data);
+ } else if (annotationDetail.isMandatoryCell()) {
+ throw new PoijiRowSpecificException(
+ "Cell value of column '" + annotationDetail.getColumnName() + "' is null,"
+ + " so cannot be applied to mandatory field '" + field.getName() + "'.",
+ currentRow.getRowNum()
+ );
}
}
@@ -278,23 +321,41 @@
private static class FieldAnnotationDetail {
private Integer column;
+ private String columnName;
private boolean disabledCellFormat;
+ private boolean mandatoryCell;
Integer getColumn() {
return column;
}
+ void setColumn(Integer column) {
+ this.column = column;
+ }
+
+ public String getColumnName() {
+ return columnName;
+ }
+
+ public void setColumnName(String columnName) {
+ this.columnName = columnName;
+ }
+
boolean isDisabledCellFormat() {
return disabledCellFormat;
}
- void setColumn(Integer column) {
- this.column = column;
- }
-
void setDisabledCellFormat(boolean disabledCellFormat) {
this.disabledCellFormat = disabledCellFormat;
}
+
+ public boolean isMandatoryCell() {
+ return mandatoryCell;
+ }
+
+ public void setMandatoryCell(boolean mandatoryCell) {
+ this.mandatoryCell = mandatoryCell;
+ }
}
}
Index: src/main/java/com/poiji/exception/PoijiMultiRowException.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/com/poiji/exception/PoijiMultiRowException.java b/src/main/java/com/poiji/exception/PoijiMultiRowException.java
new file mode 100644
--- /dev/null (revision eae239508e48579f286db2c29880864fa5f51db1)
+++ b/src/main/java/com/poiji/exception/PoijiMultiRowException.java (revision eae239508e48579f286db2c29880864fa5f51db1)
@@ -0,0 +1,38 @@
+package com.poiji.exception;
+
+import java.util.List;
+
+/**
+ * PoijiMultiRowException is the superclass of RuntimeException that
+ * can be thrown during the mapping process of excel service.
+ *
+ * @since Poiji 3.1.8
+ */
+@SuppressWarnings("serial")
+public class PoijiMultiRowException extends PoijiException {
+
+ private final List errors;
+
+ public PoijiMultiRowException(String message, List errors) {
+ super(message);
+ this.errors = errors;
+ }
+
+ public List getErrors() {
+ return errors;
+ }
+
+ public static class PoijiRowSpecificException extends RuntimeException {
+
+ private final Integer rowNum;
+
+ public PoijiRowSpecificException(String message, Integer rowNum) {
+ super(message);
+ this.rowNum = rowNum;
+ }
+
+ public Integer getRowNum() {
+ return rowNum;
+ }
+ }
+}
Index: src/main/java/com/poiji/option/PoijiOptions.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/com/poiji/option/PoijiOptions.java b/src/main/java/com/poiji/option/PoijiOptions.java
--- a/src/main/java/com/poiji/option/PoijiOptions.java (revision 65a9395cd55cf65436ad114a07b65357079685c4)
+++ b/src/main/java/com/poiji/option/PoijiOptions.java (revision eae239508e48579f286db2c29880864fa5f51db1)
@@ -49,6 +49,7 @@
private Formatting formatting;
private Locale locale;
private boolean rawData;
+ private boolean mandatoryColumnsApplyToCellValues;
public PoijiNumberFormat getPoijiNumberFormat() {
return numberFormat;
@@ -298,6 +299,15 @@
this.rawData = rawData;
return this;
}
+
+ public boolean isMandatoryColumnsApplyToCellValues() {
+ return mandatoryColumnsApplyToCellValues;
+ }
+
+ public PoijiOptions setMandatoryColumnsApplyToCellValues(boolean mandatoryColumnsApplyToCellValues) {
+ this.mandatoryColumnsApplyToCellValues = mandatoryColumnsApplyToCellValues;
+ return this;
+ }
public static class PoijiOptionsBuilder {
@@ -327,6 +337,7 @@
private String listDelimiter = "\\s*,\\s*";
private Locale locale = Locale.US;
private boolean rawData;
+ private boolean mandatoryColumnsApplyToCellValues;
private PoijiOptionsBuilder() {
}
@@ -440,7 +451,8 @@
.setListDelimiter(listDelimiter)
.setFormatting(formatting)
.setLocale(locale)
- .setRawData(rawData);
+ .setRawData(rawData)
+ .setMandatoryColumnsApplyToCellValues(mandatoryColumnsApplyToCellValues);
}
@@ -620,6 +632,7 @@
* Default - false.
*
* @param caseInsensitive true or false
+ * @return this
*/
public PoijiOptionsBuilder caseInsensitive(final boolean caseInsensitive) {
this.caseInsensitive = caseInsensitive;
@@ -631,6 +644,7 @@
* Default - false.
*
* @param ignoreWhitespaces true or false
+ * @return this
*/
public PoijiOptionsBuilder ignoreWhitespaces(final boolean ignoreWhitespaces) {
this.ignoreWhitespaces = ignoreWhitespaces;
@@ -642,6 +656,7 @@
* This option should be enabled for debugging purpose.
*
* @param cellFormat poiji cell format instance
+ * @return this
*/
public PoijiOptionsBuilder poijiLogCellFormat(final PoijiLogCellFormat cellFormat) {
this.cellFormat = cellFormat;
@@ -652,6 +667,7 @@
* Change the default cell formats of a xlsx excel file by overriding
*
* @param numberFormat poiji number format instance
+ * @return this
*/
public PoijiOptionsBuilder poijiNumberFormat(final PoijiNumberFormat numberFormat) {
this.numberFormat = numberFormat;
@@ -703,6 +719,17 @@
this.rawData = status;
return this;
}
+
+ /**
+ * Use this option to apply the mandatory column constraint to cell values as well.
+ *
+ * @param mandatoryColumnsApplyToCellValues set true to apply the mandatory column constraint to cell values as well.
+ * @return this
+ */
+ public PoijiOptionsBuilder mandatoryColumnsApplyToCellValues(boolean mandatoryColumnsApplyToCellValues) {
+ this.mandatoryColumnsApplyToCellValues = mandatoryColumnsApplyToCellValues;
+ return this;
+ }
}
}