Skip to content

Commit

Permalink
fix Zulu adapter after merge
Browse files Browse the repository at this point in the history
  • Loading branch information
zubri committed May 21, 2024
1 parent bb44696 commit b10476c
Show file tree
Hide file tree
Showing 8 changed files with 265 additions and 194 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import com.prowidesoftware.deprecation.ProwideDeprecated;
import com.prowidesoftware.deprecation.TargetYear;
import com.prowidesoftware.swift.model.mx.adapters.IsoDateTimeAdapter;
import com.prowidesoftware.swift.model.mx.adapters.ZuluDateTimeAdapter;
import com.prowidesoftware.swift.model.mx.adapters.ZuluOffsetDateTimeAdapter;
import com.prowidesoftware.swift.model.mx.dic.BusinessApplicationHeaderV01Impl;
import com.prowidesoftware.swift.model.mx.dic.Party9Choice;
import jakarta.xml.bind.JAXBContext;
Expand Down Expand Up @@ -223,7 +223,7 @@ public String xml(MxWriteParams params) {
try {
JAXBContext context;
IsoDateTimeAdapter currentAdapter = params.adapters.dateTimeAdapter;
params.adapters.dateTimeAdapter = new IsoDateTimeAdapter(new ZuluDateTimeAdapter());
params.adapters.dateTimeAdapter = new IsoDateTimeAdapter(new ZuluOffsetDateTimeAdapter());
if (params.context != null) {
context = params.context;
} else {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* Copyright 2006-2023 Prowide
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.prowidesoftware.swift.model.mx.adapters;

import jakarta.xml.bind.annotation.adapters.XmlAdapter;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* XMLGregorianCalendar adapter for date time elements.
* <p>
* Marshals the date time as a Zulu time with format YYYY-MM-DDThh:mm:ss[.sss]Z which is aligned
* with ISO 8601. Dislike the default jaxb implementation, this adapter will always print the Z
* The fractional seconds is printed only when it is different from zero.
* <p>
* Notice the configured adapter in the model is the {@link IsoDateTimeAdapter} wrapper class, but you can pass this
* default implementation or your own in the constructor.
*
* @see TypeAdaptersConfiguration
* @since 9.4,5
*/
public class ZuluOffsetDateTimeAdapter extends XmlAdapter<String, OffsetDateTime> {
private static final Logger log = Logger.getLogger(ZuluOffsetDateTimeAdapter.class.getName());
private static final String FRACTIONAL_SECONDS_REGEX = "\\.0{1,}[Z+-]";
private static final Pattern FRACTIONAL_SECONDS_PATTERN = Pattern.compile(FRACTIONAL_SECONDS_REGEX);

private final DateTimeFormatter marshalFormat;

/**
* Creates a date time adapter with the default format.
*/
public ZuluOffsetDateTimeAdapter() {
this.marshalFormat = new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd'T'HH:mm:ss")
.optionalStart()
.appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
.optionalEnd()
.appendPattern("'Z'")
.toFormatter()
.withZone(ZoneOffset.UTC);
}

/**
* Parses a date-time string to create an OffsetDateTime object.
*
* @param value the XML date time value to convert
* @return created OffsetDateTime object or null if it cannot be parsed
*/
@Override
public OffsetDateTime unmarshal(String value) {
return parseOffsetDateTime(value);
}

/**
* Formats an OffsetDateTime to a string using the configured format.
*
* @param offsetDateTime the model OffsetDateTime to marshal
* @return formatted content for the XML
*/
@Override
public String marshal(OffsetDateTime offsetDateTime) throws Exception {
// Convert to Zulu time (UTC) before formatting
OffsetDateTime utcDateTime = offsetDateTime.withOffsetSameInstant(ZoneOffset.UTC);
String formatted = formatOffsetDateTime(this.marshalFormat, utcDateTime);

// Remove trailing fractional seconds if they are all zeros
Matcher matcher = FRACTIONAL_SECONDS_PATTERN.matcher(formatted);
if (matcher.find()) {
formatted = formatted.replace(matcher.group(), "Z");
}

return formatted;
}

private static OffsetDateTime parseOffsetDateTime(String value) {
if (value == null) {
return null;
}
try {
return OffsetDateTime.parse(value);
} catch (DateTimeParseException e) {
log.log(Level.FINEST, "Error parsing OffsetDateTime: " + e.getMessage());
try {
// Attempt to parse as LocalDateTime and assume system default time zone
LocalDateTime localDateTime = LocalDateTime.parse(value);
return localDateTime.atZone(ZoneId.systemDefault()).toOffsetDateTime();
} catch (DateTimeParseException e2) {
log.log(Level.FINEST, "Error parsing LocalDateTime: " + e2.getMessage());
return null;
}
}
}

private static String formatOffsetDateTime(DateTimeFormatter dateTimeFormatter, OffsetDateTime offsetDateTime) {
return dateTimeFormatter.format(offsetDateTime);
}

@Override
public String toString() {
return "ZuluOffsetDateTimeAdapter{ yyyy-MM-dd'T'HH:mm:ss[.SSS]Z }";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
*/
package com.prowidesoftware.swift.model.mx;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -146,4 +145,32 @@ public void testParseWithWrapper() {
assertEquals("seev.037.002.02", h.getMsgDefIdr());
assertNotNull(h.getCreDt());
}

@Test
public void testCreationDatetime() {
String xml =
"<AppHdr xmlns=\"urn:iso:std:iso:20022:tech:xsd:head.001.001.01\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"
+ " <Fr>\n"
+ " <FIId>\n"
+ " <FinInstnId>\n"
+ " <BICFI>AAAACAX0XXX</BICFI>\n"
+ " </FinInstnId>\n"
+ " </FIId>\n"
+ " </Fr>\n"
+ " <To>\n"
+ " <FIId>\n"
+ " <FinInstnId>\n"
+ " <BICFI>CITIUS33XXX</BICFI>\n"
+ " </FinInstnId>\n"
+ " </FIId>\n"
+ " </To>\n"
+ " <BizMsgIdr>asdfasdfasd</BizMsgIdr>\n"
+ " <MsgDefIdr>setr.004.001.04</MsgDefIdr>\n"
+ " <CreDt>2021-06-25T00:10:21Z</CreDt>\n"
+ " </AppHdr>";
BusinessAppHdrV01 h = BusinessAppHdrV01.parse(xml);
assertNotNull(h);
// System.out.println(h.xml());
assertTrue(h.xml().contains("<CreDt>2021-06-25T00:10:21Z</CreDt>"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,32 +121,4 @@ public void testParseWithWrapper() {
assertEquals("11308917", h.getMsgRef());
assertNotNull(h.getCrDate());
}

@Test
public void testCreationDatetime() {
String xml =
"<AppHdr xmlns=\"urn:iso:std:iso:20022:tech:xsd:head.001.001.01\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"
+ " <Fr>\n"
+ " <FIId>\n"
+ " <FinInstnId>\n"
+ " <BICFI>AAAACAX0XXX</BICFI>\n"
+ " </FinInstnId>\n"
+ " </FIId>\n"
+ " </Fr>\n"
+ " <To>\n"
+ " <FIId>\n"
+ " <FinInstnId>\n"
+ " <BICFI>CITIUS33XXX</BICFI>\n"
+ " </FinInstnId>\n"
+ " </FIId>\n"
+ " </To>\n"
+ " <BizMsgIdr>asdfasdfasd</BizMsgIdr>\n"
+ " <MsgDefIdr>setr.004.001.04</MsgDefIdr>\n"
+ " <CreDt>2021-06-25T00:10:21Z</CreDt>\n"
+ " </AppHdr>";
BusinessAppHdrV01 h = BusinessAppHdrV01.parse(xml);
assertNotNull(h);
// System.out.println(h.xml());
assertTrue(h.xml().contains("<CreDt>2021-06-25T00:10:21Z</CreDt>"));
}
}
Loading

0 comments on commit b10476c

Please sign in to comment.