use of io.micronaut.core.convert.value.ConvertibleMultiValues in project micronaut-core by micronaut-projects.
the class QueryValueArgumentBinder method bind.
/**
* Binds the argument with {@link QueryValue} annotation to the request
* (Also binds without annotation if request body is not permitted).
*
* It will first try to convert to ConvertibleMultiValues type and if conversion is successful, add the
* corresponding parameters to the request. (By default the conversion will be successful if the {@link Format}
* annotation is present and has one of the supported values - see
* {@link io.micronaut.core.convert.converters.MultiValuesConverterFactory} for specific converters). Otherwise
* the uri template will be used to deduce what will be done with the request. For example, simple parameters are
* converted to {@link String}
*/
@Override
public BindingResult<T> bind(ArgumentConversionContext<T> context, HttpRequest<?> source) {
ConvertibleMultiValues<String> parameters = source.getParameters();
Argument<T> argument = context.getArgument();
AnnotationMetadata annotationMetadata = argument.getAnnotationMetadata();
boolean hasAnnotation = annotationMetadata.hasAnnotation(QueryValue.class);
HttpMethod httpMethod = source.getMethod();
boolean permitsRequestBody = HttpMethod.permitsRequestBody(httpMethod);
BindingResult<T> result;
if (hasAnnotation || !permitsRequestBody) {
// First try converting from the ConvertibleMultiValues type and if conversion is successful, return it.
// Otherwise use the given uri template to deduce what to do with the variable
Optional<T> multiValueConversion;
if (annotationMetadata.hasAnnotation(Format.class)) {
multiValueConversion = conversionService.convert(parameters, context);
} else {
multiValueConversion = Optional.empty();
}
if (multiValueConversion.isPresent()) {
result = () -> multiValueConversion;
} else {
String parameterName = annotationMetadata.stringValue(QueryValue.class).orElse(argument.getName());
// If we need to bind all request params to command object
// checks if the variable is defined with modifier char *, eg. ?pojo*
boolean bindAll = source.getAttribute(HttpAttributes.ROUTE_MATCH, UriMatchInfo.class).map(umi -> {
UriMatchVariable uriMatchVariable = umi.getVariableMap().get(parameterName);
return uriMatchVariable != null && uriMatchVariable.isExploded();
}).orElse(false);
if (bindAll) {
Object value;
// Only maps and POJOs will "bindAll", lists work like normal
if (Iterable.class.isAssignableFrom(argument.getType())) {
value = doResolve(context, parameters, parameterName);
if (value == null) {
value = Collections.emptyList();
}
} else {
value = parameters.asMap();
}
result = doConvert(value, context);
} else {
result = doBind(context, parameters, parameterName);
}
}
} else {
result = BindingResult.EMPTY;
}
return result;
}
use of io.micronaut.core.convert.value.ConvertibleMultiValues in project micronaut-core by micronaut-projects.
the class QueryValueClientArgumentRequestBinder method bind.
/**
* If value can be converted to ConvertibleMultiValues, then use it and add it to the uriContext.queryParameters.
* The ConvertibleMultiValues converters are found in
* {@link io.micronaut.core.convert.converters.MultiValuesConverterFactory} and perform conversion only when the
* {@link io.micronaut.core.convert.format.Format} annotation has one of the supported values.
* Otherwise if the {@link io.micronaut.core.convert.format.Format} annotation is present, it is converted to {@link String}. If none of these
* are satisfied, the{@link io.micronaut.http.uri.UriTemplate} decides what to do with the given value which
* is supplied as an Object (it is added to uriContext.pathParameter).
*
* <br> By default value is converted to ConvertibleMultiValues when the {@link io.micronaut.core.convert.format.Format} annotation is present and has
* one of the defined above formats. Otherwise empty optional is returned.
*
* <br> The default {@link io.micronaut.http.uri.UriTemplate} will convert the value to String and to parameters.
* Optionally, the value can be formatted if the path template states so.
*/
@Override
public void bind(@NonNull ArgumentConversionContext<Object> context, @NonNull ClientRequestUriContext uriContext, @NonNull Object value, @NonNull MutableHttpRequest<?> request) {
String parameterName = context.getAnnotationMetadata().stringValue(QueryValue.class).filter(StringUtils::isNotEmpty).orElse(context.getArgument().getName());
final UriMatchVariable uriVariable = uriContext.getUriTemplate().getVariables().stream().filter(v -> v.getName().equals(parameterName)).findFirst().orElse(null);
if (uriVariable != null) {
if (uriVariable.isExploded()) {
uriContext.setPathParameter(parameterName, value);
} else {
String convertedValue = conversionService.convert(value, ConversionContext.STRING.with(context.getAnnotationMetadata())).filter(StringUtils::isNotEmpty).orElse(null);
if (convertedValue != null) {
uriContext.setPathParameter(parameterName, convertedValue);
} else {
uriContext.setPathParameter(parameterName, value);
}
}
} else {
ArgumentConversionContext<ConvertibleMultiValues> conversionContext = context.with(Argument.of(ConvertibleMultiValues.class, context.getArgument().getName(), context.getAnnotationMetadata()));
final Optional<ConvertibleMultiValues<String>> multiValues = conversionService.convert(value, conversionContext).map(values -> (ConvertibleMultiValues<String>) values);
if (multiValues.isPresent()) {
Map<String, List<String>> queryParameters = uriContext.getQueryParameters();
// Add all the parameters
multiValues.get().forEach((k, v) -> {
if (queryParameters.containsKey(k)) {
queryParameters.get(k).addAll(v);
} else {
queryParameters.put(k, v);
}
});
} else {
conversionService.convert(value, ConversionContext.STRING.with(context.getAnnotationMetadata())).ifPresent(v -> uriContext.addQueryParameter(parameterName, v));
}
}
}
use of io.micronaut.core.convert.value.ConvertibleMultiValues in project micronaut-core by micronaut-projects.
the class PathVariableAnnotationBinder method bind.
@Override
public BindingResult<T> bind(ArgumentConversionContext<T> context, HttpRequest<?> source) {
ConvertibleMultiValues<String> parameters = source.getParameters();
Argument<T> argument = context.getArgument();
AnnotationMetadata annotationMetadata = argument.getAnnotationMetadata();
boolean hasAnnotation = annotationMetadata.hasAnnotation(PathVariable.class);
String parameterName = annotationMetadata.stringValue(PathVariable.class).orElse(argument.getName());
// If we need to bind all request params to command object
// checks if the variable is defined with modifier char *
// eg. ?pojo*
final Optional<UriMatchInfo> matchInfo = source.getAttribute(HttpAttributes.ROUTE_MATCH, UriMatchInfo.class);
boolean bindAll = matchInfo.flatMap(umi -> umi.getVariables().stream().filter(v -> v.getName().equals(parameterName)).findFirst().map(UriMatchVariable::isExploded)).orElse(false);
BindingResult<T> result;
// be manipulated to override POST or JSON variables
if (hasAnnotation && matchInfo.isPresent()) {
final ConvertibleValues<Object> variableValues = ConvertibleValues.of(matchInfo.get().getVariableValues());
if (bindAll) {
Object value;
// Only maps and POJOs will "bindAll", lists work like normal
if (Iterable.class.isAssignableFrom(argument.getType())) {
value = doResolve(context, variableValues, parameterName);
if (value == null) {
value = Collections.emptyList();
}
} else {
value = parameters.asMap();
}
result = doConvert(value, context);
} else {
result = doBind(context, variableValues, parameterName);
}
} else {
// noinspection unchecked
result = BindingResult.EMPTY;
}
return result;
}
Aggregations