Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爱吃血肠
spring-framework
提交
ae4f80cf
S
spring-framework
项目概览
爱吃血肠
/
spring-framework
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
spring-framework
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
ae4f80cf
编写于
3月 30, 2009
作者:
K
Keith Donald
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
type descriptor initial commit
上级
c057638b
变更
19
隐藏空白更改
内联
并排
Showing
19 changed file
with
569 addition
and
708 deletion
+569
-708
org.springframework.core/src/main/java/org/springframework/core/convert/ConversionExecutionException.java
...gframework/core/convert/ConversionExecutionException.java
+20
-20
org.springframework.core/src/main/java/org/springframework/core/convert/ConversionExecutor.java
.../org/springframework/core/convert/ConversionExecutor.java
+2
-12
org.springframework.core/src/main/java/org/springframework/core/convert/ConversionExecutorNotFoundException.java
...ork/core/convert/ConversionExecutorNotFoundException.java
+11
-11
org.springframework.core/src/main/java/org/springframework/core/convert/ConversionService.java
...a/org/springframework/core/convert/ConversionService.java
+30
-22
org.springframework.core/src/main/java/org/springframework/core/convert/TypeDescriptor.java
...java/org/springframework/core/convert/TypeDescriptor.java
+193
-0
org.springframework.core/src/main/java/org/springframework/core/convert/TypedValue.java
...ain/java/org/springframework/core/convert/TypedValue.java
+38
-0
org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConverterInfo.java
...springframework/core/convert/converter/ConverterInfo.java
+9
-0
org.springframework.core/src/main/java/org/springframework/core/convert/service/AbstractCollectionConverter.java
...ork/core/convert/service/AbstractCollectionConverter.java
+57
-0
org.springframework.core/src/main/java/org/springframework/core/convert/service/ArrayToArray.java
...rg/springframework/core/convert/service/ArrayToArray.java
+9
-39
org.springframework.core/src/main/java/org/springframework/core/convert/service/ArrayToCollection.java
...ringframework/core/convert/service/ArrayToCollection.java
+12
-63
org.springframework.core/src/main/java/org/springframework/core/convert/service/CollectionToArray.java
...ringframework/core/convert/service/CollectionToArray.java
+15
-39
org.springframework.core/src/main/java/org/springframework/core/convert/service/CollectionToCollection.java
...ramework/core/convert/service/CollectionToCollection.java
+23
-44
org.springframework.core/src/main/java/org/springframework/core/convert/service/DefaultConversionService.java
...mework/core/convert/service/DefaultConversionService.java
+0
-3
org.springframework.core/src/main/java/org/springframework/core/convert/service/GenericConversionService.java
...mework/core/convert/service/GenericConversionService.java
+50
-210
org.springframework.core/src/main/java/org/springframework/core/convert/service/ObjectToArray.java
...g/springframework/core/convert/service/ObjectToArray.java
+0
-67
org.springframework.core/src/main/java/org/springframework/core/convert/service/ObjectToCollection.java
...ingframework/core/convert/service/ObjectToCollection.java
+0
-83
org.springframework.core/src/main/java/org/springframework/core/convert/service/StaticConversionExecutor.java
...mework/core/convert/service/StaticConversionExecutor.java
+21
-24
org.springframework.core/src/main/java/org/springframework/core/convert/service/StaticSuperConversionExecutor.java
...k/core/convert/service/StaticSuperConversionExecutor.java
+18
-28
org.springframework.core/src/test/java/org/springframework/core/convert/service/GenericConversionServiceTests.java
...k/core/convert/service/GenericConversionServiceTests.java
+61
-43
未找到文件。
org.springframework.core/src/main/java/org/springframework/core/convert/ConversionExecutionException.java
浏览文件 @
ae4f80cf
...
...
@@ -32,39 +32,39 @@ public class ConversionExecutionException extends ConversionException {
/**
* The source type we tried to convert the value from.
*/
private
Class
<?>
sourceClass
;
private
TypeDescriptor
sourceType
;
/**
* The target type we tried to convert the value to.
*/
private
Class
<?>
targetClass
;
private
TypeDescriptor
targetType
;
/**
* Creates a new conversion exception.
* @param value the value we tried to convert
* @param source
Class
the value's original type
* @param target
Class
the value's target type
* @param source
Type
the value's original type
* @param target
Type
the value's target type
* @param cause the cause of the conversion failure
*/
public
ConversionExecutionException
(
Object
value
,
Class
<?>
sourceClass
,
Class
<?>
targetClass
,
Throwable
cause
)
{
super
(
defaultMessage
(
value
,
source
Class
,
targetClass
,
cause
),
cause
);
public
ConversionExecutionException
(
Object
value
,
TypeDescriptor
sourceType
,
TypeDescriptor
targetType
,
Throwable
cause
)
{
super
(
defaultMessage
(
value
,
source
Type
,
targetType
,
cause
),
cause
);
this
.
value
=
value
;
this
.
source
Class
=
sourceClass
;
this
.
target
Class
=
targetClass
;
this
.
source
Type
=
sourceType
;
this
.
target
Type
=
targetType
;
}
/**
* Creates a new conversion exception.
* @param value the value we tried to convert
* @param source
Class
the value's original type
* @param target
Class
the value's target type
* @param source
Type
the value's original type
* @param target
Type
the value's target type
* @param message a descriptive message of what went wrong.
*/
public
ConversionExecutionException
(
Object
value
,
Class
<?>
sourceClass
,
Class
<?>
targetClass
,
String
message
)
{
public
ConversionExecutionException
(
Object
value
,
TypeDescriptor
sourceType
,
TypeDescriptor
targetType
,
String
message
)
{
super
(
message
);
this
.
value
=
value
;
this
.
source
Class
=
sourceClass
;
this
.
target
Class
=
targetClass
;
this
.
source
Type
=
sourceType
;
this
.
target
Type
=
targetType
;
}
/**
...
...
@@ -77,20 +77,20 @@ public class ConversionExecutionException extends ConversionException {
/**
* Returns the source type we tried to convert the value from.
*/
public
Class
<?>
getSourceClass
()
{
return
source
Class
;
public
TypeDescriptor
getSourceClass
()
{
return
source
Type
;
}
/**
* Returns the target type we tried to convert the value to.
*/
public
Class
<?>
getTargetClass
()
{
return
target
Class
;
public
TypeDescriptor
getTargetClass
()
{
return
target
Type
;
}
private
static
String
defaultMessage
(
Object
value
,
Class
<?>
sourceClass
,
Class
<?>
targetClass
,
Throwable
cause
)
{
return
"Unable to convert value "
+
StylerUtils
.
style
(
value
)
+
" from type ["
+
source
Class
.
getName
()
+
"] to type ["
+
target
Class
.
getName
()
+
"]; reason = '"
+
cause
.
getMessage
()
+
"'"
;
private
static
String
defaultMessage
(
Object
value
,
TypeDescriptor
sourceType
,
TypeDescriptor
targetType
,
Throwable
cause
)
{
return
"Unable to convert value "
+
StylerUtils
.
style
(
value
)
+
" from type ["
+
source
Type
.
getName
()
+
"] to type ["
+
target
Type
.
getName
()
+
"]; reason = '"
+
cause
.
getMessage
()
+
"'"
;
}
}
\ No newline at end of file
org.springframework.core/src/main/java/org/springframework/core/convert/ConversionExecutor.java
浏览文件 @
ae4f80cf
...
...
@@ -22,23 +22,13 @@ package org.springframework.core.convert;
*
* @author Keith Donald
*/
public
interface
ConversionExecutor
<
S
,
T
>
{
/**
* The type this executor converts from.
*/
public
Class
<
S
>
getSourceClass
();
/**
* The type this executor converts to.
s */
public
Class
<
T
>
getTargetClass
();
public
interface
ConversionExecutor
{
/**
* Convert the source to T.
* @param source the source to convert
* @throws ConversionExecutionException if an exception occurs during type conversion
*/
public
T
execute
(
S
source
)
throws
ConversionExecutionException
;
public
Object
execute
(
Object
source
)
throws
ConversionExecutionException
;
}
\ No newline at end of file
org.springframework.core/src/main/java/org/springframework/core/convert/ConversionExecutorNotFoundException.java
浏览文件 @
ae4f80cf
...
...
@@ -23,33 +23,33 @@ package org.springframework.core.convert;
*/
public
class
ConversionExecutorNotFoundException
extends
ConversionException
{
private
Class
<?>
sourceClass
;
private
TypeDescriptor
sourceType
;
private
Class
<?>
targetClass
;
private
TypeDescriptor
targetType
;
/**
* Creates a new conversion executor not found exception.
* @param source
Class
the source type requested to convert from
* @param target
Class
the target type requested to convert to
* @param source
Type
the source type requested to convert from
* @param target
Type
the target type requested to convert to
* @param message a descriptive message
*/
public
ConversionExecutorNotFoundException
(
Class
<?>
sourceClass
,
Class
<?>
targetClass
,
String
message
)
{
public
ConversionExecutorNotFoundException
(
TypeDescriptor
sourceType
,
TypeDescriptor
targetType
,
String
message
)
{
super
(
message
);
this
.
source
Class
=
sourceClass
;
this
.
target
Class
=
targetClass
;
this
.
source
Type
=
sourceType
;
this
.
target
Type
=
targetType
;
}
/**
* Returns the source type requested to convert from.
*/
public
Class
<?>
getSourceClass
()
{
return
source
Class
;
public
TypeDescriptor
getSourceType
()
{
return
source
Type
;
}
/**
* Returns the target type requested to convert to.
*/
public
Class
<?>
getTargetClass
()
{
return
target
Class
;
public
TypeDescriptor
getTargetType
()
{
return
target
Type
;
}
}
org.springframework.core/src/main/java/org/springframework/core/convert/ConversionService.java
浏览文件 @
ae4f80cf
...
...
@@ -26,61 +26,69 @@ package org.springframework.core.convert;
public
interface
ConversionService
{
/**
*
Convert the source to target class T
.
*
Returns true if the source can be converted to targetType
.
* @param source the source to convert from (may be null)
* @param targetClass the target class to convert to
* @return the converted object, an instance of the <code>targetClass</code>, or <code>null</code> if a null source
* @param targetType the target type to convert to
* @return true if a conversion can be performed, false if not
*/
public
boolean
canConvert
(
TypedValue
source
,
TypeDescriptor
targetType
);
/**
* Convert the source to target type T.
* @param source the source to convert from (may be null)
* @param targetType the target type to convert to
* @return the converted object, an instance of the <code>targetType</code>, or <code>null</code> if a null source
* was provided
* @throws ConversionExecutorNotFoundException if no suitable conversion executor could be found to convert the
* source to an instance of target
Class
* source to an instance of target
Type
* @throws ConversionException if an exception occurred during the conversion process
*/
public
<
T
>
T
executeConversion
(
Object
source
,
Class
<
T
>
targetClass
)
throws
ConversionExecutorNotFoundException
,
public
Object
executeConversion
(
TypedValue
source
,
TypeDescriptor
targetType
)
throws
ConversionExecutorNotFoundException
,
ConversionException
;
/**
* Convert the source to target
class
T with a custom converter.
* Convert the source to target
type
T with a custom converter.
* @param converterId the id of the custom converter, which must be registered with this conversion service and
* capable of converting to the target
Class
* capable of converting to the target
Type
* @param source the source to convert from (may be null)
* @param target
Class the target class
to convert to
* @return the converted object, an instance of the <code>target
Class
</code>, or <code>null</code> if a null source
* @param target
Type the target type
to convert to
* @return the converted object, an instance of the <code>target
Type
</code>, or <code>null</code> if a null source
* was provided
* @throws ConversionExecutorNotFoundException if no suitable conversion executor could be found to convert the
* source to an instance of target
Class
* source to an instance of target
Type
* @throws ConversionException if an exception occurred during the conversion process
*/
public
<
T
>
T
executeConversion
(
String
converterId
,
Object
source
,
Class
<
T
>
targetClass
)
public
Object
executeConversion
(
String
converterId
,
TypedValue
source
,
TypeDescriptor
targetType
)
throws
ConversionExecutorNotFoundException
,
ConversionException
;
/**
* Get a ConversionExecutor that converts objects from S to T.
* The returned ConversionExecutor is thread-safe and may safely be cached for later use by client code.
* @param source
Class the source class
to convert from (required)
* @param target
Class the target class
to convert to (required)
* @param source
Type the source type
to convert from (required)
* @param target
Type the target type
to convert to (required)
* @return the executor that can execute instance type conversion, never null
* @throws ConversionExecutorNotFoundException when no suitable conversion executor could be found
*/
public
<
S
,
T
>
ConversionExecutor
<
S
,
T
>
getConversionExecutor
(
Class
<
S
>
sourceClass
,
Class
<
T
>
targetClass
)
public
ConversionExecutor
getConversionExecutor
(
TypeDescriptor
sourceType
,
TypeDescriptor
targetType
)
throws
ConversionExecutorNotFoundException
;
/**
* Get a ConversionExecutor that that converts objects from S to T with a custom converter.
* The returned ConversionExecutor is thread-safe and may safely be cached for use in client code.
* @param converterId the id of the custom converter, which must be registered with this conversion service and
* capable of converting from source
Class to targetClass
(required)
* @param source
Class the source class
to convert from (required)
* @param target
Class the target class
to convert to (required)
* capable of converting from source
Type to targetType
(required)
* @param source
Type the source type
to convert from (required)
* @param target
Type the target type
to convert to (required)
* @return the executor that can execute instance type conversion, never null
* @throws ConversionExecutorNotFoundException when no suitable conversion executor could be found
*/
public
<
S
,
T
>
ConversionExecutor
<
S
,
T
>
getConversionExecutor
(
String
converterId
,
Class
<
S
>
sourceClass
,
Class
<
T
>
targetClass
)
throws
ConversionExecutorNotFoundException
;
public
ConversionExecutor
getConversionExecutor
(
String
converterId
,
TypeDescriptor
sourceType
,
TypeDescriptor
targetType
)
throws
ConversionExecutorNotFoundException
;
/**
* Get a
class by its
alias.
* @return the class, or <code>null</code> if no such
alias
exists
* Get a
type by its name; may be the fully-qualified class name or a registered
alias.
* @return the class, or <code>null</code> if no such
name
exists
*/
public
Class
<?>
get
ClassForAlias
(
String
alias
);
public
Class
<?>
get
Type
(
String
name
);
}
\ No newline at end of file
org.springframework.core/src/main/java/org/springframework/core/convert/TypeDescriptor.java
0 → 100644
浏览文件 @
ae4f80cf
package
org.springframework.core.convert
;
import
java.lang.annotation.Annotation
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Modifier
;
import
java.util.Collection
;
import
org.springframework.core.GenericCollectionTypeResolver
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.util.Assert
;
/**
* Metadata about a retrieved value or value type.
*
* @author Keith Donald
*/
public
class
TypeDescriptor
{
private
MethodParameter
methodParameter
;
private
Field
field
;
private
Annotation
[]
cachedFieldAnnotations
;
private
Class
<?>
type
;
public
TypeDescriptor
(
Class
<?>
type
)
{
this
.
type
=
type
;
}
/**
* Create a new descriptor for a method or constructor parameter.
*
* @param methodParameter the MethodParameter to wrap
*/
public
TypeDescriptor
(
MethodParameter
methodParameter
)
{
Assert
.
notNull
(
methodParameter
,
"MethodParameter must not be null"
);
this
.
methodParameter
=
methodParameter
;
}
/**
* Create a new descriptor for a field. Considers the dependency as 'eager'.
*
* @param field the field to wrap
*/
public
TypeDescriptor
(
Field
field
)
{
Assert
.
notNull
(
field
,
"Field must not be null"
);
this
.
field
=
field
;
}
/**
* Determine the declared (non-generic) type of the wrapped parameter/field.
*
* @return the declared type (never <code>null</code>)
*/
public
Class
<?>
getType
()
{
if
(
type
!=
null
)
{
return
type
;
}
else
if
(
field
!=
null
)
{
return
field
.
getType
();
}
else
{
return
methodParameter
.
getParameterType
();
}
}
public
Class
<?>
getWrapperTypeIfPrimitive
()
{
Class
<?>
type
=
getType
();
if
(
type
.
isPrimitive
())
{
if
(
type
.
equals
(
int
.
class
))
{
return
Integer
.
class
;
}
else
if
(
type
.
equals
(
short
.
class
))
{
return
Short
.
class
;
}
else
if
(
type
.
equals
(
long
.
class
))
{
return
Long
.
class
;
}
else
if
(
type
.
equals
(
float
.
class
))
{
return
Float
.
class
;
}
else
if
(
type
.
equals
(
double
.
class
))
{
return
Double
.
class
;
}
else
if
(
type
.
equals
(
byte
.
class
))
{
return
Byte
.
class
;
}
else
if
(
type
.
equals
(
boolean
.
class
))
{
return
Boolean
.
class
;
}
else
if
(
type
.
equals
(
char
.
class
))
{
return
Character
.
class
;
}
else
{
throw
new
IllegalStateException
(
"Should never happen - primitive type is not a primitive?"
);
}
}
else
{
return
type
;
}
}
public
String
getName
()
{
return
getType
().
getName
();
}
public
boolean
isArray
()
{
return
getType
().
isArray
();
}
public
Class
<?>
getElementType
()
{
return
isArray
()
?
getArrayComponentType
()
:
getCollectionElementType
();
}
public
Class
<?>
getArrayComponentType
()
{
return
getType
().
getComponentType
();
}
public
boolean
isInstance
(
Object
source
)
{
return
getType
().
isInstance
(
source
);
}
/**
* Determine the generic element type of the wrapped Collection parameter/field, if any.
*
* @return the generic type, or <code>null</code> if none
*/
public
Class
<?>
getCollectionElementType
()
{
if
(
type
!=
null
)
{
return
GenericCollectionTypeResolver
.
getCollectionType
((
Class
<?
extends
Collection
>)
type
);
}
else
if
(
field
!=
null
)
{
return
GenericCollectionTypeResolver
.
getCollectionFieldType
(
field
);
}
else
{
return
GenericCollectionTypeResolver
.
getCollectionParameterType
(
methodParameter
);
}
}
/**
* Determine the generic key type of the wrapped Map parameter/field, if any.
*
* @return the generic type, or <code>null</code> if none
*/
public
Class
<?>
getMapKeyType
()
{
return
(
field
!=
null
?
GenericCollectionTypeResolver
.
getMapKeyFieldType
(
field
)
:
GenericCollectionTypeResolver
.
getMapKeyParameterType
(
methodParameter
));
}
/**
* Determine the generic value type of the wrapped Map parameter/field, if any.
*
* @return the generic type, or <code>null</code> if none
*/
public
Class
<?>
getMapValueType
()
{
return
(
field
!=
null
?
GenericCollectionTypeResolver
.
getMapValueFieldType
(
field
)
:
GenericCollectionTypeResolver
.
getMapValueParameterType
(
methodParameter
));
}
/**
* Obtain the annotations associated with the wrapped parameter/field, if any.
*/
public
Annotation
[]
getAnnotations
()
{
if
(
field
!=
null
)
{
if
(
cachedFieldAnnotations
==
null
)
{
cachedFieldAnnotations
=
field
.
getAnnotations
();
}
return
cachedFieldAnnotations
;
}
else
{
return
methodParameter
.
getParameterAnnotations
();
}
}
/**
* Return the wrapped MethodParameter, if any.
* <p>
* Note: Either MethodParameter or Field is available.
*
* @return the MethodParameter, or <code>null</code> if none
*/
public
MethodParameter
getMethodParameter
()
{
return
methodParameter
;
}
/**
* Return the wrapped Field, if any.
* <p>
* Note: Either MethodParameter or Field is available.
*
* @return the Field, or <code>null</code> if none
*/
public
Field
getField
()
{
return
field
;
}
public
boolean
isCollection
()
{
return
Collection
.
class
.
isAssignableFrom
(
getType
());
}
public
boolean
isAbstractClass
()
{
return
!
getType
().
isInterface
()
&&
Modifier
.
isAbstract
(
getType
().
getModifiers
());
}
}
org.springframework.core/src/main/java/org/springframework/core/convert/TypedValue.java
0 → 100644
浏览文件 @
ae4f80cf
package
org.springframework.core.convert
;
/**
* A value retrieved from some location such as a field access or getter invocation.
*
* @author Keith Donald
*/
public
class
TypedValue
{
private
final
Object
value
;
private
final
TypeDescriptor
typeDescriptor
;
/**
* Creates a typed value.
* @param value the actual value (may be null)
* @param typeDescriptor the value type descriptor (may be null)
*/
public
TypedValue
(
Object
value
,
TypeDescriptor
typeDescriptor
)
{
this
.
value
=
value
;
this
.
typeDescriptor
=
typeDescriptor
;
}
/**
* The actual value. May be null.
*/
public
Object
getValue
()
{
return
value
;
}
/**
* Provides additional type context about the value. May be null.
*/
public
TypeDescriptor
getTypeDescriptor
()
{
return
typeDescriptor
;
}
}
org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConverterInfo.java
0 → 100644
浏览文件 @
ae4f80cf
package
org.springframework.core.convert.converter
;
public
interface
ConverterInfo
{
public
Class
<?>
getSourceType
();
public
Class
<?>
getTargetType
();
}
org.springframework.core/src/main/java/org/springframework/core/convert/service/AbstractCollectionConverter.java
0 → 100644
浏览文件 @
ae4f80cf
package
org.springframework.core.convert.service
;
import
org.springframework.core.convert.ConversionExecutionException
;
import
org.springframework.core.convert.ConversionExecutor
;
import
org.springframework.core.convert.TypeDescriptor
;
abstract
class
AbstractCollectionConverter
implements
ConversionExecutor
{
private
TypeDescriptor
sourceCollectionType
;
private
TypeDescriptor
targetCollectionType
;
private
GenericConversionService
conversionService
;
private
ConversionExecutor
elementConverter
;
public
AbstractCollectionConverter
(
TypeDescriptor
sourceCollectionType
,
TypeDescriptor
targetCollectionType
,
GenericConversionService
conversionService
)
{
this
.
sourceCollectionType
=
sourceCollectionType
;
this
.
targetCollectionType
=
targetCollectionType
;
this
.
conversionService
=
conversionService
;
this
.
elementConverter
=
createElementConverter
();
}
private
ConversionExecutor
createElementConverter
()
{
Class
<?>
sourceElementType
=
getSourceType
().
getElementType
();
Class
<?>
targetElementType
=
getTargetType
().
getElementType
();
return
(
sourceElementType
!=
null
&&
targetElementType
!=
null
)
?
conversionService
.
getElementConverter
(
sourceElementType
,
targetElementType
)
:
null
;
}
protected
TypeDescriptor
getSourceType
()
{
return
sourceCollectionType
;
}
protected
TypeDescriptor
getTargetType
()
{
return
targetCollectionType
;
}
protected
GenericConversionService
getConversionService
()
{
return
conversionService
;
}
protected
ConversionExecutor
getElementConverter
()
{
return
elementConverter
;
}
@Override
public
Object
execute
(
Object
source
)
throws
ConversionExecutionException
{
try
{
return
doExecute
(
source
);
}
catch
(
Exception
e
)
{
throw
new
ConversionExecutionException
(
source
,
sourceCollectionType
,
targetCollectionType
,
e
);
}
}
protected
abstract
Object
doExecute
(
Object
sourceCollection
)
throws
Exception
;
}
\ No newline at end of file
org.springframework.core/src/main/java/org/springframework/core/convert/service/ArrayToArray.java
浏览文件 @
ae4f80cf
...
...
@@ -17,9 +17,8 @@ package org.springframework.core.convert.service;
import
java.lang.reflect.Array
;
import
org.springframework.core.convert.ConversionExecutor
;
import
org.springframework.core.convert.ConversionService
;
import
org.springframework.core.convert.
converter.SuperConverte
r
;
import
org.springframework.core.convert.
TypeDescripto
r
;
/**
* Special one-way converter that converts from a source array to a target array. Supports type conversion of the
...
...
@@ -28,49 +27,20 @@ import org.springframework.core.convert.converter.SuperConverter;
*
* @author Keith Donald
*/
@SuppressWarnings
(
"unchecked"
)
class
ArrayToArray
implements
SuperConverter
{
class
ArrayToArray
extends
AbstractCollectionConverter
{
private
ConversionService
conversionService
;
private
ConversionExecutor
elementConverter
;
/**
* Creates a new array-to-array converter.
* @param conversionService the service to use to lookup conversion executors for individual array elements
* dynamically
*/
public
ArrayToArray
(
ConversionService
conversionService
)
{
this
.
conversionService
=
conversionService
;
}
/**
* Creates a new array-to-array converter.
* @param elementConverter a specific conversion executor to use to convert elements in the source array to elements
* in the target array.
*/
public
ArrayToArray
(
ConversionExecutor
elementConverter
)
{
this
.
elementConverter
=
elementConverter
;
public
ArrayToArray
(
TypeDescriptor
sourceArrayType
,
TypeDescriptor
targetArrayType
,
GenericConversionService
conversionService
)
{
super
(
sourceArrayType
,
targetArrayType
,
conversionService
);
}
public
Object
convert
(
Object
source
,
Class
targetClass
)
throws
Exception
{
Class
sourceComponentType
=
source
.
getClass
().
getComponentType
();
Class
targetComponentType
=
targetClass
.
getComponentType
();
int
length
=
Array
.
getLength
(
source
);
Object
targetArray
=
Array
.
newInstance
(
targetComponentType
,
length
);
ConversionExecutor
converter
=
getElementConverter
(
sourceComponentType
,
targetComponentType
);
public
Object
doExecute
(
Object
sourceArray
)
throws
Exception
{
int
length
=
Array
.
getLength
(
sourceArray
);
Object
targetArray
=
Array
.
newInstance
(
getTargetType
().
getElementType
(),
length
);
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
Object
value
=
Array
.
get
(
source
,
i
);
Array
.
set
(
targetArray
,
i
,
converter
.
execute
(
value
));
Object
value
=
Array
.
get
(
source
Array
,
i
);
Array
.
set
(
targetArray
,
i
,
getElementConverter
()
.
execute
(
value
));
}
return
targetArray
;
}
private
ConversionExecutor
getElementConverter
(
Class
sourceComponentType
,
Class
targetComponentType
)
{
if
(
elementConverter
!=
null
)
{
return
elementConverter
;
}
else
{
return
conversionService
.
getConversionExecutor
(
sourceComponentType
,
targetComponentType
);
}
}
}
org.springframework.core/src/main/java/org/springframework/core/convert/service/ArrayToCollection.java
浏览文件 @
ae4f80cf
...
...
@@ -18,12 +18,10 @@ package org.springframework.core.convert.service;
import
java.lang.reflect.Array
;
import
java.lang.reflect.Constructor
;
import
java.util.Collection
;
import
java.util.Iterator
;
import
org.springframework.core.GenericCollectionTypeResolver
;
import
org.springframework.core.convert.ConversionExecutor
;
import
org.springframework.core.convert.ConversionService
;
import
org.springframework.core.convert.
converter.SuperTwoWayConverte
r
;
import
org.springframework.core.convert.
TypeDescripto
r
;
/**
* Special converter that converts from a source array to a target collection. Supports the selection of an
...
...
@@ -38,38 +36,23 @@ import org.springframework.core.convert.converter.SuperTwoWayConverter;
*
* @author Keith Donald
*/
@SuppressWarnings
(
"unchecked"
)
class
ArrayToCollection
implements
SuperTwoWayConverter
{
class
ArrayToCollection
extends
AbstractCollectionConverter
{
private
ConversionService
conversionService
;
private
ConversionExecutor
elementConverter
;
/**
* Creates a new array to collection converter.
* @param conversionService the conversion service to use to lookup the converter to apply to array elements added
* to the target collection
*/
public
ArrayToCollection
(
ConversionService
conversionService
)
{
this
.
conversionService
=
conversionService
;
}
/**
* Creates a new array to collection converter.
* @param elementConverter A specific converter to use on array elements when adding them to the target collection
*/
public
ArrayToCollection
(
ConversionExecutor
elementConverter
)
{
this
.
elementConverter
=
elementConverter
;
public
ArrayToCollection
(
TypeDescriptor
sourceArrayType
,
TypeDescriptor
targetCollectionType
,
GenericConversionService
conversionService
)
{
super
(
sourceArrayType
,
targetCollectionType
,
conversionService
);
}
public
Object
convert
(
Object
source
,
Class
targetClass
)
throws
Exception
{
Class
implClass
=
CollectionConversionUtils
.
getImpl
(
targetClass
);
@Override
@SuppressWarnings
(
"unchecked"
)
protected
Object
doExecute
(
Object
sourceArray
)
throws
Exception
{
Class
implClass
=
CollectionConversionUtils
.
getImpl
(
getTargetType
().
getType
());
Constructor
constructor
=
implClass
.
getConstructor
((
Class
[])
null
);
Collection
collection
=
(
Collection
)
constructor
.
newInstance
((
Object
[])
null
);
ConversionExecutor
converter
=
getArrayElementConverter
(
source
,
targetClass
);
int
length
=
Array
.
getLength
(
source
);
int
length
=
Array
.
getLength
(
sourceArray
);
ConversionExecutor
converter
=
getElementConverter
(
);
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
Object
value
=
Array
.
get
(
source
,
i
);
Object
value
=
Array
.
get
(
source
Array
,
i
);
if
(
converter
!=
null
)
{
value
=
converter
.
execute
(
value
);
}
...
...
@@ -78,38 +61,4 @@ class ArrayToCollection implements SuperTwoWayConverter {
return
collection
;
}
public
Object
convertBack
(
Object
target
,
Class
sourceClass
)
throws
Exception
{
Collection
collection
=
(
Collection
)
target
;
Class
elementType
=
sourceClass
.
getComponentType
();
Object
array
=
Array
.
newInstance
(
elementType
,
collection
.
size
());
int
i
=
0
;
for
(
Iterator
it
=
collection
.
iterator
();
it
.
hasNext
();
i
++)
{
Object
value
=
it
.
next
();
if
(
value
!=
null
)
{
ConversionExecutor
converter
;
if
(
elementConverter
!=
null
)
{
converter
=
elementConverter
;
}
else
{
converter
=
conversionService
.
getConversionExecutor
(
value
.
getClass
(),
elementType
);
}
value
=
converter
.
execute
(
value
);
}
Array
.
set
(
array
,
i
,
value
);
}
return
array
;
}
private
ConversionExecutor
getArrayElementConverter
(
Object
source
,
Class
targetClass
)
{
if
(
elementConverter
!=
null
)
{
return
elementConverter
;
}
else
{
Class
elementType
=
GenericCollectionTypeResolver
.
getCollectionType
(
targetClass
);
if
(
elementType
!=
null
)
{
Class
componentType
=
source
.
getClass
().
getComponentType
();
return
conversionService
.
getConversionExecutor
(
componentType
,
elementType
);
}
return
null
;
}
}
}
\ No newline at end of file
org.springframework.core/src/main/java/org/springframework/core/convert/service/CollectionToArray.java
浏览文件 @
ae4f80cf
...
...
@@ -21,7 +21,7 @@ import java.util.Iterator;
import
org.springframework.core.convert.ConversionExecutor
;
import
org.springframework.core.convert.ConversionService
;
import
org.springframework.core.convert.
converter.SuperConverte
r
;
import
org.springframework.core.convert.
TypeDescripto
r
;
/**
* Special converter that converts from a source array to a target collection. Supports the selection of an
...
...
@@ -36,53 +36,29 @@ import org.springframework.core.convert.converter.SuperConverter;
*
* @author Keith Donald
*/
@SuppressWarnings
(
"unchecked"
)
class
CollectionToArray
implements
SuperConverter
{
class
CollectionToArray
extends
AbstractCollectionConverter
{
private
ConversionService
conversionService
;
private
ConversionExecutor
elementConverter
;
/**
* Creates a new array to collection converter.
* @param conversionService the conversion service to use to lookup the converter to apply to array elements added
* to the target collection
*/
public
CollectionToArray
(
ConversionService
conversionService
)
{
this
.
conversionService
=
conversionService
;
}
/**
* Creates a new array to collection converter.
* @param elementConverter A specific converter to use on array elements when adding them to the target collection
*/
public
CollectionToArray
(
ConversionExecutor
elementConverter
)
{
this
.
elementConverter
=
elementConverter
;
public
CollectionToArray
(
TypeDescriptor
sourceArrayType
,
TypeDescriptor
targetCollectionType
,
GenericConversionService
conversionService
)
{
super
(
sourceArrayType
,
targetCollectionType
,
conversionService
);
}
public
Object
convert
(
Object
source
,
Class
targetClass
)
throws
Exception
{
Collection
collection
=
(
Collection
)
source
;
Object
array
=
Array
.
newInstance
(
targetClass
.
getComponentType
(),
collection
.
size
());
@Override
protected
Object
doExecute
(
Object
source
)
throws
Exception
{
Collection
<?>
collection
=
(
Collection
<?>)
source
;
Class
<?>
targetComponentType
=
getTargetType
().
getElementType
();
Object
array
=
Array
.
newInstance
(
targetComponentType
,
collection
.
size
());
int
i
=
0
;
for
(
Iterator
it
=
collection
.
iterator
();
it
.
hasNext
();
i
++)
{
ConversionExecutor
converter
=
getElementConverter
();
for
(
Iterator
<?>
it
=
collection
.
iterator
();
it
.
hasNext
();
i
++)
{
Object
value
=
it
.
next
();
if
(
value
!=
null
)
{
ConversionExecutor
converter
;
if
(
elementConverter
!=
null
)
{
converter
=
elementConverter
;
}
else
{
converter
=
conversionService
.
getConversionExecutor
(
value
.
getClass
(),
targetClass
.
getComponentType
());
}
value
=
converter
.
execute
(
value
);
if
(
converter
==
null
)
{
converter
=
getConversionService
().
getElementConverter
(
value
.
getClass
(),
targetComponentType
);
}
value
=
converter
.
execute
(
value
);
Array
.
set
(
array
,
i
,
value
);
}
return
array
;
}
public
Object
convertBack
(
Object
target
)
throws
Exception
{
throw
new
UnsupportedOperationException
(
"Should never be called"
);
}
}
\ No newline at end of file
org.springframework.core/src/main/java/org/springframework/core/convert/service/CollectionToCollection.java
浏览文件 @
ae4f80cf
...
...
@@ -20,66 +20,45 @@ import java.util.Iterator;
import
org.springframework.core.GenericCollectionTypeResolver
;
import
org.springframework.core.convert.ConversionExecutor
;
import
org.springframework.core.convert.ConversionService
;
import
org.springframework.core.convert.converter.SuperConverter
;
import
org.springframework.core.convert.TypeDescriptor
;
/**
* A converter that can convert from one collection type to another.
*
* @author Keith Donald
*/
@SuppressWarnings
(
"unchecked"
)
class
CollectionToCollection
implements
SuperConverter
<
Collection
,
Collection
>
{
private
ConversionService
conversionService
;
private
ConversionExecutor
elementConverter
;
/**
* Creates a new collection-to-collection converter
* @param conversionService the conversion service to use to convert collection elements to add to the target
* collection
*/
public
CollectionToCollection
(
ConversionService
conversionService
)
{
this
.
conversionService
=
conversionService
;
}
/**
* Creates a new collection-to-collection converter
* @param elementConverter a specific converter to use to convert collection elements added to the target collection
*/
public
CollectionToCollection
(
ConversionExecutor
elementConverter
)
{
this
.
elementConverter
=
elementConverter
;
class
CollectionToCollection
extends
AbstractCollectionConverter
{
public
CollectionToCollection
(
TypeDescriptor
sourceCollectionType
,
TypeDescriptor
targetCollectionType
,
GenericConversionService
conversionService
)
{
super
(
sourceCollectionType
,
targetCollectionType
,
conversionService
);
}
public
Collection
convert
(
Collection
source
,
Class
targetClass
)
throws
Exception
{
Class
implClass
=
CollectionConversionUtils
.
getImpl
(
targetClass
);
@Override
@SuppressWarnings
(
"unchecked"
)
protected
Object
doExecute
(
Object
source
)
throws
Exception
{
Collection
sourceCollection
=
(
Collection
)
source
;
Class
targetCollectionType
=
getTargetType
().
getType
();
Class
implClass
=
CollectionConversionUtils
.
getImpl
(
targetCollectionType
);
Collection
targetCollection
=
(
Collection
)
implClass
.
getConstructor
((
Class
[])
null
)
.
newInstance
((
Object
[])
null
);
ConversionExecutor
elementConverter
=
getElementConverter
(
source
,
targetClass
);
Collection
sourceCollection
=
(
Collection
)
source
;
ConversionExecutor
elementConverter
=
getElementConverter
();
Class
elementType
;
if
(
elementConverter
==
null
)
{
elementType
=
GenericCollectionTypeResolver
.
getCollectionType
(
targetCollectionType
);
}
else
{
elementType
=
null
;
}
Iterator
it
=
sourceCollection
.
iterator
();
while
(
it
.
hasNext
())
{
Object
value
=
it
.
next
();
if
(
elementConverter
!=
null
)
{
value
=
elementConverter
.
execute
(
value
);
if
(
elementConverter
==
null
&&
elementType
!=
null
)
{
elementConverter
=
getConversionService
().
getElementConverter
(
value
.
getClass
(),
elementType
);
}
value
=
elementConverter
.
execute
(
value
);
targetCollection
.
add
(
value
);
}
return
targetCollection
;
}
private
ConversionExecutor
getElementConverter
(
Object
source
,
Class
targetClass
)
{
if
(
elementConverter
!=
null
)
{
return
elementConverter
;
}
else
{
Class
elementType
=
GenericCollectionTypeResolver
.
getCollectionType
(
targetClass
);
if
(
elementType
!=
null
)
{
Class
componentType
=
source
.
getClass
().
getComponentType
();
return
conversionService
.
getConversionExecutor
(
componentType
,
elementType
);
}
return
null
;
}
}
}
\ No newline at end of file
org.springframework.core/src/main/java/org/springframework/core/convert/service/DefaultConversionService.java
浏览文件 @
ae4f80cf
...
...
@@ -67,9 +67,6 @@ public class DefaultConversionService extends GenericConversionService {
addConverter
(
new
StringToLocale
());
addConverter
(
new
StringToEnum
());
addConverter
(
new
NumberToNumber
());
// TODO probably don't allow these to be customized, or at least make public
addConverter
(
new
ObjectToCollection
(
this
));
addConverter
(
new
CollectionToCollection
(
this
));
}
protected
void
addDefaultAliases
()
{
...
...
org.springframework.core/src/main/java/org/springframework/core/convert/service/GenericConversionService.java
浏览文件 @
ae4f80cf
...
...
@@ -32,6 +32,8 @@ import org.springframework.core.convert.ConversionException;
import
org.springframework.core.convert.ConversionExecutor
;
import
org.springframework.core.convert.ConversionExecutorNotFoundException
;
import
org.springframework.core.convert.ConversionService
;
import
org.springframework.core.convert.TypeDescriptor
;
import
org.springframework.core.convert.TypedValue
;
import
org.springframework.core.convert.converter.Converter
;
import
org.springframework.core.convert.converter.SuperConverter
;
import
org.springframework.core.convert.converter.SuperTwoWayConverter
;
...
...
@@ -149,9 +151,9 @@ public class GenericConversionService implements ConversionService {
}
/**
* Add a convenient alias for the target type. {@link #get
ClassForAlias
(String)} can then be used to lookup the type
* Add a convenient alias for the target type. {@link #get
Type
(String)} can then be used to lookup the type
* given the alias.
* @see #get
ClassForAlias
(String)
* @see #get
Type
(String)
*/
public
void
addAlias
(
String
alias
,
Class
targetType
)
{
aliasMap
.
put
(
alias
,
targetType
);
...
...
@@ -159,225 +161,85 @@ public class GenericConversionService implements ConversionService {
// implementing ConversionService
public
Object
executeConversion
(
Object
source
,
Class
targetClass
)
throws
ConversionExecutorNotFoundException
,
public
boolean
canConvert
(
TypedValue
source
,
TypeDescriptor
targetType
)
{
return
false
;
}
public
Object
executeConversion
(
TypedValue
source
,
TypeDescriptor
targetType
)
throws
ConversionExecutorNotFoundException
,
ConversionException
{
return
getConversionExecutor
(
source
.
get
Class
(),
targetClass
).
execute
(
source
);
return
getConversionExecutor
(
source
.
get
TypeDescriptor
(),
targetType
).
execute
(
source
.
getValue
()
);
}
public
Object
executeConversion
(
String
converterId
,
Object
source
,
Class
targetClass
)
public
Object
executeConversion
(
String
converterId
,
TypedValue
source
,
TypeDescriptor
targetType
)
throws
ConversionExecutorNotFoundException
,
ConversionException
{
return
getConversionExecutor
(
converterId
,
source
.
get
Class
(),
targetClass
).
execute
(
source
);
return
getConversionExecutor
(
converterId
,
source
.
get
TypeDescriptor
(),
targetType
).
execute
(
source
.
getValue
()
);
}
public
ConversionExecutor
getConversionExecutor
(
Class
sourceClass
,
Class
targetClass
)
public
ConversionExecutor
getConversionExecutor
(
TypeDescriptor
sourceType
,
TypeDescriptor
targetType
)
throws
ConversionExecutorNotFoundException
{
Assert
.
notNull
(
sourceClass
,
"The source class to convert from is required"
);
Assert
.
notNull
(
targetClass
,
"The target class to convert to is required"
);
if
(
targetClass
.
isAssignableFrom
(
sourceClass
))
{
return
new
StaticConversionExecutor
(
sourceClass
,
targetClass
,
new
NoOpConverter
());
}
sourceClass
=
convertToWrapperClassIfNecessary
(
sourceClass
);
targetClass
=
convertToWrapperClassIfNecessary
(
targetClass
);
Assert
.
notNull
(
sourceType
,
"The sourceType to convert from is required"
);
Assert
.
notNull
(
targetType
,
"The targetType to convert to is required"
);
// special handling for arrays since they are not indexable classes
if
(
source
Class
.
isArray
())
{
if
(
target
Class
.
isArray
())
{
return
new
StaticSuperConversionExecutor
(
sourceClass
,
targetClass
,
new
ArrayToArray
(
this
)
);
}
else
if
(
Collection
.
class
.
isAssignableFrom
(
targetClass
))
{
if
(
!
targetClass
.
isInterface
()
&&
Modifier
.
isAbstract
(
targetClass
.
getModifiers
()
))
{
throw
new
IllegalArgumentException
(
"Conversion target class ["
+
target
Class
.
getName
()
if
(
source
Type
.
isArray
())
{
if
(
target
Type
.
isArray
())
{
return
new
ArrayToArray
(
sourceType
,
targetType
,
this
);
}
else
if
(
targetType
.
isCollection
(
))
{
if
(
targetType
.
isAbstractClass
(
))
{
throw
new
IllegalArgumentException
(
"Conversion target class ["
+
target
Type
.
getName
()
+
"] is invalid; cannot convert to abstract collection types--"
+
"request an interface or concrete implementation instead"
);
}
return
new
StaticSuperConversionExecutor
(
sourceClass
,
targetClass
,
new
ArrayToCollection
(
this
));
return
new
ArrayToCollection
(
sourceType
,
targetType
,
this
);
}
}
if
(
targetType
.
isArray
())
{
if
(
sourceType
.
isCollection
())
{
return
new
CollectionToArray
(
sourceType
,
targetType
,
this
);
}
else
{
throw
new
UnsupportedOperationException
(
"Object to Array not yet supported"
);
}
}
if
(
targetClass
.
isArray
())
{
if
(
Collection
.
class
.
isAssignableFrom
(
sourceClass
))
{
SuperConverter
collectionToArray
=
new
ReverseSuperConverter
(
new
ArrayToCollection
(
this
));
return
new
StaticSuperConversionExecutor
(
sourceClass
,
targetClass
,
collectionToArray
);
if
(
sourceType
.
isCollection
())
{
if
(
targetType
.
isCollection
())
{
return
new
CollectionToCollection
(
sourceType
,
targetType
,
this
);
}
else
{
return
new
StaticSuperConversionExecutor
(
sourceClass
,
targetClass
,
new
ObjectToArray
(
this
));
throw
new
UnsupportedOperationException
(
"Object to collection not yet supported"
);
}
}
Class
<?>
sourceClass
=
sourceType
.
getWrapperTypeIfPrimitive
();
Class
<?>
targetClass
=
targetType
.
getWrapperTypeIfPrimitive
();
Converter
converter
=
findRegisteredConverter
(
sourceClass
,
targetClass
);
if
(
converter
!=
null
)
{
// we found a converter
return
new
StaticConversionExecutor
(
source
Class
,
targetClass
,
converter
);
return
new
StaticConversionExecutor
(
source
Type
,
targetType
,
converter
);
}
else
{
SuperConverter
superConverter
=
findRegisteredSuperConverter
(
sourceClass
,
targetClass
);
if
(
superConverter
!=
null
)
{
return
new
StaticSuperConversionExecutor
(
source
Class
,
targetClass
,
superConverter
);
return
new
StaticSuperConversionExecutor
(
source
Type
,
targetType
,
superConverter
);
}
if
(
parent
!=
null
)
{
// try the parent
return
parent
.
getConversionExecutor
(
source
Class
,
targetClass
);
return
parent
.
getConversionExecutor
(
source
Type
,
targetType
);
}
else
{
throw
new
ConversionExecutorNotFoundException
(
source
Class
,
targetClass
,
"No ConversionExecutor found for converting from source
Class ["
+
sourceClass
.
getName
()
+
"] to target
class ["
+
targetClass
.
getName
()
+
"]"
);
throw
new
ConversionExecutorNotFoundException
(
source
Type
,
targetType
,
"No ConversionExecutor found for converting from source
Type ["
+
sourceType
.
getName
()
+
"] to target
Type ["
+
targetType
.
getName
()
+
"]"
);
}
}
}
public
ConversionExecutor
getConversionExecutor
(
String
id
,
Class
sourceClass
,
Class
targetClass
)
throws
ConversionExecutorNotFoundException
{
Assert
.
hasText
(
id
,
"The id of the custom converter is required"
);
Assert
.
notNull
(
sourceClass
,
"The source class to convert from is required"
);
Assert
.
notNull
(
targetClass
,
"The target class to convert to is required"
);
Converter
converter
=
(
Converter
)
customConverters
.
get
(
id
);
if
(
converter
==
null
)
{
if
(
parent
!=
null
)
{
return
parent
.
getConversionExecutor
(
id
,
sourceClass
,
targetClass
);
}
else
{
throw
new
ConversionExecutorNotFoundException
(
sourceClass
,
targetClass
,
"No custom Converter found with id '"
+
id
+
"' for converting from sourceClass ["
+
sourceClass
.
getName
()
+
"] to targetClass ["
+
targetClass
.
getName
()
+
"]"
);
}
}
sourceClass
=
convertToWrapperClassIfNecessary
(
sourceClass
);
targetClass
=
convertToWrapperClassIfNecessary
(
targetClass
);
// TODO Not optimal getting this each time
List
typeInfo
=
getRequiredTypeInfo
(
converter
);
Class
converterSourceClass
=
(
Class
)
typeInfo
.
get
(
0
);
Class
converterTargetClass
=
(
Class
)
typeInfo
.
get
(
1
);
if
(
sourceClass
.
isArray
())
{
Class
sourceComponentType
=
sourceClass
.
getComponentType
();
if
(
targetClass
.
isArray
())
{
Class
targetComponentType
=
targetClass
.
getComponentType
();
if
(
converterSourceClass
.
isAssignableFrom
(
sourceComponentType
))
{
if
(!
converterTargetClass
.
equals
(
targetComponentType
))
{
throw
new
ConversionExecutorNotFoundException
(
sourceClass
,
targetClass
,
"Custom Converter with id '"
+
id
+
"' cannot convert from an array storing elements of type ["
+
sourceComponentType
.
getName
()
+
"] to an array of storing elements of type ["
+
targetComponentType
.
getName
()
+
"]"
);
}
ConversionExecutor
elementConverter
=
new
StaticConversionExecutor
(
sourceComponentType
,
targetComponentType
,
converter
);
return
new
StaticSuperConversionExecutor
(
sourceClass
,
targetClass
,
new
ArrayToArray
(
elementConverter
));
}
else
if
(
converterTargetClass
.
isAssignableFrom
(
sourceComponentType
))
{
if
(!
converterSourceClass
.
equals
(
targetComponentType
))
{
throw
new
ConversionExecutorNotFoundException
(
sourceClass
,
targetClass
,
"Custom Converter with id '"
+
id
+
"' cannot convert from an array storing elements of type ["
+
sourceComponentType
.
getName
()
+
"] to an array of storing elements of type ["
+
targetComponentType
.
getName
()
+
"]"
);
}
ConversionExecutor
elementConverter
=
new
StaticConversionExecutor
(
sourceComponentType
,
targetComponentType
,
new
ReverseConverter
(
converter
));
return
new
StaticSuperConversionExecutor
(
sourceClass
,
targetClass
,
new
ArrayToArray
(
elementConverter
));
}
else
{
throw
new
ConversionExecutorNotFoundException
(
sourceClass
,
targetClass
,
"Custom Converter with id '"
+
id
+
"' cannot convert from an array storing elements of type ["
+
sourceComponentType
.
getName
()
+
"] to an array storing elements of type ["
+
targetComponentType
.
getName
()
+
"]"
);
}
}
else
if
(
Collection
.
class
.
isAssignableFrom
(
targetClass
))
{
if
(!
targetClass
.
isInterface
()
&&
Modifier
.
isAbstract
(
targetClass
.
getModifiers
()))
{
throw
new
IllegalArgumentException
(
"Conversion target class ["
+
targetClass
.
getName
()
+
"] is invalid; cannot convert to abstract collection types--"
+
"request an interface or concrete implementation instead"
);
}
if
(
converterSourceClass
.
isAssignableFrom
(
sourceComponentType
))
{
// type erasure has prevented us from getting the concrete type, this is best we can do for now
ConversionExecutor
elementConverter
=
new
StaticConversionExecutor
(
sourceComponentType
,
converterTargetClass
,
converter
);
return
new
StaticSuperConversionExecutor
(
sourceClass
,
targetClass
,
new
ArrayToCollection
(
elementConverter
));
}
else
if
(
converterTargetClass
.
isAssignableFrom
(
sourceComponentType
))
{
ConversionExecutor
elementConverter
=
new
StaticConversionExecutor
(
sourceComponentType
,
converterSourceClass
,
new
ReverseConverter
(
converter
));
return
new
StaticSuperConversionExecutor
(
sourceClass
,
targetClass
,
new
ArrayToCollection
(
elementConverter
));
}
else
{
throw
new
ConversionExecutorNotFoundException
(
sourceClass
,
targetClass
,
"Custom Converter with id '"
+
id
+
"' cannot convert from array an storing elements type ["
+
sourceComponentType
.
getName
()
+
"] to a collection of type ["
+
targetClass
.
getName
()
+
"]"
);
}
}
}
if
(
targetClass
.
isArray
())
{
Class
targetComponentType
=
targetClass
.
getComponentType
();
if
(
Collection
.
class
.
isAssignableFrom
(
sourceClass
))
{
// type erasure limits us here as well
if
(
converterTargetClass
.
equals
(
targetComponentType
))
{
ConversionExecutor
elementConverter
=
new
StaticConversionExecutor
(
converterSourceClass
,
targetComponentType
,
converter
);
SuperConverter
collectionToArray
=
new
ReverseSuperConverter
(
new
ArrayToCollection
(
elementConverter
));
return
new
StaticSuperConversionExecutor
(
sourceClass
,
targetClass
,
collectionToArray
);
}
else
if
(
converterSourceClass
.
equals
(
targetComponentType
))
{
ConversionExecutor
elementConverter
=
new
StaticConversionExecutor
(
converterTargetClass
,
targetComponentType
,
new
ReverseConverter
(
converter
));
SuperConverter
collectionToArray
=
new
ReverseSuperConverter
(
new
ArrayToCollection
(
elementConverter
));
return
new
StaticSuperConversionExecutor
(
sourceClass
,
targetClass
,
collectionToArray
);
}
else
{
throw
new
ConversionExecutorNotFoundException
(
sourceClass
,
targetClass
,
"Custom Converter with id '"
+
id
+
"' cannot convert from collection of type ["
+
sourceClass
.
getName
()
+
"] to an array storing elements of type ["
+
targetComponentType
.
getName
()
+
"]"
);
}
}
else
{
if
(
converterSourceClass
.
isAssignableFrom
(
sourceClass
))
{
if
(!
converterTargetClass
.
equals
(
targetComponentType
))
{
throw
new
ConversionExecutorNotFoundException
(
sourceClass
,
targetClass
,
"Custom Converter with id '"
+
id
+
"' cannot convert from sourceClass ["
+
sourceClass
.
getName
()
+
"] to array holding elements of type ["
+
targetComponentType
.
getName
()
+
"]"
);
}
ConversionExecutor
elementConverter
=
new
StaticConversionExecutor
(
sourceClass
,
targetComponentType
,
converter
);
return
new
StaticSuperConversionExecutor
(
sourceClass
,
targetClass
,
new
ObjectToArray
(
elementConverter
));
}
else
if
(
converterTargetClass
.
isAssignableFrom
(
sourceClass
))
{
if
(!
converterSourceClass
.
equals
(
targetComponentType
))
{
throw
new
ConversionExecutorNotFoundException
(
sourceClass
,
targetClass
,
"Custom Converter with id '"
+
id
+
"' cannot convert from sourceClass ["
+
sourceClass
.
getName
()
+
"] to array holding elements of type ["
+
targetComponentType
.
getName
()
+
"]"
);
}
ConversionExecutor
elementConverter
=
new
StaticConversionExecutor
(
sourceClass
,
targetComponentType
,
new
ReverseConverter
(
converter
));
return
new
StaticSuperConversionExecutor
(
sourceClass
,
targetClass
,
new
ObjectToArray
(
elementConverter
));
}
}
}
// TODO look to factor some of this duplicated code here and above out a bit
if
(
converterSourceClass
.
isAssignableFrom
(
sourceClass
))
{
if
(!
converterTargetClass
.
equals
(
targetClass
))
{
throw
new
ConversionExecutorNotFoundException
(
sourceClass
,
targetClass
,
"Custom Converter with id '"
+
id
+
"' cannot convert from sourceClass ["
+
sourceClass
.
getName
()
+
"] to targetClass ["
+
targetClass
.
getName
()
+
"]"
);
}
return
new
StaticConversionExecutor
(
sourceClass
,
targetClass
,
converter
);
}
else
if
(
converterTargetClass
.
isAssignableFrom
(
sourceClass
))
{
if
(!
converterSourceClass
.
equals
(
targetClass
))
{
throw
new
ConversionExecutorNotFoundException
(
sourceClass
,
targetClass
,
"Custom Converter with id '"
+
id
+
"' cannot convert from sourceClass ["
+
sourceClass
.
getName
()
+
"] to targetClass ["
+
targetClass
.
getName
()
+
"]"
);
}
return
new
StaticConversionExecutor
(
sourceClass
,
targetClass
,
new
ReverseConverter
(
converter
));
}
else
{
throw
new
ConversionExecutorNotFoundException
(
sourceClass
,
targetClass
,
"Custom Converter with id '"
+
id
+
"' cannot convert from sourceClass ["
+
sourceClass
.
getName
()
+
"] to targetClass ["
+
targetClass
.
getName
()
+
"]"
);
}
public
ConversionExecutor
getConversionExecutor
(
String
converterId
,
TypeDescriptor
sourceType
,
TypeDescriptor
targetType
)
throws
ConversionExecutorNotFoundException
{
throw
new
UnsupportedOperationException
(
"Not yet implemented"
);
}
public
Class
get
ClassForAlias
(
String
name
)
throws
IllegalArgumentException
{
public
Class
get
Type
(
String
name
)
throws
IllegalArgumentException
{
Class
clazz
=
(
Class
)
aliasMap
.
get
(
name
);
if
(
clazz
!=
null
)
{
return
clazz
;
}
else
{
if
(
parent
!=
null
)
{
return
parent
.
get
ClassForAlias
(
name
);
return
parent
.
get
Type
(
name
);
}
else
{
return
null
;
}
...
...
@@ -444,32 +306,6 @@ public class GenericConversionService implements ConversionService {
return
sourceMap
;
}
private
Class
convertToWrapperClassIfNecessary
(
Class
targetType
)
{
if
(
targetType
.
isPrimitive
())
{
if
(
targetType
.
equals
(
int
.
class
))
{
return
Integer
.
class
;
}
else
if
(
targetType
.
equals
(
short
.
class
))
{
return
Short
.
class
;
}
else
if
(
targetType
.
equals
(
long
.
class
))
{
return
Long
.
class
;
}
else
if
(
targetType
.
equals
(
float
.
class
))
{
return
Float
.
class
;
}
else
if
(
targetType
.
equals
(
double
.
class
))
{
return
Double
.
class
;
}
else
if
(
targetType
.
equals
(
byte
.
class
))
{
return
Byte
.
class
;
}
else
if
(
targetType
.
equals
(
boolean
.
class
))
{
return
Boolean
.
class
;
}
else
if
(
targetType
.
equals
(
char
.
class
))
{
return
Character
.
class
;
}
else
{
throw
new
IllegalStateException
(
"Should never happen - primitive type is not a primitive?"
);
}
}
else
{
return
targetType
;
}
}
private
Converter
findRegisteredConverter
(
Class
sourceClass
,
Class
targetClass
)
{
if
(
sourceClass
.
isInterface
())
{
LinkedList
classQueue
=
new
LinkedList
();
...
...
@@ -604,4 +440,8 @@ public class GenericConversionService implements ConversionService {
}
}
public
ConversionExecutor
getElementConverter
(
Class
<?>
sourceElementType
,
Class
<?>
targetElementType
)
{
return
getConversionExecutor
(
new
TypeDescriptor
(
sourceElementType
),
new
TypeDescriptor
(
targetElementType
));
}
}
\ No newline at end of file
org.springframework.core/src/main/java/org/springframework/core/convert/service/ObjectToArray.java
已删除
100644 → 0
浏览文件 @
c057638b
/*
* Copyright 2004-2009 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.springframework.core.convert.service
;
import
java.lang.reflect.Array
;
import
org.springframework.core.convert.ConversionExecutor
;
import
org.springframework.core.convert.ConversionService
;
import
org.springframework.core.convert.converter.SuperConverter
;
/**
* Special converter that converts an object to an single-element array. Mainly used internally by
* {@link ConversionService} implementations.
*
* @author Keith Donald
*/
@SuppressWarnings
(
"unchecked"
)
class
ObjectToArray
implements
SuperConverter
{
private
ConversionService
conversionService
;
private
ConversionExecutor
elementConverter
;
/**
* Creates a new object to array converter.
* @param conversionService the conversion service to resolve the converter to use to convert the object added to
* the target array.
*/
public
ObjectToArray
(
ConversionService
conversionService
)
{
this
.
conversionService
=
conversionService
;
}
/**
* Creates a new object to array converter.
* @param elementConverter a specific converter to use to convert the object added to the target array.
*/
public
ObjectToArray
(
ConversionExecutor
elementConverter
)
{
this
.
elementConverter
=
elementConverter
;
}
public
Object
convert
(
Object
source
,
Class
targetClass
)
throws
Exception
{
Class
componentType
=
targetClass
.
getComponentType
();
Object
array
=
Array
.
newInstance
(
componentType
,
1
);
ConversionExecutor
converter
;
if
(
elementConverter
!=
null
)
{
converter
=
elementConverter
;
}
else
{
converter
=
conversionService
.
getConversionExecutor
(
source
.
getClass
(),
componentType
);
}
Array
.
set
(
array
,
0
,
converter
.
execute
(
source
));
return
array
;
}
}
\ No newline at end of file
org.springframework.core/src/main/java/org/springframework/core/convert/service/ObjectToCollection.java
已删除
100644 → 0
浏览文件 @
c057638b
/*
* Copyright 2004-2009 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.springframework.core.convert.service
;
import
java.lang.reflect.Constructor
;
import
java.util.Collection
;
import
org.springframework.core.GenericCollectionTypeResolver
;
import
org.springframework.core.convert.ConversionExecutor
;
import
org.springframework.core.convert.ConversionService
;
import
org.springframework.core.convert.converter.SuperConverter
;
/**
* Special two-way converter that converts an object to an single-element collection. Supports type conversion of the
* individual element with parameterized collection implementations.
*
* @author Keith Donald
*/
@SuppressWarnings
(
"unchecked"
)
class
ObjectToCollection
implements
SuperConverter
<
Object
,
Collection
>
{
private
ConversionService
conversionService
;
private
ConversionExecutor
elementConverter
;
/**
* Creates a new object to collection converter
* @param conversionService the conversion service to lookup the converter to use to convert an object when adding
* it to a target collection
*/
public
ObjectToCollection
(
ConversionService
conversionService
)
{
this
.
conversionService
=
conversionService
;
}
/**
* Creates a new object to collection converter
* @param elementConverter a specific converter to execute on an object when adding it to a target collection
*/
public
ObjectToCollection
(
ConversionExecutor
elementConverter
)
{
this
.
elementConverter
=
elementConverter
;
}
public
Collection
convert
(
Object
source
,
Class
targetClass
)
throws
Exception
{
Class
implClass
=
CollectionConversionUtils
.
getImpl
(
targetClass
);
Constructor
constructor
=
implClass
.
getConstructor
((
Class
[])
null
);
Collection
collection
=
(
Collection
)
constructor
.
newInstance
((
Object
[])
null
);
ConversionExecutor
converter
=
getElementConverter
(
source
,
targetClass
);
Object
value
;
if
(
converter
!=
null
)
{
value
=
converter
.
execute
(
source
);
}
else
{
value
=
source
;
}
collection
.
add
(
value
);
return
collection
;
}
private
ConversionExecutor
getElementConverter
(
Object
source
,
Class
targetClass
)
{
if
(
elementConverter
!=
null
)
{
return
elementConverter
;
}
else
{
Class
elementType
=
GenericCollectionTypeResolver
.
getCollectionType
(
targetClass
);
if
(
elementType
!=
null
)
{
Class
componentType
=
source
.
getClass
().
getComponentType
();
return
conversionService
.
getConversionExecutor
(
componentType
,
elementType
);
}
return
null
;
}
}
}
\ No newline at end of file
org.springframework.core/src/main/java/org/springframework/core/convert/service/StaticConversionExecutor.java
浏览文件 @
ae4f80cf
...
...
@@ -17,47 +17,44 @@ package org.springframework.core.convert.service;
import
org.springframework.core.convert.ConversionExecutionException
;
import
org.springframework.core.convert.ConversionExecutor
;
import
org.springframework.core.convert.TypeDescriptor
;
import
org.springframework.core.convert.converter.Converter
;
import
org.springframework.core.style.ToStringCreator
;
import
org.springframework.util.Assert
;
class
StaticConversionExecutor
<
S
,
T
>
implements
ConversionExecutor
<
S
,
T
>
{
class
StaticConversionExecutor
implements
ConversionExecutor
{
private
final
Class
<
S
>
sourceClass
;
private
final
TypeDescriptor
sourceType
;
private
final
Class
<
T
>
targetClass
;
private
final
TypeDescriptor
targetType
;
private
final
Converter
<
S
,
T
>
converter
;
private
final
Converter
converter
;
public
StaticConversionExecutor
(
Class
<
S
>
sourceClass
,
Class
<
T
>
targetClass
,
Converter
<
S
,
T
>
converter
)
{
Assert
.
notNull
(
sourceClass
,
"The source class is required"
);
Assert
.
notNull
(
targetClass
,
"The target class is required"
);
Assert
.
notNull
(
converter
,
"The converter is required"
);
this
.
sourceClass
=
sourceClass
;
this
.
targetClass
=
targetClass
;
public
StaticConversionExecutor
(
TypeDescriptor
sourceClass
,
TypeDescriptor
targetClass
,
Converter
converter
)
{
this
.
sourceType
=
sourceClass
;
this
.
targetType
=
targetClass
;
this
.
converter
=
converter
;
}
public
Class
<
S
>
getSourceClass
()
{
return
source
Class
;
public
TypeDescriptor
getSourceType
()
{
return
source
Type
;
}
public
Class
<
T
>
getTargetClass
()
{
return
target
Class
;
public
TypeDescriptor
getTargetType
()
{
return
target
Type
;
}
public
T
execute
(
S
source
)
throws
ConversionExecutionException
{
public
Object
execute
(
Object
source
)
throws
ConversionExecutionException
{
if
(
source
==
null
)
{
return
null
;
}
if
(
!
sourceClass
.
isInstance
(
source
))
{
throw
new
ConversionExecutionException
(
source
,
getSource
Class
(),
getTargetClass
(),
"Source object "
+
source
+
" to convert is expected to be an instance of ["
+
getSource
Class
().
getName
()
+
"]"
);
if
(
sourceType
!=
null
&&
!
sourceType
.
isInstance
(
source
))
{
throw
new
ConversionExecutionException
(
source
,
getSource
Type
(),
getTargetType
(),
"Source object "
+
source
+
" to convert is expected to be an instance of ["
+
getSource
Type
().
getName
()
+
"]"
);
}
try
{
return
converter
.
convert
(
source
);
}
catch
(
Exception
e
)
{
throw
new
ConversionExecutionException
(
source
,
getSource
Class
(),
getTargetClass
(),
e
);
throw
new
ConversionExecutionException
(
source
,
getSource
Type
(),
getTargetType
(),
e
);
}
}
...
...
@@ -65,16 +62,16 @@ class StaticConversionExecutor<S, T> implements ConversionExecutor<S, T> {
if
(!(
o
instanceof
StaticConversionExecutor
))
{
return
false
;
}
StaticConversionExecutor
<?,
?>
other
=
(
StaticConversionExecutor
<?,
?>
)
o
;
return
source
Class
.
equals
(
other
.
sourceClass
)
&&
targetClass
.
equals
(
other
.
targetClass
);
StaticConversionExecutor
other
=
(
StaticConversionExecutor
)
o
;
return
source
Type
.
equals
(
other
.
sourceType
)
&&
targetType
.
equals
(
other
.
targetType
);
}
public
int
hashCode
()
{
return
source
Class
.
hashCode
()
+
targetClass
.
hashCode
();
return
source
Type
.
hashCode
()
+
targetType
.
hashCode
();
}
public
String
toString
()
{
return
new
ToStringCreator
(
this
).
append
(
"sourceClass"
,
source
Class
).
append
(
"targetClass"
,
targetClass
)
return
new
ToStringCreator
(
this
).
append
(
"sourceClass"
,
source
Type
).
append
(
"targetClass"
,
targetType
)
.
toString
();
}
}
\ No newline at end of file
org.springframework.core/src/main/java/org/springframework/core/convert/service/StaticSuperConversionExecutor.java
浏览文件 @
ae4f80cf
...
...
@@ -17,47 +17,37 @@ package org.springframework.core.convert.service;
import
org.springframework.core.convert.ConversionExecutionException
;
import
org.springframework.core.convert.ConversionExecutor
;
import
org.springframework.core.convert.TypeDescriptor
;
import
org.springframework.core.convert.converter.SuperConverter
;
import
org.springframework.core.style.ToStringCreator
;
import
org.springframework.util.Assert
;
class
StaticSuperConversionExecutor
<
S
,
T
>
implements
ConversionExecutor
<
S
,
T
>
{
class
StaticSuperConversionExecutor
implements
ConversionExecutor
{
private
final
Class
<
S
>
sourceClass
;
private
final
TypeDescriptor
sourceType
;
private
final
Class
<
T
>
targetClass
;
private
final
TypeDescriptor
targetType
;
private
final
SuperConverter
<
S
,
T
>
converter
;
private
final
SuperConverter
converter
;
public
StaticSuperConversionExecutor
(
Class
<
S
>
sourceClass
,
Class
<
T
>
targetClass
,
SuperConverter
<
S
,
T
>
converter
)
{
Assert
.
notNull
(
sourceClass
,
"The source class is required"
);
Assert
.
notNull
(
targetClass
,
"The target class is required"
);
Assert
.
notNull
(
converter
,
"The super converter is required"
);
this
.
sourceClass
=
sourceClass
;
this
.
targetClass
=
targetClass
;
public
StaticSuperConversionExecutor
(
TypeDescriptor
sourceType
,
TypeDescriptor
targetType
,
SuperConverter
converter
)
{
this
.
sourceType
=
sourceType
;
this
.
targetType
=
targetType
;
this
.
converter
=
converter
;
}
public
Class
<
S
>
getSourceClass
()
{
return
sourceClass
;
}
public
Class
<
T
>
getTargetClass
()
{
return
targetClass
;
}
public
T
execute
(
S
source
)
throws
ConversionExecutionException
{
public
Object
execute
(
Object
source
)
throws
ConversionExecutionException
{
if
(
source
==
null
)
{
return
null
;
}
if
(!
source
Class
.
isInstance
(
source
))
{
throw
new
ConversionExecutionException
(
source
,
getSourceClass
(),
getTargetClass
()
,
"Source object "
+
source
+
" to convert is expected to be an instance of ["
+
getSourceClass
()
.
getName
()
+
"]"
);
if
(!
source
Type
.
isInstance
(
source
))
{
throw
new
ConversionExecutionException
(
source
,
sourceType
,
targetType
,
"Source object "
+
source
+
" to convert is expected to be an instance of ["
+
sourceType
.
getName
()
+
"]"
);
}
try
{
return
converter
.
convert
(
source
,
target
Class
);
return
converter
.
convert
(
source
,
target
Type
.
getType
()
);
}
catch
(
Exception
e
)
{
throw
new
ConversionExecutionException
(
source
,
getSourceClass
(),
getTargetClass
()
,
e
);
throw
new
ConversionExecutionException
(
source
,
sourceType
,
targetType
,
e
);
}
}
...
...
@@ -65,16 +55,16 @@ class StaticSuperConversionExecutor<S, T> implements ConversionExecutor<S, T> {
if
(!(
o
instanceof
StaticSuperConversionExecutor
))
{
return
false
;
}
StaticSuperConversionExecutor
<?,
?>
other
=
(
StaticSuperConversionExecutor
<?,
?>
)
o
;
return
source
Class
.
equals
(
other
.
sourceClass
)
&&
targetClass
.
equals
(
other
.
targetClass
);
StaticSuperConversionExecutor
other
=
(
StaticSuperConversionExecutor
)
o
;
return
source
Type
.
equals
(
other
.
sourceType
)
&&
targetType
.
equals
(
other
.
targetType
);
}
public
int
hashCode
()
{
return
source
Class
.
hashCode
()
+
targetClass
.
hashCode
();
return
source
Type
.
hashCode
()
+
targetType
.
hashCode
();
}
public
String
toString
()
{
return
new
ToStringCreator
(
this
).
append
(
"sourceClass"
,
source
Class
).
append
(
"targetClass"
,
targetClass
)
return
new
ToStringCreator
(
this
).
append
(
"sourceClass"
,
source
Type
).
append
(
"targetClass"
,
targetType
)
.
toString
();
}
}
\ No newline at end of file
org.springframework.core/src/test/java/org/springframework/core/convert/service/GenericConversionServiceTests.java
浏览文件 @
ae4f80cf
...
...
@@ -28,6 +28,8 @@ import org.springframework.core.convert.ConversionException;
import
org.springframework.core.convert.ConversionExecutionException
;
import
org.springframework.core.convert.ConversionExecutor
;
import
org.springframework.core.convert.ConversionExecutorNotFoundException
;
import
org.springframework.core.convert.TypeDescriptor
;
import
org.springframework.core.convert.TypedValue
;
import
org.springframework.core.convert.converter.Converter
;
import
org.springframework.core.convert.converter.NumberToNumber
;
import
org.springframework.core.convert.converter.StringToEnum
;
...
...
@@ -37,47 +39,55 @@ public class GenericConversionServiceTests extends TestCase {
private
GenericConversionService
service
=
new
GenericConversionService
();
private
TypedValue
value
(
Object
obj
)
{
return
new
TypedValue
(
obj
,
new
TypeDescriptor
(
obj
.
getClass
()));
}
private
TypeDescriptor
type
(
Class
clazz
)
{
return
new
TypeDescriptor
(
clazz
);
}
public
void
testExecuteConversion
()
{
service
.
addConverter
(
new
StringToInteger
());
assertEquals
(
new
Integer
(
3
),
service
.
executeConversion
(
"3"
,
Integer
.
class
));
assertEquals
(
new
Integer
(
3
),
service
.
executeConversion
(
value
(
"3"
),
type
(
Integer
.
class
)
));
}
public
void
testConverterConversionForwardIndex
()
{
service
.
addConverter
(
new
StringToInteger
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
String
.
class
,
Integer
.
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
String
.
class
),
type
(
Integer
.
class
)
);
Integer
three
=
(
Integer
)
executor
.
execute
(
"3"
);
assertEquals
(
3
,
three
.
intValue
());
}
public
void
testConverterConversionReverseIndex
()
{
service
.
addConverter
(
new
StringToInteger
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
Integer
.
class
,
String
.
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
Integer
.
class
),
type
(
String
.
class
)
);
String
threeString
=
(
String
)
executor
.
execute
(
new
Integer
(
3
));
assertEquals
(
"3"
,
threeString
);
}
public
void
testConversionExecutorNotFound
()
{
try
{
service
.
getConversionExecutor
(
String
.
class
,
Integer
.
class
);
service
.
getConversionExecutor
(
type
(
String
.
class
),
type
(
Integer
.
class
)
);
fail
(
"Should have thrown an exception"
);
}
catch
(
ConversionExecutorNotFoundException
e
)
{
}
}
public
void
testConversionCompatibleTypes
()
{
ArrayList
source
=
new
ArrayList
()
;
assertSame
(
source
,
service
.
getConversionExecutor
(
ArrayList
.
class
,
List
.
class
).
execute
(
source
));
String
source
=
"foo"
;
assertSame
(
source
,
service
.
getConversionExecutor
(
type
(
String
.
class
),
type
(
String
.
class
)
).
execute
(
source
));
}
public
void
testConversionExecutorNullArgument
()
{
service
.
addConverter
(
new
StringToInteger
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
String
.
class
,
Integer
.
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
String
.
class
),
type
(
Integer
.
class
)
);
assertNull
(
executor
.
execute
(
null
));
}
public
void
testConversionExecutorWrongTypeArgument
()
{
service
.
addConverter
(
new
StringToInteger
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
Integer
.
class
,
String
.
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
Integer
.
class
),
type
(
String
.
class
)
);
try
{
executor
.
execute
(
"BOGUS"
);
fail
(
"Should have failed"
);
...
...
@@ -96,7 +106,7 @@ public class GenericConversionServiceTests extends TestCase {
return
target
.
toString
();
}
});
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
String
.
class
,
Integer
.
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
String
.
class
),
type
(
Integer
.
class
)
);
Integer
result
=
(
Integer
)
executor
.
execute
(
"3"
);
assertEquals
(
new
Integer
(
3
),
result
);
}
...
...
@@ -112,7 +122,7 @@ public class GenericConversionServiceTests extends TestCase {
}
});
try
{
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
String
.
class
,
Integer
.
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
String
.
class
),
type
(
Integer
.
class
)
);
fail
(
"Should have failed"
);
}
catch
(
ConversionExecutorNotFoundException
e
)
{
...
...
@@ -121,14 +131,14 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testConversionObjectToPrimitive
()
{
service
.
addConverter
(
new
StringToInteger
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
String
.
class
,
int
.
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
String
.
class
),
type
(
int
.
class
)
);
Integer
three
=
(
Integer
)
executor
.
execute
(
"3"
);
assertEquals
(
3
,
three
.
intValue
());
}
public
void
testConversionArrayToArray
()
{
service
.
addConverter
(
new
StringToInteger
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
String
[].
class
,
Integer
[].
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
String
[].
class
),
type
(
Integer
[].
class
)
);
Integer
[]
result
=
(
Integer
[])
executor
.
execute
(
new
String
[]
{
"1"
,
"2"
,
"3"
});
assertEquals
(
new
Integer
(
1
),
result
[
0
]);
assertEquals
(
new
Integer
(
2
),
result
[
1
]);
...
...
@@ -137,7 +147,7 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testConversionArrayToPrimitiveArray
()
{
service
.
addConverter
(
new
StringToInteger
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
String
[].
class
,
int
[].
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
String
[].
class
),
type
(
int
[].
class
)
);
int
[]
result
=
(
int
[])
executor
.
execute
(
new
String
[]
{
"1"
,
"2"
,
"3"
});
assertEquals
(
1
,
result
[
0
]);
assertEquals
(
2
,
result
[
1
]);
...
...
@@ -145,15 +155,23 @@ public class GenericConversionServiceTests extends TestCase {
}
public
void
testConversionArrayToListInterface
()
{
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
String
[].
class
,
List
.
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
String
[].
class
),
type
(
List
.
class
)
);
List
result
=
(
List
)
executor
.
execute
(
new
String
[]
{
"1"
,
"2"
,
"3"
});
assertEquals
(
"1"
,
result
.
get
(
0
));
assertEquals
(
"2"
,
result
.
get
(
1
));
assertEquals
(
"3"
,
result
.
get
(
2
));
}
public
void
testConversionArrayToListGenericTypeConversion
()
{
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
String
[].
class
),
type
(
List
.
class
));
List
result
=
(
List
)
executor
.
execute
(
new
String
[]
{
"1"
,
"2"
,
"3"
});
assertEquals
(
new
Integer
(
"1"
),
result
.
get
(
0
));
assertEquals
(
new
Integer
(
"2"
),
result
.
get
(
1
));
assertEquals
(
new
Integer
(
"3"
),
result
.
get
(
2
));
}
public
void
testConversionArrayToListImpl
()
{
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
String
[].
class
,
LinkedList
.
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
String
[].
class
),
type
(
LinkedList
.
class
)
);
LinkedList
result
=
(
LinkedList
)
executor
.
execute
(
new
String
[]
{
"1"
,
"2"
,
"3"
});
assertEquals
(
"1"
,
result
.
get
(
0
));
assertEquals
(
"2"
,
result
.
get
(
1
));
...
...
@@ -162,14 +180,14 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testConversionArrayToAbstractList
()
{
try
{
service
.
getConversionExecutor
(
String
[].
class
,
AbstractList
.
class
);
service
.
getConversionExecutor
(
type
(
String
[].
class
),
type
(
AbstractList
.
class
)
);
}
catch
(
IllegalArgumentException
e
)
{
}
}
public
void
testConversionListToArray
()
{
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
Collection
.
class
,
String
[].
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
Collection
.
class
),
type
(
String
[].
class
)
);
List
list
=
new
ArrayList
();
list
.
add
(
"1"
);
list
.
add
(
"2"
);
...
...
@@ -182,7 +200,7 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testConversionListToArrayWithComponentConversion
()
{
service
.
addConverter
(
new
StringToInteger
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
Collection
.
class
,
Integer
[].
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
Collection
.
class
),
type
(
Integer
[].
class
)
);
List
list
=
new
ArrayList
();
list
.
add
(
"1"
);
list
.
add
(
"2"
);
...
...
@@ -194,7 +212,7 @@ public class GenericConversionServiceTests extends TestCase {
}
public
void
testConversionObjectToArray
()
{
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
String
.
class
,
String
[].
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
String
.
class
),
type
(
String
[].
class
)
);
String
[]
result
=
(
String
[])
executor
.
execute
(
"1,2,3"
);
assertEquals
(
1
,
result
.
length
);
assertEquals
(
"1,2,3"
,
result
[
0
]);
...
...
@@ -202,7 +220,7 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testConversionObjectToArrayWithElementConversion
()
{
service
.
addConverter
(
new
StringToInteger
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
String
.
class
,
Integer
[].
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
String
.
class
),
type
(
Integer
[].
class
)
);
Integer
[]
result
=
(
Integer
[])
executor
.
execute
(
"123"
);
assertEquals
(
1
,
result
.
length
);
assertEquals
(
new
Integer
(
123
),
result
[
0
]);
...
...
@@ -214,19 +232,19 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testSuperConverterConversionForwardIndex
()
{
service
.
addConverter
(
new
StringToEnum
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
String
.
class
,
FooEnum
.
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
String
.
class
),
type
(
FooEnum
.
class
)
);
assertEquals
(
FooEnum
.
BAR
,
executor
.
execute
(
"BAR"
));
}
public
void
testSuperTwoWayConverterConversionReverseIndex
()
{
service
.
addConverter
(
new
StringToEnum
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
FooEnum
.
class
,
String
.
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
FooEnum
.
class
),
type
(
String
.
class
)
);
assertEquals
(
"BAR"
,
executor
.
execute
(
FooEnum
.
BAR
));
}
public
void
testSuperConverterConversionNotConvertibleAbstractType
()
{
service
.
addConverter
(
new
StringToEnum
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
String
.
class
,
Enum
.
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
String
.
class
),
type
(
Enum
.
class
)
);
try
{
executor
.
execute
(
"WHATEV"
);
fail
(
"Should have failed"
);
...
...
@@ -258,7 +276,7 @@ public class GenericConversionServiceTests extends TestCase {
return
0
;
}
};
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
Integer
.
class
,
customNumber
.
getClass
(
));
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
type
(
Integer
.
class
),
type
(
customNumber
.
getClass
()
));
try
{
executor
.
execute
(
3
);
fail
(
"Should have failed"
);
...
...
@@ -286,13 +304,13 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testCustomConverterConversionForwardIndex
()
{
service
.
addConverter
(
"princy"
,
new
CustomTwoWayConverter
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
String
.
class
,
Principal
.
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
type
(
String
.
class
),
type
(
Principal
.
class
)
);
assertEquals
(
"keith"
,
((
Principal
)
executor
.
execute
(
"keith"
)).
getName
());
}
public
void
testCustomConverterConversionReverseIndex
()
{
service
.
addConverter
(
"princy"
,
new
CustomTwoWayConverter
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
Principal
.
class
,
String
.
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
type
(
Principal
.
class
),
type
(
String
.
class
)
);
assertEquals
(
"keith"
,
executor
.
execute
(
new
Principal
()
{
public
String
getName
()
{
return
"keith"
;
...
...
@@ -302,14 +320,14 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testCustomConverterConversionForSameType
()
{
service
.
addConverter
(
"trimmer"
,
new
Trimmer
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"trimmer"
,
String
.
class
,
String
.
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"trimmer"
,
type
(
String
.
class
),
type
(
String
.
class
)
);
assertEquals
(
"a string"
,
executor
.
execute
(
"a string "
));
}
public
void
testCustomConverterLookupNotCompatibleSource
()
{
service
.
addConverter
(
"trimmer"
,
new
Trimmer
());
try
{
service
.
getConversionExecutor
(
"trimmer"
,
Object
.
class
,
String
.
class
);
service
.
getConversionExecutor
(
"trimmer"
,
type
(
Object
.
class
),
type
(
String
.
class
)
);
fail
(
"Should have failed"
);
}
catch
(
ConversionException
e
)
{
...
...
@@ -319,7 +337,7 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testCustomConverterLookupNotCompatibleTarget
()
{
service
.
addConverter
(
"trimmer"
,
new
Trimmer
());
try
{
service
.
getConversionExecutor
(
"trimmer"
,
String
.
class
,
Object
.
class
);
service
.
getConversionExecutor
(
"trimmer"
,
type
(
String
.
class
),
type
(
Object
.
class
)
);
}
catch
(
ConversionException
e
)
{
}
...
...
@@ -328,7 +346,7 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testCustomConverterLookupNotCompatibleTargetReverse
()
{
service
.
addConverter
(
"princy"
,
new
CustomTwoWayConverter
());
try
{
service
.
getConversionExecutor
(
"princy"
,
Principal
.
class
,
Integer
.
class
);
service
.
getConversionExecutor
(
"princy"
,
type
(
Principal
.
class
),
type
(
Integer
.
class
)
);
}
catch
(
ConversionException
e
)
{
}
...
...
@@ -336,7 +354,7 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testCustomConverterConversionArrayToArray
()
{
service
.
addConverter
(
"princy"
,
new
CustomTwoWayConverter
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
String
[].
class
,
Principal
[].
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
type
(
String
[].
class
),
type
(
Principal
[].
class
)
);
Principal
[]
p
=
(
Principal
[])
executor
.
execute
(
new
String
[]
{
"princy1"
,
"princy2"
});
assertEquals
(
"princy1"
,
p
[
0
].
getName
());
assertEquals
(
"princy2"
,
p
[
1
].
getName
());
...
...
@@ -344,7 +362,7 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testCustomConverterConversionArrayToArrayReverse
()
{
service
.
addConverter
(
"princy"
,
new
CustomTwoWayConverter
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
Principal
[].
class
,
String
[].
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
type
(
Principal
[].
class
),
type
(
String
[].
class
)
);
final
Principal
princy1
=
new
Principal
()
{
public
String
getName
()
{
return
"princy1"
;
...
...
@@ -363,7 +381,7 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testCustomConverterLookupArrayToArrayBogusSource
()
{
service
.
addConverter
(
"princy"
,
new
CustomTwoWayConverter
());
try
{
service
.
getConversionExecutor
(
"princy"
,
Integer
[].
class
,
Principal
[].
class
);
service
.
getConversionExecutor
(
"princy"
,
type
(
Integer
[].
class
),
type
(
Principal
[].
class
)
);
fail
(
"Should have failed"
);
}
catch
(
ConversionExecutorNotFoundException
e
)
{
}
...
...
@@ -372,7 +390,7 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testCustomConverterLookupArrayToArrayBogusTarget
()
{
service
.
addConverter
(
"princy"
,
new
CustomTwoWayConverter
());
try
{
service
.
getConversionExecutor
(
"princy"
,
Principal
[].
class
,
Integer
[].
class
);
service
.
getConversionExecutor
(
"princy"
,
type
(
Principal
[].
class
),
type
(
Integer
[].
class
)
);
}
catch
(
ConversionExecutorNotFoundException
e
)
{
}
...
...
@@ -380,7 +398,7 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testCustomConverterConversionArrayToCollection
()
{
service
.
addConverter
(
"princy"
,
new
CustomTwoWayConverter
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
String
[].
class
,
List
.
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
type
(
String
[].
class
),
type
(
List
.
class
)
);
List
list
=
(
List
)
executor
.
execute
(
new
String
[]
{
"princy1"
,
"princy2"
});
assertEquals
(
"princy1"
,
((
Principal
)
list
.
get
(
0
)).
getName
());
assertEquals
(
"princy2"
,
((
Principal
)
list
.
get
(
1
)).
getName
());
...
...
@@ -388,7 +406,7 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testCustomConverterConversionArrayToCollectionReverse
()
{
service
.
addConverter
(
"princy"
,
new
CustomTwoWayConverter
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
Principal
[].
class
,
List
.
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
type
(
Principal
[].
class
),
type
(
List
.
class
)
);
final
Principal
princy1
=
new
Principal
()
{
public
String
getName
()
{
return
"princy1"
;
...
...
@@ -407,7 +425,7 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testCustomConverterLookupArrayToCollectionBogusSource
()
{
service
.
addConverter
(
"princy"
,
new
CustomTwoWayConverter
());
try
{
service
.
getConversionExecutor
(
"princy"
,
Integer
[].
class
,
List
.
class
);
service
.
getConversionExecutor
(
"princy"
,
type
(
Integer
[].
class
),
type
(
List
.
class
)
);
fail
(
"Should have failed"
);
}
catch
(
ConversionExecutorNotFoundException
e
)
{
...
...
@@ -416,7 +434,7 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testCustomConverterLookupCollectionToArray
()
{
service
.
addConverter
(
"princy"
,
new
CustomTwoWayConverter
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
List
.
class
,
Principal
[].
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
type
(
List
.
class
),
type
(
Principal
[].
class
)
);
List
princyList
=
new
ArrayList
();
princyList
.
add
(
"princy1"
);
princyList
.
add
(
"princy2"
);
...
...
@@ -427,7 +445,7 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testCustomConverterLookupCollectionToArrayReverse
()
{
service
.
addConverter
(
"princy"
,
new
CustomTwoWayConverter
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
List
.
class
,
String
[].
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
type
(
List
.
class
),
type
(
String
[].
class
)
);
final
Principal
princy1
=
new
Principal
()
{
public
String
getName
()
{
return
"princy1"
;
...
...
@@ -449,7 +467,7 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testtestCustomConverterLookupCollectionToArrayBogusTarget
()
{
service
.
addConverter
(
"princy"
,
new
CustomTwoWayConverter
());
try
{
service
.
getConversionExecutor
(
"princy"
,
List
.
class
,
Integer
[].
class
);
service
.
getConversionExecutor
(
"princy"
,
type
(
List
.
class
),
type
(
Integer
[].
class
)
);
fail
(
"Should have failed"
);
}
catch
(
ConversionExecutorNotFoundException
e
)
{
...
...
@@ -458,14 +476,14 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testCustomConverterConversionObjectToArray
()
{
service
.
addConverter
(
"princy"
,
new
CustomTwoWayConverter
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
String
.
class
,
Principal
[].
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
type
(
String
.
class
),
type
(
Principal
[].
class
)
);
Principal
[]
p
=
(
Principal
[])
executor
.
execute
(
"princy1"
);
assertEquals
(
"princy1"
,
p
[
0
].
getName
());
}
public
void
testCustomConverterConversionObjectToArrayReverse
()
{
service
.
addConverter
(
"princy"
,
new
CustomTwoWayConverter
());
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
Principal
.
class
,
String
[].
class
);
ConversionExecutor
executor
=
service
.
getConversionExecutor
(
"princy"
,
type
(
Principal
.
class
),
type
(
String
[].
class
)
);
final
Principal
princy1
=
new
Principal
()
{
public
String
getName
()
{
return
"princy1"
;
...
...
@@ -478,7 +496,7 @@ public class GenericConversionServiceTests extends TestCase {
public
void
testCustomConverterLookupObjectToArrayBogusSource
()
{
service
.
addConverter
(
"princy"
,
new
CustomTwoWayConverter
());
try
{
service
.
getConversionExecutor
(
"princy"
,
Integer
.
class
,
Principal
[].
class
);
service
.
getConversionExecutor
(
"princy"
,
type
(
Integer
.
class
),
type
(
Principal
[].
class
)
);
fail
(
"Should have failed"
);
}
catch
(
ConversionExecutorNotFoundException
e
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录