Leo Simons wrote:

>>>Other important points are that a extension provider can 
>>>declare its own 
>>>phase dependencies and also classic service dependencies.  
>>>Merlin will 
>>>take care of the ordering of component establishment based on 
>>>the phase 
>>>and service dependencies that the component publishes. 
>>>
>>>Extension providers must implement the following interface:
>>>
>>>    org.apache.excalibur.merlin.assembly.resource.Extension
>>>
>>>The interface declares the operation "extend( int stage, 
>>>Object object, 
>>>Context context ) which will be invoked by the Merlin 
>>>container during 
>>>the appropriate stages.  Merlin defines a number of stages 
>>>that can be 
>>>associated with an extension provider.  Merlin will only 
>>>invoke extend 
>>>if the provider declares that it supports the particular stage.
>>>
>>>Standard stages include the following:
>>>
>>>   CREATE    invoked immediately before initialization
>>>   ACCESS    invoked immediate before lookup
>>>   RELEASE   invoked immediately before release
>>>   DESTROY   invoked immediately before dispose
>>>   INNER     equivalent to ACCESS + RELEASE
>>>   OUTER     equivalinet to CREATE + DESTROY
>>>   ALL       equivalent to INNER + OUTER
>>>      
>>>
>>:/
>>
>>I kind of like Marcus' solution a bit better.  We have simple
>>methods that have a specific meaning.  If a lifecycle event happens
>>on more than one type of use (create/destroy/access/release),
>>the implementor has the freedom to use OO principles more clearly
>>by encapsulating the common elements in a separate method.
>>    
>>
>
>what we have here is the flexibility vs simplicity problem.
>
>we could replace all lifecycle interfaces with
>
>public interface LifecycleEnabled
>{
>       // default stages
>       public final static String STAGE_ENABLE_LOGGING = "LogEnabled";
>       public final static String STAGE_CONFIGURE = "Configurable";
>       public final static String STAGE_START = "Start";
>       public final static String STAGE_STOP = "Stop";
>       // ...
>
>       handleStage( String phase, Object parameters )
>                       throws LifecycleException;
>}
>
>public abstract class AbstractLifecycleEnabled
>               implements LifecycleEnabled
>{
>       public Object handleStage( String phase, Object[] parameters )
>                       throws LifecycleException
>       {
>               switch(phase)
>               {
>                       case STAGE_ENABLE_LOGGING:
>                          logEnabled( (Logger)parameters[0] );
>                          return null;
>                       case STAGE_CONFIGURE:
>                          configure( (Configuration)parameters[0] );
>                          return null;
>                       default:
>                          return ExtensionManager.handleStage( this,
>                                       phase, parameters );
>               }
>       }
>
>       abstract void logEnabled( Logger logger );
>       abstract void configure( Configuration configuration );
>}
>
>public NoopLifecycleEnabled
>{
>       void logEnabled( Logger logger ) {}
>       void configure( Configuration configuration ) {}
>}
>
>public MyComponent extends NoopLifecycleEnabled
>{
>       void configure( Configuration configuration )
>       {
>               // do stuff
>       }
>}
>
>which would make working with the standard lifecycle somewhat more
>complex but extension easier. It is a matter of where to put the
>complexity I guess.
>I like Marcus' version as writing an extension is more similar to
>writing a component that way. To follow this line of thought completely
>it should probably be something like:
>
>class PersistentConfigurableHandler implements
>               CreationExtensionHandler, DestructionExtensionHandler
>{
>     /** By contract, Other methods are only called if this returns
>        true. This is defined in ExtensionHandler, the common
>        superinterface to the implemented interfaces. */
>     boolean accept( Object obj )
>     {
>          if( obj instanceof PersistantConfigurable )
>               return true;
>
>          return false;
>     }
>
>     /** from CreationExtensionHandler */
>     void create( Object component, Context context )
>            throws PersistentConfigurationException
>     {
>       ((PersistantConfigurable)component).configure(
>               (Configuration)context.get("configuration" ) );
>     }
>     /** from DestructionExtensionHandler */
>     void destroy( Object component, Context context )
>            throws PersistentConfigurationException
>     {
>       Configuration = ((PersistantConfigurable)component)
>                       .saveConfiguration();
>     }
>}
>
>which would make it the extension setup even more similar to the
>'normal' avalon framework lifecycle.
>

The last example was was I was imagining while building the 
implementation - except I don't agree with the accept method becuase the 
extension has already declared that it supports objects implementing the 
particular lifecycle interface relative to a particular set of stages.

At the end of the day you can break this down into the following four 
interfaces:

    interface Creator
    {
         void create( Object object, Context context );
    }

    interface Destroyer
    {
         void destroy( Object );
    }

    interface Accessor
    {
         void access( Object object );
    }

    interface Releaser
    {
         void release( Object object );
    }

About the only functional difference between the above and what Marcus 
has proposed is that I'm only passing context once - on the creation stage.

Cheers, Steve.





--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to