Improved component naming
* Setting a component information record's name to null will lead to an anonymous component, while setting it to an empty string will lead to an component whose name is that of its class. * New Anonymous annotation to indicate that a component is meant to be anonymous (conflicts with ParametricComponent or valued Component annotations).
This commit is contained in:
parent
36887ae759
commit
0c23f613d6
6 changed files with 158 additions and 27 deletions
1
TODO
1
TODO
|
@ -2,7 +2,6 @@ To Do:
|
|||
* Implement "DriverFor" support
|
||||
* Scanning packages for annotated components
|
||||
* General usage documentation
|
||||
* Easier anonymous components
|
||||
* Uncouple component-provided names from the library
|
||||
|
||||
Other ideas (maybe later if needed):
|
||||
|
|
21
src/main/java/info/ebenoit/ebul/cmp/Anonymous.java
Normal file
21
src/main/java/info/ebenoit/ebul/cmp/Anonymous.java
Normal file
|
@ -0,0 +1,21 @@
|
|||
package info.ebenoit.ebul.cmp;
|
||||
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Annotation indicating that a component will not have a name.
|
||||
*
|
||||
* @author <a href="mailto:ebenoit@ebenoit.info">E. Benoît</a>
|
||||
*/
|
||||
@Retention( RetentionPolicy.RUNTIME )
|
||||
@Target( ElementType.TYPE )
|
||||
public @interface Anonymous
|
||||
{
|
||||
// EMPTY
|
||||
}
|
|
@ -84,7 +84,7 @@ public final class ComponentState
|
|||
name = ( (ParametricComponent) component ).getComponentName( );
|
||||
} else {
|
||||
name = ci.getName( );
|
||||
if ( name == null ) {
|
||||
if ( "".equals( name ) ) {
|
||||
name = component.getClass( ).getSimpleName( );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,15 +75,22 @@ public final class NewComponentInfo< T >
|
|||
|
||||
// Sets the new component's name
|
||||
final Component aComp = klass.getAnnotation( Component.class );
|
||||
if ( aComp != null && !"".equals( aComp.value( ) ) ) {
|
||||
final boolean isAnon = klass.isAnnotationPresent( Anonymous.class );
|
||||
if ( isAnon ) {
|
||||
if ( ParametricComponent.class.isAssignableFrom( klass ) ) {
|
||||
throw new ComponentDefinitionException( "parametric component can't be anonymous" );
|
||||
}
|
||||
if ( aComp != null && !"".equals( aComp.value( ) ) ) {
|
||||
throw new ComponentDefinitionException( "named component can't be anonymous" );
|
||||
}
|
||||
info.setName( null );
|
||||
} else if ( aComp != null ) {
|
||||
if ( !"".equals( aComp.value( ) ) && ParametricComponent.class.isAssignableFrom( klass ) ) {
|
||||
throw new ComponentDefinitionException( "parametric component can't be named" );
|
||||
}
|
||||
info.setName( aComp.value( ) );
|
||||
} else if ( !ParametricComponent.class.isAssignableFrom( klass ) ) {
|
||||
info.setName( klass.getSimpleName( ) );
|
||||
} else {
|
||||
info.setName( null );
|
||||
info.setName( "" );
|
||||
}
|
||||
|
||||
// Autostart flag
|
||||
|
@ -365,7 +372,8 @@ public final class NewComponentInfo< T >
|
|||
* Sets the new component's name
|
||||
*
|
||||
* @param name
|
||||
* the new component's name
|
||||
* the new component's name. May be <code>null</code> for an anonymous component or {@code ""} for a
|
||||
* component whose class name will serve as its name.
|
||||
* @return the current object
|
||||
*/
|
||||
public NewComponentInfo< T > setName( final String name )
|
||||
|
@ -376,7 +384,8 @@ public final class NewComponentInfo< T >
|
|||
|
||||
|
||||
/**
|
||||
* @return the name of the new component
|
||||
* @return the name of the new component. May be <code>null</code> for an anonymous component or {@code ""} for a
|
||||
* component whose class name will serve as its name.
|
||||
*/
|
||||
public String getName( )
|
||||
{
|
||||
|
|
|
@ -71,6 +71,7 @@ public class TestComponentState
|
|||
{
|
||||
private ComponentRegistry registry;
|
||||
|
||||
|
||||
@Override
|
||||
public void setComponentRegistry( ComponentRegistry registry )
|
||||
{
|
||||
|
@ -138,7 +139,6 @@ public class TestComponentState
|
|||
final NewComponentInfo< Object > ci = new NewComponentInfo< Object >( object );
|
||||
final ComponentState cs = new ComponentState( this.reg , ci );
|
||||
Assert.assertSame( object , cs.getComponent( ) );
|
||||
Assert.assertEquals( "Object" , cs.getName( ) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -150,7 +150,6 @@ public class TestComponentState
|
|||
final NewComponentInfo< Object > ci = new NewComponentInfo< Object >( ( ) -> object );
|
||||
final ComponentState cs = new ComponentState( this.reg , ci );
|
||||
Assert.assertSame( object , cs.getComponent( ) );
|
||||
Assert.assertEquals( "Object" , cs.getName( ) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -168,6 +167,29 @@ public class TestComponentState
|
|||
}
|
||||
|
||||
|
||||
/** Test: initialising a {@link ComponentState} with a <code>null</code> name */
|
||||
@Test
|
||||
public void testInitialiseNullName( )
|
||||
{
|
||||
final Object object = new Object( );
|
||||
final NewComponentInfo< Object > ci = new NewComponentInfo< Object >( object );
|
||||
final ComponentState cs = new ComponentState( this.reg , ci );
|
||||
Assert.assertNull( cs.getName( ) );
|
||||
}
|
||||
|
||||
|
||||
/** Test: initialising a {@link ComponentState} with an automatic name */
|
||||
@Test
|
||||
public void testInitialiseAutoName( )
|
||||
{
|
||||
final Object object = new Object( );
|
||||
final NewComponentInfo< Object > ci = new NewComponentInfo< Object >( object ) //
|
||||
.setName( "" );
|
||||
final ComponentState cs = new ComponentState( this.reg , ci );
|
||||
Assert.assertEquals( "Object" , cs.getName( ) );
|
||||
}
|
||||
|
||||
|
||||
/** Test: initialising a {@link ComponentState} with a supplied name */
|
||||
@Test
|
||||
public void testInitialiseWithName( )
|
||||
|
|
|
@ -62,6 +62,50 @@ public class TestNewComponentInfo
|
|||
// EMPTY
|
||||
}
|
||||
|
||||
/** Test anonymous component */
|
||||
@Anonymous
|
||||
private static class TestCmpAnon
|
||||
{
|
||||
// EMPTY
|
||||
}
|
||||
|
||||
/** Test anonymous component with empty {@link Component} annotation */
|
||||
@Anonymous
|
||||
@Component
|
||||
private static class TestCmpAnonComponent
|
||||
{
|
||||
// EMPTY
|
||||
}
|
||||
|
||||
/** Test anonymous component that implements {@link ParametricComponent} (invalid!) */
|
||||
@Anonymous
|
||||
private static class TestCmpAnonPN
|
||||
implements ParametricComponent
|
||||
{
|
||||
|
||||
@Override
|
||||
public String getComponentName( )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Test anonymous component that has a specified name (invalid!) */
|
||||
@Component( "Fail!" )
|
||||
@Anonymous
|
||||
private static class TestCmpAnonNamed
|
||||
implements ParametricComponent
|
||||
{
|
||||
|
||||
@Override
|
||||
public String getComponentName( )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Test component with a parametric name */
|
||||
private static class TestCmpPN
|
||||
implements ParametricComponent
|
||||
|
@ -372,7 +416,7 @@ public class TestNewComponentInfo
|
|||
public void testFromClass1( )
|
||||
{
|
||||
NewComponentInfo< ? > nci = NewComponentInfo.fromClass( TestCmp1.class );
|
||||
assertEquals( "TestCmp1" , nci.getName( ) );
|
||||
assertEquals( "" , nci.getName( ) );
|
||||
assertFalse( nci.getAutostart( ) );
|
||||
assertTrue( nci.getDependencies( ).isEmpty( ) );
|
||||
assertNull( nci.getDriverFor( ) );
|
||||
|
@ -412,7 +456,7 @@ public class TestNewComponentInfo
|
|||
public void testFromClass4( )
|
||||
{
|
||||
NewComponentInfo< ? > nci = NewComponentInfo.fromClass( TestCmp4.class );
|
||||
assertEquals( "component name was inherited!" , "TestCmp4" , nci.getName( ) );
|
||||
assertNotEquals( "component name was inherited!" , "Test component" , nci.getName( ) );
|
||||
assertFalse( "autostart state was inherited!" , nci.getAutostart( ) );
|
||||
HashSet< DependencyInfo > deps = nci.getDependencies( );
|
||||
assertEquals( 3 , deps.size( ) );
|
||||
|
@ -422,6 +466,49 @@ public class TestNewComponentInfo
|
|||
}
|
||||
|
||||
|
||||
/** Test: {@link NewComponentInfo#fromClass(Class)} on a component class with the {@link Anonymous} annotation */
|
||||
@Test
|
||||
public void testFromClassAnon( )
|
||||
{
|
||||
NewComponentInfo< ? > nci = NewComponentInfo.fromClass( TestCmpAnon.class );
|
||||
assertNull( nci.getName( ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test: {@link NewComponentInfo#fromClass(Class)} on a component class with the {@link Anonymous} annotation and an
|
||||
* empty {@link Component} annotation
|
||||
*/
|
||||
@Test
|
||||
public void testFromClassAnonComponent( )
|
||||
{
|
||||
NewComponentInfo< ? > nci = NewComponentInfo.fromClass( TestCmpAnonComponent.class );
|
||||
assertNull( nci.getName( ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test: {@link NewComponentInfo#fromClass(Class)} on a component class with the {@link Anonymous} annotation that
|
||||
* implements {@link ParametricComponent}
|
||||
*/
|
||||
@Test( expected = ComponentDefinitionException.class )
|
||||
public void testFromClassAnonPN( )
|
||||
{
|
||||
NewComponentInfo.fromClass( TestCmpAnonPN.class );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test: {@link NewComponentInfo#fromClass(Class)} on a component class with the {@link Anonymous} annotation and a
|
||||
* {@link Component} annotation carrying a value
|
||||
*/
|
||||
@Test( expected = ComponentDefinitionException.class )
|
||||
public void testFromClassAnonNamed( )
|
||||
{
|
||||
NewComponentInfo.fromClass( TestCmpAnonNamed.class );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test: {@link NewComponentInfo#fromClass(Class)} on a component class that implements {@link ParametricComponent}
|
||||
*/
|
||||
|
@ -429,7 +516,7 @@ public class TestNewComponentInfo
|
|||
public void testFromClassPN1( )
|
||||
{
|
||||
NewComponentInfo< ? > nci = NewComponentInfo.fromClass( TestCmpPN.class );
|
||||
assertNull( nci.getName( ) );
|
||||
assertEquals( "" , nci.getName( ) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -527,8 +614,7 @@ public class TestNewComponentInfo
|
|||
assertEquals( 1 , deps.size( ) );
|
||||
assertTrue( deps.contains( expectedDep ) );
|
||||
|
||||
HashMap< DependencyInfo , ArrayList< ThrowingBiConsumer< Object , Object > > > injectors = nci
|
||||
.getInjectors( );
|
||||
HashMap< DependencyInfo , ArrayList< ThrowingBiConsumer< Object , Object > > > injectors = nci.getInjectors( );
|
||||
assertEquals( 1 , injectors.size( ) );
|
||||
ArrayList< ThrowingBiConsumer< Object , Object > > diList = injectors.get( expectedDep );
|
||||
assertEquals( 1 , diList.size( ) );
|
||||
|
@ -556,8 +642,7 @@ public class TestNewComponentInfo
|
|||
assertEquals( 1 , deps.size( ) );
|
||||
assertTrue( deps.contains( expectedDep ) );
|
||||
|
||||
HashMap< DependencyInfo , ArrayList< ThrowingBiConsumer< Object , Object > > > injectors = nci
|
||||
.getInjectors( );
|
||||
HashMap< DependencyInfo , ArrayList< ThrowingBiConsumer< Object , Object > > > injectors = nci.getInjectors( );
|
||||
assertEquals( 1 , injectors.size( ) );
|
||||
ArrayList< ThrowingBiConsumer< Object , Object > > diList = injectors.get( expectedDep );
|
||||
assertEquals( 1 , diList.size( ) );
|
||||
|
@ -626,8 +711,7 @@ public class TestNewComponentInfo
|
|||
assertEquals( 1 , deps.size( ) );
|
||||
assertTrue( deps.contains( expectedDep ) );
|
||||
|
||||
HashMap< DependencyInfo , ArrayList< ThrowingBiConsumer< Object , Object > > > injectors = nci
|
||||
.getInjectors( );
|
||||
HashMap< DependencyInfo , ArrayList< ThrowingBiConsumer< Object , Object > > > injectors = nci.getInjectors( );
|
||||
assertEquals( 1 , injectors.size( ) );
|
||||
ArrayList< ThrowingBiConsumer< Object , Object > > diList = injectors.get( expectedDep );
|
||||
assertEquals( 1 , diList.size( ) );
|
||||
|
@ -655,8 +739,7 @@ public class TestNewComponentInfo
|
|||
assertEquals( 1 , deps.size( ) );
|
||||
assertTrue( deps.contains( expectedDep ) );
|
||||
|
||||
HashMap< DependencyInfo , ArrayList< ThrowingBiConsumer< Object , Object > > > injectors = nci
|
||||
.getInjectors( );
|
||||
HashMap< DependencyInfo , ArrayList< ThrowingBiConsumer< Object , Object > > > injectors = nci.getInjectors( );
|
||||
assertEquals( 1 , injectors.size( ) );
|
||||
ArrayList< ThrowingBiConsumer< Object , Object > > diList = injectors.get( expectedDep );
|
||||
assertEquals( 1 , diList.size( ) );
|
||||
|
@ -739,8 +822,7 @@ public class TestNewComponentInfo
|
|||
assertEquals( 1 , deps.size( ) );
|
||||
assertTrue( deps.contains( expectedDep ) );
|
||||
|
||||
HashMap< DependencyInfo , ArrayList< ThrowingBiConsumer< Object , Object > > > injectors = nci
|
||||
.getInjectors( );
|
||||
HashMap< DependencyInfo , ArrayList< ThrowingBiConsumer< Object , Object > > > injectors = nci.getInjectors( );
|
||||
assertEquals( 1 , injectors.size( ) );
|
||||
ArrayList< ThrowingBiConsumer< Object , Object > > diList = injectors.get( expectedDep );
|
||||
assertEquals( 1 , diList.size( ) );
|
||||
|
@ -767,8 +849,7 @@ public class TestNewComponentInfo
|
|||
assertEquals( 1 , deps.size( ) );
|
||||
assertTrue( deps.contains( expectedDep ) );
|
||||
|
||||
HashMap< DependencyInfo , ArrayList< ThrowingBiConsumer< Object , Object > > > injectors = nci
|
||||
.getInjectors( );
|
||||
HashMap< DependencyInfo , ArrayList< ThrowingBiConsumer< Object , Object > > > injectors = nci.getInjectors( );
|
||||
assertEquals( 1 , injectors.size( ) );
|
||||
ArrayList< ThrowingBiConsumer< Object , Object > > diList = injectors.get( expectedDep );
|
||||
assertEquals( 1 , diList.size( ) );
|
||||
|
@ -796,8 +877,7 @@ public class TestNewComponentInfo
|
|||
assertEquals( 1 , deps.size( ) );
|
||||
assertTrue( deps.contains( expectedDep ) );
|
||||
|
||||
HashMap< DependencyInfo , ArrayList< ThrowingBiConsumer< Object , Object > > > injectors = nci
|
||||
.getInjectors( );
|
||||
HashMap< DependencyInfo , ArrayList< ThrowingBiConsumer< Object , Object > > > injectors = nci.getInjectors( );
|
||||
assertEquals( 1 , injectors.size( ) );
|
||||
ArrayList< ThrowingBiConsumer< Object , Object > > diList = injectors.get( expectedDep );
|
||||
assertEquals( 1 , diList.size( ) );
|
||||
|
|
Loading…
Reference in a new issue