Skip to content

Commit

Permalink
Merge pull request #712 from goldmansachs/serialization
Browse files Browse the repository at this point in the history
Serialization
  • Loading branch information
opatrascoiu authored Sep 18, 2024
2 parents 0d4a23a + e8b0b5d commit 82926f1
Show file tree
Hide file tree
Showing 20 changed files with 653 additions and 127 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@

import com.gs.dmn.feel.lib.type.time.BaseDateTimeLib;
import com.gs.dmn.feel.lib.type.time.DateTimeLib;
import com.gs.dmn.feel.lib.type.time.xml.DefaultDateTimeLib;
import com.gs.dmn.runtime.DMNRuntimeException;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.TextStyle;
import java.time.temporal.*;
import java.util.List;
Expand All @@ -33,10 +33,8 @@
public class TemporalDateTimeLib extends BaseDateTimeLib implements DateTimeLib<Number, LocalDate, TemporalAccessor, TemporalAccessor, TemporalAmount> {
private static final BigDecimal E9 = BigDecimal.valueOf(1000000000);

private final DefaultDateTimeLib dateTimeLib;

public TemporalDateTimeLib() {
this.dateTimeLib = new DefaultDateTimeLib();
}

//
Expand Down Expand Up @@ -76,7 +74,7 @@ public TemporalAccessor time(String literal) {
}

literal = this.fixDateTimeFormat(literal);
return this.dateTimeLib.timeTemporalAccessor(literal);
return this.timeTemporalAccessor(literal);
}

@Override
Expand Down Expand Up @@ -140,7 +138,7 @@ public TemporalAccessor dateAndTime(String literal) {
}

literal = this.fixDateTimeFormat(literal);
return this.dateTimeLib.dateTimeTemporalAccessor(literal);
return this.dateTimeTemporalAccessor(literal);
}

@Override
Expand Down Expand Up @@ -407,4 +405,65 @@ private <T> T minMax(List<T> list, TemporalComparator temporalComparator, Tempor
}
return result;
}

public TemporalAccessor dateTemporalAccessor(String literal) {
if (literal == null) {
return null;
}

if (!BEGIN_YEAR.matcher(literal).find()) {
throw new DMNRuntimeException(String.format("Illegal year in '%s'", literal));
}
try {
return LocalDate.from(FEEL_DATE.parse(literal));
} catch (DateTimeException e) {
throw new RuntimeException("Parsing exception in date literal", e);
}
}

public TemporalAccessor timeTemporalAccessor(String literal) {
if (literal == null) {
return null;
}

if (this.hasZoneOffset(literal) && this.hasZoneId(literal)) {
throw new DMNRuntimeException(String.format("Time literal '%s' has both a zone offset and zone id", literal));
}
try {
TemporalAccessor parsed = FEEL_TIME.parse(literal);

if (parsed.query(TemporalQueries.offset()) != null) {
return parsed.query(OffsetTime::from);
} else if (parsed.query(TemporalQueries.zone()) == null) {
return parsed.query(LocalTime::from);
}

return parsed;
} catch (DateTimeException e) {
throw new DMNRuntimeException("Parsing exception in time literal", e);
}
}

private TemporalAccessor dateTimeTemporalAccessor(String literal) {
if (literal == null) {
return null;
}

if (!BaseDateTimeLib.BEGIN_YEAR.matcher(literal).find()) {
throw new DMNRuntimeException(String.format("Illegal year in '%s'", literal));
}
if (this.hasZoneOffset(literal) && this.hasZoneId(literal)) {
throw new DMNRuntimeException(String.format("Time literal '%s' has both a zone offset and zone id", literal));
}
try {
if (literal.contains("T")) {
return FEEL_DATE_TIME.parseBest(literal, ZonedDateTime::from, OffsetDateTime::from, LocalDateTime::from);
} else {
LocalDate value = DateTimeFormatter.ISO_DATE.parse(literal, LocalDate::from);
return LocalDateTime.of(value, LocalTime.of(0, 0));
}
} catch (Exception e) {
throw new RuntimeException("Parsing exception in date and time literal", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2016 Goldman Sachs.
*
* 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.gs.dmn.runtime.serialization;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.gs.dmn.feel.lib.type.time.pure.TemporalDateTimeLib;
import com.gs.dmn.runtime.DMNRuntimeException;

import java.io.IOException;
import java.time.LocalDate;

public class LocalDateDeserializer extends JsonDeserializer<LocalDate> {
private final TemporalDateTimeLib dateTimeLib = new TemporalDateTimeLib();

public LocalDateDeserializer() {
}

@Override
public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
ObjectCodec oc = jp.getCodec();
JsonNode node = oc.readTree(jp);

try {
String literal = node.asText();
if (literal == null) {
return null;
} else {
return dateTimeLib.date(literal);
}
} catch (Exception e) {
throw new DMNRuntimeException(String.format("Error deserializing '%s' ", node), e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2016 Goldman Sachs.
*
* 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.gs.dmn.runtime.serialization;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.gs.dmn.feel.lib.JavaTimeFEELLib;

import java.io.IOException;
import java.time.LocalDate;

public class LocalDateSerializer extends JsonSerializer<LocalDate> {
private final JavaTimeFEELLib feelLib = new JavaTimeFEELLib();
@Override
public void serialize(LocalDate value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(feelLib.string(value));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2016 Goldman Sachs.
*
* 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.gs.dmn.runtime.serialization;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.gs.dmn.feel.lib.type.time.mixed.MixedDateTimeLib;
import com.gs.dmn.runtime.DMNRuntimeException;

import java.io.IOException;
import java.time.OffsetTime;

public class OffsetTimeDeserializer extends JsonDeserializer<OffsetTime> {
private final MixedDateTimeLib dateTimeLib = new MixedDateTimeLib();

public OffsetTimeDeserializer() {
}

@Override
public OffsetTime deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
ObjectCodec oc = jp.getCodec();
JsonNode node = oc.readTree(jp);

try {
String literal = node.asText();
if (literal == null) {
return null;
} else {
return this.dateTimeLib.time(literal);
}
} catch (Exception e) {
throw new DMNRuntimeException(String.format("Error deserializing '%s' ", node), e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2016 Goldman Sachs.
*
* 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.gs.dmn.runtime.serialization;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.gs.dmn.feel.lib.MixedJavaTimeFEELLib;

import java.io.IOException;
import java.time.OffsetTime;

public class OffsetTimeSerializer extends JsonSerializer<OffsetTime> {
private final MixedJavaTimeFEELLib feelLib = new MixedJavaTimeFEELLib();
@Override
public void serialize(OffsetTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(feelLib.string(value));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2016 Goldman Sachs.
*
* 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.gs.dmn.runtime.serialization;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.gs.dmn.feel.lib.type.time.pure.TemporalDateTimeLib;
import com.gs.dmn.runtime.DMNRuntimeException;

import java.io.IOException;
import java.time.temporal.TemporalAccessor;

public class TemporalAccessorDeserializer extends JsonDeserializer<TemporalAccessor> {
private final TemporalDateTimeLib dateTimeLib = new TemporalDateTimeLib();

public TemporalAccessorDeserializer() {
}

@Override
public TemporalAccessor deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
ObjectCodec oc = jp.getCodec();
JsonNode node = oc.readTree(jp);

try {
String literal = node.asText();
if (literal == null) {
return null;
} else {
if (literal.contains("T")) {
return dateTimeLib.dateAndTime(literal);
} else {
try {
return this.dateTimeLib.dateTemporalAccessor(literal);
} catch (Exception e) {
}
return this.dateTimeLib.timeTemporalAccessor(literal);
}
}
} catch (Exception e) {
throw new DMNRuntimeException(String.format("Error deserializing '%s' ", node), e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2016 Goldman Sachs.
*
* 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.gs.dmn.runtime.serialization;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.gs.dmn.feel.lib.JavaTimeFEELLib;

import java.io.IOException;
import java.time.temporal.TemporalAccessor;

public class TemporalAccessorSerializer extends JsonSerializer<TemporalAccessor> {
private final JavaTimeFEELLib feelLib = new JavaTimeFEELLib();
@Override
public void serialize(TemporalAccessor value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(feelLib.string(value));
}
}
Loading

0 comments on commit 82926f1

Please sign in to comment.