Skip to content

Commit

Permalink
Merge pull request #550 from LukasDetermann/feature/optional-request-…
Browse files Browse the repository at this point in the history
…parameters

added support for Optional Request Parameters
  • Loading branch information
SentryMan authored Jan 18, 2025
2 parents 25d13ba + 8e70331 commit eccb601
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.time.*;
import java.math.BigInteger;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
Expand Down Expand Up @@ -60,6 +61,10 @@ public static <T> Set<T> set(Function<String, T> func, List<String> params) {
return params.stream().map(func).collect(Collectors.toSet());
}

public static <T> Optional<T> optional(Function<String, T> func, String value) {
return Optional.ofNullable(func.apply(value));
}

/** Convert to int. */
public static int asInt(String value) {
checkNull(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,18 +119,23 @@ TypeHandler initTypeHandler() {
final var isMap =
!isCollection && typeOp.filter(t -> t.mainType().startsWith("java.util.Map")).isPresent();

final var isOptional = typeOp.filter(t -> t.mainType().startsWith("java.util.Optional")).isPresent();

if (mainTypeEnum) {
return TypeMap.enumParamHandler(typeOp.orElseThrow());
} else if (isCollection) {
this.isParamCollection = true;
final var isEnumCollection =
} else if (isCollection || isOptional) {
final var isEnumContainer =
typeOp
.flatMap(t -> Optional.ofNullable(typeElement(t.param0())))
.map(TypeElement::getKind)
.filter(ElementKind.ENUM::equals)
.isPresent();

return TypeMap.collectionHandler(typeOp.orElseThrow(), isEnumCollection);
if (isOptional) {//Needs to be checked first, as 'isCollection' is too broad
return TypeMap.optionalHandler(typeOp.orElseThrow(), isEnumContainer);
}
this.isParamCollection = true;
return TypeMap.collectionHandler(typeOp.orElseThrow(), isEnumContainer);
} else if (isMap) {
this.isParamMap = true;
return new TypeMap.StringHandler();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,21 @@ static TypeHandler collectionHandler(UType type, boolean isEnum) {
isEnum));
}

static TypeHandler optionalHandler(UType type, boolean isEnum) {
final var handler = types.get(type.param0());

if (!isEnum && handler == null) {
return null;
}

return types.computeIfAbsent(
type.full(),
k ->
new OptionalHandler(
isEnum ? enumParamHandler(type.paramRaw()) : handler,
isEnum));
}

static TypeHandler enumParamHandler(UType type) {
return new EnumHandler(type);
}
Expand Down Expand Up @@ -374,6 +389,54 @@ public String toMethod() {
}
}

static class OptionalHandler implements TypeHandler {

private final List<String> importTypes;
private final String shortName;
private String toMethod;

OptionalHandler(TypeHandler handler, boolean isEnum) {

this.importTypes = new ArrayList<>(handler.importTypes());
importTypes.add("io.avaje.http.api.PathTypeConversion");
this.shortName = handler.shortName();
this.toMethod =
"optional("
+ (isEnum
? "qp -> " + handler.toMethod() + " qp)"
: "PathTypeConversion::as" + shortName)
+ ", ";

this.toMethod = toMethod.replace("PathTypeConversion::asString", "Object::toString");
}

@Override
public boolean isPrimitive() {
return false;
}

@Override
public List<String> importTypes() {

return importTypes;
}

@Override
public String shortName() {
return shortName;
}

@Override
public String asMethod() {
return null;
}

@Override
public String toMethod() {
return toMethod;
}
}

abstract static class ObjectHandler implements TypeHandler {

private final String importType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ default String param1() {
}

/**
* Return the raw generic parameter if this UType is a Collection.
* Return the raw generic parameter if this UType is a Collection or an Optional.
*/
default UType paramRaw() {
return null;
Expand Down Expand Up @@ -212,6 +212,7 @@ private String extractRawParam() {
switch (mainType()) {
case "java.util.Set":
case "java.util.List":
case "java.util.Optional":
case "java.util.stream.Stream":
case "java.net.http.HttpResponse":
case "java.util.concurrent.CompletableFuture":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;

Expand Down Expand Up @@ -176,4 +177,22 @@ String controlStatusCode(Context ctx) {
String takesNestedEnum(Foo.NestedEnum myEnum) {
return "takesNestedEnum-" + myEnum;
}

@Produces(value = "text/plain")
@Get("takesOptional{myOptional}")
String takesOptional(@QueryParam("myOptional") Optional<Long> myOptional) {
return "takesOptional-" + myOptional;
}

@Produces(value = "text/plain")
@Get("takesOptionalEnum{myOptional}")
String takesOptionalEnum(@QueryParam("myOptional") Optional<Foo.NestedEnum> myOptional) {
return "takesOptionalEnum-" + myOptional;
}

@Produces(value = "text/plain")
@Get("takesOptionalEnum{myOptional}")
String takesOptionalString(@QueryParam("myOptional") Optional<String> myOptional) {
return "takesOptionalString-" + myOptional;
}
}

0 comments on commit eccb601

Please sign in to comment.