Polishing
This commit is contained in:
parent
fd13c994c9
commit
16bf501b30
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -17,30 +17,32 @@
|
|||
package org.springframework.expression;
|
||||
|
||||
/**
|
||||
* Instances of a type comparator should be able to compare pairs of objects for equality, the specification of the
|
||||
* return value is the same as for {@link Comparable}.
|
||||
* Instances of a type comparator should be able to compare pairs of objects for equality.
|
||||
* The specification of the return value is the same as for {@link java.lang.Comparable}.
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @since 3.0
|
||||
* @see java.lang.Comparable
|
||||
*/
|
||||
public interface TypeComparator {
|
||||
|
||||
/**
|
||||
* Compare two objects.
|
||||
* Return {@code true} if the comparator can compare these two objects.
|
||||
* @param firstObject the first object
|
||||
* @param secondObject the second object
|
||||
* @return 0 if they are equal, <0 if the first is smaller than the second, or >0 if the first is larger than the
|
||||
* second
|
||||
* @throws EvaluationException if a problem occurs during comparison (or they are not comparable)
|
||||
*/
|
||||
int compare(Object firstObject, Object secondObject) throws EvaluationException;
|
||||
|
||||
/**
|
||||
* Return true if the comparator can compare these two objects
|
||||
* @param firstObject the first object
|
||||
* @param secondObject the second object
|
||||
* @return true if the comparator can compare these objects
|
||||
* @return {@code true} if the comparator can compare these objects
|
||||
*/
|
||||
boolean canCompare(Object firstObject, Object secondObject);
|
||||
|
||||
/**
|
||||
* Compare two given objects.
|
||||
* @param firstObject the first object
|
||||
* @param secondObject the second object
|
||||
* @return 0 if they are equal, <0 if the first is smaller than the second,
|
||||
* or >0 if the first is larger than the second
|
||||
* @throws EvaluationException if a problem occurs during comparison
|
||||
* (or if they are not comparable in the first place)
|
||||
*/
|
||||
int compare(Object firstObject, Object secondObject) throws EvaluationException;
|
||||
|
||||
}
|
||||
|
|
|
@ -35,22 +35,23 @@ public interface TypeConverter {
|
|||
* to the desired target type.
|
||||
* @param sourceType a type descriptor that describes the source type
|
||||
* @param targetType a type descriptor that describes the requested result type
|
||||
* @return true if that conversion can be performed
|
||||
* @return {@code true} if that conversion can be performed
|
||||
*/
|
||||
boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);
|
||||
|
||||
/**
|
||||
* Convert (may coerce) a value from one type to another, for example from a boolean
|
||||
* to a string. The typeDescriptor parameter enables support for typed collections -
|
||||
* if the caller really wishes they can have a List<Integer> for example, rather
|
||||
* than simply a List.
|
||||
* Convert (or coerce) a value from one type to another, for example from a
|
||||
* {@code boolean} to a {@code String}.
|
||||
* <p>The {@link TypeDescriptor} parameters enable support for typed collections:
|
||||
* A caller may prefer a {@code List<Integer>}, for example, rather than
|
||||
* simply any {@code List}.
|
||||
* @param value the value to be converted
|
||||
* @param sourceType a type descriptor that supplies extra information about the
|
||||
* source object
|
||||
* @param targetType a type descriptor that supplies extra information about the
|
||||
* requested result type
|
||||
* @return the converted value
|
||||
* @throws EvaluationException if conversion is not possible
|
||||
* @throws EvaluationException if conversion failed or is not possible to begin with
|
||||
*/
|
||||
Object convertValue(Object value, TypeDescriptor sourceType, TypeDescriptor targetType);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -17,9 +17,12 @@
|
|||
package org.springframework.expression;
|
||||
|
||||
/**
|
||||
* Implementors of this interface are expected to be able to locate types. They may use custom classloaders
|
||||
* or the and deal with common package prefixes (java.lang, etc) however they wish. See
|
||||
* {@link org.springframework.expression.spel.support.StandardTypeLocator} for an example implementation.
|
||||
* Implementers of this interface are expected to be able to locate types.
|
||||
* They may use a custom {@link ClassLoader} and/or deal with common
|
||||
* package prefixes (e.g. {@code java.lang}) however they wish.
|
||||
*
|
||||
* <p>See {@link org.springframework.expression.spel.support.StandardTypeLocator}
|
||||
* for an example implementation.
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @since 3.0
|
||||
|
@ -27,11 +30,12 @@ package org.springframework.expression;
|
|||
public interface TypeLocator {
|
||||
|
||||
/**
|
||||
* Find a type by name. The name may or may not be fully qualified (eg. String or java.lang.String)
|
||||
* @param typename the type to be located
|
||||
* @return the class object representing that type
|
||||
* @throws EvaluationException if there is a problem finding it
|
||||
* Find a type by name. The name may or may not be fully qualified
|
||||
* (e.g. {@code String} or {@code java.lang.String}).
|
||||
* @param typeName the type to be located
|
||||
* @return the {@code Class} object representing that type
|
||||
* @throws EvaluationException if there is a problem finding the type
|
||||
*/
|
||||
Class<?> findType(String typename) throws EvaluationException;
|
||||
Class<?> findType(String typeName) throws EvaluationException;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -21,7 +21,8 @@ import org.springframework.expression.spel.SpelEvaluationException;
|
|||
import org.springframework.expression.spel.SpelMessage;
|
||||
|
||||
/**
|
||||
* A simple basic TypeComparator implementation. It supports comparison of numbers and types implementing Comparable.
|
||||
* A simple basic {@link TypeComparator} implementation.
|
||||
* It supports comparison of Numbers and types implementing Comparable.
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Juergen Hoeller
|
||||
|
@ -29,49 +30,6 @@ import org.springframework.expression.spel.SpelMessage;
|
|||
*/
|
||||
public class StandardTypeComparator implements TypeComparator {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public int compare(Object left, Object right) throws SpelEvaluationException {
|
||||
// If one is null, check if the other is
|
||||
if (left == null) {
|
||||
return right == null ? 0 : -1;
|
||||
} else if (right == null) {
|
||||
return 1; // left cannot be null
|
||||
}
|
||||
|
||||
// Basic number comparisons
|
||||
if (left instanceof Number && right instanceof Number) {
|
||||
Number leftNumber = (Number) left;
|
||||
Number rightNumber = (Number) right;
|
||||
if (leftNumber instanceof Double || rightNumber instanceof Double) {
|
||||
double d1 = leftNumber.doubleValue();
|
||||
double d2 = rightNumber.doubleValue();
|
||||
return Double.compare(d1,d2);
|
||||
} else if (leftNumber instanceof Float || rightNumber instanceof Float) {
|
||||
float f1 = leftNumber.floatValue();
|
||||
float f2 = rightNumber.floatValue();
|
||||
return Float.compare(f1,f2);
|
||||
} else if (leftNumber instanceof Long || rightNumber instanceof Long) {
|
||||
Long l1 = leftNumber.longValue();
|
||||
Long l2 = rightNumber.longValue();
|
||||
return l1.compareTo(l2);
|
||||
} else {
|
||||
Integer i1 = leftNumber.intValue();
|
||||
Integer i2 = rightNumber.intValue();
|
||||
return i1.compareTo(i2);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (left instanceof Comparable) {
|
||||
return ((Comparable) left).compareTo(right);
|
||||
}
|
||||
} catch (ClassCastException cce) {
|
||||
throw new SpelEvaluationException(cce, SpelMessage.NOT_COMPARABLE, left.getClass(), right.getClass());
|
||||
}
|
||||
|
||||
throw new SpelEvaluationException(SpelMessage.NOT_COMPARABLE, left.getClass(), right.getClass());
|
||||
}
|
||||
|
||||
public boolean canCompare(Object left, Object right) {
|
||||
if (left == null || right == null) {
|
||||
return true;
|
||||
|
@ -85,4 +43,56 @@ public class StandardTypeComparator implements TypeComparator {
|
|||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public int compare(Object left, Object right) throws SpelEvaluationException {
|
||||
// If one is null, check if the other is
|
||||
if (left == null) {
|
||||
return (right == null ? 0 : -1);
|
||||
}
|
||||
else if (right == null) {
|
||||
return 1; // left cannot be null at this point
|
||||
}
|
||||
|
||||
// Basic number comparisons
|
||||
if (left instanceof Number && right instanceof Number) {
|
||||
Number leftNumber = (Number) left;
|
||||
Number rightNumber = (Number) right;
|
||||
|
||||
if (leftNumber instanceof Double || rightNumber instanceof Double) {
|
||||
return Double.compare(leftNumber.doubleValue(), rightNumber.doubleValue());
|
||||
}
|
||||
else if (leftNumber instanceof Float || rightNumber instanceof Float) {
|
||||
return Float.compare(leftNumber.floatValue(), rightNumber.floatValue());
|
||||
}
|
||||
else if (leftNumber instanceof Long || rightNumber instanceof Long) {
|
||||
// Don't call Long.compare here - only available on JDK 1.7+
|
||||
return compare(leftNumber.longValue(), rightNumber.longValue());
|
||||
}
|
||||
else {
|
||||
// Don't call Integer.compare here - only available on JDK 1.7+
|
||||
return compare(leftNumber.intValue(), rightNumber.intValue());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (left instanceof Comparable) {
|
||||
return ((Comparable) left).compareTo(right);
|
||||
}
|
||||
}
|
||||
catch (ClassCastException ex) {
|
||||
throw new SpelEvaluationException(ex, SpelMessage.NOT_COMPARABLE, left.getClass(), right.getClass());
|
||||
}
|
||||
|
||||
throw new SpelEvaluationException(SpelMessage.NOT_COMPARABLE, left.getClass(), right.getClass());
|
||||
}
|
||||
|
||||
|
||||
private static int compare(int x, int y) {
|
||||
return (x < y ? -1 : (x > y ? 1 : 0));
|
||||
}
|
||||
|
||||
private static int compare(long x, long y) {
|
||||
return (x < y ? -1 : (x > y ? 1 : 0));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ package org.springframework.expression.spel.support;
|
|||
|
||||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.ConverterNotFoundException;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.expression.TypeConverter;
|
||||
|
@ -27,8 +26,8 @@ import org.springframework.expression.spel.SpelMessage;
|
|||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Default implementation of the {@link TypeConverter} interface, delegating to a core
|
||||
* Spring {@link ConversionService}.
|
||||
* Default implementation of the {@link TypeConverter} interface,
|
||||
* delegating to a core Spring {@link ConversionService}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Andy Clement
|
||||
|
@ -42,6 +41,9 @@ public class StandardTypeConverter implements TypeConverter {
|
|||
private final ConversionService conversionService;
|
||||
|
||||
|
||||
/**
|
||||
* Create a StandardTypeConverter for the default ConversionService.
|
||||
*/
|
||||
public StandardTypeConverter() {
|
||||
synchronized (this) {
|
||||
if (defaultConversionService == null) {
|
||||
|
@ -51,6 +53,10 @@ public class StandardTypeConverter implements TypeConverter {
|
|||
this.conversionService = defaultConversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a StandardTypeConverter for the given ConversionService.
|
||||
* @param conversionService the ConversionService to delegate to
|
||||
*/
|
||||
public StandardTypeConverter(ConversionService conversionService) {
|
||||
Assert.notNull(conversionService, "ConversionService must not be null");
|
||||
this.conversionService = conversionService;
|
||||
|
@ -65,10 +71,6 @@ public class StandardTypeConverter implements TypeConverter {
|
|||
try {
|
||||
return this.conversionService.convert(value, sourceType, targetType);
|
||||
}
|
||||
catch (ConverterNotFoundException ex) {
|
||||
throw new SpelEvaluationException(
|
||||
ex, SpelMessage.TYPE_CONVERSION_ERROR, sourceType.toString(), targetType.toString());
|
||||
}
|
||||
catch (ConversionException ex) {
|
||||
throw new SpelEvaluationException(
|
||||
ex, SpelMessage.TYPE_CONVERSION_ERROR, sourceType.toString(), targetType.toString());
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,8 +16,8 @@
|
|||
|
||||
package org.springframework.expression.spel.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.expression.EvaluationException;
|
||||
|
@ -27,8 +27,9 @@ import org.springframework.expression.spel.SpelMessage;
|
|||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* A default implementation of a TypeLocator that uses the context classloader (or any classloader set upon it). It
|
||||
* supports 'well known' packages so if a type cannot be found it will try the registered imports to locate it.
|
||||
* A simple implementation of {@link TypeLocator} that uses the context ClassLoader
|
||||
* (or any ClassLoader set upon it). It supports 'well-known' packages: So if a
|
||||
* type cannot be found, it will try the registered imports to locate it.
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Juergen Hoeller
|
||||
|
@ -36,49 +37,30 @@ import org.springframework.util.ClassUtils;
|
|||
*/
|
||||
public class StandardTypeLocator implements TypeLocator {
|
||||
|
||||
private ClassLoader loader;
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
private final List<String> knownPackagePrefixes = new ArrayList<String>();
|
||||
private final List<String> knownPackagePrefixes = new LinkedList<String>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a StandardTypeLocator for the default ClassLoader
|
||||
* (typically, the thread context ClassLoader).
|
||||
*/
|
||||
public StandardTypeLocator() {
|
||||
this(ClassUtils.getDefaultClassLoader());
|
||||
}
|
||||
|
||||
public StandardTypeLocator(ClassLoader loader) {
|
||||
this.loader = loader;
|
||||
// Similar to when writing Java, it only knows about java.lang by default
|
||||
/**
|
||||
* Create a StandardTypeLocator for the given ClassLoader.
|
||||
* @param classLoader the ClassLoader to delegate to
|
||||
*/
|
||||
public StandardTypeLocator(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
// Similar to when writing regular Java code, it only knows about java.lang by default
|
||||
registerImport("java.lang");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find a (possibly unqualified) type reference - first using the typename as is, then trying any registered
|
||||
* prefixes if the typename cannot be found.
|
||||
* @param typename the type to locate
|
||||
* @return the class object for the type
|
||||
* @throws EvaluationException if the type cannot be found
|
||||
*/
|
||||
public Class<?> findType(String typename) throws EvaluationException {
|
||||
String nameToLookup = typename;
|
||||
try {
|
||||
return this.loader.loadClass(nameToLookup);
|
||||
}
|
||||
catch (ClassNotFoundException ey) {
|
||||
// try any registered prefixes before giving up
|
||||
}
|
||||
for (String prefix : this.knownPackagePrefixes) {
|
||||
try {
|
||||
nameToLookup = new StringBuilder().append(prefix).append(".").append(typename).toString();
|
||||
return this.loader.loadClass(nameToLookup);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// might be a different prefix
|
||||
}
|
||||
}
|
||||
throw new SpelEvaluationException(SpelMessage.TYPE_NOT_FOUND, typename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new import prefix that will be used when searching for unqualified types.
|
||||
* Expected format is something like "java.lang".
|
||||
|
@ -88,16 +70,48 @@ public class StandardTypeLocator implements TypeLocator {
|
|||
this.knownPackagePrefixes.add(prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove that specified prefix from this locator's list of imports.
|
||||
* @param prefix the prefix to remove
|
||||
*/
|
||||
public void removeImport(String prefix) {
|
||||
this.knownPackagePrefixes.remove(prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of all the import prefixes registered with this StandardTypeLocator.
|
||||
* @return list of registered import prefixes
|
||||
* @return a list of registered import prefixes
|
||||
*/
|
||||
public List<String> getImportPrefixes() {
|
||||
return Collections.unmodifiableList(this.knownPackagePrefixes);
|
||||
}
|
||||
|
||||
public void removeImport(String prefix) {
|
||||
this.knownPackagePrefixes.remove(prefix);
|
||||
|
||||
/**
|
||||
* Find a (possibly unqualified) type reference - first using the type name as-is,
|
||||
* then trying any registered prefixes if the type name cannot be found.
|
||||
* @param typeName the type to locate
|
||||
* @return the class object for the type
|
||||
* @throws EvaluationException if the type cannot be found
|
||||
*/
|
||||
public Class<?> findType(String typeName) throws EvaluationException {
|
||||
String nameToLookup = typeName;
|
||||
try {
|
||||
return this.classLoader.loadClass(nameToLookup);
|
||||
}
|
||||
catch (ClassNotFoundException ey) {
|
||||
// try any registered prefixes before giving up
|
||||
}
|
||||
for (String prefix : this.knownPackagePrefixes) {
|
||||
try {
|
||||
nameToLookup = prefix + "." + typeName;
|
||||
return this.classLoader.loadClass(nameToLookup);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// might be a different prefix
|
||||
}
|
||||
}
|
||||
throw new SpelEvaluationException(SpelMessage.TYPE_NOT_FOUND, typeName);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue