Component registry - clean-up

This commit is contained in:
Emmanuel BENOîT 2015-09-22 09:16:24 +02:00
parent 7ccae60ba9
commit dc6668e6dc

View file

@ -28,7 +28,7 @@ public class ComponentRegistry
private boolean added; private boolean added;
private TempBuildRec( NewComponentInfo< ? > info ) private TempBuildRec( final NewComponentInfo< ? > info )
{ {
this.info = info; this.info = info;
this.state = new ComponentState( ComponentRegistry.this , info ); this.state = new ComponentState( ComponentRegistry.this , info );
@ -43,12 +43,12 @@ public class ComponentRegistry
private final HashSet< Field > setFields; private final HashSet< Field > setFields;
private SingletonClass( Class< ? > klass ) private SingletonClass( final Class< ? > klass )
{ {
this.missingFields = new HashSet< >( ); this.missingFields = new HashSet< >( );
this.setFields = new HashSet< >( ); this.setFields = new HashSet< >( );
for ( Field fld : klass.getFields( ) ) { for ( final Field fld : klass.getFields( ) ) {
if ( !fld.isAnnotationPresent( ComponentSingleton.class ) ) { if ( !fld.isAnnotationPresent( ComponentSingleton.class ) ) {
continue; continue;
} }
@ -64,7 +64,7 @@ public class ComponentRegistry
throw new ComponentManagementException( "singleton field " + fld.getName( ) + " in class " throw new ComponentManagementException( "singleton field " + fld.getName( ) + " in class "
+ klass.getCanonicalName( ) + " is final" ); + klass.getCanonicalName( ) + " is final" );
} }
missingFields.add( fld ); this.missingFields.add( fld );
} }
} }
} }
@ -80,18 +80,18 @@ public class ComponentRegistry
private boolean active; private boolean active;
public void addSingletonClass( Class< ? > klass ) public void addSingletonClass( final Class< ? > klass )
throws ComponentManagementException , AmbiguousComponentException throws ComponentManagementException , AmbiguousComponentException
{ {
if ( !this.singletonClasses.containsKey( klass ) ) { if ( !this.singletonClasses.containsKey( klass ) ) {
SingletonClass info = new SingletonClass( klass ); final SingletonClass info = new SingletonClass( klass );
this.fillSingletonFields( info ); this.fillSingletonFields( info );
this.singletonClasses.put( klass , info ); this.singletonClasses.put( klass , info );
} }
} }
public void removeSingletonClass( Class< ? > klass ) public void removeSingletonClass( final Class< ? > klass )
{ {
this.singletonClasses.remove( klass ); this.singletonClasses.remove( klass );
} }
@ -99,32 +99,32 @@ public class ComponentRegistry
public boolean hasFailed( ) public boolean hasFailed( )
{ {
return failed; return this.failed;
} }
public boolean isInitialised( ) public boolean isInitialised( )
{ {
return initialised; return this.initialised;
} }
public boolean isActive( ) public boolean isActive( )
{ {
return active; return this.active;
} }
public ComponentState getState( String name ) public ComponentState getState( final String name )
{ {
return this.byName.get( name ); return this.byName.get( name );
} }
public ComponentState getState( Class< ? > type ) public ComponentState getState( final Class< ? > type )
throws AmbiguousComponentException throws AmbiguousComponentException
{ {
ArrayList< ComponentState > l = this.byType.get( type ); final ArrayList< ComponentState > l = this.byType.get( type );
if ( l == null ) { if ( l == null ) {
return null; return null;
} }
@ -135,10 +135,10 @@ public class ComponentRegistry
} }
public List< ComponentState > getStates( Class< ? > type ) public List< ComponentState > getStates( final Class< ? > type )
throws AmbiguousComponentException throws AmbiguousComponentException
{ {
ArrayList< ComponentState > l = this.byType.get( type ); final ArrayList< ComponentState > l = this.byType.get( type );
if ( l == null ) { if ( l == null ) {
return Collections.emptyList( ); return Collections.emptyList( );
} }
@ -146,11 +146,11 @@ public class ComponentRegistry
} }
public void getStates( Class< ? > type , Collection< ComponentState > states ) public void getStates( final Class< ? > type , final Collection< ComponentState > states )
{ {
ArrayList< ComponentState > l = this.byType.get( type ); final ArrayList< ComponentState > l = this.byType.get( type );
if ( l != null ) { if ( l != null ) {
int nFound = l.size( ); final int nFound = l.size( );
for ( int i = 0 ; i < nFound ; i++ ) { for ( int i = 0 ; i < nFound ; i++ ) {
states.add( l.get( i ) ); states.add( l.get( i ) );
} }
@ -160,27 +160,27 @@ public class ComponentRegistry
public List< ComponentState > getAllStates( ) public List< ComponentState > getAllStates( )
{ {
return Collections.unmodifiableList( components ); return Collections.unmodifiableList( this.components );
} }
public void getAllStates( Collection< ComponentState > result ) public void getAllStates( final Collection< ComponentState > result )
{ {
result.addAll( result ); result.addAll( result );
} }
public Object get( String name ) public Object get( final String name )
{ {
ComponentState cs = this.byName.get( name ); final ComponentState cs = this.byName.get( name );
return cs == null ? null : cs.getComponent( ); return cs == null ? null : cs.getComponent( );
} }
public < T > T get( Class< T > type ) public < T > T get( final Class< T > type )
throws AmbiguousComponentException throws AmbiguousComponentException
{ {
ArrayList< ComponentState > l = this.byType.get( type ); final ArrayList< ComponentState > l = this.byType.get( type );
if ( l == null ) { if ( l == null ) {
return null; return null;
} }
@ -191,15 +191,15 @@ public class ComponentRegistry
} }
public < T > List< T > getAll( Class< T > type ) public < T > List< T > getAll( final Class< T > type )
{ {
ArrayList< ComponentState > l = this.byType.get( type ); final ArrayList< ComponentState > l = this.byType.get( type );
if ( l == null ) { if ( l == null ) {
return Collections.emptyList( ); return Collections.emptyList( );
} }
int nFound = l.size( ); final int nFound = l.size( );
ArrayList< T > result = new ArrayList< >( nFound ); final ArrayList< T > result = new ArrayList< >( nFound );
for ( int i = 0 ; i < nFound ; i++ ) { for ( int i = 0 ; i < nFound ; i++ ) {
result.add( type.cast( l.get( i ).getComponent( ) ) ); result.add( type.cast( l.get( i ).getComponent( ) ) );
} }
@ -207,11 +207,11 @@ public class ComponentRegistry
} }
public < T > void getAll( Class< T > type , Collection< T > result ) public < T > void getAll( final Class< T > type , final Collection< T > result )
{ {
ArrayList< ComponentState > l = this.byType.get( type ); final ArrayList< ComponentState > l = this.byType.get( type );
if ( l != null ) { if ( l != null ) {
int nFound = l.size( ); final int nFound = l.size( );
for ( int i = 0 ; i < nFound ; i++ ) { for ( int i = 0 ; i < nFound ; i++ ) {
result.add( type.cast( l.get( i ).getComponent( ) ) ); result.add( type.cast( l.get( i ).getComponent( ) ) );
} }
@ -219,7 +219,7 @@ public class ComponentRegistry
} }
public ComponentRegistry register( Collection< NewComponentInfo< ? > > components ) public ComponentRegistry register( final Collection< NewComponentInfo< ? > > components )
throws ComponentCreationException , DuplicateComponentException , RecursiveDependenciesException , throws ComponentCreationException , DuplicateComponentException , RecursiveDependenciesException ,
DependencyInjectionException , AmbiguousComponentException , ComponentInitialisationException , DependencyInjectionException , AmbiguousComponentException , ComponentInitialisationException ,
ComponentStartupException ComponentStartupException
@ -229,23 +229,23 @@ public class ComponentRegistry
} }
// Create "raw" state records for the new components // Create "raw" state records for the new components
int nAdd = components.size( ); final int nAdd = components.size( );
int nLeft = nAdd; int nLeft = nAdd;
ArrayList< TempBuildRec > adding = new ArrayList< >( nAdd ); final ArrayList< TempBuildRec > adding = new ArrayList< >( nAdd );
for ( NewComponentInfo< ? > nci : components ) { for ( final NewComponentInfo< ? > nci : components ) {
adding.add( new TempBuildRec( nci ) ); adding.add( new TempBuildRec( nci ) );
} }
// Create the registry's new state // Create the registry's new state
ArrayList< ComponentState > nComponents = new ArrayList< >( this.components ); final ArrayList< ComponentState > nComponents = new ArrayList< >( this.components );
HashMap< String , ComponentState > byName = new HashMap< >( this.byName ); final HashMap< String , ComponentState > byName = new HashMap< >( this.byName );
HashMap< Class< ? > , ArrayList< ComponentState > > byType = new HashMap< >( this.byType ); final HashMap< Class< ? > , ArrayList< ComponentState > > byType = new HashMap< >( this.byType );
// Add all new components whose dependencies are satisfied. Stop when there are no new components left. If there // Add all new components whose dependencies are satisfied. Stop when there are no new components left. If there
// are components left in the input list but no component can be added, it means there are some circular // are components left in the input list but no component can be added, it means there are some circular
// dependencies. // dependencies.
while ( nLeft > 0 ) { while ( nLeft > 0 ) {
int found = resolveNewDependencies( adding , nComponents , byName , byType ); final int found = ComponentRegistry.resolveNewDependencies( adding , nComponents , byName , byType );
if ( found == 0 ) { if ( found == 0 ) {
throw new RecursiveDependenciesException( adding.stream( ) // throw new RecursiveDependenciesException( adding.stream( ) //
.filter( r -> !r.added ) // .filter( r -> !r.added ) //
@ -257,27 +257,27 @@ public class ComponentRegistry
// Set up driver components // Set up driver components
for ( int i = 0 ; i < nAdd ; i++ ) { for ( int i = 0 ; i < nAdd ; i++ ) {
TempBuildRec c = adding.get( i ); final TempBuildRec c = adding.get( i );
String df = c.info.getDriverFor( ); final String df = c.info.getDriverFor( );
if ( df != null ) { if ( df != null ) {
c.state.setDriverFor( byName.get( df ) ); c.state.setDriverFor( byName.get( df ) );
} }
} }
// Inject and track dependencies // Inject and track dependencies
injectDependencies( adding ); ComponentRegistry.injectDependencies( adding );
// Replace registry contents // Replace registry contents
int nOld = this.components.size( ); final int nOld = this.components.size( );
this.components = nComponents; this.components = nComponents;
this.byName = byName; this.byName = byName;
this.byType = byType; this.byType = byType;
// Update singleton classes // Update singleton classes
for ( SingletonClass sc : this.singletonClasses.values( ) ) { for ( final SingletonClass sc : this.singletonClasses.values( ) ) {
try { try {
this.fillSingletonFields( sc ); this.fillSingletonFields( sc );
} catch ( ComponentManagementException e ) { } catch ( final ComponentManagementException e ) {
this.failed = true; this.failed = true;
throw e; throw e;
} }
@ -286,14 +286,14 @@ public class ComponentRegistry
// Initialise all new components if the registry has been initialised // Initialise all new components if the registry has been initialised
if ( this.initialised ) { if ( this.initialised ) {
for ( int i = nOld ; i < nOld + nAdd ; i++ ) { for ( int i = nOld ; i < nOld + nAdd ; i++ ) {
initComponent( i ); this.initComponent( i );
} }
} }
// Activate autostart components // Activate autostart components
if ( this.active ) { if ( this.active ) {
for ( int i = 0 ; i < nOld + nAdd ; i++ ) { for ( int i = 0 ; i < nOld + nAdd ; i++ ) {
autostartComponent( i ); this.autostartComponent( i );
} }
} }
@ -311,9 +311,9 @@ public class ComponentRegistry
return; return;
} }
int nComponents = this.components.size( ); final int nComponents = this.components.size( );
for ( int i = 0 ; i < nComponents ; i++ ) { for ( int i = 0 ; i < nComponents ; i++ ) {
initComponent( i ); this.initComponent( i );
} }
this.initialised = true; this.initialised = true;
@ -332,7 +332,7 @@ public class ComponentRegistry
this.stop( ); this.stop( );
for ( int i = this.components.size( ) - 1 ; i >= 0 ; i-- ) { for ( int i = this.components.size( ) - 1 ; i >= 0 ; i-- ) {
destroyComponent( i ); this.destroyComponent( i );
} }
this.initialised = false; this.initialised = false;
} }
@ -351,9 +351,9 @@ public class ComponentRegistry
return; return;
} }
int nComponents = this.components.size( ); final int nComponents = this.components.size( );
for ( int i = 0 ; i < nComponents ; i++ ) { for ( int i = 0 ; i < nComponents ; i++ ) {
autostartComponent( i ); this.autostartComponent( i );
} }
this.initialised = true; this.initialised = true;
} }
@ -370,18 +370,18 @@ public class ComponentRegistry
} }
for ( int i = this.components.size( ) - 1 ; i >= 0 ; i-- ) { for ( int i = this.components.size( ) - 1 ; i >= 0 ; i-- ) {
stopComponent( i ); this.stopComponent( i );
} }
this.active = false; this.active = false;
} }
private void fillSingletonFields( SingletonClass info ) private void fillSingletonFields( final SingletonClass info )
throws ComponentManagementException , AmbiguousComponentException throws ComponentManagementException , AmbiguousComponentException
{ {
HashMap< Field , Object > matches = new HashMap< >( ); final HashMap< Field , Object > matches = new HashMap< >( );
for ( Field fld : info.missingFields ) { for ( final Field fld : info.missingFields ) {
ComponentSingleton cs = fld.getAnnotation( ComponentSingleton.class ); final ComponentSingleton cs = fld.getAnnotation( ComponentSingleton.class );
ComponentState target; ComponentState target;
if ( "".equals( cs.value( ) ) ) { if ( "".equals( cs.value( ) ) ) {
target = this.getState( fld.getType( ) ); target = this.getState( fld.getType( ) );
@ -397,10 +397,10 @@ public class ComponentRegistry
return; return;
} }
for ( Map.Entry< Field , Object > entry : matches.entrySet( ) ) { for ( final Map.Entry< Field , Object > entry : matches.entrySet( ) ) {
try { try {
entry.getKey( ).set( null , entry.getValue( ) ); entry.getKey( ).set( null , entry.getValue( ) );
} catch ( IllegalAccessException e ) { } catch ( final IllegalAccessException e ) {
throw new ComponentManagementException( "internal error while setting singleton" , e ); throw new ComponentManagementException( "internal error while setting singleton" , e );
} }
} }
@ -409,30 +409,30 @@ public class ComponentRegistry
} }
private static int resolveNewDependencies( ArrayList< TempBuildRec > adding , private static int resolveNewDependencies( final ArrayList< TempBuildRec > adding ,
ArrayList< ComponentState > nComponents , HashMap< String , ComponentState > byName , final ArrayList< ComponentState > nComponents , final HashMap< String , ComponentState > byName ,
HashMap< Class< ? > , ArrayList< ComponentState > > byType ) final HashMap< Class< ? > , ArrayList< ComponentState > > byType )
throws AmbiguousComponentException , DuplicateComponentException throws AmbiguousComponentException , DuplicateComponentException
{ {
int size = adding.size( ); final int size = adding.size( );
int found = 0; int found = 0;
for ( int i = 0 ; i < size ; i++ ) { for ( int i = 0 ; i < size ; i++ ) {
TempBuildRec rec = adding.get( i ); final TempBuildRec rec = adding.get( i );
if ( rec.added || !checkDependencies( byName , byType , rec ) ) { if ( rec.added || !ComponentRegistry.checkDependencies( byName , byType , rec ) ) {
continue; continue;
} }
// Add the component // Add the component
found++; found++;
nComponents.add( rec.state ); nComponents.add( rec.state );
String name = rec.state.getName( ); final String name = rec.state.getName( );
if ( name != null ) { if ( name != null ) {
if ( byName.put( name , rec.state ) != null ) { if ( byName.put( name , rec.state ) != null ) {
throw new DuplicateComponentException( name ); throw new DuplicateComponentException( name );
} }
} }
for ( Class< ? > cls : Classes.getAllTypes( rec.state.getComponent( ).getClass( ) ) ) { for ( final Class< ? > cls : Classes.getAllTypes( rec.state.getComponent( ).getClass( ) ) ) {
if ( cls == Object.class ) { if ( cls == Object.class ) {
continue; continue;
} }
@ -450,12 +450,12 @@ public class ComponentRegistry
} }
private static boolean checkDependencies( HashMap< String , ComponentState > byName , private static boolean checkDependencies( final HashMap< String , ComponentState > byName ,
HashMap< Class< ? > , ArrayList< ComponentState > > byType , TempBuildRec rec ) final HashMap< Class< ? > , ArrayList< ComponentState > > byType , final TempBuildRec rec )
throws AmbiguousComponentException throws AmbiguousComponentException
{ {
boolean depsOk = true; boolean depsOk = true;
for ( DependencyInfo dep : rec.info.getDependencies( ) ) { for ( final DependencyInfo dep : rec.info.getDependencies( ) ) {
if ( rec.deps.containsKey( dep ) ) { if ( rec.deps.containsKey( dep ) ) {
continue; continue;
} }
@ -465,7 +465,7 @@ public class ComponentRegistry
cs = byName.get( dep.getTargetName( ) ); cs = byName.get( dep.getTargetName( ) );
continue; continue;
} else { } else {
ArrayList< ComponentState > lt = byType.get( dep.getTargetClass( ) ); final ArrayList< ComponentState > lt = byType.get( dep.getTargetClass( ) );
if ( lt == null ) { if ( lt == null ) {
cs = null; cs = null;
} else if ( lt.size( ) == 1 ) { } else if ( lt.size( ) == 1 ) {
@ -485,24 +485,24 @@ public class ComponentRegistry
} }
private static void injectDependencies( ArrayList< TempBuildRec > adding ) private static void injectDependencies( final ArrayList< TempBuildRec > adding )
throws DependencyInjectionException throws DependencyInjectionException
{ {
int size = adding.size( ); final int size = adding.size( );
for ( int i = 0 ; i < size ; i++ ) { for ( int i = 0 ; i < size ; i++ ) {
TempBuildRec rec = adding.get( i ); final TempBuildRec rec = adding.get( i );
Object cmp = rec.state.getComponent( ); final Object cmp = rec.state.getComponent( );
for ( Map.Entry< DependencyInfo , ArrayList< ThrowingBiConsumer< Object , Object > > > di : rec.info for ( final Map.Entry< DependencyInfo , ArrayList< ThrowingBiConsumer< Object , Object > > > di : rec.info
.getInjectors( ).entrySet( ) ) { .getInjectors( ).entrySet( ) ) {
ComponentState toInject = rec.deps.get( di.getKey( ) ); final ComponentState toInject = rec.deps.get( di.getKey( ) );
assert toInject != null; assert toInject != null;
for ( ThrowingBiConsumer< Object , Object > action : di.getValue( ) ) { for ( final ThrowingBiConsumer< Object , Object > action : di.getValue( ) ) {
try { try {
action.accept( cmp , toInject.getComponent( ) ); action.accept( cmp , toInject.getComponent( ) );
} catch ( FunctionException e ) { } catch ( final FunctionException e ) {
throw new DependencyInjectionException( rec.state , toInject , e.getCause( ) ); throw new DependencyInjectionException( rec.state , toInject , e.getCause( ) );
} catch ( RuntimeException e ) { } catch ( final RuntimeException e ) {
throw new DependencyInjectionException( rec.state , toInject , e ); throw new DependencyInjectionException( rec.state , toInject , e );
} }
} }
@ -510,59 +510,59 @@ public class ComponentRegistry
} }
for ( int i = 0 ; i < size ; i++ ) { for ( int i = 0 ; i < size ; i++ ) {
TempBuildRec rec = adding.get( i ); final TempBuildRec rec = adding.get( i );
for ( ComponentState dep : rec.deps.values( ) ) { for ( final ComponentState dep : rec.deps.values( ) ) {
rec.state.addDependency( dep ); rec.state.addDependency( dep );
} }
} }
} }
private void initComponent( int index ) private void initComponent( final int index )
throws ComponentInitialisationException throws ComponentInitialisationException
{ {
try { try {
this.components.get( index ).init( ); this.components.get( index ).init( );
} catch ( RuntimeException e ) { } catch ( final RuntimeException e ) {
this.failed = true; this.failed = true;
throw e; throw e;
} }
} }
private void autostartComponent( int index ) private void autostartComponent( final int index )
throws ComponentStartupException throws ComponentStartupException
{ {
try { try {
ComponentState cmp = this.components.get( index ); final ComponentState cmp = this.components.get( index );
if ( cmp.hasAutostart( ) ) { if ( cmp.hasAutostart( ) ) {
cmp.start( ); cmp.start( );
} }
} catch ( RuntimeException e ) { } catch ( final RuntimeException e ) {
this.failed = true; this.failed = true;
throw e; throw e;
} }
} }
private void stopComponent( int index ) private void stopComponent( final int index )
throws ComponentDestructionException throws ComponentDestructionException
{ {
try { try {
this.components.get( index ).stop( ); this.components.get( index ).stop( );
} catch ( RuntimeException e ) { } catch ( final RuntimeException e ) {
this.failed = true; this.failed = true;
throw e; throw e;
} }
} }
private void destroyComponent( int index ) private void destroyComponent( final int index )
throws ComponentDestructionException throws ComponentDestructionException
{ {
try { try {
this.components.get( index ).destroy( ); this.components.get( index ).destroy( );
} catch ( RuntimeException e ) { } catch ( final RuntimeException e ) {
this.failed = true; this.failed = true;
throw e; throw e;
} }