Search in sources :

Example 1 with ConvertibleMultiValues

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;
}
Also used : ConvertibleMultiValues(io.micronaut.core.convert.value.ConvertibleMultiValues) HttpMethod(io.micronaut.http.HttpMethod) UriMatchVariable(io.micronaut.http.uri.UriMatchVariable) ArgumentConversionContext(io.micronaut.core.convert.ArgumentConversionContext) QueryValue(io.micronaut.http.annotation.QueryValue) AbstractAnnotatedArgumentBinder(io.micronaut.core.bind.annotation.AbstractAnnotatedArgumentBinder) Format(io.micronaut.core.convert.format.Format) UriMatchInfo(io.micronaut.http.uri.UriMatchInfo) Optional(java.util.Optional) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) HttpAttributes(io.micronaut.http.HttpAttributes) Argument(io.micronaut.core.type.Argument) HttpRequest(io.micronaut.http.HttpRequest) ConversionService(io.micronaut.core.convert.ConversionService) Collections(java.util.Collections) QueryValue(io.micronaut.http.annotation.QueryValue) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) UriMatchVariable(io.micronaut.http.uri.UriMatchVariable) HttpMethod(io.micronaut.http.HttpMethod)

Example 2 with ConvertibleMultiValues

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));
        }
    }
}
Also used : ConvertibleMultiValues(io.micronaut.core.convert.value.ConvertibleMultiValues) List(java.util.List) UriMatchVariable(io.micronaut.http.uri.UriMatchVariable)

Example 3 with ConvertibleMultiValues

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;
}
Also used : ConvertibleMultiValues(io.micronaut.core.convert.value.ConvertibleMultiValues) ConvertibleValues(io.micronaut.core.convert.value.ConvertibleValues) UriMatchVariable(io.micronaut.http.uri.UriMatchVariable) ArgumentConversionContext(io.micronaut.core.convert.ArgumentConversionContext) AbstractAnnotatedArgumentBinder(io.micronaut.core.bind.annotation.AbstractAnnotatedArgumentBinder) PathVariable(io.micronaut.http.annotation.PathVariable) UriMatchInfo(io.micronaut.http.uri.UriMatchInfo) Optional(java.util.Optional) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) HttpAttributes(io.micronaut.http.HttpAttributes) Argument(io.micronaut.core.type.Argument) HttpRequest(io.micronaut.http.HttpRequest) ConversionService(io.micronaut.core.convert.ConversionService) Collections(java.util.Collections) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) UriMatchVariable(io.micronaut.http.uri.UriMatchVariable) UriMatchInfo(io.micronaut.http.uri.UriMatchInfo) PathVariable(io.micronaut.http.annotation.PathVariable)

Aggregations

ConvertibleMultiValues (io.micronaut.core.convert.value.ConvertibleMultiValues)3 UriMatchVariable (io.micronaut.http.uri.UriMatchVariable)3 AnnotationMetadata (io.micronaut.core.annotation.AnnotationMetadata)2 AbstractAnnotatedArgumentBinder (io.micronaut.core.bind.annotation.AbstractAnnotatedArgumentBinder)2 ArgumentConversionContext (io.micronaut.core.convert.ArgumentConversionContext)2 ConversionService (io.micronaut.core.convert.ConversionService)2 Argument (io.micronaut.core.type.Argument)2 HttpAttributes (io.micronaut.http.HttpAttributes)2 HttpRequest (io.micronaut.http.HttpRequest)2 UriMatchInfo (io.micronaut.http.uri.UriMatchInfo)2 Collections (java.util.Collections)2 Optional (java.util.Optional)2 Format (io.micronaut.core.convert.format.Format)1 ConvertibleValues (io.micronaut.core.convert.value.ConvertibleValues)1 HttpMethod (io.micronaut.http.HttpMethod)1 PathVariable (io.micronaut.http.annotation.PathVariable)1 QueryValue (io.micronaut.http.annotation.QueryValue)1 List (java.util.List)1