diff --git a/iso20022-core/src/main/java/com/prowidesoftware/swift/model/mx/adapters/OffsetDateTimeJsonAdapter.java b/iso20022-core/src/main/java/com/prowidesoftware/swift/model/mx/adapters/OffsetDateTimeJsonAdapter.java index 831d460e4..f866bd8c2 100644 --- a/iso20022-core/src/main/java/com/prowidesoftware/swift/model/mx/adapters/OffsetDateTimeJsonAdapter.java +++ b/iso20022-core/src/main/java/com/prowidesoftware/swift/model/mx/adapters/OffsetDateTimeJsonAdapter.java @@ -17,6 +17,7 @@ import com.google.gson.*; import java.lang.reflect.Type; +import java.math.BigDecimal; import java.time.LocalDateTime; import java.time.OffsetDateTime; import java.time.ZoneId; @@ -26,6 +27,9 @@ /** * This adapter enables accepting OffsetDateTime time Json format. + *

The adapter supports two DTO formats: the current one and the + * legacy one based on XMLGregorianCalendar model with Java 1.8. + *

* * @since 10.0.1 */ @@ -58,46 +62,101 @@ public JsonElement serialize( public OffsetDateTime deserialize( JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) { try { - // Parse DTO model - DateTimeOffsetDTO dateTimeOffsetDTO = gson.fromJson(jsonElement, DateTimeOffsetDTO.class); - - // Prepare OffsetDateTime - OffsetDateTime offsetDateTime; - int nano = 0; - if (dateTimeOffsetDTO.dateTime.time.nano != null) { - nano = dateTimeOffsetDTO.dateTime.time.nano; - } - - if (dateTimeOffsetDTO.offset != null) { - ZoneOffset zoneoffset = ZoneOffset.ofTotalSeconds(dateTimeOffsetDTO.offset.totalSeconds); - offsetDateTime = OffsetDateTime.of( - dateTimeOffsetDTO.dateTime.date.year, - dateTimeOffsetDTO.dateTime.date.month, - dateTimeOffsetDTO.dateTime.date.day, - dateTimeOffsetDTO.dateTime.time.hour, - dateTimeOffsetDTO.dateTime.time.minute, - dateTimeOffsetDTO.dateTime.time.second, - nano, - zoneoffset); - } else { - LocalDateTime localDateTime = LocalDateTime.of( - dateTimeOffsetDTO.dateTime.date.year, - dateTimeOffsetDTO.dateTime.date.month, - dateTimeOffsetDTO.dateTime.date.day, - dateTimeOffsetDTO.dateTime.time.hour, - dateTimeOffsetDTO.dateTime.time.minute, - dateTimeOffsetDTO.dateTime.time.second, - nano); - - ZoneId zoneId = ZoneOffset.systemDefault(); - offsetDateTime = localDateTime.atZone(zoneId).toOffsetDateTime(); - } - - return offsetDateTime; - } catch (Exception e) { - log.log(Level.FINEST, "Cannot parse JSON into OffsetDateTime: " + e.getMessage(), e); - return null; + // Parse DTO from current OffsetDateTime model + return deserializeFromOffsetDateTimeDTO(gson.fromJson(jsonElement, DateTimeOffsetDTO.class)); + } catch (final Exception e) { + log.log( + Level.FINEST, + "Cannot parse JSON into OffsetDateTime from current DTO format: " + e.getMessage(), + e); } + log.log(Level.FINEST, "Attempting parsing from legacy DTO format"); + try { + // Parse DTO from legacy XMLGregorianCalendar model + return deserializeFromXMLGregorianCalendarDTO(gson.fromJson(jsonElement, XMLGregorianCalendarDTO.class)); + } catch (final Exception e) { + log.log(Level.FINEST, "Cannot parse JSON into OffsetDateTime from legacy DTO format: " + e.getMessage(), e); + } + return null; + } + + private OffsetDateTime deserializeFromOffsetDateTimeDTO(final DateTimeOffsetDTO dateTimeOffsetDTO) { + // Prepare OffsetDateTime + OffsetDateTime offsetDateTime; + int nano = 0; + if (dateTimeOffsetDTO.dateTime.time.nano != null) { + nano = dateTimeOffsetDTO.dateTime.time.nano; + } + + if (dateTimeOffsetDTO.offset != null) { + ZoneOffset zoneoffset = ZoneOffset.ofTotalSeconds(dateTimeOffsetDTO.offset.totalSeconds); + offsetDateTime = OffsetDateTime.of( + dateTimeOffsetDTO.dateTime.date.year, + dateTimeOffsetDTO.dateTime.date.month, + dateTimeOffsetDTO.dateTime.date.day, + dateTimeOffsetDTO.dateTime.time.hour, + dateTimeOffsetDTO.dateTime.time.minute, + dateTimeOffsetDTO.dateTime.time.second, + nano, + zoneoffset); + } else { + LocalDateTime localDateTime = LocalDateTime.of( + dateTimeOffsetDTO.dateTime.date.year, + dateTimeOffsetDTO.dateTime.date.month, + dateTimeOffsetDTO.dateTime.date.day, + dateTimeOffsetDTO.dateTime.time.hour, + dateTimeOffsetDTO.dateTime.time.minute, + dateTimeOffsetDTO.dateTime.time.second, + nano); + + ZoneId zoneId = ZoneOffset.systemDefault(); + offsetDateTime = localDateTime.atZone(zoneId).toOffsetDateTime(); + } + + return offsetDateTime; + } + + private OffsetDateTime deserializeFromXMLGregorianCalendarDTO( + final XMLGregorianCalendarDTO xmlGregorianCalendarDTO) { + if (Integer.MIN_VALUE == xmlGregorianCalendarDTO.year) { + xmlGregorianCalendarDTO.year = 0; + } + if (Integer.MIN_VALUE == xmlGregorianCalendarDTO.month) { + xmlGregorianCalendarDTO.month = 0; + } + if (Integer.MIN_VALUE == xmlGregorianCalendarDTO.day) { + xmlGregorianCalendarDTO.day = 0; + } + if (Integer.MIN_VALUE == xmlGregorianCalendarDTO.hour) { + xmlGregorianCalendarDTO.hour = 0; + } + if (Integer.MIN_VALUE == xmlGregorianCalendarDTO.minute) { + xmlGregorianCalendarDTO.minute = 0; + } + if (Integer.MIN_VALUE == xmlGregorianCalendarDTO.second) { + xmlGregorianCalendarDTO.second = 0; + } + if (Integer.MIN_VALUE == xmlGregorianCalendarDTO.timezone) { + xmlGregorianCalendarDTO.timezone = null; + } + + return LocalDateTime.of( + xmlGregorianCalendarDTO.year, + xmlGregorianCalendarDTO.month, + xmlGregorianCalendarDTO.day, + xmlGregorianCalendarDTO.hour, + xmlGregorianCalendarDTO.minute, + xmlGregorianCalendarDTO.second, + xmlGregorianCalendarDTO + .fractionalSecond + .scaleByPowerOfTen(9) + .toBigInteger() + .intValueExact()) + .atZone( + xmlGregorianCalendarDTO.timezone != null + ? ZoneOffset.ofHours(xmlGregorianCalendarDTO.timezone) + : ZoneOffset.systemDefault()) + .toOffsetDateTime(); } static class DateTimeOffsetDTO { @@ -126,4 +185,15 @@ static class TimeDTO { static class OffsetDTO { Integer totalSeconds = 0; } + + static class XMLGregorianCalendarDTO { + Integer year; + Integer month; + Integer day; + Integer hour = 0; + Integer minute = 0; + Integer second = 0; + BigDecimal fractionalSecond = BigDecimal.ZERO; + Integer timezone; + } } diff --git a/iso20022-core/src/test/java/com/prowidesoftware/swift/model/mx/adapters/DateTimeJsonAdapterBackwardCompatibilityTest.java b/iso20022-core/src/test/java/com/prowidesoftware/swift/model/mx/adapters/DateTimeJsonAdapterBackwardCompatibilityTest.java new file mode 100644 index 000000000..5051c809d --- /dev/null +++ b/iso20022-core/src/test/java/com/prowidesoftware/swift/model/mx/adapters/DateTimeJsonAdapterBackwardCompatibilityTest.java @@ -0,0 +1,547 @@ +package com.prowidesoftware.swift.model.mx.adapters; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.prowidesoftware.swift.model.mx.AbstractMX; +import com.prowidesoftware.swift.model.mx.MxSese02500109; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +class DateTimeJsonAdapterBackwardCompatibilityTest { + private static final String XML_MX = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " IJKLMNOPXXX\n" + + " \n" + + " ABCDEFGHXXX\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " ABCDEFGHXXX\n" + + " \n" + + " ABCDEFGHXXX\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 1423905641002\n" + + " sese.025.001.09\n" + + " 2024-07-17T05:27:51Z\n" + + " COPY\n" + + " true\n" + + " 2024071700000208\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " FOO\n" + + " BAR\n" + + " TOTO\n" + + " RECE\n" + + " APMT\n" + + " TITI\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " EXCH\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " QRSTUVWYXXX\n" + + " \n" + + " \n" + + "
\n" + + "
2024-07-16
\n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
2024-07-17
\n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + " 2024-07-17T07:26:04.207459\n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + " NL0000009165\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 0\n" + + " \n" + + " \n" + + " \n" + + " NECISOGEFRPPAGN000L10\n" + + " \n" + + " \n" + + " CFREURSOGEFRPPTIT-DCA-SGSS\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " NETT\n" + + " \n" + + " PARQ\n" + + " \n" + + " DLVR\n" + + " T2S\n" + + " RT\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " ABCDEFGHXXX\n" + + " \n" + + " 2407162881091741\n" + + " \n" + + " \n" + + " \n" + + " QRSTUVWYXXX\n" + + " \n" + + " \n" + + " MOTICCEGITRRXXX9100000\n" + + " \n" + + " 1VUVZK\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " HGFEDCBAXXX\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " SOGEFRPPAGN\n" + + " \n" + + " \n" + + " NECISOGEFRPPAGN000L10\n" + + " \n" + + " FOO\n" + + " \n" + + " \n" + + " \n" + + " 1\n" + + " DBIT\n" + + " \n" + + " \n" + + " /Document/SctiesSttlmTxConf/TxIdDtls\n" + + " \n" + + " \n" + + " \n" + + " 42\n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + "
"; + + private static final String JSON_MX_V9 = "{\n" + " \"sctiesSttlmTxConf\": {\n" + + " \"txIdDtls\": {\n" + + " \"acctOwnrTxId\": \"FOO\",\n" + + " \"mktInfrstrctrTxId\": \"BAR\",\n" + + " \"prcrTxId\": \"TOTO\",\n" + + " \"sctiesMvmntTp\": \"RECE\",\n" + + " \"pmt\": \"APMT\",\n" + + " \"cmonId\": \"TITI\"\n" + + " },\n" + + " \"tradDtls\": {\n" + + " \"plcOfTrad\": {\n" + + " \"mktTpAndId\": {\n" + + " \"tp\": {\n" + + " \"cd\": \"EXCH\"\n" + + " }\n" + + " }\n" + + " },\n" + + " \"plcOfClr\": {\n" + + " \"id\": \"QRSTUVWYXXX\"\n" + + " },\n" + + " \"tradDt\": {\n" + + " \"dt\": {\n" + + " \"dt\": {\n" + + " \"year\": 2024,\n" + + " \"month\": 7,\n" + + " \"day\": 16,\n" + + " \"timezone\": -2147483648,\n" + + " \"hour\": -2147483648,\n" + + " \"minute\": -2147483648,\n" + + " \"second\": -2147483648\n" + + " }\n" + + " }\n" + + " },\n" + + " \"sttlmDt\": {\n" + + " \"dt\": {\n" + + " \"dt\": {\n" + + " \"year\": 2024,\n" + + " \"month\": 7,\n" + + " \"day\": 17,\n" + + " \"timezone\": -2147483648,\n" + + " \"hour\": -2147483648,\n" + + " \"minute\": -2147483648,\n" + + " \"second\": -2147483648\n" + + " }\n" + + " }\n" + + " },\n" + + " \"fctvSttlmDt\": {\n" + + " \"dt\": {\n" + + " \"dtTm\": {\n" + + " \"year\": 2024,\n" + + " \"month\": 7,\n" + + " \"day\": 17,\n" + + " \"timezone\": -2147483648,\n" + + " \"hour\": 7,\n" + + " \"minute\": 26,\n" + + " \"second\": 4,\n" + + " \"fractionalSecond\": 0.207459\n" + + " }\n" + + " }\n" + + " }\n" + + " },\n" + + " \"finInstrmId\": {\n" + + " \"isin\": \"NL0000009165\"\n" + + " },\n" + + " \"qtyAndAcctDtls\": {\n" + + " \"sttldQty\": {\n" + + " \"qty\": {\n" + + " \"unit\": 0\n" + + " }\n" + + " },\n" + + " \"sfkpgAcct\": {\n" + + " \"id\": \"NECISOGEFRPPAGN000L10\"\n" + + " },\n" + + " \"cshAcct\": {\n" + + " \"prtry\": \"CFREURSOGEFRPPTIT-DCA-SGSS\"\n" + + " }\n" + + " },\n" + + " \"sttlmParams\": {\n" + + " \"sctiesTxTp\": {\n" + + " \"cd\": \"NETT\"\n" + + " },\n" + + " \"prtlSttlmInd\": \"PARQ\",\n" + + " \"cshSubBalTp\": {\n" + + " \"id\": \"DLVR\",\n" + + " \"issr\": \"T2S\",\n" + + " \"schmeNm\": \"RT\"\n" + + " }\n" + + " },\n" + + " \"dlvrgSttlmPties\": {\n" + + " \"dpstry\": {\n" + + " \"id\": {\n" + + " \"anyBIC\": \"ABCDEFGHXXX\"\n" + + " },\n" + + " \"prcgId\": \"2407162881091741\"\n" + + " },\n" + + " \"pty1\": {\n" + + " \"id\": {\n" + + " \"anyBIC\": \"QRSTUVWYXXX\"\n" + + " },\n" + + " \"sfkpgAcct\": {\n" + + " \"id\": \"MOTICCEGITRRXXX9100000\"\n" + + " },\n" + + " \"prcgId\": \"1VUVZK\"\n" + + " }\n" + + " },\n" + + " \"rcvgSttlmPties\": {\n" + + " \"dpstry\": {\n" + + " \"id\": {\n" + + " \"anyBIC\": \"HGFEDCBAXXX\"\n" + + " }\n" + + " },\n" + + " \"pty1\": {\n" + + " \"id\": {\n" + + " \"anyBIC\": \"SOGEFRPPAGN\"\n" + + " },\n" + + " \"sfkpgAcct\": {\n" + + " \"id\": \"NECISOGEFRPPAGN000L10\"\n" + + " },\n" + + " \"prcgId\": \"FOO\"\n" + + " }\n" + + " },\n" + + " \"sttldAmt\": {\n" + + " \"amt\": {\n" + + " \"value\": 1,\n" + + " \"ccy\": \"EUR\"\n" + + " },\n" + + " \"cdtDbtInd\": \"DBIT\"\n" + + " },\n" + + " \"splmtryData\": [\n" + + " {\n" + + " \"plcAndNm\": \"/Document/SctiesSttlmTxConf/TxIdDtls\",\n" + + " \"envlp\": {}\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"appHdr\": {\n" + + " \"fr\": {\n" + + " \"fiId\": {\n" + + " \"finInstnId\": {\n" + + " \"bicfi\": \"IJKLMNOPXXX\",\n" + + " \"othr\": {\n" + + " \"id\": \"ABCDEFGHXXX\"\n" + + " }\n" + + " }\n" + + " }\n" + + " },\n" + + " \"to\": {\n" + + " \"fiId\": {\n" + + " \"finInstnId\": {\n" + + " \"bicfi\": \"ABCDEFGHXXX\",\n" + + " \"othr\": {\n" + + " \"id\": \"ABCDEFGHXXX\"\n" + + " }\n" + + " }\n" + + " }\n" + + " },\n" + + " \"bizMsgIdr\": \"1423905641002\",\n" + + " \"msgDefIdr\": \"sese.025.001.09\",\n" + + " \"creDt\": {\n" + + " \"year\": 2024,\n" + + " \"month\": 7,\n" + + " \"day\": 17,\n" + + " \"timezone\": 0,\n" + + " \"hour\": 5,\n" + + " \"minute\": 27,\n" + + " \"second\": 51\n" + + " },\n" + + " \"cpyDplct\": \"COPY\",\n" + + " \"pssblDplct\": true,\n" + + " \"prty\": \"2024071700000208\",\n" + + " \"namespace\": \"urn:iso:std:iso:20022:tech:xsd:head.001.001.01\"\n" + + " },\n" + + " \"type\": \"MX\",\n" + + " \"@xmlns\": \"urn:iso:std:iso:20022:tech:xsd:sese.025.001.09\",\n" + + " \"identifier\": \"sese.025.001.09\"\n" + + " }"; + + private static final String JSON_MX_V10 = "{\n" + " \"sctiesSttlmTxConf\": {\n" + + " \"txIdDtls\": {\n" + + " \"acctOwnrTxId\": \"FOO\",\n" + + " \"mktInfrstrctrTxId\": \"BAR\",\n" + + " \"prcrTxId\": \"TOTO\",\n" + + " \"sctiesMvmntTp\": \"RECE\",\n" + + " \"pmt\": \"APMT\",\n" + + " \"cmonId\": \"TITI\"\n" + + " },\n" + + " \"tradDtls\": {\n" + + " \"plcOfTrad\": {\n" + + " \"mktTpAndId\": {\n" + + " \"tp\": {\n" + + " \"cd\": \"EXCH\"\n" + + " }\n" + + " }\n" + + " },\n" + + " \"plcOfClr\": {\n" + + " \"id\": \"QRSTUVWYXXX\"\n" + + " },\n" + + " \"tradDt\": {\n" + + " \"dt\": {\n" + + " \"dt\": {\n" + + " \"year\": 2024,\n" + + " \"month\": 7,\n" + + " \"day\": 16\n" + + " }\n" + + " }\n" + + " },\n" + + " \"sttlmDt\": {\n" + + " \"dt\": {\n" + + " \"dt\": {\n" + + " \"year\": 2024,\n" + + " \"month\": 7,\n" + + " \"day\": 17\n" + + " }\n" + + " }\n" + + " },\n" + + " \"fctvSttlmDt\": {\n" + + " \"dt\": {\n" + + " \"dtTm\": {\n" + + " \"dateTime\": {\n" + + " \"date\": {\n" + + " \"year\": 2024,\n" + + " \"month\": 7,\n" + + " \"day\": 17\n" + + " },\n" + + " \"time\": {\n" + + " \"hour\": 7,\n" + + " \"minute\": 26,\n" + + " \"second\": 4,\n" + + " \"nano\": 207459000\n" + + " }\n" + + " },\n" + + " \"offset\": {\n" + + " \"totalSeconds\": 7200\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + " },\n" + + " \"finInstrmId\": {\n" + + " \"isin\": \"NL0000009165\"\n" + + " },\n" + + " \"qtyAndAcctDtls\": {\n" + + " \"sttldQty\": {\n" + + " \"qty\": {\n" + + " \"unit\": 0\n" + + " }\n" + + " },\n" + + " \"sfkpgAcct\": {\n" + + " \"id\": \"NECISOGEFRPPAGN000L10\"\n" + + " },\n" + + " \"cshAcct\": {\n" + + " \"prtry\": \"CFREURSOGEFRPPTIT-DCA-SGSS\"\n" + + " }\n" + + " },\n" + + " \"sttlmParams\": {\n" + + " \"sctiesTxTp\": {\n" + + " \"cd\": \"NETT\"\n" + + " },\n" + + " \"prtlSttlmInd\": \"PARQ\",\n" + + " \"cshSubBalTp\": {\n" + + " \"id\": \"DLVR\",\n" + + " \"issr\": \"T2S\",\n" + + " \"schmeNm\": \"RT\"\n" + + " }\n" + + " },\n" + + " \"dlvrgSttlmPties\": {\n" + + " \"dpstry\": {\n" + + " \"id\": {\n" + + " \"anyBIC\": \"ABCDEFGHXXX\"\n" + + " },\n" + + " \"prcgId\": \"2407162881091741\"\n" + + " },\n" + + " \"pty1\": {\n" + + " \"id\": {\n" + + " \"anyBIC\": \"QRSTUVWYXXX\"\n" + + " },\n" + + " \"sfkpgAcct\": {\n" + + " \"id\": \"MOTICCEGITRRXXX9100000\"\n" + + " },\n" + + " \"prcgId\": \"1VUVZK\"\n" + + " }\n" + + " },\n" + + " \"rcvgSttlmPties\": {\n" + + " \"dpstry\": {\n" + + " \"id\": {\n" + + " \"anyBIC\": \"HGFEDCBAXXX\"\n" + + " }\n" + + " },\n" + + " \"pty1\": {\n" + + " \"id\": {\n" + + " \"anyBIC\": \"SOGEFRPPAGN\"\n" + + " },\n" + + " \"sfkpgAcct\": {\n" + + " \"id\": \"NECISOGEFRPPAGN000L10\"\n" + + " },\n" + + " \"prcgId\": \"FOO\"\n" + + " }\n" + + " },\n" + + " \"sttldAmt\": {\n" + + " \"amt\": {\n" + + " \"value\": 1,\n" + + " \"ccy\": \"EUR\"\n" + + " },\n" + + " \"cdtDbtInd\": \"DBIT\"\n" + + " },\n" + + " \"splmtryData\": [\n" + + " {\n" + + " \"plcAndNm\": \"/Document/SctiesSttlmTxConf/TxIdDtls\",\n" + + " \"envlp\": {}\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"appHdr\": {\n" + + " \"fr\": {\n" + + " \"fiId\": {\n" + + " \"finInstnId\": {\n" + + " \"bicfi\": \"IJKLMNOPXXX\",\n" + + " \"othr\": {\n" + + " \"id\": \"ABCDEFGHXXX\"\n" + + " }\n" + + " }\n" + + " }\n" + + " },\n" + + " \"to\": {\n" + + " \"fiId\": {\n" + + " \"finInstnId\": {\n" + + " \"bicfi\": \"ABCDEFGHXXX\",\n" + + " \"othr\": {\n" + + " \"id\": \"ABCDEFGHXXX\"\n" + + " }\n" + + " }\n" + + " }\n" + + " },\n" + + " \"bizMsgIdr\": \"1423905641002\",\n" + + " \"msgDefIdr\": \"sese.025.001.09\",\n" + + " \"creDt\": {\n" + + " \"dateTime\": {\n" + + " \"date\": {\n" + + " \"year\": 2024,\n" + + " \"month\": 7,\n" + + " \"day\": 17\n" + + " },\n" + + " \"time\": {\n" + + " \"hour\": 5,\n" + + " \"minute\": 27,\n" + + " \"second\": 51,\n" + + " \"nano\": 0\n" + + " }\n" + + " },\n" + + " \"offset\": {\n" + + " \"totalSeconds\": 0\n" + + " }\n" + + " },\n" + + " \"cpyDplct\": \"COPY\",\n" + + " \"pssblDplct\": true,\n" + + " \"prty\": \"2024071700000208\",\n" + + " \"namespace\": \"urn:iso:std:iso:20022:tech:xsd:head.001.001.01\"\n" + + " },\n" + + " \"type\": \"MX\",\n" + + " \"@xmlns\": \"urn:iso:std:iso:20022:tech:xsd:sese.025.001.09\",\n" + + " \"identifier\": \"sese.025.001.09\"\n" + + " }"; + + @Test + void v10_should_be_able_to_parse_json_with_date_time_created_from_v9() { + final MxSese02500109 mx = (MxSese02500109) AbstractMX.fromJson(JSON_MX_V9); + assertThat(mx.getSctiesSttlmTxConf().getTradDtls().getTradDt().getDt().getDt()) + .isNotNull(); // Success + assertThat(mx.getSctiesSttlmTxConf() + .getTradDtls() + .getFctvSttlmDt() + .getDt() + .getDtTm()) + .isNotNull(); // Fail + } + + @Test + void v10_should_be_able_to_parse_json_from_v9_and_read_same_content_than_json_from_v10_and_xml() { + final MxSese02500109 reference = (MxSese02500109) AbstractMX.parse(XML_MX); + final MxSese02500109 fromV9 = (MxSese02500109) AbstractMX.fromJson(JSON_MX_V9); + final String toV10 = reference.toJson(); + final MxSese02500109 fromV10 = (MxSese02500109) AbstractMX.fromJson(JSON_MX_V10); + + assertThat(fromV9).isEqualTo(reference); + assertThat(fromV10).isEqualTo(reference); + assertThat(fromV9).isEqualTo(fromV10); + assertThat(toV10).isEqualToIgnoringWhitespace(JSON_MX_V10); + assertThat(toV10).isNotEqualToIgnoringWhitespace(JSON_MX_V9); + } +} diff --git a/iso20022-core/src/test/java/com/prowidesoftware/swift/model/mx/adapters/OffsetTimeJsonAdapterTest.java b/iso20022-core/src/test/java/com/prowidesoftware/swift/model/mx/adapters/OffsetTimeJsonAdapterTest.java index d92996d36..4c5b1fe02 100644 --- a/iso20022-core/src/test/java/com/prowidesoftware/swift/model/mx/adapters/OffsetTimeJsonAdapterTest.java +++ b/iso20022-core/src/test/java/com/prowidesoftware/swift/model/mx/adapters/OffsetTimeJsonAdapterTest.java @@ -19,7 +19,9 @@ import com.google.gson.JsonElement; import com.google.gson.JsonParser; +import java.time.Instant; import java.time.OffsetTime; +import java.time.ZoneId; import org.junit.jupiter.api.Test; class OffsetTimeJsonAdapterTest { @@ -28,7 +30,10 @@ class OffsetTimeJsonAdapterTest { @Test void testSerializationAndDeserialization() { - int systemOffsetSeconds = OffsetTime.now().getOffset().getTotalSeconds(); + int systemOffsetSeconds = ZoneId.systemDefault() + .getRules() + .getStandardOffset(Instant.now()) + .getTotalSeconds(); // without offset, nano 0 String jsonActual = "{\"time\":{\"hour\":12,\"minute\":13,\"second\":14,\"nano\":0}}";