package io.micronaut.http.bind.binders;
import io.micronaut.core.annotation.AnnotationMetadata;
import io.micronaut.core.bind.annotation.AbstractAnnotatedArgumentBinder;
import io.micronaut.core.convert.ArgumentConversionContext;
import io.micronaut.core.convert.ConversionService;
import io.micronaut.core.convert.value.ConvertibleValues;
import io.micronaut.core.reflect.ClassUtils;
import io.micronaut.core.type.Argument;
import io.micronaut.http.HttpMethod;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.annotation.QueryValue;
import java.util.Optional;
public class ParameterAnnotationBinder<T> extends AbstractAnnotatedArgumentBinder<QueryValue, T, HttpRequest<?>> implements AnnotatedRequestArgumentBinder<QueryValue, T> {
QueryValueArgumentBinder<T> queryValueArgumentBinder;
public ParameterAnnotationBinder(ConversionService<?> conversionService) {
super(conversionService);
this.queryValueArgumentBinder = new QueryValueArgumentBinder<>(conversionService);
}
@Override
public Class<QueryValue> getAnnotationType() {
return QueryValue.class;
}
@Override
public BindingResult<T> bind(ArgumentConversionContext<T> context, HttpRequest<?> source) {
Argument<T> argument = context.getArgument();
HttpMethod httpMethod = source.getMethod();
boolean permitsRequestBody = HttpMethod.permitsRequestBody(httpMethod);
AnnotationMetadata annotationMetadata = argument.getAnnotationMetadata();
boolean hasAnnotation = annotationMetadata.hasAnnotation(QueryValue.class);
String parameterName = argument.getName();
BindingResult<T> result = queryValueArgumentBinder.bind(context, source);
Optional<T> val = result.getValue();
if (!val.isPresent() && !hasAnnotation) {
result = doBind(context, source.getAttributes(), parameterName, BindingResult.UNSATISFIED);
}
Class argumentType;
if (argument.getType() == Optional.class) {
argumentType = argument.getFirstTypeVariable().orElse(argument).getType();
} else {
argumentType = argument.getType();
}
if (!result.getValue().isPresent() && !hasAnnotation && permitsRequestBody) {
Optional<ConvertibleValues> body = source.getBody(ConvertibleValues.class);
if (body.isPresent()) {
result = doBind(context, body.get(), parameterName);
if (!result.getValue().isPresent()) {
if (ClassUtils.isJavaLangType(argumentType)) {
return Optional::empty;
} else {
return () -> source.getBody(argumentType);
}
}
} else {
if (source.getBody().isPresent()) {
Optional<String> text = source.getBody(String.class);
if (text.isPresent()) {
return doConvert(text.get(), context);
}
}
return BindingResult.UNSATISFIED;
}
}
return result;
}
}