package io.dropwizard.jersey.optional;

import io.dropwizard.jersey.DefaultValueUtils;

import javax.annotation.Nullable;
import javax.inject.Singleton;
import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.OptionalDouble;

@Singleton
public class OptionalDoubleParamConverterProvider implements ParamConverterProvider {
    private final OptionalDoubleParamConverter paramConverter = new OptionalDoubleParamConverter();

    
{@inheritDoc}
/** * {@inheritDoc} */
@Override @SuppressWarnings("unchecked") @Nullable public <T> ParamConverter<T> getConverter(final Class<T> rawType, final Type genericType, final Annotation[] annotations) { if (!OptionalDouble.class.equals(rawType)) { return null; } final String defaultValue = DefaultValueUtils.getDefaultValue(annotations); return (ParamConverter<T>) (defaultValue == null ? paramConverter : new OptionalDoubleParamConverter(defaultValue)); } public static class OptionalDoubleParamConverter implements ParamConverter<OptionalDouble> { @Nullable private final String defaultValue; public OptionalDoubleParamConverter() { this(null); } public OptionalDoubleParamConverter(@Nullable String defaultValue) { this.defaultValue = defaultValue; } @SuppressWarnings("OptionalAssignedToNull") @Override @Nullable public OptionalDouble fromString(final String value) { try { final double d = Double.parseDouble(value); return OptionalDouble.of(d); } catch (NullPointerException | NumberFormatException e) { if (defaultValue != null) { // If an invalid default value is specified, we want to fail fast. // This is the same behavior as DropWizard 1.3.x and matches Jersey's handling of @DefaultValue for Double. if (defaultValue.equals(value)) { throw e; } // In order to fall back to use a default value for an empty query param, we must return null here. // This preserves backwards compatibility with DropWizard 1.3.x handling of empty query params. if (value == null || value.isEmpty()) { return null; } } return OptionalDouble.empty(); } } @Override public String toString(final OptionalDouble value) { if (value == null) { throw new IllegalArgumentException("value must not be null"); } return value.isPresent() ? Double.toString(value.getAsDouble()) : ""; } } }