use of org.springframework.core.convert.TypeDescriptor in project spring-framework by spring-projects.
the class ReflectivePropertyAccessor method getTypeDescriptor.
private TypeDescriptor getTypeDescriptor(EvaluationContext context, Object target, String name) {
if (target == null) {
return null;
}
Class<?> type = (target instanceof Class ? (Class<?>) target : target.getClass());
if (type.isArray() && name.equals("length")) {
return TypeDescriptor.valueOf(Integer.TYPE);
}
PropertyCacheKey cacheKey = new PropertyCacheKey(type, name, target instanceof Class);
TypeDescriptor typeDescriptor = this.typeDescriptorCache.get(cacheKey);
if (typeDescriptor == null) {
// attempt to populate the cache entry
try {
if (canRead(context, target, name)) {
typeDescriptor = this.typeDescriptorCache.get(cacheKey);
} else if (canWrite(context, target, name)) {
typeDescriptor = this.typeDescriptorCache.get(cacheKey);
}
} catch (AccessException ex) {
// continue with null type descriptor
}
}
return typeDescriptor;
}
use of org.springframework.core.convert.TypeDescriptor in project spring-framework by spring-projects.
the class BooleanExpressionTests method testConvertAndHandleNull.
@Test
public void testConvertAndHandleNull() {
// SPR-9445
// without null conversion
evaluateAndCheckError("null or true", SpelMessage.TYPE_CONVERSION_ERROR, 0, "null", "boolean");
evaluateAndCheckError("null and true", SpelMessage.TYPE_CONVERSION_ERROR, 0, "null", "boolean");
evaluateAndCheckError("!null", SpelMessage.TYPE_CONVERSION_ERROR, 1, "null", "boolean");
evaluateAndCheckError("null ? 'foo' : 'bar'", SpelMessage.TYPE_CONVERSION_ERROR, 0, "null", "boolean");
// with null conversion (null -> false)
GenericConversionService conversionService = new GenericConversionService() {
@Override
protected Object convertNullSource(TypeDescriptor sourceType, TypeDescriptor targetType) {
return targetType.getType() == Boolean.class ? false : null;
}
};
eContext.setTypeConverter(new StandardTypeConverter(conversionService));
evaluate("null or true", Boolean.TRUE, Boolean.class, false);
evaluate("null and true", Boolean.FALSE, Boolean.class, false);
evaluate("!null", Boolean.TRUE, Boolean.class, false);
evaluate("null ? 'foo' : 'bar'", "bar", String.class, false);
}
use of org.springframework.core.convert.TypeDescriptor in project spring-framework by spring-projects.
the class PropertyOrFieldReference method getValueInternal.
private TypedValue getValueInternal(TypedValue contextObject, EvaluationContext evalContext, boolean isAutoGrowNullReferences) throws EvaluationException {
TypedValue result = readProperty(contextObject, evalContext, this.name);
// Dynamically create the objects if the user has requested that optional behavior
if (result.getValue() == null && isAutoGrowNullReferences && nextChildIs(Indexer.class, PropertyOrFieldReference.class)) {
TypeDescriptor resultDescriptor = result.getTypeDescriptor();
// Create a new collection or map ready for the indexer
if (List.class == resultDescriptor.getType()) {
if (isWritableProperty(this.name, contextObject, evalContext)) {
List<?> newList = new ArrayList<>();
writeProperty(contextObject, evalContext, this.name, newList);
result = readProperty(contextObject, evalContext, this.name);
}
} else if (Map.class == resultDescriptor.getType()) {
if (isWritableProperty(this.name, contextObject, evalContext)) {
Map<?, ?> newMap = new HashMap<>();
writeProperty(contextObject, evalContext, this.name, newMap);
result = readProperty(contextObject, evalContext, this.name);
}
} else {
// 'simple' object
try {
if (isWritableProperty(this.name, contextObject, evalContext)) {
Class<?> clazz = result.getTypeDescriptor().getType();
Object newObject = ReflectionUtils.accessibleConstructor(clazz).newInstance();
writeProperty(contextObject, evalContext, this.name, newObject);
result = readProperty(contextObject, evalContext, this.name);
}
} catch (InvocationTargetException ex) {
throw new SpelEvaluationException(getStartPosition(), ex.getTargetException(), SpelMessage.UNABLE_TO_DYNAMICALLY_CREATE_OBJECT, result.getTypeDescriptor().getType());
} catch (Throwable ex) {
throw new SpelEvaluationException(getStartPosition(), ex, SpelMessage.UNABLE_TO_DYNAMICALLY_CREATE_OBJECT, result.getTypeDescriptor().getType());
}
}
}
return result;
}
use of org.springframework.core.convert.TypeDescriptor in project spring-framework by spring-projects.
the class ReflectionHelper method compareArgumentsVarargs.
/**
* Compare argument arrays and return information about whether they match.
* A supplied type converter and conversionAllowed flag allow for matches to
* take into account that a type may be transformed into a different type by the
* converter. This variant of compareArguments also allows for a varargs match.
* @param expectedArgTypes the types the method/constructor is expecting
* @param suppliedArgTypes the types that are being supplied at the point of invocation
* @param typeConverter a registered type converter
* @return a MatchInfo object indicating what kind of match it was,
* or {@code null} if it was not a match
*/
static ArgumentsMatchInfo compareArgumentsVarargs(List<TypeDescriptor> expectedArgTypes, List<TypeDescriptor> suppliedArgTypes, TypeConverter typeConverter) {
Assert.isTrue(expectedArgTypes != null && expectedArgTypes.size() > 0, "Expected arguments must at least include one array (the vargargs parameter)");
Assert.isTrue(expectedArgTypes.get(expectedArgTypes.size() - 1).isArray(), "Final expected argument should be array type (the varargs parameter)");
ArgumentsMatchKind match = ArgumentsMatchKind.EXACT;
// Check up until the varargs argument:
// Deal with the arguments up to 'expected number' - 1 (that is everything but the varargs argument)
int argCountUpToVarargs = expectedArgTypes.size() - 1;
for (int i = 0; i < argCountUpToVarargs && match != null; i++) {
TypeDescriptor suppliedArg = suppliedArgTypes.get(i);
TypeDescriptor expectedArg = expectedArgTypes.get(i);
if (suppliedArg == null) {
if (expectedArg.isPrimitive()) {
match = null;
}
} else {
if (!expectedArg.equals(suppliedArg)) {
if (suppliedArg.isAssignableTo(expectedArg)) {
if (match != ArgumentsMatchKind.REQUIRES_CONVERSION) {
match = ArgumentsMatchKind.CLOSE;
}
} else if (typeConverter.canConvert(suppliedArg, expectedArg)) {
match = ArgumentsMatchKind.REQUIRES_CONVERSION;
} else {
match = null;
}
}
}
}
// If already confirmed it cannot be a match, then return
if (match == null) {
return null;
}
if (suppliedArgTypes.size() == expectedArgTypes.size() && expectedArgTypes.get(expectedArgTypes.size() - 1).equals(suppliedArgTypes.get(suppliedArgTypes.size() - 1))) {
// Special case: there is one parameter left and it is an array and it matches the varargs
// expected argument - that is a match, the caller has already built the array. Proceed with it.
} else {
// Now... we have the final argument in the method we are checking as a match and we have 0
// or more other arguments left to pass to it.
TypeDescriptor varargsDesc = expectedArgTypes.get(expectedArgTypes.size() - 1);
Class<?> varargsParamType = varargsDesc.getElementTypeDescriptor().getType();
// All remaining parameters must be of this type or convertible to this type
for (int i = expectedArgTypes.size() - 1; i < suppliedArgTypes.size(); i++) {
TypeDescriptor suppliedArg = suppliedArgTypes.get(i);
if (suppliedArg == null) {
if (varargsParamType.isPrimitive()) {
match = null;
}
} else {
if (varargsParamType != suppliedArg.getType()) {
if (ClassUtils.isAssignable(varargsParamType, suppliedArg.getType())) {
if (match != ArgumentsMatchKind.REQUIRES_CONVERSION) {
match = ArgumentsMatchKind.CLOSE;
}
} else if (typeConverter.canConvert(suppliedArg, TypeDescriptor.valueOf(varargsParamType))) {
match = ArgumentsMatchKind.REQUIRES_CONVERSION;
} else {
match = null;
}
}
}
}
}
return (match != null ? new ArgumentsMatchInfo(match) : null);
}
use of org.springframework.core.convert.TypeDescriptor in project spring-framework by spring-projects.
the class ReflectionHelper method getTypeDifferenceWeight.
/**
* Based on {@link MethodInvoker#getTypeDifferenceWeight(Class[], Object[])} but operates on TypeDescriptors.
*/
public static int getTypeDifferenceWeight(List<TypeDescriptor> paramTypes, List<TypeDescriptor> argTypes) {
int result = 0;
for (int i = 0; i < paramTypes.size(); i++) {
TypeDescriptor paramType = paramTypes.get(i);
TypeDescriptor argType = (i < argTypes.size() ? argTypes.get(i) : null);
if (argType == null) {
if (paramType.isPrimitive()) {
return Integer.MAX_VALUE;
}
} else {
Class<?> paramTypeClazz = paramType.getType();
if (!ClassUtils.isAssignable(paramTypeClazz, argType.getType())) {
return Integer.MAX_VALUE;
}
if (paramTypeClazz.isPrimitive()) {
paramTypeClazz = Object.class;
}
Class<?> superClass = argType.getType().getSuperclass();
while (superClass != null) {
if (paramTypeClazz.equals(superClass)) {
result = result + 2;
superClass = null;
} else if (ClassUtils.isAssignable(paramTypeClazz, superClass)) {
result = result + 2;
superClass = superClass.getSuperclass();
} else {
superClass = null;
}
}
if (paramTypeClazz.isInterface()) {
result = result + 1;
}
}
}
return result;
}
Aggregations