Skip to Content.
Sympa Menu

notify-dpml - svn commit: r2296 - in development/main/metro: . composition/builder/src/main/net/dpml/composition/builder composition/control/src/main/net/dpml/composition/control composition/testing/activity composition/testing/activity/src/main/net/dpml/test composition/testing/activity/src/test/net/dpml/test meta/api/src/main/net/dpml/meta/info state state/src state/src/main state/src/main/net state/src/main/net/dpml state/src/main/net/dpml/state

notify-dpml AT lists.ibiblio.org

Subject: DPML Notify

List archive

Chronological Thread  
  • From: mcconnell AT dpml.net
  • To: notify-dpml AT lists.ibiblio.org
  • Subject: svn commit: r2296 - in development/main/metro: . composition/builder/src/main/net/dpml/composition/builder composition/control/src/main/net/dpml/composition/control composition/testing/activity composition/testing/activity/src/main/net/dpml/test composition/testing/activity/src/test/net/dpml/test meta/api/src/main/net/dpml/meta/info state state/src state/src/main state/src/main/net state/src/main/net/dpml state/src/main/net/dpml/state
  • Date: Sun, 17 Apr 2005 01:23:28 -0400

Author: mcconnell AT dpml.net
Date: Sun Apr 17 01:23:25 2005
New Revision: 2296

Added:

development/main/metro/composition/control/src/main/net/dpml/composition/control/StateInvocationHandler.java

development/main/metro/composition/control/src/main/net/dpml/composition/control/StateManagerInvocationHandler.java

development/main/metro/composition/testing/activity/src/main/net/dpml/test/Component.java
- copied, changed from r2295,
development/main/metro/composition/testing/activity/src/main/net/dpml/test/ActivityComponent.java

development/main/metro/composition/testing/activity/src/main/net/dpml/test/Container.java

development/main/metro/composition/testing/activity/src/test/net/dpml/test/ComponentTestCase.java
- copied, changed from r2295,
development/main/metro/composition/testing/activity/src/test/net/dpml/test/ActivityTestCase.java

development/main/metro/composition/testing/activity/src/test/net/dpml/test/ContainerTestCase.java
development/main/metro/state/
development/main/metro/state/build.xml
development/main/metro/state/src/
development/main/metro/state/src/main/
development/main/metro/state/src/main/net/
development/main/metro/state/src/main/net/dpml/
development/main/metro/state/src/main/net/dpml/state/

development/main/metro/state/src/main/net/dpml/state/NoSuchTransitionException.java
development/main/metro/state/src/main/net/dpml/state/State.java
development/main/metro/state/src/main/net/dpml/state/StateManager.java
Removed:

development/main/metro/composition/testing/activity/src/main/net/dpml/test/ActivityComponent.java

development/main/metro/composition/testing/activity/src/test/net/dpml/test/ActivityTestCase.java
Modified:

development/main/metro/composition/builder/src/main/net/dpml/composition/builder/TypeBuilderTask.java

development/main/metro/composition/control/src/main/net/dpml/composition/control/PartsInvocationHandler.java
development/main/metro/composition/testing/activity/ (props changed)
development/main/metro/composition/testing/activity/build.xml
development/main/metro/index.xml

development/main/metro/meta/api/src/main/net/dpml/meta/info/PartDescriptor.java
Log:
Add support for state management.

Modified:
development/main/metro/composition/builder/src/main/net/dpml/composition/builder/TypeBuilderTask.java
==============================================================================
---
development/main/metro/composition/builder/src/main/net/dpml/composition/builder/TypeBuilderTask.java
(original)
+++
development/main/metro/composition/builder/src/main/net/dpml/composition/builder/TypeBuilderTask.java
Sun Apr 17 01:23:25 2005
@@ -68,6 +68,7 @@
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Path;

+import net.dpml.state.StateManager;

/**
* The TypeTask creates a serialized descriptor of a component type.
@@ -562,7 +563,7 @@
{
validateNoExceptions( method );
Class returnType = method.getReturnType();
- validateNonNullReturnType( method, returnType );
+ validateNonNullReturnType( method );
validateNonArrayReturnType( method, returnType );
String type = returnType.getName();
String postfix = PartDescriptor.getPartPostfix( method );
@@ -571,6 +572,11 @@
validateEntryReturnType( method );
validateAtMostOneParameter( method );
}
+ if( PartDescriptor.STATE_MANAGER_KEY.equals( postfix ) )
+ {
+ validateNonNullReturnType( method );
+ validateAtMostOneParameter( method );
+ }
else if( PartDescriptor.PARTS_MAP_KEY.equals( postfix ) ||
PartDescriptor.CONTEXT_MAP_KEY.equals( postfix ) )
{
validateMapReturnType( method );
@@ -683,7 +689,7 @@
// required context entry
//

- validateNonNullReturnType( method, returnType );
+ validateNonNullReturnType( method );
validateNonArrayReturnType( method, returnType );
String type = returnType.getName();
return new EntryDescriptor( key, type, EntryDescriptor.REQUIRED
);
@@ -811,9 +817,10 @@
}


- private void validateNonNullReturnType( Method method, Class returnType
)
+ private void validateNonNullReturnType( Method method )
throws IntrospectionException
{
+ Class returnType = method.getReturnType();
if( Void.TYPE.equals( returnType ) )
{
final String error =

Modified:
development/main/metro/composition/control/src/main/net/dpml/composition/control/PartsInvocationHandler.java
==============================================================================
---
development/main/metro/composition/control/src/main/net/dpml/composition/control/PartsInvocationHandler.java
(original)
+++
development/main/metro/composition/control/src/main/net/dpml/composition/control/PartsInvocationHandler.java
Sun Apr 17 01:23:25 2005
@@ -43,6 +43,8 @@

import net.dpml.system.SystemContext;

+import net.dpml.state.StateManager;
+
/**
* The parts invocation handler maps client request for 'get', 'create' and
* 'release' relative to keys identified by the method name. Method name
@@ -235,7 +237,12 @@
// later
//

- throw new UnsupportedOperationException(
method.getName() );
+ final String error =
+ "Dynamic creation of context managers for foreign
object types is not supported."
+ + "\nClass: " + provider.getClass().getName()
+ + "\nKey: " + provider.getKey()
+ + "Instance: " + m_holder.getURI();
+ throw new UnsupportedOperationException( error );
}

CompositionModel model = (CompositionModel) provider;
@@ -247,6 +254,40 @@
new ContextManagerInvocationHandler( system, holder );
return Proxy.newProxyInstance( classloader, new Class[]{
clazz }, handler );
}
+ else if( PartDescriptor.STATE_MANAGER_KEY.equals( postfix ) )
+ {
+ if( false == ( provider instanceof CompositionModel ) )
+ {
+ //
+ // TODO: we could construct a state manager with no
+ // visible state entries - but let's leave that till
+ // later
+ //
+
+ final String error =
+ "Dynamic creation of state managers for foreign object
types is not supported."
+ + "\nClass: " + provider.getClass().getName()
+ + "\nKey: " + provider.getKey()
+ + "Instance: " + m_holder.getURI();
+ throw new UnsupportedOperationException( error );
+ }
+
+ CompositionModel model = (CompositionModel) provider;
+ Controller controller = model.getController();
+ Holder holder = getHolder( model, args );
+ Object manager = holder.getProcessController();
+ if( null == manager )
+ {
+ return new
StateManagerInvocationHandler.NullStateManager();
+ }
+ else
+ {
+ ClassLoader classloader = model.getClassLoader();
+ StateManagerInvocationHandler handler =
+ new StateManagerInvocationHandler( holder );
+ return Proxy.newProxyInstance( classloader, new Class[]{
StateManager.class }, handler );
+ }
+ }
else if( PartDescriptor.PARTS_MANAGER_KEY.equals( postfix )
|| PartDescriptor.PARTS_MAP_KEY.equals( postfix ) )
{

Added:
development/main/metro/composition/control/src/main/net/dpml/composition/control/StateInvocationHandler.java
==============================================================================
--- (empty file)
+++
development/main/metro/composition/control/src/main/net/dpml/composition/control/StateInvocationHandler.java
Sun Apr 17 01:23:25 2005
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2004 Stephen J. McConnell.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.composition.control;
+
+import java.net.URI;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.ArrayList;
+
+import net.dpml.composition.models.Holder;
+
+import net.dpml.state.NoSuchTransitionException;
+
+/**
+ * This makes a dynamic proxy for an object. The object can be represented
+ * by one, some or all of it's interfaces.
+ *
+ * @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
+ * @version $Id: ApplianceInvocationHandler.java 2106 2005-03-21 18:46:10Z
mcconnell AT dpml.net $
+ */
+final class StateInvocationHandler implements InvocationHandler
+{
+ //-------------------------------------------------------------------
+ // state
+ //-------------------------------------------------------------------
+
+ private final Holder m_holder;
+ private final String[] m_transitions;
+ private final String m_name;
+
+ //-------------------------------------------------------------------
+ // constructor
+ //-------------------------------------------------------------------
+
+ /**
+ * Create a new state manager invocation handler.
+ *
+ * @param system the system context
+ * @param model the component model
+ */
+ StateInvocationHandler( Holder holder, Object state )
+ {
+ if( null == state )
+ {
+ throw new NullPointerException( "state" );
+ }
+ m_holder = holder;
+ Class c = state.getClass();
+ m_transitions = getTransitions( c );
+ m_name = getName( c );
+ }
+
+ //-------------------------------------------------------------------
+ // implementation
+ //-------------------------------------------------------------------
+
+ /**
+ * Invoke the specified method on underlying object.
+ * This is called by the proxy object.
+ *
+ * @param proxy the proxy object
+ * @param method the method invoked on proxy object
+ * @param args the arguments supplied to method
+ * @return the return value of method
+ * @throws Throwable if an error occurs
+ */
+ public Object invoke( final Object proxy, final Method method, final
Object[] args )
+ throws Throwable
+ {
+ String name = method.getName();
+ Class source = method.getDeclaringClass();
+ if( Object.class == method.getDeclaringClass() )
+ {
+ return method.invoke( this, args );
+ }
+ else
+ {
+ if( "getName".equals( name ) )
+ {
+ return m_name;
+ }
+ else if( "getTransitions".equals( name ) )
+ {
+ return m_transitions;
+ }
+ else
+ {
+ final String error =
+ "The requested operation is not recognized."
+ + "\nOperation: " + name
+ + "\nState: " + m_name
+ + "\nInstance: " + m_holder.getURI();
+ throw new UnsupportedOperationException( error );
+ }
+ }
+ }
+
+ public static String[] getTransitions( Class state )
+ {
+ if( null == state )
+ {
+ return new String[0];
+ }
+ List list = new ArrayList();
+ Method[] methods = state.getMethods();
+ for( int i=0; i<methods.length; i++ )
+ {
+ Method method = methods[i];
+ if( method.getDeclaringClass() != Object.class )
+ {
+ String name = method.getName();
+ Class returnType = method.getReturnType();
+ Class[] params = method.getParameterTypes();
+ if(( null != returnType ) && ( params.length == 1 ) &&
!name.startsWith( "get" ) )
+ {
+ String transition = method.getName();
+ list.add( transition );
+ }
+ }
+ }
+ return (String[]) list.toArray( new String[0] );
+ }
+
+ public static Method getTransitionMethod( Class type, Class state,
String key )
+ {
+ try
+ {
+ Method method = state.getMethod( key, new Class[]{ type } );
+ String name = method.getName();
+ if( name.startsWith( "get" ) )
+ {
+ throw new NoSuchTransitionException( key );
+ }
+ else if( null == method.getReturnType() )
+ {
+ throw new NoSuchTransitionException( key );
+ }
+ else
+ {
+ return method;
+ }
+ }
+ catch( NoSuchMethodException e )
+ {
+ throw new NoSuchTransitionException( key );
+ }
+ }
+
+ private static String getName( Class state )
+ {
+ if( null == state )
+ {
+ throw new NullPointerException( "state" );
+ }
+ String name = state.getName();
+ String s = trimToLastClass( name );
+ return formatKey( s );
+ }
+
+ private static String trimToLastClass( String name )
+ {
+ int n = name.indexOf( "$" );
+ if( name.indexOf( "$" ) > -1 )
+ {
+ String s = name.substring( n + 1 );
+ return s.replace( '$', '.' );
+ }
+ else
+ {
+ int j = name.lastIndexOf( "." );
+ if( j == -1 )
+ {
+ return name;
+ }
+ else if( name.length() > j )
+ {
+ return name.substring( j+1 );
+ }
+ else
+ {
+ return name;
+ }
+ }
+ }
+
+ private static String formatKey( String name )
+ {
+ if( name.length() < 1 )
+ {
+ throw new IllegalArgumentException( "name" );
+ }
+ String first = name.substring( 0, 1 ).toLowerCase();
+ String remainder = name.substring( 1 );
+ return first + remainder;
+ }
+
+}

Added:
development/main/metro/composition/control/src/main/net/dpml/composition/control/StateManagerInvocationHandler.java
==============================================================================
--- (empty file)
+++
development/main/metro/composition/control/src/main/net/dpml/composition/control/StateManagerInvocationHandler.java
Sun Apr 17 01:23:25 2005
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2004 Stephen J. McConnell.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.composition.control;
+
+import java.net.URI;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import net.dpml.activity.Executable;
+import net.dpml.activity.Startable;
+import net.dpml.activity.Disposable;
+
+import net.dpml.composition.models.Holder;
+import net.dpml.composition.data.ValueDirective;
+
+import net.dpml.system.SystemContext;
+
+import net.dpml.state.State;
+import net.dpml.state.StateManager;
+import net.dpml.state.NoSuchTransitionException;
+
+/**
+ * This makes a dynamic proxy for an object. The object can be represented
+ * by one, some or all of it's interfaces.
+ *
+ * @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
+ * @version $Id: ApplianceInvocationHandler.java 2106 2005-03-21 18:46:10Z
mcconnell AT dpml.net $
+ */
+final class StateManagerInvocationHandler implements InvocationHandler
+{
+ //-------------------------------------------------------------------
+ // state
+ //-------------------------------------------------------------------
+
+ private final Holder m_holder;
+ private final Object m_control;
+ private final Class m_class;
+
+ //-------------------------------------------------------------------
+ // constructor
+ //-------------------------------------------------------------------
+
+ /**
+ * Create a new state manager invocation handler.
+ *
+ * @param system the system context
+ * @param model the component model
+ */
+ StateManagerInvocationHandler( Holder holder )
+ {
+ m_holder = holder;
+ m_control = holder.getProcessController();
+ if( null == m_control )
+ {
+ m_class = null;
+ }
+ else
+ {
+ m_class = m_control.getClass();
+ }
+ }
+
+ //-------------------------------------------------------------------
+ // implementation
+ //-------------------------------------------------------------------
+
+ private Class getControlClass()
+ {
+ return m_class;
+ }
+
+ private Method getInitializeMethod()
+ {
+ return getMethod( "initialize" );
+ }
+
+ private Method getTerminateMethod()
+ {
+ return getMethod( "terminate" );
+ }
+
+ private Method getStateMethod()
+ {
+ return getMethod( "getState" );
+ }
+
+ private Method getMethod( String name )
+ {
+ Class base = getControlClass();
+ if( null == base )
+ {
+ return null;
+ }
+ else
+ {
+ return getMethod( base, name );
+ }
+ }
+
+ private Method getMethod( Class base, String name )
+ {
+ if( null == base )
+ {
+ throw new NullPointerException( "base" );
+ }
+ if( null == name )
+ {
+ throw new NullPointerException( "name" );
+ }
+ try
+ {
+ return base.getMethod( name, new Class[0] );
+ }
+ catch( NoSuchMethodException e )
+ {
+ return null;
+ }
+ }
+
+ private Object getStateObject( Method method ) throws Exception
+ {
+ Method getState = getStateMethod();
+ if( null == getState )
+ {
+ return null;
+ }
+ else
+ {
+ return getState.invoke( m_control, new Object[0] );
+ }
+ }
+
+ /**
+ * Invoke the specified method on underlying object.
+ * This is called by the proxy object.
+ *
+ * @param proxy the proxy object
+ * @param method the method invoked on proxy object
+ * @param args the arguments supplied to method
+ * @return the return value of method
+ * @throws Throwable if an error occurs
+ * @exception NullPointerException if any one of the proxy or method
arguments
+ * is null, or if the object instance has been destroyed
earlier.
+ */
+ public Object invoke( final Object proxy, final Method method, final
Object[] args )
+ throws Throwable
+ {
+ String name = method.getName();
+ Class source = method.getDeclaringClass();
+ Class control = getControlClass();
+ if( Object.class == method.getDeclaringClass() )
+ {
+ return method.invoke( this, args );
+ }
+ else if( "initialize".equals( name ) )
+ {
+ Method initialize = getInitializeMethod();
+ if( null != initialize )
+ {
+ return initialize.invoke( m_control, new Object[0] );
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else if( "terminate".equals( name ) )
+ {
+ Method terminate = getTerminateMethod();
+ if( null != terminate )
+ {
+ return terminate.invoke( m_control, new Object[0] );
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else if( "getState".equals( name ) )
+ {
+ Object state = getStateObject( method );
+ if( null != state )
+ {
+ Class c = state.getClass();
+ if( State.class.isAssignableFrom( c ) )
+ {
+ return state;
+ }
+ else
+ {
+ StateInvocationHandler handler =
+ new StateInvocationHandler( m_holder, state );
+ ClassLoader classloader =
m_holder.getModel().getClassLoader();
+ return Proxy.newProxyInstance( classloader, new Class[]{
State.class }, handler );
+ }
+ }
+ else
+ {
+ return new Available();
+ }
+ }
+ else if( "apply".equals( name ) )
+ {
+ if( args.length < 1 )
+ {
+ final String error =
+ "Insuffient arguments to 'apply' operation."
+ + "\nMethod: " + name
+ + "\nArgs: " + args.length
+ + "\nInstance: " + m_holder.getURI();
+ throw new IllegalArgumentException( error );
+ }
+
+ Object arg = args[0];
+
+ if( false == ( arg instanceof String ) )
+ {
+ final String error =
+ "Transition argument is not a string."
+ + "\nMethod: " + name
+ + "\nInvalid Argument: " + arg.getClass().getName()
+ + "\nInstance: " + m_holder.getURI();
+ throw new IllegalArgumentException( error );
+ }
+
+ String key = (String) arg;
+ Object state = getStateObject( method );
+ if( null != state )
+ {
+ final String error =
+ "Cannot appply a transition to a stateless instance."
+ + "\nTransition: " + key
+ + "\nInstance: " + m_holder.getURI();
+ throw new IllegalArgumentException( error );
+ }
+ else if( args.length > 1 )
+ {
+ final String error =
+ "Multiarg apply not supported."
+ + "\nTransition: " + key
+ + "\nInstance: " + m_holder.getURI();
+ throw new UnsupportedOperationException( error );
+ }
+ else
+ {
+ Class stateClass = state.getClass();
+ Class type = m_holder.getModel().getDeploymentClass();
+ Method m = StateInvocationHandler.getTransitionMethod( type,
stateClass, key );
+ return m.invoke( state, new Object[0] );
+ }
+ }
+ else
+ {
+ final String error =
+ "The requested operation is not recognized."
+ + "\nOperation: " + name
+ + "\nInstance: " + m_holder.getURI();
+ throw new UnsupportedOperationException( error );
+ }
+ }
+
+ public static class Available implements State
+ {
+ public String getName()
+ {
+ return "available";
+ }
+ public String[] getTransitions()
+ {
+ return new String[0];
+ }
+ }
+
+ public static class SimpleStateManager implements StateManager
+ {
+ private static final State AVALIABLE = new Available();
+
+ private Object m_instance;
+ private boolean m_initialized = false;
+
+ public SimpleStateManager( Object instance )
+ {
+ m_instance = instance;
+ }
+
+ public void initialize() throws Exception
+ {
+ Class c = m_instance.getClass();
+ if( Executable.class.isAssignableFrom( c ) )
+ {
+ ((Executable)m_instance).execute();
+ }
+ else if( Startable.class.isAssignableFrom( c ) )
+ {
+ ((Startable)m_instance).start();
+ m_initialized = true;
+ }
+ }
+
+ public State getState()
+ {
+ return AVALIABLE;
+ }
+
+ public State apply( String transition )
+ {
+ throw new NoSuchTransitionException( transition );
+ }
+
+ public void terminate()
+ {
+ Class c = m_instance.getClass();
+ if( m_initialized && Startable.class.isAssignableFrom( c ) )
+ {
+ try
+ {
+ ((Startable)m_instance).stop();
+ }
+ catch( Throwable e )
+ {
+ // TODO: we need a monitor down here
+ }
+ }
+ if( Disposable.class.isAssignableFrom( c ) )
+ {
+ try
+ {
+ ((Disposable)m_instance).dispose();
+ }
+ catch( Throwable e )
+ {
+ // TODO: we need a monitor down here
+ }
+ }
+ }
+ }
+}

Modified: development/main/metro/composition/testing/activity/build.xml
==============================================================================
--- development/main/metro/composition/testing/activity/build.xml
(original)
+++ development/main/metro/composition/testing/activity/build.xml Sun
Apr 17 01:23:25 2005
@@ -9,19 +9,33 @@

<!-- create the component types -->
<types xmlns="plugin:dpml/composition/dpml-composition-builder">
- <type class="net.dpml.test.ActivityComponent"/>
+ <type class="net.dpml.test.Component"/>
+ <type class="net.dpml.test.Container"/>
</types>

<!-- creation of a component for reference by uri -->
<component xmlns="plugin:dpml/composition/dpml-composition-builder"
- type="net.dpml.test.ActivityComponent"
- name="test"/>
+ type="net.dpml.test.Container"
+ name="container">
+ <parts>
+ <component key="test" type="net.dpml.test.Component"/>
+ </parts>
+ </component>

- <!-- creation of a component for local testing -->
+ <!-- creation of the component part for local testing -->
<component xmlns="plugin:dpml/composition/dpml-composition-builder"
- type="net.dpml.test.ActivityComponent"
- name="test"
- dest="target/test/test.part"/>
+ type="net.dpml.test.Component"
+ name="component" dest="target/test/component.part"/>
+
+ <!-- creation of the container part for local testing -->
+ <component xmlns="plugin:dpml/composition/dpml-composition-builder"
+ type="net.dpml.test.Container"
+ name="container"
+ dest="target/test/container.part">
+ <parts>
+ <component key="test" type="net.dpml.test.Component"/>
+ </parts>
+ </component>

</target>


Copied:
development/main/metro/composition/testing/activity/src/main/net/dpml/test/Component.java
(from r2295,
development/main/metro/composition/testing/activity/src/main/net/dpml/test/ActivityComponent.java)
==============================================================================
---
development/main/metro/composition/testing/activity/src/main/net/dpml/test/ActivityComponent.java
(original)
+++
development/main/metro/composition/testing/activity/src/main/net/dpml/test/Component.java
Sun Apr 17 01:23:25 2005
@@ -32,7 +32,7 @@
*
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
*/
-public class ActivityComponent
+public class Component
{
//------------------------------------------------------------------
// static
@@ -55,7 +55,7 @@
*
* @param logger the logging channel assigned by the container
*/
- public ActivityComponent( final Logger logger )
+ public Component( final Logger logger )
{
m_logger = logger;
}
@@ -76,13 +76,13 @@
public static final State STOPPED = new Stopped();
public static final State TERMINATED = new Terminated();

- protected final ActivityComponent m_instance;
+ protected final Component m_instance;
protected final ChangeListener m_listener;
protected final Logger m_logger;

protected State m_state = AVAILABLE;

- public Controller( ActivityComponent instance, Logger logger,
ChangeListener listener )
+ public Controller( Component instance, Logger logger, ChangeListener
listener )
{
m_instance = instance;
m_listener = listener;
@@ -164,7 +164,7 @@

public static class Started extends Available
{
- public State stop( ActivityComponent activity )
+ public State stop( Component activity )
{
activity.stop();
return Controller.STOPPED;
@@ -173,7 +173,7 @@

public static class Stopped extends Available
{
- public State start( ActivityComponent activity )
+ public State start( Component activity )
{
activity.start();
return Controller.STARTED;

Added:
development/main/metro/composition/testing/activity/src/main/net/dpml/test/Container.java
==============================================================================
--- (empty file)
+++
development/main/metro/composition/testing/activity/src/main/net/dpml/test/Container.java
Sun Apr 17 01:23:25 2005
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.test;
+
+import java.util.logging.Logger;
+
+import net.dpml.activity.Executable;
+
+import net.dpml.state.StateManager;
+import net.dpml.state.State;
+
+/**
+ * Demonstration of a component that manages the state of a contained part.
+ *
+ * @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
+ */
+public class Container implements Executable
+{
+ //------------------------------------------------------------------
+ // static
+ //------------------------------------------------------------------
+
+ public static final boolean TYPE_THREADSAFE_CAPABLE = true;
+
+ //------------------------------------------------------------------
+ // state
+ //------------------------------------------------------------------
+
+ private final Logger m_logger;
+ private final Parts m_parts;
+
+ //------------------------------------------------------------------
+ // constructor
+ //------------------------------------------------------------------
+
+ /**
+ * Creation of a composite component. This implementation demonstrates
+ * access to parts within itself and invocation of service and non-service
+ * operations on its parts.
+ *
+ * @param logger the logging channel asign by the container
+ */
+ public Container( final Logger logger, Parts parts )
+ {
+ m_logger = logger;
+ m_parts = parts;
+ }
+
+ //------------------------------------------------------------------
+ // implementation
+ //------------------------------------------------------------------
+
+ public void execute() throws Exception
+ {
+ Parts parts = getParts();
+ StateManager manager = parts.selectTestStateManager();
+ State initial = manager.getState();
+ getLogger().info( "initial state is : " + initial.getName() );
+ manager.initialize();
+ State initialized = manager.getState();
+ getLogger().info( "initialized state is : " + initialized.getName()
);
+ String[] transitions = initialized.getTransitions();
+ for( int i=0; i<transitions.length; i++ )
+ {
+ getLogger().info( "transition : " + transitions[i] );
+ }
+ manager.terminate();
+ }
+
+ private Logger getLogger()
+ {
+ return m_logger;
+ }
+
+ private Parts getParts()
+ {
+ return m_parts;
+ }
+
+ //------------------------------------------------------------------
+ // concerns
+ //------------------------------------------------------------------
+
+ public interface Parts
+ {
+ StateManager selectTestStateManager();
+ Component selectTest();
+ }
+
+ private void debug( String message )
+ {
+ getLogger().fine( message );
+ }
+}

Copied:
development/main/metro/composition/testing/activity/src/test/net/dpml/test/ComponentTestCase.java
(from r2295,
development/main/metro/composition/testing/activity/src/test/net/dpml/test/ActivityTestCase.java)
==============================================================================
---
development/main/metro/composition/testing/activity/src/test/net/dpml/test/ActivityTestCase.java
(original)
+++
development/main/metro/composition/testing/activity/src/test/net/dpml/test/ComponentTestCase.java
Sun Apr 17 01:23:25 2005
@@ -38,7 +38,7 @@
* @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
* @version $Id: AbstractDescriptorTestCase.java 1556 2005-01-22 12:43:42Z
niclas $
*/
-public class ActivityTestCase extends TestCase
+public class ComponentTestCase extends TestCase
{
/**
* Test the construction of the example component and the invocation of
@@ -47,8 +47,8 @@
public void testManagedComponent() throws Exception
{
Holder holder = getComponentHolder();
- ActivityComponent.Controller manager =
- (ActivityComponent.Controller) holder.getProcessController();
+ Component.Controller manager =
+ (Component.Controller) holder.getProcessController();
manager.initialize();
Method[] transitions = getTransitions( manager );
for( int i=0; i<transitions.length; i++ )
@@ -60,7 +60,7 @@
holder.dispose();
}

- private Method[] getTransitions( ActivityComponent.Controller manager )
+ private Method[] getTransitions( Component.Controller manager )
{
List list = new ArrayList();
Method[] methods = manager.getState().getClass().getMethods();
@@ -81,8 +81,8 @@

Holder getComponentHolder() throws Exception
{
- CompositionHelper helper = new CompositionHelper( true );
- URI uri = helper.toURI( "test.part" );
+ CompositionHelper helper = new CompositionHelper( false );
+ URI uri = helper.toURI( "component.part" );
Model model = helper.getCompositionManager().getModel( uri );
return (Holder) helper.getCompositionManager().create( model );
}

Added:
development/main/metro/composition/testing/activity/src/test/net/dpml/test/ContainerTestCase.java
==============================================================================
--- (empty file)
+++
development/main/metro/composition/testing/activity/src/test/net/dpml/test/ContainerTestCase.java
Sun Apr 17 01:23:25 2005
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2004 Stephen J. McConnell.
+ * Copyright 1999-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.test;
+
+import java.net.URI;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Map.Entry;
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import net.dpml.automation.model.Model;
+import net.dpml.composition.unit.CompositionHelper;
+import net.dpml.composition.models.Holder;
+
+/**
+ * Test a simple component case.
+ *
+ * @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
+ * @version $Id: AbstractDescriptorTestCase.java 1556 2005-01-22 12:43:42Z
niclas $
+ */
+public class ContainerTestCase extends TestCase
+{
+ /**
+ * Test the construction of the example component and the invocation of
+ * an operation on the example service interface.
+ */
+ public void testContainer() throws Exception
+ {
+ CompositionHelper helper = new CompositionHelper( false );
+ URI uri = helper.toURI( "container.part" );
+ Model model = helper.getCompositionManager().getModel( uri );
+ Entry entry = helper.getCompositionManager().create( model );
+ Container container = (Container) entry.getValue();
+ container.execute();
+ }
+}
+
+

Modified: development/main/metro/index.xml
==============================================================================
--- development/main/metro/index.xml (original)
+++ development/main/metro/index.xml Sun Apr 17 01:23:25 2005
@@ -23,6 +23,20 @@
</dependencies>
</project>

+ <!-- State -->
+
+ <project basedir="state">
+ <info>
+ <group>dpml/metro/public</group>
+ <name>dpml-state-api</name>
+ <version>1.0.0</version>
+ <status>SNAPSHOT</status>
+ <types>
+ <type>jar</type>
+ </types>
+ </info>
+ </project>
+
<!-- Automation -->

<project basedir="automation/control">
@@ -444,6 +458,8 @@
</info>
<dependencies>
<include key="dpml-transit-main" tag="api"/>
+ <include key="dpml-state-api" tag="api"/>
+ <include key="dpml-activity-api" tag="api"/>
<include key="dpml-automation-control" tag="spi"/>
<include key="dpml-composition-api" tag="spi"/>
<include key="dpml-system-api" tag="spi"/>
@@ -526,6 +542,8 @@
</types>
</info>
<dependencies>
+ <include key="dpml-state-api"/>
+ <include key="dpml-activity-api"/>
<include key="dpml-composition-unit" runtime="false"/>
</dependencies>
<plugins>

Modified:
development/main/metro/meta/api/src/main/net/dpml/meta/info/PartDescriptor.java
==============================================================================
---
development/main/metro/meta/api/src/main/net/dpml/meta/info/PartDescriptor.java
(original)
+++
development/main/metro/meta/api/src/main/net/dpml/meta/info/PartDescriptor.java
Sun Apr 17 01:23:25 2005
@@ -69,6 +69,7 @@
public static final String CONTEXT_MANAGER_KEY = "ContextManager";
public static final String PARTS_MANAGER_KEY = "PartsManager";
public static final String PARTS_MAP_KEY = "PartsMap";
+ public static final String STATE_MANAGER_KEY = "StateManager";
public static final String ENTRY_KEY = "Entry";

public static String toString( int semantic )
@@ -110,6 +111,10 @@
{
return PARTS_MANAGER_KEY;
}
+ else if( name.endsWith( STATE_MANAGER_KEY ) )
+ {
+ return STATE_MANAGER_KEY;
+ }
else if( name.endsWith( PARTS_MAP_KEY ) )
{
return PARTS_MAP_KEY;
@@ -192,6 +197,13 @@
String substring = name.substring( 0, j );
return formatKey( substring, 6 );
}
+ else if( name.endsWith( STATE_MANAGER_KEY ) )
+ {
+ int n = STATE_MANAGER_KEY.length();
+ int j = name.length() - n;
+ String substring = name.substring( 0, j );
+ return formatKey( substring, 6 );
+ }
else if( name.endsWith( PARTS_MAP_KEY ) )
{
int n = PARTS_MAP_KEY.length();

Added: development/main/metro/state/build.xml
==============================================================================
--- (empty file)
+++ development/main/metro/state/build.xml Sun Apr 17 01:23:25 2005
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<project name="dpml-state-api" default="install" basedir="."
+ xmlns:transit="antlib:net.dpml.transit">
+
+ <transit:import uri="artifact:template:dpml/magic/standard"/>
+
+</project>

Added:
development/main/metro/state/src/main/net/dpml/state/NoSuchTransitionException.java
==============================================================================
--- (empty file)
+++
development/main/metro/state/src/main/net/dpml/state/NoSuchTransitionException.java
Sun Apr 17 01:23:25 2005
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.state;
+
+
+/**
+ * Exception thrown when a request is made to apply a transition that is
unknown
+ * relative to the target state.
+ *
+ * @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
+ */
+public class NoSuchTransitionException extends RuntimeException
+{
+ private String m_transition;
+
+ /**
+ * Construct a new <code>NoSuchTransitionException</code> instance.
+ *
+ * @param transition the transition name
+ */
+ public NoSuchTransitionException( final String transition )
+ {
+ super( transition );
+ }
+
+}
+

Added: development/main/metro/state/src/main/net/dpml/state/State.java
==============================================================================
--- (empty file)
+++ development/main/metro/state/src/main/net/dpml/state/State.java Sun
Apr 17 01:23:25 2005
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.state;
+
+/**
+ * The State interface is an interface representing an immutable state of
+ * a component instance.
+ *
+ * @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
+ */
+public interface State
+{
+ /**
+ * Return the name of the state.
+ * @return the state name
+ */
+ String getName();
+
+ /**
+ * Return the array of transition operations available under the state.
+ * @return the transition names
+ */
+ String[] getTransitions();
+}

Added: development/main/metro/state/src/main/net/dpml/state/StateManager.java
==============================================================================
--- (empty file)
+++ development/main/metro/state/src/main/net/dpml/state/StateManager.java
Sun Apr 17 01:23:25 2005
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2005 Stephen J. McConnell.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dpml.state;
+
+/**
+ * The StateManager interface is an interface representing a component
controller.
+ *
+ * @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
+ */
+public interface StateManager
+{
+ /**
+ * Initialize the component. If the component declares an inner
Controller
+ * class and if the class implements an "initialize" operation then
execution
+ * of the operation will be delegated to that method otherwise the method
+ * does nothing and returns.
+ */
+ void initialize() throws Exception;
+
+ /**
+ * If the component declares an inner Controller class and the class
+ * implements the getState method with Object return type, the current
+ * state will be derived from the short classname of the returned instance
+ * otherwise an empty state (i.e. a state with not transitions) will be
+ * returned.
+ */
+ State getState();
+
+ /**
+ * Termination of the component. If the component declares an inner
Controller
+ * class and if the class implements an "terminate" operation then
execution
+ * of the operation will be delegated to that method otherwise the method
+ * does nothing and returns.
+ */
+ void terminate();
+
+ /**
+ * Applies a state transition to the controller. If the transition
argument
+ * corresponds to a method name declared by the current state object
returned
+ * from $Controller.getState(), that method will be invoked. The object
retured
+ * from the operation will be evaluated as a state object thereby
establishing
+ * the available transitions. If the transition argument does not match
a method
+ * declared by the current state object exposed by the controller an
+ * IllegalArgumentException will be thrown.
+ *
+ * @param transition the name of a transition to apply to the component's
controller
+ * @return the state established by the transition
+ * @exception if a transition error occurs
+ */
+ State apply( String transition ) throws Exception;
+}



  • svn commit: r2296 - in development/main/metro: . composition/builder/src/main/net/dpml/composition/builder composition/control/src/main/net/dpml/composition/control composition/testing/activity composition/testing/activity/src/main/net/dpml/test composition/testing/activity/src/test/net/dpml/test meta/api/src/main/net/dpml/meta/info state state/src state/src/main state/src/main/net state/src/main/net/dpml state/src/main/net/dpml/state, mcconnell, 04/16/2005

Archive powered by MHonArc 2.6.24.

Top of Page