diff --git a/src/main/java/com/example/parser/FlowableExcelMapper.java b/src/main/java/com/example/parser/FlowableExcelMapper.java index b28515e..3a54ca0 100644 --- a/src/main/java/com/example/parser/FlowableExcelMapper.java +++ b/src/main/java/com/example/parser/FlowableExcelMapper.java @@ -62,7 +62,7 @@ public class FlowableExcelMapper { // The 1st row contains the paths paths.addAll(rows.get(rowNum)); } else if (rowNum == 1) { - // The 1st row contains the types of the variables + // The 2nd row contains the types of the variables types.addAll(rows.get(rowNum)); } else { // All other rows contain the values of the variables @@ -75,29 +75,41 @@ public class FlowableExcelMapper { protected JsonNode rowToJsonNode(ArrayList types, ArrayList paths, ArrayList row, JsonNode jsonNode) { for (int cellNum = 0; cellNum < row.size(); cellNum++) { String cellValue = row.get(cellNum); + // Empty cells are not added to node if (cellValue != null && !cellValue.isEmpty()) { String type = types.get(cellNum); Object content; - switch (type) { - case "String": content = cellValue; break; - case "Boolean": content = Boolean.parseBoolean(cellValue); break; - case "Integer": content = Integer.parseInt(cellValue); break; - case "Double": content = Double.parseDouble(cellValue); break; - case "Long": content = Long.parseLong(cellValue); break; - case "Date": - // Excel considers dates as local dates, but we want them as UTC - Instant instant; - try { - LocalDateTime localDateTime = LocalDateTime.parse(cellValue, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); - instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant(); - } catch (DateTimeParseException e) { - LocalDate localDate = LocalDate.parse(cellValue, DateTimeFormatter.ofPattern("yyyy-MM-dd")); - instant = localDate.atStartOfDay(ZoneId.systemDefault()).toInstant(); - } - content = instant.plusSeconds(ZonedDateTime.now().getOffset().getTotalSeconds()); - break; + switch (cellValue) { + case "__NULL": content = null; break; + case "__N_A": content = "__N_A"; break; default: - throw new RuntimeException("Variable type not supported: " + type); + switch (type) { + case "String": + switch (cellValue) { + case "__EMPTY": content = ""; break; + case "__BLANK": content = " "; break; + default: content = cellValue; + } + break; + case "Boolean": content = Boolean.parseBoolean(cellValue); break; + case "Integer": content = Integer.parseInt(cellValue); break; + case "Double": content = Double.parseDouble(cellValue); break; + case "Long": content = Long.parseLong(cellValue); break; + case "Date": + // Excel considers dates as local dates, but we want them as UTC + Instant instant; + try { + LocalDateTime localDateTime = LocalDateTime.parse(cellValue, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant(); + } catch (DateTimeParseException e) { + LocalDate localDate = LocalDate.parse(cellValue, DateTimeFormatter.ofPattern("yyyy-MM-dd")); + instant = localDate.atStartOfDay(ZoneId.systemDefault()).toInstant(); + } + content = instant.plusSeconds(ZonedDateTime.now().getOffset().getTotalSeconds()); + break; + default: + throw new RuntimeException("Variable type not supported: " + type); + } } jsonNode = addNode(jsonNode, paths.get(cellNum), content); } diff --git a/src/test/java/com/example/parser/FlowableExcelMapperTest.java b/src/test/java/com/example/parser/FlowableExcelMapperTest.java index 0351650..2443988 100644 --- a/src/test/java/com/example/parser/FlowableExcelMapperTest.java +++ b/src/test/java/com/example/parser/FlowableExcelMapperTest.java @@ -23,34 +23,39 @@ class FlowableExcelMapperTest { @Autowired private FlowableExcelMapper flowableExcelMapper; + protected static final Logger logger = LoggerFactory.getLogger(FlowableExcelMapperTest.class); + public boolean isSubset(JsonNode root, JsonNode test) { // If test is null, it is always a subset of root if (test == null) { return true; } - // If root is null, but test is not, test is not a subset of root - if (root == null) { - return false; - } // If test is a value node, compare values if (test.isValueNode()) { + if (test.isTextual() && "__N_A".equals(test.asText())) { + return false; + } + if (root == null) { + return false; + } return root.isValueNode() && root.asText().equals(test.asText()); } // If test is an array node, check if all elements of test exist in root if(test.isArray()){ - if (!root.isArray() || test.size() > root.size()) { - return false; - } - for (JsonNode rootElement : test) { - boolean found = false; - for (JsonNode testElement : root) { - if (isSubset(testElement, rootElement)) { - found = true; - break; - } + for (int i = 0; i < test.size(); i++) { + JsonNode testElement = test.get(i); + JsonNode rootElement = null; + if (root != null) { + rootElement = root.get(i); } - if (!found) { + if (testElement.isTextual() && "__N_A".equals(testElement.asText())) { + if (rootElement != null && !rootElement.isNull()) { + return false; + } + continue; + } + if (!isSubset(rootElement, testElement)) { return false; } } @@ -58,12 +63,20 @@ class FlowableExcelMapperTest { } // If test is an object node, check if all fields in test exist in root if (test.isObject()){ - if (!root.isObject()){ - return false; - } for (Iterator iterator = test.fieldNames(); iterator.hasNext(); ) { String fieldName = iterator.next(); - if (!root.has(fieldName) || !isSubset(root.get(fieldName), test.get(fieldName))){ + JsonNode testValue = test.get(fieldName); + JsonNode rootValue = null; + if (root != null) { + rootValue = root.get(fieldName); + } + if (testValue.isTextual() && "__N_A".equals(testValue.asText())) { + if (rootValue != null && !rootValue.isNull()) { + return false; + } + continue; + } + if (!isSubset(rootValue, testValue)){ return false; } } @@ -84,16 +97,29 @@ class FlowableExcelMapperTest { return argumentList.stream(); } - protected Stream excelMapperTestData() { - return getArgumentsFromExcel("flowableExcelMapperTestData.xlsx"); + protected Stream excelMapperTestDataOk() { + return getArgumentsFromExcel("flowableExcelMapperTestData_ok.xlsx"); } @ParameterizedTest - @MethodSource("excelMapperTestData") - public void excelMapperTest(JsonNode row) { - JsonNode asIs = row.get("root"); - JsonNode toBe = row.get("test"); - //logger.info("{}root={}{}test={}", System.lineSeparator(), asIs, System.lineSeparator(), toBe); - Assertions.assertThat(isSubset(asIs, toBe)) - .withFailMessage(System.lineSeparator() + "root=" + asIs + System.lineSeparator() + "test=" + toBe).isTrue(); + @MethodSource("excelMapperTestDataOk") + public void excelMapperTestOk(JsonNode row) { + JsonNode root = row.get("root"); + JsonNode test = row.get("test"); + logger.info("{}root={}{}test={}", System.lineSeparator(), root, System.lineSeparator(), test); + Assertions.assertThat(isSubset(root, test)) + .withFailMessage(System.lineSeparator() + "root=" + root + System.lineSeparator() + "test=" + test).isTrue(); + } + + protected Stream excelMapperTestDataFail() { + return getArgumentsFromExcel("flowableExcelMapperTestData_fail.xlsx"); + } + @ParameterizedTest + @MethodSource("excelMapperTestDataFail") + public void excelMapperTestFail(JsonNode row) { + JsonNode root = row.get("root"); + JsonNode test = row.get("test"); + logger.info("{}root={}{}test={}", System.lineSeparator(), root, System.lineSeparator(), test); + Assertions.assertThat(isSubset(root, test)) + .withFailMessage(System.lineSeparator() + "root=" + root + System.lineSeparator() + "test=" + test).isFalse(); } } diff --git a/src/test/resources/flowableExcelMapperTestData.xlsx b/src/test/resources/flowableExcelMapperTestData.xlsx deleted file mode 100644 index b36a75f..0000000 Binary files a/src/test/resources/flowableExcelMapperTestData.xlsx and /dev/null differ diff --git a/src/test/resources/flowableExcelMapperTestData_fail.xlsx b/src/test/resources/flowableExcelMapperTestData_fail.xlsx new file mode 100644 index 0000000..498685b Binary files /dev/null and b/src/test/resources/flowableExcelMapperTestData_fail.xlsx differ diff --git a/src/test/resources/flowableExcelMapperTestData_ok.xlsx b/src/test/resources/flowableExcelMapperTestData_ok.xlsx new file mode 100644 index 0000000..5c830ba Binary files /dev/null and b/src/test/resources/flowableExcelMapperTestData_ok.xlsx differ