下面列出了org.springframework.core.convert.TypeDescriptor#getType ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Nullable
@Override
public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
if (StringUtil.isBlank((String) source)) {
return null;
}
Class<?> clazz = targetType.getType();
AccessibleObject accessibleObject = ENUM_CACHE_MAP.computeIfAbsent(clazz, StringToEnumConverter::getAnnotation);
String value = ((String) source).trim();
// 如果为null,走默认的转换
if (accessibleObject == null) {
return valueOf(clazz, value);
}
try {
return StringToEnumConverter.invoke(clazz, accessibleObject, value);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return null;
}
@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);
}
@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;
}
};
context.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);
}
/**
* Obtains the descriptor of the filtered field
*
* @param fieldName
* @param entity
* @return
*/
public static <T> TypeDescriptor getTypeDescriptor(String fieldName,
PathBuilder<T> entity) {
Class<?> entityType = entity.getType();
if (entityType == Object.class) {
// Remove from path the root "entity" alias
String fromRootPath = entity.toString().replaceFirst("^[^.]+[.]",
"");
TypeDescriptor fromRoot = getTypeDescriptor(fromRootPath, entity
.getRoot().getType());
if (fromRoot == null) {
return null;
}
entityType = fromRoot.getType();
}
return getTypeDescriptor(fieldName, entityType);
}
@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;
}
};
context.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);
}
@Override
public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
if (source == null) {
return null;
}
Class<?> sourceClazz = sourceType.getType();
AccessibleObject accessibleObject = ENUM_CACHE_MAP.computeIfAbsent(sourceClazz, EnumToStringConverter::getAnnotation);
Class<?> targetClazz = targetType.getType();
// 如果为null,走默认的转换
if (accessibleObject == null) {
if (String.class == targetClazz) {
return ((Enum) source).name();
}
int ordinal = ((Enum) source).ordinal();
return ConvertUtil.convert(ordinal, targetClazz);
}
try {
return EnumToStringConverter.invoke(sourceClazz, accessibleObject, source, targetClazz);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public <T> TypeDescriptor getTypeDescriptor(String fieldName,
PathBuilder<T> entity) {
Class<?> entityType = entity.getType();
if (entityType == Object.class) {
// Remove from path the root "entity" alias
String fromRootPath = entity.toString().replaceFirst("^[^.]+[.]",
"");
TypeDescriptor fromRoot = getTypeDescriptor(fromRootPath, entity
.getRoot().getType());
if (fromRoot == null) {
return null;
}
entityType = fromRoot.getType();
}
return getTypeDescriptor(fieldName, entityType);
}
/**
* Check if a string is valid for a type <br/>
* If conversion service is not provided try to check by apache commons
* utilities. <b>TODO</b> in this (no-conversionService) case just
* implemented for numerics
*
* @param string
* @param typeDescriptor
* @param conversionService (optional)
* @return
*/
private static boolean isValidValueFor(String string,
TypeDescriptor typeDescriptor, ConversionService conversionService) {
if (conversionService != null) {
try {
conversionService.convert(string, STRING_TYPE_DESCRIPTOR,
typeDescriptor);
}
catch (ConversionException e) {
return false;
}
return true;
}
else {
Class<?> fieldType = typeDescriptor.getType();
if (Number.class.isAssignableFrom(fieldType)
|| NUMBER_PRIMITIVES.contains(fieldType)) {
return NumberUtils.isNumber(string);
}
// TODO implement other types
return true;
}
}
@Override
@Nullable
public Class<?> getValueType(EvaluationContext context, Object rootObject) throws EvaluationException {
ExpressionState expressionState = new ExpressionState(context, toTypedValue(rootObject), this.configuration);
TypeDescriptor typeDescriptor = this.ast.getValueInternal(expressionState).getTypeDescriptor();
return (typeDescriptor != null ? typeDescriptor.getType() : null);
}
@Override
public Object convertValue(Object value, TypeDescriptor sourceType, TypeDescriptor targetType) {
if (targetType.getType() == Void.class || targetType.getType() == Void.TYPE) {
return null;
}
if (conversionService.canConvert(sourceType, targetType)) {
return conversionService.convert(value, sourceType, targetType);
}
if (!String.class.isAssignableFrom(sourceType.getType())) {
PropertyEditor editor = delegate.findCustomEditor(sourceType.getType(), null);
editor.setValue(value);
return editor.getAsText();
}
return delegate.convertIfNecessary(value, targetType.getType());
}
/**
* 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;
}
@Override
@Nullable
public Class<?> getValueType(EvaluationContext context) throws EvaluationException {
Assert.notNull(context, "EvaluationContext is required");
ExpressionState expressionState = new ExpressionState(context, this.configuration);
TypeDescriptor typeDescriptor = this.ast.getValueInternal(expressionState).getTypeDescriptor();
return (typeDescriptor != null ? typeDescriptor.getType() : null);
}
/**
* 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;
}
@Override
public Object convertValue(Object value, TypeDescriptor sourceType, TypeDescriptor targetType) {
if (targetType.getType() == Void.class || targetType.getType() == Void.TYPE) {
return null;
}
if (conversionService.canConvert(sourceType, targetType)) {
return conversionService.convert(value, sourceType, targetType);
}
if (!String.class.isAssignableFrom(sourceType.getType())) {
PropertyEditor editor = delegate.findCustomEditor(sourceType.getType(), null);
editor.setValue(value);
return editor.getAsText();
}
return delegate.convertIfNecessary(value, targetType.getType());
}
private PropertyValue createDefaultPropertyValue(PropertyTokenHolder tokens) {
TypeDescriptor desc = getPropertyTypeDescriptor(tokens.canonicalName);
Class<?> type = desc.getType();
if (type == null) {
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + tokens.canonicalName,
"Could not determine property type for auto-growing a default value");
}
Object defaultValue = newValue(type, desc, tokens.canonicalName);
return new PropertyValue(tokens.canonicalName, defaultValue);
}
@Override
public Class<?> getValueType(EvaluationContext context) throws EvaluationException {
Assert.notNull(context, "EvaluationContext is required");
ExpressionState expressionState = new ExpressionState(context, this.configuration);
TypeDescriptor typeDescriptor = this.ast.getValueInternal(expressionState).getTypeDescriptor();
return (typeDescriptor != null ? typeDescriptor.getType() : null);
}
private PropertyValue createDefaultPropertyValue(PropertyTokenHolder tokens) {
TypeDescriptor desc = getPropertyTypeDescriptor(tokens.canonicalName);
Class<?> type = desc.getType();
if (type == null) {
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + tokens.canonicalName,
"Could not determine property type for auto-growing a default value");
}
Object defaultValue = newValue(type, desc, tokens.canonicalName);
return new PropertyValue(tokens.canonicalName, defaultValue);
}
/**
* {@inheritDoc}
*/
@Override
public <T> Class<?> getFieldType(String fieldName, PathBuilder<T> entity) {
TypeDescriptor descriptor = getTypeDescriptor(fieldName, entity);
return descriptor.getType();
}
/**
* {@inheritDoc}
*/
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> Predicate createFilterExpression(PathBuilder<T> entityPath,
String fieldName, String searchStr) {
TypeDescriptor descriptor = getTypeDescriptor(fieldName, entityPath);
if (descriptor == null) {
throw new IllegalArgumentException(String.format(
"Can't found field '%s' on entity '%s'", fieldName,
entityPath.getType()));
}
Class<?> fieldType = descriptor.getType();
// Check for field type in order to delegate in custom-by-type
// create expression method
if (String.class == fieldType) {
return createStringExpressionWithOperators(entityPath, fieldName,
searchStr);
}
else if (Boolean.class == fieldType || boolean.class == fieldType) {
return createBooleanExpressionWithOperators(entityPath, fieldName,
searchStr);
}
else if (Number.class.isAssignableFrom(fieldType)
|| NUMBER_PRIMITIVES.contains(fieldType)) {
return createNumberExpressionGenericsWithOperators(entityPath,
fieldName, descriptor, searchStr);
}
else if (Date.class.isAssignableFrom(fieldType)
|| Calendar.class.isAssignableFrom(fieldType)) {
String datePattern = "dd/MM/yyyy";
if (messageSource != null) {
datePattern = messageSource.getMessage(
"global.filters.operations.date.pattern", null,
LocaleContextHolder.getLocale());
}
BooleanExpression expression = createDateExpressionWithOperators(
entityPath, fieldName, (Class<Date>) fieldType, searchStr,
datePattern);
return expression;
}
else if (fieldType.isEnum()) {
return createEnumExpression(entityPath, fieldName, searchStr,
(Class<? extends Enum>) fieldType);
}
return null;
}
@Override
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
return (sourceType.getType() != targetType.getType() &&
hasConversionMethodOrConstructor(targetType.getType(), sourceType.getType()));
}