Search in sources :

Example 16 with TypeDescriptor

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;
}
Also used : AccessException(org.springframework.expression.AccessException) TypeDescriptor(org.springframework.core.convert.TypeDescriptor)

Example 17 with 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);
}
Also used : StandardTypeConverter(org.springframework.expression.spel.support.StandardTypeConverter) TypeDescriptor(org.springframework.core.convert.TypeDescriptor) GenericConversionService(org.springframework.core.convert.support.GenericConversionService) Test(org.junit.Test)

Example 18 with TypeDescriptor

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;
}
Also used : SpelEvaluationException(org.springframework.expression.spel.SpelEvaluationException) ArrayList(java.util.ArrayList) InvocationTargetException(java.lang.reflect.InvocationTargetException) TypeDescriptor(org.springframework.core.convert.TypeDescriptor) HashMap(java.util.HashMap) Map(java.util.Map) TypedValue(org.springframework.expression.TypedValue)

Example 19 with TypeDescriptor

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);
}
Also used : TypeDescriptor(org.springframework.core.convert.TypeDescriptor)

Example 20 with TypeDescriptor

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;
}
Also used : TypeDescriptor(org.springframework.core.convert.TypeDescriptor)

Aggregations

TypeDescriptor (org.springframework.core.convert.TypeDescriptor)115 Test (org.junit.Test)61 ArrayList (java.util.ArrayList)35 List (java.util.List)20 Map (java.util.Map)16 HashMap (java.util.HashMap)14 LinkedHashMap (java.util.LinkedHashMap)13 LinkedList (java.util.LinkedList)12 MethodParameter (org.springframework.core.MethodParameter)12 Collection (java.util.Collection)11 ConversionFailedException (org.springframework.core.convert.ConversionFailedException)10 Method (java.lang.reflect.Method)9 AccessException (org.springframework.expression.AccessException)9 ConverterNotFoundException (org.springframework.core.convert.ConverterNotFoundException)8 TypedValue (org.springframework.expression.TypedValue)8 StandardEvaluationContext (org.springframework.expression.spel.support.StandardEvaluationContext)8 LinkedMultiValueMap (org.springframework.util.LinkedMultiValueMap)8 MultiValueMap (org.springframework.util.MultiValueMap)8 AbstractList (java.util.AbstractList)7 Field (java.lang.reflect.Field)6