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]>