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;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@ -12,6 +13,7 @@ import java.util.HashSet;
import info.ebenoit.ebul.func.ThrowingBiConsumer;
import info.ebenoit.ebul.func.ThrowingConsumer;
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 >
{
/** 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.
*
* @param klass
* the class to extract the information from
* @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 )
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
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
*