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