Search in sources :

Example 1 with ArgumentConversionContext

use of io.micronaut.core.convert.ArgumentConversionContext 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 ArgumentConversionContext

use of io.micronaut.core.convert.ArgumentConversionContext in project micronaut-core by micronaut-projects.

the class RequestBeanAnnotationBinder method bind.

@Override
public BindingResult<T> bind(ArgumentConversionContext<T> context, HttpRequest<?> source) {
    Argument<T> argument = context.getArgument();
    AnnotationMetadata annotationMetadata = argument.getAnnotationMetadata();
    boolean hasAnnotation = annotationMetadata.hasAnnotation(RequestBean.class);
    if (hasAnnotation) {
        BeanIntrospection<T> introspection = BeanIntrospection.getIntrospection(context.getArgument().getType());
        Map<String, BeanProperty<T, Object>> beanProperties = introspection.getBeanProperties().stream().collect(Collectors.toMap(Named::getName, p -> p));
        if (introspection.getConstructorArguments().length > 0) {
            // Handle injection with Constructor or @Creator
            Argument<?>[] constructorArguments = introspection.getConstructorArguments();
            Object[] argumentValues = new Object[constructorArguments.length];
            for (int i = 0; i < constructorArguments.length; i++) {
                @SuppressWarnings("unchecked") Argument<Object> constructorArgument = (Argument<Object>) constructorArguments[i];
                BeanProperty<T, Object> bp = beanProperties.get(constructorArgument.getName());
                Argument<Object> argumentToBind;
                if (bp != null) {
                    argumentToBind = bp.asArgument();
                } else {
                    argumentToBind = constructorArgument;
                }
                Optional<Object> bindableResult = getBindableResult(source, argumentToBind);
                argumentValues[i] = constructorArgument.isOptional() ? bindableResult : bindableResult.orElse(null);
            }
            return () -> Optional.of(introspection.instantiate(false, argumentValues));
        } else {
            // Handle injection with setters, we checked that all values are writable at compile time
            T bean = introspection.instantiate();
            for (BeanProperty<T, Object> property : beanProperties.values()) {
                Argument<Object> propertyArgument = property.asArgument();
                Optional<Object> bindableResult = getBindableResult(source, propertyArgument);
                property.set(bean, propertyArgument.isOptional() ? bindableResult : bindableResult.orElse(null));
            }
            return () -> Optional.of(bean);
        }
    } else {
        // noinspection unchecked
        return BindingResult.EMPTY;
    }
}
Also used : java.util(java.util) BeanProperty(io.micronaut.core.beans.BeanProperty) ArgumentConversionContext(io.micronaut.core.convert.ArgumentConversionContext) ConversionErrorException(io.micronaut.core.convert.exceptions.ConversionErrorException) Collectors(java.util.stream.Collectors) ArgumentBinder(io.micronaut.core.bind.ArgumentBinder) UnsatisfiedArgumentException(io.micronaut.core.bind.exceptions.UnsatisfiedArgumentException) AbstractAnnotatedArgumentBinder(io.micronaut.core.bind.annotation.AbstractAnnotatedArgumentBinder) ConversionContext(io.micronaut.core.convert.ConversionContext) ConversionError(io.micronaut.core.convert.ConversionError) Named(io.micronaut.core.naming.Named) BeanIntrospection(io.micronaut.core.beans.BeanIntrospection) RequestBean(io.micronaut.http.annotation.RequestBean) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Argument(io.micronaut.core.type.Argument) HttpRequest(io.micronaut.http.HttpRequest) ConversionService(io.micronaut.core.convert.ConversionService) RequestBinderRegistry(io.micronaut.http.bind.RequestBinderRegistry) Argument(io.micronaut.core.type.Argument) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) BeanProperty(io.micronaut.core.beans.BeanProperty)

Example 3 with ArgumentConversionContext

use of io.micronaut.core.convert.ArgumentConversionContext in project micronaut-core by micronaut-projects.

the class AbstractInitializableBeanDefinition method resolveValue.

private Object resolveValue(BeanResolutionContext resolutionContext, BeanContext context, AnnotationMetadata parentAnnotationMetadata, Argument<?> argument, Qualifier qualifier) {
    if (!(context instanceof PropertyResolver)) {
        throw new DependencyInjectionException(resolutionContext, "@Value requires a BeanContext that implements PropertyResolver");
    }
    String valueAnnVal = argument.getAnnotationMetadata().stringValue(Value.class).orElse(null);
    Argument<?> argumentType;
    boolean isCollection = false;
    final boolean wrapperType = argument.isWrapperType();
    final Class<?> argumentJavaType = argument.getType();
    if (Collection.class.isAssignableFrom(argumentJavaType)) {
        argumentType = argument.getFirstTypeVariable().orElse(Argument.OBJECT_ARGUMENT);
        isCollection = true;
    } else if (wrapperType) {
        argumentType = argument.getWrappedType();
    } else {
        argumentType = argument;
    }
    if (isInnerConfiguration(argumentType.getType())) {
        qualifier = qualifier == null ? resolveQualifierWithInnerConfiguration(resolutionContext, argument, true) : qualifier;
        if (isCollection) {
            Collection beans = ((DefaultBeanContext) context).getBeansOfType(resolutionContext, argumentType, qualifier);
            return coerceCollectionToCorrectType((Class) argumentJavaType, beans, resolutionContext, argument);
        } else {
            return ((DefaultBeanContext) context).getBean(resolutionContext, argumentType, qualifier);
        }
    } else {
        String valString = resolvePropertyValueName(resolutionContext, parentAnnotationMetadata, argument.getAnnotationMetadata(), valueAnnVal);
        ArgumentConversionContext conversionContext = wrapperType ? ConversionContext.of(argumentType) : ConversionContext.of(argument);
        Optional value = resolveValue((ApplicationContext) context, conversionContext, valueAnnVal != null, valString);
        if (argument.isOptional()) {
            if (!value.isPresent()) {
                return value;
            } else {
                Object convertedOptional = value.get();
                if (convertedOptional instanceof Optional) {
                    return convertedOptional;
                } else {
                    return value;
                }
            }
        } else {
            if (wrapperType) {
                final Object v = value.orElse(null);
                if (OptionalInt.class == argumentJavaType) {
                    return v instanceof Integer ? OptionalInt.of((Integer) v) : OptionalInt.empty();
                } else if (OptionalLong.class == argumentJavaType) {
                    return v instanceof Long ? OptionalLong.of((Long) v) : OptionalLong.empty();
                } else if (OptionalDouble.class == argumentJavaType) {
                    return v instanceof Double ? OptionalDouble.of((Double) v) : OptionalDouble.empty();
                }
            }
            if (value.isPresent()) {
                return value.get();
            } else {
                if (argument.isDeclaredNullable()) {
                    return null;
                }
                return argument.getAnnotationMetadata().getValue(Bindable.class, "defaultValue", argument).orElseThrow(() -> DependencyInjectionException.missingProperty(resolutionContext, conversionContext, valString));
            }
        }
    }
}
Also used : Optional(java.util.Optional) Bindable(io.micronaut.core.bind.annotation.Bindable) PropertyResolver(io.micronaut.core.value.PropertyResolver) OptionalDouble(java.util.OptionalDouble) DependencyInjectionException(io.micronaut.context.exceptions.DependencyInjectionException) ArgumentConversionContext(io.micronaut.core.convert.ArgumentConversionContext) Value(io.micronaut.context.annotation.Value) OptionalLong(java.util.OptionalLong) Collection(java.util.Collection) OptionalLong(java.util.OptionalLong)

Example 4 with ArgumentConversionContext

use of io.micronaut.core.convert.ArgumentConversionContext in project micronaut-core by micronaut-projects.

the class AbstractBeanDefinition method getValueForMethodArgument.

/**
 * Obtains a value for the given method argument.
 *
 * @param resolutionContext The resolution context
 * @param context           The bean context
 * @param methodIndex       The method index
 * @param argIndex          The argument index
 * @return The value
 */
@SuppressWarnings({ "unused", "unchecked" })
@Internal
protected final Object getValueForMethodArgument(BeanResolutionContext resolutionContext, BeanContext context, int methodIndex, int argIndex) {
    MethodInjectionPoint injectionPoint = methodInjectionPoints.get(methodIndex);
    Argument argument = injectionPoint.getArguments()[argIndex];
    BeanResolutionContext.Path path = resolutionContext.getPath();
    path.pushMethodArgumentResolve(this, injectionPoint, argument);
    if (context instanceof ApplicationContext) {
        // can't use orElseThrow here due to compiler bug
        try {
            String valueAnnStr = argument.getAnnotationMetadata().stringValue(Value.class).orElse(null);
            Argument<?> argumentType;
            boolean isCollection = false;
            if (Collection.class.isAssignableFrom(argument.getType())) {
                argumentType = argument.getFirstTypeVariable().orElse(Argument.OBJECT_ARGUMENT);
                isCollection = true;
            } else {
                argumentType = argument;
            }
            if (isInnerConfiguration(argumentType, context)) {
                Qualifier qualifier = resolveQualifier(resolutionContext, argument, true);
                if (isCollection) {
                    Collection beans = ((DefaultBeanContext) context).getBeansOfType(resolutionContext, argumentType, qualifier);
                    return coerceCollectionToCorrectType(argument.getType(), beans);
                } else {
                    return ((DefaultBeanContext) context).getBean(resolutionContext, argumentType, qualifier);
                }
            } else {
                String valString = resolvePropertyValueName(resolutionContext, injectionPoint.getAnnotationMetadata(), argument, valueAnnStr);
                ApplicationContext applicationContext = (ApplicationContext) context;
                ArgumentConversionContext conversionContext = ConversionContext.of(argument);
                Optional value = resolveValue(applicationContext, conversionContext, valueAnnStr != null, valString);
                if (argumentType.isOptional()) {
                    return resolveOptionalObject(value);
                } else {
                    if (value.isPresent()) {
                        return value.get();
                    } else {
                        if (argument.isDeclaredNullable()) {
                            return null;
                        }
                        throw new DependencyInjectionException(resolutionContext, injectionPoint, conversionContext, valString);
                    }
                }
            }
        } finally {
            path.pop();
        }
    } else {
        path.pop();
        throw new DependencyInjectionException(resolutionContext, argument, "BeanContext must support property resolution");
    }
}
Also used : Argument(io.micronaut.core.type.Argument) DefaultArgument(io.micronaut.core.type.DefaultArgument) ArgumentConversionContext(io.micronaut.core.convert.ArgumentConversionContext) TypeAnnotationQualifier(io.micronaut.inject.qualifiers.TypeAnnotationQualifier) InterceptorBindingQualifier(io.micronaut.inject.qualifiers.InterceptorBindingQualifier)

Example 5 with ArgumentConversionContext

use of io.micronaut.core.convert.ArgumentConversionContext in project micronaut-core by micronaut-projects.

the class PropertySourcePropertyResolver method resolveSubProperties.

/**
 * @param name              The property name
 * @param entries           The entries
 * @param conversionContext The conversion context
 * @return The subproperties
 */
protected Properties resolveSubProperties(String name, Map<String, Object> entries, ArgumentConversionContext<?> conversionContext) {
    // special handling for maps for resolving sub keys
    Properties properties = new Properties();
    AnnotationMetadata annotationMetadata = conversionContext.getAnnotationMetadata();
    StringConvention keyConvention = annotationMetadata.enumValue(MapFormat.class, "keyFormat", StringConvention.class).orElse(null);
    if (keyConvention == StringConvention.RAW) {
        entries = resolveEntriesForKey(name, false, PropertyCatalog.RAW);
    }
    String prefix = name + '.';
    entries.entrySet().stream().filter(map -> map.getKey().startsWith(prefix)).forEach(entry -> {
        Object value = entry.getValue();
        if (value != null) {
            String key = entry.getKey().substring(prefix.length());
            key = keyConvention != null ? keyConvention.format(key) : key;
            properties.put(key, resolvePlaceHoldersIfNecessary(value.toString()));
        }
    });
    return properties;
}
Also used : Arrays(java.util.Arrays) ListIterator(java.util.ListIterator) StringConvention(io.micronaut.core.naming.conventions.StringConvention) ArgumentConversionContext(io.micronaut.core.convert.ArgumentConversionContext) HashMap(java.util.HashMap) Random(java.util.Random) Supplier(java.util.function.Supplier) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) PropertyResolver(io.micronaut.core.value.PropertyResolver) Matcher(java.util.regex.Matcher) EnvironmentProperties(io.micronaut.core.util.EnvironmentProperties) Nullable(io.micronaut.core.annotation.Nullable) MapPropertyResolver(io.micronaut.core.value.MapPropertyResolver) Map(java.util.Map) Argument(io.micronaut.core.type.Argument) NameUtils(io.micronaut.core.naming.NameUtils) ConversionService(io.micronaut.core.convert.ConversionService) StaticOptimizations(io.micronaut.core.optim.StaticOptimizations) ConfigurationException(io.micronaut.context.exceptions.ConfigurationException) ClassUtils(io.micronaut.core.reflect.ClassUtils) Logger(org.slf4j.Logger) Properties(java.util.Properties) ValueException(io.micronaut.core.value.ValueException) SocketUtils(io.micronaut.core.io.socket.SocketUtils) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) MapFormat(io.micronaut.core.convert.format.MapFormat) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) Consumer(java.util.function.Consumer) NonNull(io.micronaut.core.annotation.NonNull) StringUtils(io.micronaut.core.util.StringUtils) List(java.util.List) ConversionContext(io.micronaut.core.convert.ConversionContext) CollectionUtils(io.micronaut.core.util.CollectionUtils) Optional(java.util.Optional) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Pattern(java.util.regex.Pattern) Collections(java.util.Collections) MapFormat(io.micronaut.core.convert.format.MapFormat) StringConvention(io.micronaut.core.naming.conventions.StringConvention) EnvironmentProperties(io.micronaut.core.util.EnvironmentProperties) Properties(java.util.Properties) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata)

Aggregations

ArgumentConversionContext (io.micronaut.core.convert.ArgumentConversionContext)17 Argument (io.micronaut.core.type.Argument)12 Optional (java.util.Optional)9 AnnotationMetadata (io.micronaut.core.annotation.AnnotationMetadata)5 ConversionContext (io.micronaut.core.convert.ConversionContext)5 ConversionService (io.micronaut.core.convert.ConversionService)5 ConversionErrorException (io.micronaut.core.convert.exceptions.ConversionErrorException)5 HttpRequest (io.micronaut.http.HttpRequest)5 Collection (java.util.Collection)5 ConversionError (io.micronaut.core.convert.ConversionError)4 Collections (java.util.Collections)4 ConfigurationException (io.micronaut.context.exceptions.ConfigurationException)3 Internal (io.micronaut.core.annotation.Internal)3 Nullable (io.micronaut.core.annotation.Nullable)3 ArgumentBinder (io.micronaut.core.bind.ArgumentBinder)3 AbstractAnnotatedArgumentBinder (io.micronaut.core.bind.annotation.AbstractAnnotatedArgumentBinder)3 Collectors (java.util.stream.Collectors)3 AnnotationValue (io.micronaut.core.annotation.AnnotationValue)2 NonNull (io.micronaut.core.annotation.NonNull)2 Bindable (io.micronaut.core.bind.annotation.Bindable)2