diff --git a/TODO b/TODO
index bf0ef94..701fbd3 100644
--- a/TODO
+++ b/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):
diff --git a/src/main/java/info/ebenoit/ebul/cmp/Anonymous.java b/src/main/java/info/ebenoit/ebul/cmp/Anonymous.java
new file mode 100644
index 0000000..a13e421
--- /dev/null
+++ b/src/main/java/info/ebenoit/ebul/cmp/Anonymous.java
@@ -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 E. BenoƮt
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( ElementType.TYPE )
+public @interface Anonymous
+{
+ // EMPTY
+}
diff --git a/src/main/java/info/ebenoit/ebul/cmp/ComponentState.java b/src/main/java/info/ebenoit/ebul/cmp/ComponentState.java
index a78e17a..0f94658 100644
--- a/src/main/java/info/ebenoit/ebul/cmp/ComponentState.java
+++ b/src/main/java/info/ebenoit/ebul/cmp/ComponentState.java
@@ -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( );
}
}
diff --git a/src/main/java/info/ebenoit/ebul/cmp/NewComponentInfo.java b/src/main/java/info/ebenoit/ebul/cmp/NewComponentInfo.java
index 5f59bfb..7078bad 100644
--- a/src/main/java/info/ebenoit/ebul/cmp/NewComponentInfo.java
+++ b/src/main/java/info/ebenoit/ebul/cmp/NewComponentInfo.java
@@ -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 null
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 null
for an anonymous component or {@code ""} for a
+ * component whose class name will serve as its name.
*/
public String getName( )
{
diff --git a/src/test/java/info/ebenoit/ebul/cmp/TestComponentState.java b/src/test/java/info/ebenoit/ebul/cmp/TestComponentState.java
index c1ecda3..610b230 100644
--- a/src/test/java/info/ebenoit/ebul/cmp/TestComponentState.java
+++ b/src/test/java/info/ebenoit/ebul/cmp/TestComponentState.java
@@ -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 null
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( )
diff --git a/src/test/java/info/ebenoit/ebul/cmp/TestNewComponentInfo.java b/src/test/java/info/ebenoit/ebul/cmp/TestNewComponentInfo.java
index e534b22..5206ae8 100644
--- a/src/test/java/info/ebenoit/ebul/cmp/TestNewComponentInfo.java
+++ b/src/test/java/info/ebenoit/ebul/cmp/TestNewComponentInfo.java
@@ -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( ) );