DurationScalar.java
/*
* Licensed to The Apereo Foundation under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
*
* The Apereo Foundation licenses this file to you under the Educational
* Community 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://opensource.org/licenses/ecl2.txt
*
* 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 org.opencastproject.graphql.scalar;
import java.time.Duration;
import java.util.Locale;
import java.util.function.Function;
import graphql.GraphQLContext;
import graphql.execution.CoercedVariables;
import graphql.language.StringValue;
import graphql.language.Value;
import graphql.schema.Coercing;
import graphql.schema.CoercingParseLiteralException;
import graphql.schema.CoercingParseValueException;
import graphql.schema.CoercingSerializeException;
import graphql.schema.GraphQLScalarType;
public final class DurationScalar {
public static final GraphQLScalarType INSTANCE;
private DurationScalar() { }
static {
Coercing<Duration, String> coercing = new Coercing<Duration, String>() {
@Override
public String serialize(Object dataFetcherResult, GraphQLContext graphQLContext, Locale locale)
throws CoercingSerializeException {
Duration duration;
if (dataFetcherResult instanceof Duration) {
duration = (Duration) dataFetcherResult;
} else if (dataFetcherResult instanceof String) {
duration = parseDuration((String) dataFetcherResult, CoercingSerializeException::new);
} else if (dataFetcherResult instanceof Long) {
duration = Duration.of((Long) dataFetcherResult, java.time.temporal.ChronoUnit.MILLIS);
} else {
throw new CoercingSerializeException("Expected something we can convert to 'java.time.Duration' but was '"
+ dataFetcherResult.getClass().getSimpleName() + "'.");
}
return duration.toString();
}
@Override
public Duration parseValue(Object input, GraphQLContext graphQLContext, Locale locale)
throws CoercingParseValueException {
Duration duration;
if (input instanceof Duration) {
duration = (Duration) input;
} else if (input instanceof String) {
duration = parseDuration((String) input, CoercingParseValueException::new);
} else if (input instanceof Long) {
duration = Duration.of((Long) input, java.time.temporal.ChronoUnit.MILLIS);
} else {
throw new CoercingSerializeException("Expected something we can convert to 'java.time.Duration' but was '"
+ input.getClass().getSimpleName() + "'.");
}
return duration;
}
@Override
public Duration parseLiteral(Value<?> input, CoercedVariables variables, GraphQLContext graphQLContext,
Locale locale) throws CoercingParseLiteralException {
if (input instanceof StringValue) {
return parseDuration(((StringValue) input).getValue(), CoercingParseLiteralException::new);
} else {
throw new CoercingParseLiteralException("Expected AST type 'StringValue' but was '"
+ input.getClass().getSimpleName() + "'.");
}
}
@Override
public Value<?> valueToLiteral(Object input, GraphQLContext graphQLContext, Locale locale) {
String s = serialize(input, graphQLContext, locale);
return StringValue.newStringValue(s).build();
}
private Duration parseDuration(String input, Function<String, RuntimeException> exceptionMaker) {
try {
if (input.isEmpty()) {
return Duration.ZERO;
}
if (!input.contains("P")) {
return Duration.of(Long.parseLong(input), java.time.temporal.ChronoUnit.MILLIS);
}
return Duration.parse(input);
} catch (Exception e) {
throw exceptionMaker.apply("Invalid RFC-3339 compliant Duration value: " + input);
}
}
};
INSTANCE = GraphQLScalarType.newScalar()
.name("Duration")
.description("A slightly refined version of RFC-3339 compliant DateTime Scalar")
.specifiedByUrl("https://scalars.opencast.org/duration")
.coercing(coercing)
.build();
}
}