@ -3,6 +3,7 @@ package org.springframework.data.persistence;
@@ -3,6 +3,7 @@ package org.springframework.data.persistence;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
import org.springframework.util.ClassUtils ;
import sun.reflect.ReflectionFactory ;
import java.lang.reflect.Constructor ;
import java.lang.reflect.InvocationTargetException ;
@ -20,7 +21,7 @@ public abstract class AbstractConstructorEntityInstantiator<BACKING_INTERFACE, S
@@ -20,7 +21,7 @@ public abstract class AbstractConstructorEntityInstantiator<BACKING_INTERFACE, S
private final Logger log = LoggerFactory . getLogger ( getClass ( ) ) ;
private final Map < Class < ? extends BACKING_INTERFACE > , StateBackedCreator < ? extends BACKING_INTERFACE , STATE > > cache = new HashMap < Class < ? extends BACKING_INTERFACE > , StateBackedCreator < ? extends BACKING_INTERFACE , STATE > > ( ) ;
final public < T extends BACKING_INTERFACE > T createEntityFromState ( STATE n , Class < T > c ) {
public < T extends BACKING_INTERFACE > T createEntityFromState ( STATE n , Class < T > c ) {
try {
StateBackedCreator < T , STATE > creator = ( StateBackedCreator < T , STATE > ) cache . get ( c ) ;
if ( creator ! = null ) return creator . create ( n , c ) ;
@ -47,34 +48,34 @@ public abstract class AbstractConstructorEntityInstantiator<BACKING_INTERFACE, S
@@ -47,34 +48,34 @@ public abstract class AbstractConstructorEntityInstantiator<BACKING_INTERFACE, S
}
protected < T extends BACKING_INTERFACE > StateBackedCreator < T , STATE > createInstantiator ( Class < T > type , final Class < STATE > stateType ) {
StateBackedCreator < T , STATE > creator = stateTakingConstructorInstantiator ( type , stateType ) ;
StateBackedCreator < T , STATE > creator = stateTakingConstructorInstantiator ( type , stateType ) ;
if ( creator ! = null ) return creator ;
creator = emptyConstructorStateSettingInstantiator ( type , stateType ) ;
if ( creator ! = null ) return creator ;
return createFailingInstantiator ( stateType ) ;
}
private < T extends BACKING_INTERFACE > StateBackedCreator < T , STATE > createFailingInstantiator ( final Class < STATE > stateType ) {
protected < T extends BACKING_INTERFACE > StateBackedCreator < T , STATE > createFailingInstantiator ( final Class < STATE > stateType ) {
return new StateBackedCreator < T , STATE > ( ) {
public T create ( STATE n , Class < T > c ) throws Exception {
public T create ( STATE state , Class < T > c ) throws Exception {
throw new IllegalArgumentException ( getClass ( ) . getSimpleName ( ) + ": entity " + c +
" must have either a constructor taking [" + stateType + "] or a no-arg constructor and state set method" ) ;
}
} ;
}
private < T extends BACKING_INTERFACE > StateBackedCreator < T , STATE > emptyConstructorStateSettingInstantiator ( Class < T > type , Class < STATE > stateType ) {
protected < T extends BACKING_INTERFACE > StateBackedCreator < T , STATE > emptyConstructorStateSettingInstantiator ( Class < T > type , Class < STATE > stateType ) {
final Constructor < T > constructor = getNoArgConstructor ( type ) ;
if ( constructor = = null ) return null ;
log . info ( "Using " + type + " no-arg constructor" ) ;
return new StateBackedCreator < T , STATE > ( ) {
public T create ( STATE n , Class < T > c ) throws Exception {
public T create ( STATE state , Class < T > c ) throws Exception {
try {
StateProvider . setUnderlyingState ( n ) ;
StateProvider . setUnderlyingState ( state ) ;
T newInstance = constructor . newInstance ( ) ;
setState ( newInstance , n ) ;
setState ( newInstance , state ) ;
return newInstance ;
} finally {
StateProvider . retrieveState ( ) ;
@ -83,13 +84,28 @@ public abstract class AbstractConstructorEntityInstantiator<BACKING_INTERFACE, S
@@ -83,13 +84,28 @@ public abstract class AbstractConstructorEntityInstantiator<BACKING_INTERFACE, S
} ;
}
private < T extends BACKING_INTERFACE > Constructor < T > getNoArgConstructor ( Class < T > type ) {
@SuppressWarnings ( "unchecked" )
protected < T extends BACKING_INTERFACE > StateBackedCreator < T , STATE > createWithoutConstructorInvocation ( final Class < T > type , Class < STATE > stateType ) {
ReflectionFactory rf = ReflectionFactory . getReflectionFactory ( ) ;
Constructor < ? > objectConstructor = getDeclaredConstructor ( Object . class ) ;
final Constructor < ? > serializationConstructor = rf . newConstructorForSerialization ( type , objectConstructor ) ;
return new StateBackedCreator < T , STATE > ( ) {
public T create ( STATE state , Class < T > c ) throws Exception {
final T result = type . cast ( serializationConstructor . newInstance ( ) ) ;
setState ( result , state ) ;
return result ;
}
} ;
}
protected < T extends BACKING_INTERFACE > Constructor < T > getNoArgConstructor ( Class < T > type ) {
Constructor < T > constructor = ClassUtils . getConstructorIfAvailable ( type ) ;
if ( constructor ! = null ) return constructor ;
return getDeclaredConstructor ( type ) ;
}
private < T extends BACKING_INTERFACE > StateBackedCreator < T , STATE > stateTakingConstructorInstantiator ( Class < T > type , Class < STATE > stateType ) {
protected < T extends BACKING_INTERFACE > StateBackedCreator < T , STATE > stateTakingConstructorInstantiator ( Class < T > type , Class < STATE > stateType ) {
Class < ? extends STATE > stateInterface = ( Class < ? extends STATE > ) stateType . getInterfaces ( ) [ 0 ] ;
final Constructor < T > constructor = ClassUtils . getConstructorIfAvailable ( type , stateInterface ) ;
if ( constructor = = null ) return null ;
@ -102,7 +118,7 @@ public abstract class AbstractConstructorEntityInstantiator<BACKING_INTERFACE, S
@@ -102,7 +118,7 @@ public abstract class AbstractConstructorEntityInstantiator<BACKING_INTERFACE, S
} ;
}
private < T > Constructor < T > getDeclaredConstructor ( Class < T > c ) {
protected < T > Constructor < T > getDeclaredConstructor ( Class < T > c ) {
try {
final Constructor < T > declaredConstructor = c . getDeclaredConstructor ( ) ;
declaredConstructor . setAccessible ( true ) ;