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;
}
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;
}
}
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));
}
}
}
}
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");
}
}
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;
}
Aggregations