Search in sources :

Example 16 with ConversionService

use of org.springframework.core.convert.ConversionService in project spring-framework by spring-projects.

the class TypeConverterDelegate method convertIfNecessary.

/**
	 * Convert the value to the required type (if necessary from a String),
	 * for the specified property.
	 * @param propertyName name of the property
	 * @param oldValue the previous value, if available (may be {@code null})
	 * @param newValue the proposed new value
	 * @param requiredType the type we must convert to
	 * (or {@code null} if not known, for example in case of a collection element)
	 * @param typeDescriptor the descriptor for the target property or field
	 * @return the new value, possibly the result of type conversion
	 * @throws IllegalArgumentException if type conversion failed
	 */
@SuppressWarnings("unchecked")
public <T> T convertIfNecessary(String propertyName, Object oldValue, Object newValue, Class<T> requiredType, TypeDescriptor typeDescriptor) throws IllegalArgumentException {
    // Custom editor for this type?
    PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);
    ConversionFailedException conversionAttemptEx = null;
    // No custom editor but custom ConversionService specified?
    ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
    if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) {
        TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
        if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
            try {
                return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
            } catch (ConversionFailedException ex) {
                // fallback to default conversion logic below
                conversionAttemptEx = ex;
            }
        }
    }
    Object convertedValue = newValue;
    // Value not of required type?
    if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
        if (typeDescriptor != null && requiredType != null && Collection.class.isAssignableFrom(requiredType) && convertedValue instanceof String) {
            TypeDescriptor elementTypeDesc = typeDescriptor.getElementTypeDescriptor();
            if (elementTypeDesc != null) {
                Class<?> elementType = elementTypeDesc.getType();
                if (Class.class == elementType || Enum.class.isAssignableFrom(elementType)) {
                    convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
                }
            }
        }
        if (editor == null) {
            editor = findDefaultEditor(requiredType);
        }
        convertedValue = doConvertValue(oldValue, convertedValue, requiredType, editor);
    }
    boolean standardConversion = false;
    if (requiredType != null) {
        if (convertedValue != null) {
            if (Object.class == requiredType) {
                return (T) convertedValue;
            } else if (requiredType.isArray()) {
                // Array required -> apply appropriate conversion of elements.
                if (convertedValue instanceof String && Enum.class.isAssignableFrom(requiredType.getComponentType())) {
                    convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
                }
                return (T) convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType());
            } else if (convertedValue instanceof Collection) {
                // Convert elements to target type, if determined.
                convertedValue = convertToTypedCollection((Collection<?>) convertedValue, propertyName, requiredType, typeDescriptor);
                standardConversion = true;
            } else if (convertedValue instanceof Map) {
                // Convert keys and values to respective target type, if determined.
                convertedValue = convertToTypedMap((Map<?, ?>) convertedValue, propertyName, requiredType, typeDescriptor);
                standardConversion = true;
            }
            if (convertedValue.getClass().isArray() && Array.getLength(convertedValue) == 1) {
                convertedValue = Array.get(convertedValue, 0);
                standardConversion = true;
            }
            if (String.class == requiredType && ClassUtils.isPrimitiveOrWrapper(convertedValue.getClass())) {
                // We can stringify any primitive value...
                return (T) convertedValue.toString();
            } else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {
                if (conversionAttemptEx == null && !requiredType.isInterface() && !requiredType.isEnum()) {
                    try {
                        Constructor<T> strCtor = requiredType.getConstructor(String.class);
                        return BeanUtils.instantiateClass(strCtor, convertedValue);
                    } catch (NoSuchMethodException ex) {
                        // proceed with field lookup
                        if (logger.isTraceEnabled()) {
                            logger.trace("No String constructor found on type [" + requiredType.getName() + "]", ex);
                        }
                    } catch (Exception ex) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("Construction via String failed for type [" + requiredType.getName() + "]", ex);
                        }
                    }
                }
                String trimmedValue = ((String) convertedValue).trim();
                if (requiredType.isEnum() && "".equals(trimmedValue)) {
                    // It's an empty enum identifier: reset the enum value to null.
                    return null;
                }
                convertedValue = attemptToConvertStringToEnum(requiredType, trimmedValue, convertedValue);
                standardConversion = true;
            } else if (convertedValue instanceof Number && Number.class.isAssignableFrom(requiredType)) {
                convertedValue = NumberUtils.convertNumberToTargetClass((Number) convertedValue, (Class<Number>) requiredType);
                standardConversion = true;
            }
        } else {
            // convertedValue == null
            if (requiredType == Optional.class) {
                convertedValue = Optional.empty();
            }
        }
        if (!ClassUtils.isAssignableValue(requiredType, convertedValue)) {
            if (conversionAttemptEx != null) {
                // Original exception from former ConversionService call above...
                throw conversionAttemptEx;
            } else if (conversionService != null) {
                // ConversionService not tried before, probably custom editor found
                // but editor couldn't produce the required type...
                TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
                if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
                    return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
                }
            }
            // Definitely doesn't match: throw IllegalArgumentException/IllegalStateException
            StringBuilder msg = new StringBuilder();
            msg.append("Cannot convert value of type '").append(ClassUtils.getDescriptiveType(newValue));
            msg.append("' to required type '").append(ClassUtils.getQualifiedName(requiredType)).append("'");
            if (propertyName != null) {
                msg.append(" for property '").append(propertyName).append("'");
            }
            if (editor != null) {
                msg.append(": PropertyEditor [").append(editor.getClass().getName()).append("] returned inappropriate value of type '").append(ClassUtils.getDescriptiveType(convertedValue)).append("'");
                throw new IllegalArgumentException(msg.toString());
            } else {
                msg.append(": no matching editors or conversion strategy found");
                throw new IllegalStateException(msg.toString());
            }
        }
    }
    if (conversionAttemptEx != null) {
        if (editor == null && !standardConversion && requiredType != null && Object.class != requiredType) {
            throw conversionAttemptEx;
        }
        logger.debug("Original ConversionService attempt failed - ignored since " + "PropertyEditor based conversion eventually succeeded", conversionAttemptEx);
    }
    return (T) convertedValue;
}
Also used : Constructor(java.lang.reflect.Constructor) ConversionFailedException(org.springframework.core.convert.ConversionFailedException) ConversionFailedException(org.springframework.core.convert.ConversionFailedException) TypeDescriptor(org.springframework.core.convert.TypeDescriptor) ConversionService(org.springframework.core.convert.ConversionService) PropertyEditor(java.beans.PropertyEditor) Collection(java.util.Collection) Map(java.util.Map)

Example 17 with ConversionService

use of org.springframework.core.convert.ConversionService in project spring-framework by spring-projects.

the class MimeTypeTests method withConversionService.

@Test
public void withConversionService() {
    ConversionService conversionService = new DefaultConversionService();
    assertTrue(conversionService.canConvert(String.class, MimeType.class));
    MimeType mimeType = MimeType.valueOf("application/xml");
    assertEquals(mimeType, conversionService.convert("application/xml", MimeType.class));
}
Also used : ConversionService(org.springframework.core.convert.ConversionService) DefaultConversionService(org.springframework.core.convert.support.DefaultConversionService) DefaultConversionService(org.springframework.core.convert.support.DefaultConversionService) Test(org.junit.Test)

Example 18 with ConversionService

use of org.springframework.core.convert.ConversionService in project spring-framework by spring-projects.

the class ConversionServiceFactoryBeanTests method createDefaultConversionServiceWithSupplements.

@Test
public void createDefaultConversionServiceWithSupplements() {
    ConversionServiceFactoryBean factory = new ConversionServiceFactoryBean();
    Set<Object> converters = new HashSet<>();
    converters.add(new Converter<String, Foo>() {

        @Override
        public Foo convert(String source) {
            return new Foo();
        }
    });
    converters.add(new ConverterFactory<String, Bar>() {

        @Override
        public <T extends Bar> Converter<String, T> getConverter(Class<T> targetType) {
            return new Converter<String, T>() {

                @SuppressWarnings("unchecked")
                @Override
                public T convert(String source) {
                    return (T) new Bar();
                }
            };
        }
    });
    converters.add(new GenericConverter() {

        @Override
        public Set<ConvertiblePair> getConvertibleTypes() {
            return Collections.singleton(new ConvertiblePair(String.class, Baz.class));
        }

        @Override
        public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
            return new Baz();
        }
    });
    factory.setConverters(converters);
    factory.afterPropertiesSet();
    ConversionService service = factory.getObject();
    assertTrue(service.canConvert(String.class, Integer.class));
    assertTrue(service.canConvert(String.class, Foo.class));
    assertTrue(service.canConvert(String.class, Bar.class));
    assertTrue(service.canConvert(String.class, Baz.class));
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) GenericConverter(org.springframework.core.convert.converter.GenericConverter) TypeDescriptor(org.springframework.core.convert.TypeDescriptor) ConversionService(org.springframework.core.convert.ConversionService) Converter(org.springframework.core.convert.converter.Converter) GenericConverter(org.springframework.core.convert.converter.GenericConverter) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 19 with ConversionService

use of org.springframework.core.convert.ConversionService in project spring-framework by spring-projects.

the class StandardBeanExpressionResolver method evaluate.

@Override
public Object evaluate(String value, BeanExpressionContext evalContext) throws BeansException {
    if (!StringUtils.hasLength(value)) {
        return value;
    }
    try {
        Expression expr = this.expressionCache.get(value);
        if (expr == null) {
            expr = this.expressionParser.parseExpression(value, this.beanExpressionParserContext);
            this.expressionCache.put(value, expr);
        }
        StandardEvaluationContext sec = this.evaluationCache.get(evalContext);
        if (sec == null) {
            sec = new StandardEvaluationContext();
            sec.setRootObject(evalContext);
            sec.addPropertyAccessor(new BeanExpressionContextAccessor());
            sec.addPropertyAccessor(new BeanFactoryAccessor());
            sec.addPropertyAccessor(new MapAccessor());
            sec.addPropertyAccessor(new EnvironmentAccessor());
            sec.setBeanResolver(new BeanFactoryResolver(evalContext.getBeanFactory()));
            sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader()));
            ConversionService conversionService = evalContext.getBeanFactory().getConversionService();
            if (conversionService != null) {
                sec.setTypeConverter(new StandardTypeConverter(conversionService));
            }
            customizeEvaluationContext(sec);
            this.evaluationCache.put(evalContext, sec);
        }
        return expr.getValue(sec);
    } catch (Exception ex) {
        throw new BeanExpressionException("Expression parsing failed", ex);
    }
}
Also used : StandardTypeConverter(org.springframework.expression.spel.support.StandardTypeConverter) StandardEvaluationContext(org.springframework.expression.spel.support.StandardEvaluationContext) BeanExpressionException(org.springframework.beans.factory.BeanExpressionException) StandardTypeLocator(org.springframework.expression.spel.support.StandardTypeLocator) Expression(org.springframework.expression.Expression) ConversionService(org.springframework.core.convert.ConversionService) BeanExpressionException(org.springframework.beans.factory.BeanExpressionException) BeansException(org.springframework.beans.BeansException)

Example 20 with ConversionService

use of org.springframework.core.convert.ConversionService in project spring-framework by spring-projects.

the class ObjectToStringHttpMessageConverterTests method defaultCharsetModified.

@Test
public void defaultCharsetModified() throws IOException {
    ConversionService cs = new DefaultConversionService();
    ObjectToStringHttpMessageConverter converter = new ObjectToStringHttpMessageConverter(cs, StandardCharsets.UTF_16);
    converter.write((byte) 31, null, this.response);
    assertEquals("UTF-16", this.servletResponse.getCharacterEncoding());
}
Also used : ConversionService(org.springframework.core.convert.ConversionService) DefaultConversionService(org.springframework.core.convert.support.DefaultConversionService) DefaultConversionService(org.springframework.core.convert.support.DefaultConversionService) Test(org.junit.Test)

Aggregations

ConversionService (org.springframework.core.convert.ConversionService)21 Test (org.junit.Test)11 DefaultConversionService (org.springframework.core.convert.support.DefaultConversionService)5 TypeDescriptor (org.springframework.core.convert.TypeDescriptor)4 ApplicationContext (org.springframework.context.ApplicationContext)3 LocalValidatorFactoryBean (org.springframework.validation.beanvalidation.LocalValidatorFactoryBean)3 WebDataBinder (org.springframework.web.bind.WebDataBinder)3 ConfigurableWebBindingInitializer (org.springframework.web.bind.support.ConfigurableWebBindingInitializer)3 Collection (java.util.Collection)2 Map (java.util.Map)2 ConversionFailedException (org.springframework.core.convert.ConversionFailedException)2 StandardEvaluationContext (org.springframework.expression.spel.support.StandardEvaluationContext)2 StandardTypeConverter (org.springframework.expression.spel.support.StandardTypeConverter)2 FormattingConversionService (org.springframework.format.support.FormattingConversionService)2 Validator (org.springframework.validation.Validator)2 WebDataBinderFactory (org.springframework.web.bind.support.WebDataBinderFactory)2 RequestMappingHandlerAdapter (org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter)2 RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter)2 FAIL_ON_UNKNOWN_PROPERTIES (com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)1 DEFAULT_VIEW_INCLUSION (com.fasterxml.jackson.databind.MapperFeature.DEFAULT_VIEW_INCLUSION)1