diff --git a/common-tara/pom.xml b/common-tara/pom.xml index dada12b..f00bd13 100644 --- a/common-tara/pom.xml +++ b/common-tara/pom.xml @@ -9,12 +9,12 @@ com.sondertara tara - 0.0.3.200 + 0.0.3.201 ../pom.xml com.sondertara common-tara - 0.0.3.200 + 0.0.3.201 common-tara common utils. diff --git a/common-tara/src/main/java/com/sondertara/common/util/DateUtil.java b/common-tara/src/main/java/com/sondertara/common/util/DateUtil.java index a1a0d67..13a8ff6 100644 --- a/common-tara/src/main/java/com/sondertara/common/util/DateUtil.java +++ b/common-tara/src/main/java/com/sondertara/common/util/DateUtil.java @@ -40,7 +40,7 @@ public static String format(String pattern, Date value) throws ExecutionExceptio * 判断两个时间内的时间间隔(毫秒) * * @param startDate 开始时间 - * @param endDate 终止时间 + * @param endDate 终止时间 */ public static long afterTime(Date startDate, Date endDate) { if (startDate != null & endDate != null) { @@ -51,7 +51,6 @@ public static long afterTime(Date startDate, Date endDate) { } - /** * 尝试转换日期 * @@ -59,6 +58,9 @@ public static long afterTime(Date startDate, Date endDate) { * @return 转换后的date,尝试转换失败时返回null */ public static Date parse(String dateString) throws ExecutionException { + if (StringUtil.isBlank(dateString)) { + return null; + } Date date = null; if (date == null) { @@ -168,7 +170,6 @@ public static Date addMinute(Date date, int n) { } - //日期转为字符串,格式为月日 public static String dateToMD(Date d) { if (d == null) { @@ -191,5 +192,4 @@ public static String dateToStringYMM(Date d) { int year = calendar.get(Calendar.YEAR); return year + "年" + dateToMD(d); } - } diff --git a/excel-tara/pom.xml b/excel-tara/pom.xml index 88b4263..314868a 100644 --- a/excel-tara/pom.xml +++ b/excel-tara/pom.xml @@ -7,12 +7,12 @@ com.sondertara tara - 0.0.3.200 + 0.0.3.201 ../pom.xml com.sondertara excel-tara - 0.0.3.200 + 0.0.3.201 excel-tara high performance excel kit. https://github.com/sondertara/tara @@ -118,7 +118,7 @@ com.sondertara common-tara - 0.0.3.200 + 0.0.3.201 diff --git a/excel-tara/src/main/java/com/sondertara/excel/annotation/ImportField.java b/excel-tara/src/main/java/com/sondertara/excel/annotation/ImportField.java index 2bcdf73..139b9f7 100644 --- a/excel-tara/src/main/java/com/sondertara/excel/annotation/ImportField.java +++ b/excel-tara/src/main/java/com/sondertara/excel/annotation/ImportField.java @@ -1,6 +1,8 @@ package com.sondertara.excel.annotation; +import com.sondertara.excel.enums.FieldRangeType; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -59,4 +61,18 @@ * 最大值,需要配合required一起使用 */ double max() default Double.MAX_VALUE; + + /** + * range + * + * @return the field value rang + */ + String[] range() default {}; + + /** + * the range type + * + * @return range type enum + */ + FieldRangeType rangeType() default FieldRangeType.RANGE_CLOSE; } diff --git a/excel-tara/src/main/java/com/sondertara/excel/entity/ExcelPropertyEntity.java b/excel-tara/src/main/java/com/sondertara/excel/entity/ExcelPropertyEntity.java index 2b44ca6..2d4a954 100644 --- a/excel-tara/src/main/java/com/sondertara/excel/entity/ExcelPropertyEntity.java +++ b/excel-tara/src/main/java/com/sondertara/excel/entity/ExcelPropertyEntity.java @@ -1,6 +1,7 @@ package com.sondertara.excel.entity; +import com.sondertara.excel.enums.FieldRangeType; import lombok.Builder; import lombok.Getter; import lombok.Setter; @@ -57,11 +58,15 @@ public class ExcelPropertyEntity { */ private Boolean required; /** - * 最小值 + * range + *

+ * number eg:{"2",""}(2, ),{"2","5"},{"","5"} + * date eg:{"2019-08-01 12:00:00",""},{"2019-08-01 12:00:00","2019-10-01 12:00:00"} + *

*/ - private Double min; + private String[] range; /** - * 最大值 + * range type {@link FieldRangeType} ,default is {@link FieldRangeType#RANGE_CLOSE} */ - private Double max; + private FieldRangeType rangeType; } diff --git a/excel-tara/src/main/java/com/sondertara/excel/enums/FieldRangeType.java b/excel-tara/src/main/java/com/sondertara/excel/enums/FieldRangeType.java new file mode 100644 index 0000000..fd59d3b --- /dev/null +++ b/excel-tara/src/main/java/com/sondertara/excel/enums/FieldRangeType.java @@ -0,0 +1,27 @@ +package com.sondertara.excel.enums; + +public enum FieldRangeType { + /** + * range[] + */ + RANGE_CLOSE(1), + /** + * range() + */ + RANGE_OPEN(2), + /** + * range(] + */ + RANGE_LEFT_OPEN(3), + /** + * range[) + */ + RANGE_RIGHT_OPEN(4), + ; + + private Integer type; + + FieldRangeType(Integer type) { + this.type = type; + } +} diff --git a/excel-tara/src/main/java/com/sondertara/excel/factory/ExcelMappingFactory.java b/excel-tara/src/main/java/com/sondertara/excel/factory/ExcelMappingFactory.java index 31ade03..829c270 100644 --- a/excel-tara/src/main/java/com/sondertara/excel/factory/ExcelMappingFactory.java +++ b/excel-tara/src/main/java/com/sondertara/excel/factory/ExcelMappingFactory.java @@ -41,8 +41,8 @@ public static ExcelEntity loadImportExcelClass(Class clazz) { .regexMessage(importField.regexMessage().trim()) .scale(importField.scale()) .roundingMode(importField.roundingMode()) - .min(importField.min()) - .max(importField.max()) + .range(importField.range()) + .rangeType(importField.rangeType()) .build(); propertyList.add(excelPropertyEntity); } diff --git a/excel-tara/src/main/java/com/sondertara/excel/parser/ExcelReader.java b/excel-tara/src/main/java/com/sondertara/excel/parser/ExcelReader.java index d6d300e..10ab8c9 100644 --- a/excel-tara/src/main/java/com/sondertara/excel/parser/ExcelReader.java +++ b/excel-tara/src/main/java/com/sondertara/excel/parser/ExcelReader.java @@ -10,6 +10,7 @@ import com.sondertara.excel.entity.ErrorEntity; import com.sondertara.excel.entity.ExcelEntity; import com.sondertara.excel.entity.ExcelPropertyEntity; +import com.sondertara.excel.enums.FieldRangeType; import com.sondertara.excel.exception.AllEmptyRowException; import com.sondertara.excel.exception.ExcelTaraException; import com.sondertara.excel.function.ImportFunction; @@ -501,6 +502,7 @@ private Object convertCellValue(ExcelPropertyEntity mappingProperty, Object cell */ private ErrorEntity checkCellValue(Integer cellIndex, ExcelPropertyEntity mappingProperty, Object cellValue) throws Exception { + // is required Boolean required = mappingProperty.getRequired(); if (null != required && required) { if (null == cellValue || StringUtil.isBlank(cellValue)) { @@ -509,21 +511,8 @@ private ErrorEntity checkCellValue(Integer cellIndex, ExcelPropertyEntity mappin , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1); return buildErrorMsg(cellIndex, cellValue, validErrorMessage); } - if (Double.MIN_VALUE != mappingProperty.getMin() || Double.MAX_VALUE != mappingProperty.getMax()) { - final Double v = NumberUtil.toDouble(cellValue); - if (null == v) { - String validErrorMessage = String.format("The sheet[{}],row[{}],column[{}] is empty after converted!" - , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1); - return buildErrorMsg(cellIndex, cellValue, validErrorMessage); - } else if (v > mappingProperty.getMax() || v < mappingProperty.getMin()) { - String validErrorMessage = String.format("The sheet[{}],row[{}],column[{}],cell value[%s] not pass the number range validation!" - , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue); - return buildErrorMsg(cellIndex, cellValue, validErrorMessage); - - } - } } - + //regex String regex = mappingProperty.getRegex(); if (!StringUtil.isBlank(cellValue) && !StringUtils.isBlank(regex)) { boolean matches = RegexUtil.isMatch(regex, cellValue.toString()); @@ -534,8 +523,29 @@ private ErrorEntity checkCellValue(Integer cellIndex, ExcelPropertyEntity mappin return buildErrorMsg(cellIndex, cellValue, validErrorMessage); } } - - + // value range + Class filedClazz = mappingProperty.getFieldEntity().getType(); + String[] range = mappingProperty.getRange(); + if (range.length == 0) { + return null; + } else if (StringUtil.isEmpty(range[0]) && StringUtil.isEmpty(range[1])) { + return null; + } else if (range.length != 2) { + throw new Exception("the ImportFiled annotation attribute[range] should a string[] with two elements!"); + } + String simpleName = filedClazz.getSimpleName(); + + if ("Date".equals(simpleName)) { + return checkRangeDate(cellIndex, filedClazz, range, cellValue, mappingProperty.getRangeType()); + } else if ("Integer".equals(simpleName) + || "double".equals(simpleName.toLowerCase()) + || "BigDecimal".equals(simpleName) + || "float".equals(simpleName.toLowerCase()) + || "int".equals(simpleName) + || "short".equals(simpleName.toLowerCase()) + || "long".equals(simpleName.toLowerCase())) { + return checkRangeNumber(cellIndex, filedClazz, range, cellValue, mappingProperty.getRangeType()); + } return null; } @@ -600,6 +610,214 @@ private String fillChar(String str, int len, char let, boolean isPre) { return str; } + /** + * if the field is date check date range + * + * @param cellIndex + * @param filedClazz + * @param range + * @param cellValue + * @param rangeType + * @return error entity + * @throws Exception + */ + private ErrorEntity checkRangeDate(Integer cellIndex, Class filedClazz, String[] range, Object cellValue, FieldRangeType rangeType) throws Exception { + final Date min = DateUtil.parse(range[0]); + final Date max = DateUtil.parse(range[1]); + if (null == min && null == max) { + throw new Exception("The ImportFiled annotation attribute[range] value must be date string[]"); + } else if (null != max && null != min && max.getTime() <= min.getTime()) { + throw new Exception(String.format("The ImportFiled annotation attribute[range] value %s is illegal!", Arrays.toString(range))) + ; + } + Date v = null; + try { + v = DateUtil.parse(String.valueOf(cellValue)); + } catch (ExecutionException e) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] must can be parsed to a date!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[0], range[1]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } + if (null == v) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s] is empty after converted!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } + switch (rangeType) { + case RANGE_CLOSE: + if (null == max && v.getTime() < min.getTime()) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the date range '[%s,]' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[0]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } else if (null == min && v.getTime() > max.getTime()) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the date range '[,%s]' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[1]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } else if (v.getTime() > max.getTime() || v.getTime() < min.getTime()) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the date range '[%s,%s]' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[0], range[1]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } + break; + case RANGE_OPEN: + if (null == max && v.getTime() <= min.getTime()) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '(%s,)' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[0]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } else if (null == min && v.getTime() >= max.getTime()) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '(,%s)' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[1]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } else if (v.getTime() >= max.getTime() || v.getTime() <= min.getTime()) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '(%s,%s)' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[0], range[1]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } + break; + case RANGE_LEFT_OPEN: + if (null == max && v.getTime() <= min.getTime()) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '(%s,]' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[0]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } else if (null == min && v.getTime() > max.getTime()) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '(,%s]' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[1]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } else if (v.getTime() > max.getTime() || v.getTime() <= min.getTime()) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '(%s,%s]' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[0], range[1]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } + break; + case RANGE_RIGHT_OPEN: + if (null == max && v.getTime() < min.getTime()) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '[%s,)' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[0]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } else if (null == min && v.getTime() >= max.getTime()) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '[,%s)' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[1]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } else if (v.getTime() >= max.getTime() || v.getTime() < min.getTime()) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '[%s,%s)' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[0], range[1]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } + break; + default: + } + return null; + + } + + /** + * if the field is number check range + * + * @param cellIndex + * @param filedClazz + * @param range + * @param cellValue + * @param rangeType + * @return error entity + * @throws Exception + */ + private ErrorEntity checkRangeNumber(Integer cellIndex, Class filedClazz, String[] range, Object cellValue, FieldRangeType rangeType) throws Exception { + + Double min = null; + Double max = null; + try { + min = NumberUtil.toDouble(range[0]); + max = NumberUtil.toDouble(range[1]); + } catch (Exception e) { + throw new Exception("the ImportFiled annotation attribute[range] value must be number string[]"); + } + Double v = null; + try { + v = NumberUtil.toDouble(cellValue); + } catch (Exception e) { + } + if (null == min && null == max) { + throw new Exception("the ImportFiled annotation attribute[range] value must be number string[]"); + } else if (null != max && null != min && max <= min) { + throw new Exception(String.format("The ImportFiled annotation attribute[range] value %s is illegal!", Arrays.toString(range))); + } + if (null == v) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s] is empty after converted!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } + switch (rangeType) { + case RANGE_CLOSE: + if (null == max && v < min) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '[%s,]' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[0]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + + } else if (null == min && v > max) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '[,%s]' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[1]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } else if (v > max || v < min) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '[%s,%s]' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[0], range[1]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } + break; + case RANGE_OPEN: + if (null == max && v <= min) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '(%s,]' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[0]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + + } else if (null == min && v >= max) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '[,%s)' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[1]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } else if (v >= max || v <= min) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '(%s,%s)' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[0], range[1]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } + break; + case RANGE_LEFT_OPEN: + if (null == max && v <= min) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '(%s,]' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[0]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + + } else if (null == min && v > min) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '(,%s]' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[1]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + + } else if (v > max || v <= min) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '(%s,%s]' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[0], range[1]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + + } + break; + case RANGE_RIGHT_OPEN: + if (null == max && v < min) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '[%s,)' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[0]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } else if (null == min && v >= max) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '[,%s)' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[1]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } else if (v >= max || v < min) { + String validErrorMessage = String.format("The sheet[%s],row[%s],column[%s],cell value[%s] not pass the number range '[%s,%s)' validation!" + , currentSheetIndex + 1, currentRowIndex + 1, cellIndex + 1, cellValue, range[0], range[1]); + return buildErrorMsg(cellIndex, cellValue, validErrorMessage); + } + break; + default: + } + return null; + } + + /** * cell type */ diff --git a/excel-tara/src/test/java/com/sondertara/ExcelTaraTest.java b/excel-tara/src/test/java/com/sondertara/ExcelTaraTest.java index 3305632..2b70960 100644 --- a/excel-tara/src/test/java/com/sondertara/ExcelTaraTest.java +++ b/excel-tara/src/test/java/com/sondertara/ExcelTaraTest.java @@ -80,7 +80,7 @@ public void importTest() throws Exception { CSVPrinter errorPrinter = CSVFormat.EXCEL.print(errorWriter); - ExcelTara.builder(new FileInputStream(new File("/Users/huangxiaohu/Desktop/保费结算导入结果/error.xlsx")), ImportParam.class) + ExcelTara.builder(new FileInputStream(new File("/Users/huangxiaohu/Desktop/7-9导入服务费金额有误数据.xlsx")), ImportParam.class) .importExcel(true, new ImportFunction() { /** diff --git a/excel-tara/src/test/java/com/sondertara/model/ImportParam.java b/excel-tara/src/test/java/com/sondertara/model/ImportParam.java index a323308..562a6c9 100644 --- a/excel-tara/src/test/java/com/sondertara/model/ImportParam.java +++ b/excel-tara/src/test/java/com/sondertara/model/ImportParam.java @@ -54,7 +54,7 @@ public class ImportParam implements Serializable { private String specialInvoiceNo; @ImportField(index = 26) private Date commitTime; - @ImportField(index = 27) + @ImportField(index = 27, range = {"300","200"}) private BigDecimal commissionAmount; diff --git a/notify-tara/pom.xml b/notify-tara/pom.xml index 9d99160..102c557 100644 --- a/notify-tara/pom.xml +++ b/notify-tara/pom.xml @@ -7,12 +7,12 @@ com.sondertara tara - 0.0.3.200 + 0.0.3.201 ../pom.xml com.sondertara notify-tara - 0.0.3.200 + 0.0.3.201 notify-tara notify kit. diff --git a/pom.xml b/pom.xml index 315794d..de6dd8b 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.sondertara tara - 0.0.3.200 + 0.0.3.201 pom tara tara is a awesome java advance Kit. @@ -43,19 +43,18 @@ - + + + org.projectlombok + lombok + 1.18.10 + provided + com.alibaba fastjson 1.2.58 - - - - org.projectlombok - lombok - 1.16.10 - org.reflections reflections @@ -168,7 +167,12 @@ maven-jar-plugin 3.2.0 - + + + org.apache.maven.plugins + maven-release-plugin + 2.5.3 +