Skip to Content.
Sympa Menu

notify-dpml - svn commit: r2321 - in development/main/metro: composition/control/src/main/net/dpml/composition/control composition/testing/activity/src/main/net/dpml/test state/api/src/main/net/dpml/state state/impl/src/main/net/dpml/state/impl

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: r2321 - in development/main/metro: composition/control/src/main/net/dpml/composition/control composition/testing/activity/src/main/net/dpml/test state/api/src/main/net/dpml/state state/impl/src/main/net/dpml/state/impl
  • Date: Mon, 18 Apr 2005 23:58:41 -0400

Author: mcconnell AT dpml.net
Date: Mon Apr 18 23:58:38 2005
New Revision: 2321

Added:

development/main/metro/state/api/src/main/net/dpml/state/NoSuchOperationException.java
development/main/metro/state/api/src/main/net/dpml/state/Operation.java

development/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultOperation.java
Modified:

development/main/metro/composition/control/src/main/net/dpml/composition/control/LifecycleHandler.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

development/main/metro/composition/testing/activity/src/main/net/dpml/test/Container.java
development/main/metro/state/api/src/main/net/dpml/state/State.java
development/main/metro/state/api/src/main/net/dpml/state/StateManager.java

development/main/metro/state/impl/src/main/net/dpml/state/impl/AbstractStateManager.java

development/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultState.java
Log:
Add support in operations within the active state chain.

Modified:
development/main/metro/composition/control/src/main/net/dpml/composition/control/LifecycleHandler.java
==============================================================================
---
development/main/metro/composition/control/src/main/net/dpml/composition/control/LifecycleHandler.java
(original)
+++
development/main/metro/composition/control/src/main/net/dpml/composition/control/LifecycleHandler.java
Mon Apr 18 23:58:38 2005
@@ -184,6 +184,7 @@
URI uri = holder.getURI();

Class subject = model.getDeploymentClass();
+ Class parts = getInnerClass( subject, "$Parts" );
ClassLoader classloader = subject.getClassLoader();
Class control = getInnerClass( subject, "Controller" );
if( null == control )
@@ -207,6 +208,10 @@
{
args[i] =
model.getCompositionController().getLoggingChannel( model );
}
+ else if( ( null != parts ) && parts.isAssignableFrom( c ) )
+ {
+ args[i] = newPartsInvocationHandler( holder, parts );
+ }
else if( subject.isAssignableFrom( c ) )
{
args[i] = instance;

Modified:
development/main/metro/composition/control/src/main/net/dpml/composition/control/StateManagerInvocationHandler.java
==============================================================================
---
development/main/metro/composition/control/src/main/net/dpml/composition/control/StateManagerInvocationHandler.java
(original)
+++
development/main/metro/composition/control/src/main/net/dpml/composition/control/StateManagerInvocationHandler.java
Mon Apr 18 23:58:38 2005
@@ -37,7 +37,9 @@
import net.dpml.state.State;
import net.dpml.state.StateManager;
import net.dpml.state.Transition;
+import net.dpml.state.Operation;
import net.dpml.state.NoSuchTransitionException;
+import net.dpml.state.NoSuchOperationException;

import net.dpml.lang.DelegationRuntimeException;

@@ -100,7 +102,7 @@
return method.invoke( m_control, args );
}

- if( name.equals( "terminate" ) || name.equals( "terminate" ) )
+ if( name.equals( "initialize" ) || name.equals( "terminate" ) )
{
try
{
@@ -132,7 +134,7 @@
throw handleInvocationThrowable( method, e );
}
}
- else if( "apply".equals( name ) )
+ else if( "apply".equals( name ) || "execute".equals( name ) )
{
try
{
@@ -142,7 +144,9 @@
catch( NoSuchMethodException e )
{
final String error =
- "The apply method is not implemented."
+ "The "
+ + name
+ + " method is not implemented."
+ "\nOperation: " + name
+ "\nInstance: " + m_holder.getURI();
throw new UnsupportedOperationException( error );
@@ -213,18 +217,27 @@
{
return "available";
}
+
public String[] getTransitionNames()
{
return new String[0];
}
+
+ public Operation getOperation( String key )
+ {
+ throw new NoSuchOperationException( key );
+ }
+
public Transition getTransition( String key )
{
throw new NoSuchTransitionException( key );
}
+
public String list()
{
return "state:available";
}
+
public boolean isTerminal()
{
return true;
@@ -267,6 +280,11 @@
throw new NoSuchTransitionException( key );
}

+ public void execute( String key )
+ {
+ throw new NoSuchOperationException( key );
+ }
+
public void terminate()
{
Class c = m_instance.getClass();

Modified:
development/main/metro/composition/testing/activity/src/main/net/dpml/test/Component.java
==============================================================================
---
development/main/metro/composition/testing/activity/src/main/net/dpml/test/Component.java
(original)
+++
development/main/metro/composition/testing/activity/src/main/net/dpml/test/Component.java
Mon Apr 18 23:58:38 2005
@@ -122,6 +122,28 @@
getLogger().info( "stopping the component" );
}

+ //
+ // The following two methods are examples of methods invoked
+ // via operation declarations. Operations do not trigger state
+ // change - instead they are gaurded methods that become visible
+ // to a controlling application when the state to which the operation
+ // is assigned becomes visible in the active state chain.
+ //
+
+ public void audit( State state )
+ {
+ String listing = STATE.list();
+ String current = state.getName();
+ StringBuffer buffer = new StringBuffer( "Audit Report" );
+ buffer.append( "\n-------------------------------------------------"
);
+ buffer.append( "\nState Model:" );
+ buffer.append( "\nCurrent State: " + current );
+ buffer.append( "\n-------------------------------------------------"
);
+ buffer.append( listing );
+ buffer.append( "\n-------------------------------------------------"
);
+ getLogger().info( buffer.toString() );
+ }
+
// ------------------------------------------------------------------
// static utilities
// ------------------------------------------------------------------
@@ -165,6 +187,14 @@
initialized.addTransition( "start", new URI( "method:start" ),
started );
started.addTransition( "stop", new URI( "method:stop" ), stopped
);
stopped.addTransition( "start", new URI( "method:start" ),
started );
+
+ //
+ // add an operations that is only accessible in the active state
chain
+ // when the component is in the started state
+ //
+
+ started.addOperation( "audit", new URI( "method:audit" ) );
+
}
catch( URISyntaxException e )
{

Modified:
development/main/metro/composition/testing/activity/src/main/net/dpml/test/Container.java
==============================================================================
---
development/main/metro/composition/testing/activity/src/main/net/dpml/test/Container.java
(original)
+++
development/main/metro/composition/testing/activity/src/main/net/dpml/test/Container.java
Mon Apr 18 23:58:38 2005
@@ -19,6 +19,7 @@
package net.dpml.test;

import java.util.logging.Logger;
+import java.util.logging.Level;

import net.dpml.activity.Executable;
import net.dpml.state.State;
@@ -71,6 +72,7 @@
StateManager manager = parts.selectTestStateManager();
manager.initialize();
manager.apply( "start" );
+ manager.execute( "audit" );
manager.terminate();
}

@@ -88,6 +90,8 @@
// concerns
//------------------------------------------------------------------

+
+
public interface Parts
{
StateManager selectTestStateManager();

Added:
development/main/metro/state/api/src/main/net/dpml/state/NoSuchOperationException.java
==============================================================================
--- (empty file)
+++
development/main/metro/state/api/src/main/net/dpml/state/NoSuchOperationException.java
Mon Apr 18 23:58:38 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 for retrival of an operation
+ * via an operation key and the key is unresolvable.
+ *
+ * @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
+ */
+public class NoSuchOperationException extends RuntimeException
+{
+ private String m_key;
+
+ /**
+ * Construct a new <code>NoSuchOperationException</code> instance.
+ *
+ * @param key the operation key
+ */
+ public NoSuchOperationException( final String key )
+ {
+ super( key );
+ }
+
+}
+

Added: development/main/metro/state/api/src/main/net/dpml/state/Operation.java
==============================================================================
--- (empty file)
+++ development/main/metro/state/api/src/main/net/dpml/state/Operation.java
Mon Apr 18 23:58:38 2005
@@ -0,0 +1,33 @@
+/*
+ * 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 Operation interface is a base interface to actions executable withing
+ * scope of a state. An implementation of an operation must implement a
single
+ * "execute" method. Argument parameter applied to the execute method will
be
+ * resolved by the state manager relative to the runtime context and
declared
+ * parameter types.
+ *
+ * @author <a href="mailto:info AT dpml.net";>The Digital Product Meta
Library</a>
+ */
+public interface Operation
+{
+ // public void execute( .... ) throws Exception;
+}

Modified: development/main/metro/state/api/src/main/net/dpml/state/State.java
==============================================================================
--- development/main/metro/state/api/src/main/net/dpml/state/State.java
(original)
+++ development/main/metro/state/api/src/main/net/dpml/state/State.java Mon
Apr 18 23:58:38 2005
@@ -40,6 +40,12 @@
String[] getTransitionNames();

/**
+ * Return a named operation.
+ * @return the operation
+ */
+ Operation getOperation( String key );
+
+ /**
* Return a named transition.
* @return the transition
*/

Modified:
development/main/metro/state/api/src/main/net/dpml/state/StateManager.java
==============================================================================
---
development/main/metro/state/api/src/main/net/dpml/state/StateManager.java
(original)
+++
development/main/metro/state/api/src/main/net/dpml/state/StateManager.java
Mon Apr 18 23:58:38 2005
@@ -50,4 +50,13 @@
* @exception if a transition error occurs
*/
boolean apply( String key ) throws Exception;
+
+ /**
+ * Executes an operation identified by a supplied operation key.
+ *
+ * @param key the key identifying the operation to execute
+ * @exception if a transition error occurs
+ */
+ void execute( String key ) throws Exception;
+
}

Modified:
development/main/metro/state/impl/src/main/net/dpml/state/impl/AbstractStateManager.java
==============================================================================
---
development/main/metro/state/impl/src/main/net/dpml/state/impl/AbstractStateManager.java
(original)
+++
development/main/metro/state/impl/src/main/net/dpml/state/impl/AbstractStateManager.java
Mon Apr 18 23:58:38 2005
@@ -35,6 +35,8 @@
import net.dpml.state.StateManager;
import net.dpml.state.DuplicateKeyException;
import net.dpml.state.NoSuchTransitionException;
+import net.dpml.state.NoSuchOperationException;
+import net.dpml.state.Operation;

/**
* The State interface is an interface representing an immutable state of
@@ -83,7 +85,7 @@
protected abstract DefaultState getStateModel();

/**
- * Return an registered transition handler.
+ * Return an registered transition or operation handler.
*
* @param uri a handler uri
* @return the handler instance
@@ -105,12 +107,12 @@
}

/**
- * Register a transtion handler with the manager. The handler object must
+ * Register a handler with the manager. The handler object must
* implement a publically accessible method named 'handle'. Method
parameters
- * may include java.net.Logger, up to two occurance of
net.dpml.state.State (
- * the first occurance will be assingned the current state and second the
- * transition target state, and lastly, a type assignable to the current
- * component instance. All parameters are option.
+ * may include java.net.logging.Logger, up to two occurance of
net.dpml.state.State
+ * (the first occurance will be assingned the current state and second
the
+ * transition target state), and lastly, a type assignable to the current
+ * component instance. All parameters are optional.
*
* @param key the key under which the handler is registered
* @param handler the handler instance
@@ -159,7 +161,6 @@
{
return;
}
-
boolean flag = true;
while( flag )
{
@@ -254,11 +255,37 @@
getLogger().fine( message );
}
Logger logger = getLogger();
- execute( handler, state, target, logger );
+ execution( handler, state, target, logger );
setState( target );
return true;
}
}
+
+ /**
+ * Execute an operation identified by a supplied operation key. The
+ * implementation will attempt to locate the operation relative to the
current
+ * state (taking into account the DefaultState search semantics) from
which
+ * a invocation handler is resolve and invoked.
+ *
+ * @param key the operation key
+ * @exception if a error occurs in transition execution
+ */
+ public void execute( String key ) throws Exception
+ {
+ DefaultState state = getCurrentState();
+ DefaultOperation operation = state.getNamedOperation( key );
+ URI handler = operation.getHandlerURI();
+ if( getLogger().isLoggable( Level.FINE ) )
+ {
+ final String message =
+ "executing operation ["
+ + handler.toString()
+ + "]";
+ getLogger().info( message );
+ }
+ Logger logger = getLogger();
+ execution( handler, state, null, logger );
+ }

/**
* Internal utility method that handles the resolution of a handler based
on
@@ -280,7 +307,7 @@
* @param logger the assigned logging channel
* @excetion Exception of an invocation or handler error occurs
*/
- private void execute( URI uri, State state, State target, Logger logger
) throws Exception
+ private void execution( URI uri, State state, State target, Logger
logger ) throws Exception
{
String scheme = uri.getScheme();
if( "part".equals( scheme ) )
@@ -344,11 +371,12 @@

/**
* Internal utility to populate method arguments using the current state,
target state
- * assigned logging channel, and the active component instance.
+ * (in the case of transitions), assigned logging channel, and the active
component
+ * instance.
*
* @param parameters the array of method parameter arguments
* @param state the current state
- * @param target the transition target state
+ * @param target the transition target state (possible null when handling
operations)
* @param logger the assinged logging channel
* @return the populated object array
*/
@@ -368,7 +396,7 @@
args[i] = state;
firstStateAssigned = true;
}
- else if( State.class.isAssignableFrom( c ) && ( true ==
firstStateAssigned ) )
+ else if( ( null != target ) && State.class.isAssignableFrom( c )
&& ( true == firstStateAssigned ) )
{
args[i] = target;
}

Added:
development/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultOperation.java
==============================================================================
--- (empty file)
+++
development/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultOperation.java
Mon Apr 18 23:58:38 2005
@@ -0,0 +1,63 @@
+/*
+ * 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.impl;
+
+import java.util.Map;
+import java.util.Hashtable;
+import java.util.TreeMap;
+import java.util.ArrayList;
+import java.net.URI;
+
+import net.dpml.state.State;
+import net.dpml.state.Operation;
+
+/**
+ * The DefaultOperation links an operation to a handler uri.
+ *
+ * @author <a href="mailto:dev-dpml AT lists.ibiblio.org";>The Digital Product
Meta Library</a>
+ */
+public class DefaultOperation implements Operation
+{
+ private final URI m_handler;
+
+ /**
+ * Internal utility to construct a new operation instance. This
constructor
+ * is used by the DefaultState state implmentation class as part of it's
operation
+ * factory service.
+ *
+ * @param handler the uri identifying the handler
+ */
+ protected DefaultOperation( URI handler )
+ {
+ if( null == handler )
+ {
+ throw new NullPointerException( "handler" );
+ }
+ m_handler = handler;
+ }
+
+ /**
+ * Return the handler uri identifier associated with this transition.
+ * @return the transition handler identfier
+ */
+ public URI getHandlerURI()
+ {
+ return m_handler;
+ }
+}

Modified:
development/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultState.java
==============================================================================
---
development/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultState.java
(original)
+++
development/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultState.java
Mon Apr 18 23:58:38 2005
@@ -29,7 +29,9 @@
import net.dpml.state.State;
import net.dpml.state.NoSuchStateException;
import net.dpml.state.NoSuchTransitionException;
+import net.dpml.state.NoSuchOperationException;
import net.dpml.state.DuplicateKeyException;
+import net.dpml.state.Operation;
import net.dpml.state.Transition;

import net.dpml.lang.DefaultInvocationHandler;
@@ -46,6 +48,7 @@
private final DefaultState m_parent;
private final boolean m_terminal;

+ private final Map m_operations = new Hashtable();
private final Map m_transitions = new Hashtable();
private final Map m_states = new Hashtable();
private final State m_proxy;
@@ -136,7 +139,7 @@
}

/**
- * Returns an array of transtion names declared in this state and all
+ * Returns an array of transition names declared in this state and all
* parent states in the active state chain. This method via the
* StateManager interface (through exposeure of State) to controlling
* applications. The controlling application can apply a tranistion
@@ -166,6 +169,32 @@
}

/**
+ * Returns an array of operation names declared in this state and all
+ * parent states in the active state chain. This method is exposed via
the
+ * StateManager interface (through exposure of State) to controlling
+ * applications. The controlling application can execute an operation
+ * by invoking the 'execute' method on the associated ServiceManager.
+ *
+ * @return the available operation names
+ */
+ public String[] getOperationNames()
+ {
+ if( null == m_parent )
+ {
+ return getLocalOperationNames();
+ }
+ else
+ {
+ String[] keys = m_parent.getOperationNames();
+ String[] local = getLocalOperationNames();
+ String[] result = new String[ keys.length + local.length ];
+ System.arraycopy( keys, 0, result, 0, keys.length );
+ System.arraycopy( local, 0, result, keys.length, local.length
);
+ return result;
+ }
+ }
+
+ /**
* Add a new sub-state to the set of states contained within this
* state. If the supplied key is not unique within the scope of the graph
* an exception will be thrown.
@@ -429,6 +458,38 @@
}

/**
+ * An operation is the declarion of the association of a handler with a
particular
+ * state. When the active state chain includes the state the the
operaiton is
+ * asssigned to, the operation is available. Operation do not modify the
current
+ * state maintained by the state manager (unlike transitions). Operations
can be
+ * be considered as dynamic methods that are exposed to a controller as a
function
+ * of the active state of the component. The operation key must be
unique within
+ * the scope of the state to which it is assinged. If the an operation
with the
+ * same name is assigned to a parent or higher state then this operation
will
+ * override that operation.
+ *
+ * @param key the operation key
+ * @param uri the uri identifying the operation handler
+ */
+ public void addOperation( String key, URI uri )
+ {
+ if( null == key )
+ {
+ throw new NullPointerException( "key" );
+ }
+ if( null == uri )
+ {
+ throw new NullPointerException( "uri" );
+ }
+ if( m_operations.containsKey( key ) )
+ {
+ throw new DuplicateKeyException( key );
+ }
+ DefaultOperation operation = new DefaultOperation( uri );
+ m_operations.put( key, operation );
+ }
+
+ /**
* Return the first transition matching the supplied key in this state
graph. The search
* for a matching transition proceeds from the local state upwards uptil
the root state is
* reached unless a local or intermidiate transition matches the supplied
key.
@@ -443,6 +504,20 @@
}

/**
+ * Return the first operation matching the supplied key in this state
graph. The search
+ * for a matching operation proceeds from the local state upwards uptil
the root state is
+ * reached unless a local or intermidiate operation matches the supplied
key.
+ *
+ * @param key the operation key
+ * @return a matching operation
+ * @exception NoSuchOperationException if no matching operation can be
found
+ */
+ public Operation getOperation( String key )
+ {
+ return getNamedOperation( key );
+ }
+
+ /**
* Return the fisrt transition matching the supplied key in this state
graph. The search
* for a matching transition proceeds from the local state upwards uptil
the root state is
* reached unless a local or intermidiate transition matches the supplied
key.
@@ -476,6 +551,39 @@
}

/**
+ * Return the fisrt operation matching the supplied key in this state
graph. The search
+ * for a matching operation proceeds from the local state upwards uptil
the root state is
+ * reached unless a local or intermidiate operation matches the supplied
key.
+ *
+ * @param key the operation key
+ * @return a matching operation
+ * @exception NoSuchOperationException if no matching operation can be
found
+ */
+ public DefaultOperation getNamedOperation( String key )
+ {
+ if( null == key )
+ {
+ throw new NullPointerException( "key" );
+ }
+ DefaultOperation operation = (DefaultOperation) m_operations.get(
key );
+ if( null != operation )
+ {
+ return operation;
+ }
+ else
+ {
+ if( null == m_parent )
+ {
+ throw new NoSuchOperationException( key );
+ }
+ else
+ {
+ return m_parent.getNamedOperation( key );
+ }
+ }
+ }
+
+ /**
* Return the list of transition names local to this state.
* @return the array of transition names
*/
@@ -485,6 +593,15 @@
}

/**
+ * Return the list of operation names local to this state.
+ * @return the array of operation names
+ */
+ protected String[] getLocalOperationNames()
+ {
+ return (String[]) m_operations.keySet().toArray( new String[0] );
+ }
+
+ /**
* return a string representation of this state.
* @return the string representation
*/
@@ -582,6 +699,13 @@
buffer.append( " (system terminator)" );
}
}
+ String[] operations = state.getLocalOperationNames();
+ for( int i=0; i<operations.length; i++ )
+ {
+ String o = operations[i];
+ DefaultOperation operation = state.getNamedOperation( o );
+ buffer.append( "\n " + offset + "operation:" + o );
+ }

DefaultState[] states = state.getStates();
for( int i=0; i<states.length; i++ )



  • svn commit: r2321 - in development/main/metro: composition/control/src/main/net/dpml/composition/control composition/testing/activity/src/main/net/dpml/test state/api/src/main/net/dpml/state state/impl/src/main/net/dpml/state/impl, mcconnell, 04/18/2005

Archive powered by MHonArc 2.6.24.

Top of Page