All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.xlrit.gears.server.graphql.OffsetDateTimeScalar Maven / Gradle / Ivy

The newest version!
package com.xlrit.gears.server.graphql;

import java.time.DateTimeException;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
import java.util.function.Function;

import graphql.language.StringValue;
import graphql.language.Value;
import graphql.schema.*;

import static graphql.scalar.CoercingUtil.typeName;

public final class OffsetDateTimeScalar {
    public static final GraphQLScalarType INSTANCE;

    private OffsetDateTimeScalar() {}
    private static final DateTimeFormatter customOutputFormatter = getCustomDateTimeFormatter();

    static {
        Coercing coercing = new Coercing<>() {
            @Override
            public String serialize(Object input) throws CoercingSerializeException {
                if (!(input instanceof OffsetDateTime offsetDateTime)) {
                    throw new CoercingSerializeException(
                            "Expected something we can convert to 'java.time.OffsetDateTime' but was '" + typeName(input) + "'."
                    );
                }
                try {
                    return customOutputFormatter.format(offsetDateTime);
                }
                catch (DateTimeException e) {
                    throw new CoercingSerializeException(
                            "Unable to turn TemporalAccessor into OffsetDateTime because of : '" + e.getMessage() + "'."
                    );
                }
            }

            @Override
            public OffsetDateTime parseValue(Object input) throws CoercingParseValueException {
                if (input instanceof OffsetDateTime offsetDateTime) {
                    return offsetDateTime;
                }
                else if (input instanceof ZonedDateTime zonedDateTime) {
                    return zonedDateTime.toOffsetDateTime();
                }
                else if (input instanceof String s) {
                    return parseOffsetDateTime(s, CoercingParseValueException::new);
                }
                else {
                    throw new CoercingParseValueException(
                            "Expected a 'String' but was '" + typeName(input) + "'."
                    );
                }
            }

            @Override
            public OffsetDateTime parseLiteral(Object input) throws CoercingParseLiteralException {
                if (!(input instanceof StringValue)) {
                    throw new CoercingParseLiteralException(
                            "Expected AST type 'StringValue' but was '" + typeName(input) + "'."
                    );
                }
                return parseOffsetDateTime(((StringValue) input).getValue(), CoercingParseLiteralException::new);
            }

            @Override
            public Value valueToLiteral(Object input) {
                String s = serialize(input);
                return StringValue.newStringValue(s).build();
            }

            private OffsetDateTime parseOffsetDateTime(String s, Function exceptionMaker) {
                try {
                    OffsetDateTime parse = OffsetDateTime.parse(s, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
                    if (parse.get(ChronoField.OFFSET_SECONDS) == 0 && s.endsWith("-00:00")) {
                        throw exceptionMaker.apply("Invalid value : '" + s + "'. Negative zero offset is not allowed");
                    }
                    return parse;
                } catch (DateTimeParseException e) {
                    throw exceptionMaker.apply("Invalid RFC3339 value : '" + s + "'. because of : '" + e.getMessage() + "'");
                }
            }
        };

        INSTANCE = GraphQLScalarType.newScalar()
                .name("DateTime")
                .description("A slightly refined version of RFC-3339 compliant DateTime Scalar")
                .specifiedByUrl("https://scalars.graphql.org/andimarek/date-time")
                .coercing(coercing)
                .build();
    }

    private static DateTimeFormatter getCustomDateTimeFormatter() {
        return new DateTimeFormatterBuilder()
                .parseCaseInsensitive()
                .append(DateTimeFormatter.ISO_LOCAL_DATE)
                .appendLiteral('T')
                .appendValue(ChronoField.HOUR_OF_DAY, 2)
                .appendLiteral(':')
                .appendValue(ChronoField.MINUTE_OF_HOUR, 2)
                .appendLiteral(':')
                .appendValue(ChronoField.SECOND_OF_MINUTE, 2)
                .appendFraction(ChronoField.NANO_OF_SECOND, 3, 3, true)
                .appendOffset("+HH:MM", "Z")
                .toFormatter();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy