NewComponentInfo - Fixed default constructor access

This commit is contained in:
Emmanuel BENOîT 2015-09-13 16:00:44 +02:00
parent 93e8c9a90e
commit 095ecca3dc

View file

@ -1,6 +1,7 @@
package info.ebenoit.ebul.cmp; package info.ebenoit.ebul.cmp;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
@ -12,6 +13,7 @@ import java.util.HashSet;
import info.ebenoit.ebul.func.ThrowingBiConsumer; import info.ebenoit.ebul.func.ThrowingBiConsumer;
import info.ebenoit.ebul.func.ThrowingConsumer; import info.ebenoit.ebul.func.ThrowingConsumer;
import info.ebenoit.ebul.func.ThrowingSupplier; import info.ebenoit.ebul.func.ThrowingSupplier;
import info.ebenoit.ebul.reflection.MemberFinder;
@ -23,16 +25,34 @@ import info.ebenoit.ebul.func.ThrowingSupplier;
*/ */
public final class NewComponentInfo< T > public final class NewComponentInfo< T >
{ {
/** Member finder that looks for the default constructor */
private static final MemberFinder< Constructor< ? > > CONSTRUCTOR_FINDER;
static {
CONSTRUCTOR_FINDER = new MemberFinder< >( ( final Class< ? > c ) -> c.getDeclaredConstructors( ) , false );
NewComponentInfo.CONSTRUCTOR_FINDER
.setMemberFilter( ( final Constructor< ? > c ) -> c.getParameterCount( ) == 0 );
}
/** /**
* Creates a new component information record based on a component's annotated class. * Creates a new component information record based on a component's annotated class.
* *
* @param klass * @param klass
* the class to extract the information from * the class to extract the information from
* @return the generated information record * @return the generated information record
* @throws ComponentDefinitionException
* if the class cannot be used as a component
*/ */
public static < T > NewComponentInfo< T > fromClass( final Class< T > klass ) public static < T > NewComponentInfo< T > fromClass( final Class< T > klass )
throws ComponentDefinitionException
{ {
final NewComponentInfo< T > info = new NewComponentInfo< >( ( ) -> klass.newInstance( ) ); final Constructor< ? > constructor = NewComponentInfo.getDefaultConstructor( klass );
constructor.setAccessible( true );
final NewComponentInfo< T > info = new NewComponentInfo< T >( ( ) -> {
return klass.cast( constructor.newInstance( ) );
} );
// Sets the new component's name // Sets the new component's name
final Component aComp = klass.getAnnotation( Component.class ); final Component aComp = klass.getAnnotation( Component.class );
@ -68,6 +88,32 @@ public final class NewComponentInfo< T >
} }
/**
* Finds the default constructor for the specified class
*
* @param klass
* the class
* @return the default constructor (even if it is private)
* @throws ComponentDefinitionException
* if there is no default constructor
*/
private static < T > Constructor< ? > getDefaultConstructor( final Class< T > klass )
throws ComponentDefinitionException
{
final ArrayList< Constructor< ? > > constructors = new ArrayList< >( );
NewComponentInfo.CONSTRUCTOR_FINDER.find( constructors , klass );
if ( constructors.isEmpty( ) ) {
throw new ComponentDefinitionException( "could not find default constructor in " + klass );
}
final Constructor< ? > constructor = constructors.get( 0 );
if ( constructor.getDeclaringClass( ) != klass ) {
throw new ComponentDefinitionException( "could not find default constructor in " + klass );
}
return constructor;
}
/** /**
* Finds annotations from the members of a component's class and of its ancestors * Finds annotations from the members of a component's class and of its ancestors
* *