Skip to content

Commit

Permalink
Support more optionals
Browse files Browse the repository at this point in the history
Signed-off-by: Jorge Bescos Gascon <[email protected]>
  • Loading branch information
jbescos committed Apr 26, 2021
1 parent 6206ef6 commit 1faa8bb
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
import java.text.ParseException;
import java.util.Date;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.OptionalLong;

import javax.inject.Inject;
import javax.inject.Singleton;
Expand Down Expand Up @@ -266,24 +269,31 @@ public OptionalProvider(AggregatedProvider aggregated) {

@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
return (rawType != Optional.class) ? null : new ParamConverter<T>() {
final Optionals optionals = Optionals.getOptional(rawType);
return (optionals == null) ? null : new ParamConverter<T>() {

@Override
public T fromString(String value) {
if (value == null) {
return (T) Optional.empty();
return (T) optionals.empty();
} else {
ParameterizedType parametrized = (ParameterizedType) genericType;
Type type = parametrized.getActualTypeArguments()[0];
T val = aggregated.getConverter((Class<T>) type, type, annotations).fromString(value.toString());
if (val != null) {
return (T) Optional.of(val);
if (genericType instanceof ParameterizedType) {
// Optional is parameterized
ParameterizedType parametrized = (ParameterizedType) genericType;
Type type = parametrized.getActualTypeArguments()[0];
T val = aggregated.getConverter((Class<T>) type, type, annotations).fromString(value.toString());
if (val != null) {
return (T) optionals.of(val);
} else {
/*
* In this case we don't send Optional.empty() because 'value' is not null.
* But we return null because the provider didn't find how to parse it.
*/
return null;
}
} else {
/*
* In this case we don't send Optional.empty() because 'value' is not null.
* But we return null because the provider didn't find how to parse it.
*/
return null;
// Others are not parameterized
return (T) optionals.of(value);
}
}
}
Expand All @@ -300,6 +310,65 @@ public String toString(T value) throws IllegalArgumentException {
};
}

private static enum Optionals {

OPTIONAL(Optional.class) {
@Override
Object empty() {
return Optional.empty();
}
@Override
Object of(Object value) {
return Optional.of(value);
}
}, OPTIONAL_INT(OptionalInt.class) {
@Override
Object empty() {
return OptionalInt.empty();
}
@Override
Object of(Object value) {
return OptionalInt.of(Integer.parseInt((String) value));
}
}, OPTIONAL_DOUBLE(OptionalDouble.class) {
@Override
Object empty() {
return OptionalDouble.empty();
}
@Override
Object of(Object value) {
return OptionalDouble.of(Double.parseDouble((String) value));
}
}, OPTIONAL_LONG(OptionalLong.class) {
@Override
Object empty() {
return OptionalLong.empty();
}
@Override
Object of(Object value) {
return OptionalLong.of(Long.parseLong((String) value));
}
};

private final Class<?> clazz;

private Optionals(Class<?> clazz) {
this.clazz = clazz;
}

private static Optionals getOptional(Class<?> clazz) {
for (Optionals optionals : Optionals.values()) {
if (optionals.clazz == clazz) {
return optionals;
}
}
return null;
}

abstract Object empty();

abstract Object of(Object value);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,13 @@

package org.glassfish.jersey.tests.e2e.server;

import static org.junit.Assert.assertEquals;

import java.util.List;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.OptionalLong;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
Expand All @@ -29,8 +34,6 @@
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class OptionalParamConverterTest extends JerseyTest {

private static final String PARAM_NAME = "paramName";
Expand Down Expand Up @@ -59,6 +62,24 @@ public Response fromList(@QueryParam(PARAM_NAME) List<Optional<Integer>> data) {
}
return Response.ok(builder.toString()).build();
}

@GET
@Path("/fromInteger2")
public Response fromInteger2(@QueryParam(PARAM_NAME) OptionalInt data) {
return Response.ok(data.orElse(0)).build();
}

@GET
@Path("/fromLong")
public Response fromLong(@QueryParam(PARAM_NAME) OptionalLong data) {
return Response.ok(data.orElse(0)).build();
}

@GET
@Path("/fromDouble")
public Response fromDouble(@QueryParam(PARAM_NAME) OptionalDouble data) {
return Response.ok(data.orElse(0.1)).build();
}
}

@Override
Expand Down Expand Up @@ -86,6 +107,16 @@ public void fromOptionalInt() {
assertEquals(Integer.valueOf(1), notEmpty.readEntity(Integer.class));
}

@Test
public void fromOptionalInt2() {
Response empty = target("/OptionalResource/fromInteger2").request().get();
Response notEmpty = target("/OptionalResource/fromInteger2").queryParam(PARAM_NAME, 1).request().get();
assertEquals(200, empty.getStatus());
assertEquals(Integer.valueOf(0), empty.readEntity(Integer.class));
assertEquals(200, notEmpty.getStatus());
assertEquals(Integer.valueOf(1), notEmpty.readEntity(Integer.class));
}

@Test
public void fromOptionalList() {
Response empty = target("/OptionalResource/fromList").request().get();
Expand All @@ -96,4 +127,24 @@ public void fromOptionalList() {
assertEquals(200, notEmpty.getStatus());
assertEquals("12", notEmpty.readEntity(String.class));
}

@Test
public void fromOptionalLong() {
Response empty = target("/OptionalResource/fromLong").request().get();
Response notEmpty = target("/OptionalResource/fromLong").queryParam(PARAM_NAME, 1L).request().get();
assertEquals(200, empty.getStatus());
assertEquals(Long.valueOf(0L), empty.readEntity(Long.class));
assertEquals(200, notEmpty.getStatus());
assertEquals(Long.valueOf(1L), notEmpty.readEntity(Long.class));
}

@Test
public void fromOptionalDouble() {
Response empty = target("/OptionalResource/fromDouble").request().get();
Response notEmpty = target("/OptionalResource/fromDouble").queryParam(PARAM_NAME, 1.1).request().get();
assertEquals(200, empty.getStatus());
assertEquals(Double.valueOf(0.1), empty.readEntity(Double.class));
assertEquals(200, notEmpty.getStatus());
assertEquals(Double.valueOf(1.1), notEmpty.readEntity(Double.class));
}
}

0 comments on commit 1faa8bb

Please sign in to comment.