Skip to Content.
Sympa Menu

notify-dpml - r1515 - in trunk/main/metro: . runtime/src/main/net/dpml/metro/runtime runtime/src/test/net/dpml/metro state/api/src/main/net/dpml/state state/api/src/test/net/dpml/state state/impl/src/main/net/dpml/state/impl state/impl/src/test/net/dpml/state state/impl/src/test/net/dpml/state/test

notify-dpml AT lists.ibiblio.org

Subject: DPML Notify

List archive

Chronological Thread  
  • From: mcconnell at BerliOS <mcconnell AT mail.berlios.de>
  • To: notify-dpml AT lists.ibiblio.org
  • Subject: r1515 - in trunk/main/metro: . runtime/src/main/net/dpml/metro/runtime runtime/src/test/net/dpml/metro state/api/src/main/net/dpml/state state/api/src/test/net/dpml/state state/impl/src/main/net/dpml/state/impl state/impl/src/test/net/dpml/state state/impl/src/test/net/dpml/state/test
  • Date: Tue, 20 Jun 2006 07:14:13 +0200

Author: mcconnell
Date: 2006-06-20 07:13:57 +0200 (Tue, 20 Jun 2006)
New Revision: 1515

Added:

trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultStateMachine.java

trunk/main/metro/runtime/src/test/net/dpml/metro/DefaultStateMachineTestCase.java
trunk/main/metro/runtime/src/test/net/dpml/metro/runtime/
trunk/main/metro/state/api/src/main/net/dpml/state/ApplyAction.java
trunk/main/metro/state/api/src/main/net/dpml/state/DefaultInterface.java
trunk/main/metro/state/api/src/main/net/dpml/state/DefaultOperation.java
trunk/main/metro/state/api/src/main/net/dpml/state/DefaultState.java
trunk/main/metro/state/api/src/main/net/dpml/state/DefaultTransition.java
trunk/main/metro/state/api/src/main/net/dpml/state/DefaultTrigger.java
trunk/main/metro/state/api/src/main/net/dpml/state/ExecAction.java
trunk/main/metro/state/api/src/main/net/dpml/state/StateDecoder.java
trunk/main/metro/state/api/src/main/net/dpml/state/StateEncoder.java
trunk/main/metro/state/api/src/test/net/dpml/state/EmptyTestCase.java
trunk/main/metro/state/api/src/test/net/dpml/state/TransitionTestCase.java
Removed:
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/ApplyAction.java

trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultInterface.java

trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultOperation.java
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultState.java

trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultStateMachine.java

trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultTransition.java

trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultTrigger.java
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/ExecAction.java
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/StateDecoder.java
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/StateEncoder.java
trunk/main/metro/state/impl/src/test/net/dpml/state/EmptyTestCase.java
trunk/main/metro/state/impl/src/test/net/dpml/state/TransitionTestCase.java

trunk/main/metro/state/impl/src/test/net/dpml/state/test/DefaultStateMachineTestCase.java
Modified:
trunk/main/metro/module.xml
Log:
sorting out state package to separate runtime versus model concerns

Modified: trunk/main/metro/module.xml
===================================================================
--- trunk/main/metro/module.xml 2006-06-20 05:11:03 UTC (rev 1514)
+++ trunk/main/metro/module.xml 2006-06-20 05:13:57 UTC (rev 1515)
@@ -53,7 +53,7 @@
</test>
</dependencies>
</project>
-
+
<project name="dpml-metro-component" basedir="component">
<types>
<type id="jar"/>

Copied:
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultStateMachine.java
(from rev 1513,
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultStateMachine.java)
===================================================================
---
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultStateMachine.java
2006-06-19 03:26:47 UTC (rev 1513)
+++
trunk/main/metro/runtime/src/main/net/dpml/metro/runtime/DefaultStateMachine.java
2006-06-20 05:13:57 UTC (rev 1515)
@@ -0,0 +1,1005 @@
+/*
+ * 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.metro.runtime;
+
+import java.beans.Expression;
+import java.beans.Statement;
+import java.beans.PropertyChangeSupport;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeEvent;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.WeakHashMap;
+import java.util.EventObject;
+import java.util.EventListener;
+import java.rmi.RemoteException;
+
+import net.dpml.state.State;
+import net.dpml.state.Transition;
+import net.dpml.state.Operation;
+import net.dpml.state.Interface;
+import net.dpml.state.Trigger;
+import net.dpml.state.Trigger.TriggerEvent;
+import net.dpml.state.Action;
+import net.dpml.state.StateMachine;
+import net.dpml.state.UnknownOperationException;
+import net.dpml.state.UnknownTransitionException;
+import net.dpml.state.IntegrityRuntimeException;
+import net.dpml.state.StateListener;
+import net.dpml.state.StateEvent;
+
+import net.dpml.util.Logger;
+import net.dpml.util.UnicastEventSource;
+import net.dpml.util.EventQueue;
+import net.dpml.util.EventHandler;
+
+/**
+ * Default state-machine implementation.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class DefaultStateMachine implements StateMachine, EventHandler
+{
+ /**
+ * Constant name used to reference a state change in a property event.
+ */
+ public static final String PROPERTY_NAME = "state";
+
+ /**
+ * Validate the state integrity.
+ * @param state the state to validate
+ */
+ public static void validate( State state )
+ {
+ validateState( state );
+ }
+
+
//-------------------------------------------------------------------------------
+ // state
+
//-------------------------------------------------------------------------------
+
+ //private final PropertyChangeSupport m_support;
+
+ private State m_state;
+ private boolean m_active = false;
+ private boolean m_disposed = false;
+
+ private final Object m_lock = new Object();
+
+ private final EventQueue m_queue;
+
+ private final WeakHashMap m_listeners = new WeakHashMap();
+
+ private final Logger m_logger;
+
+
//-------------------------------------------------------------------------------
+ // constructor
+
//-------------------------------------------------------------------------------
+
+ /**
+ * Creation of a new state machine using a state graph.
+ * @param state the state graph
+ */
+ public DefaultStateMachine( EventQueue queue, Logger logger, State state
) throws RemoteException
+ {
+ m_queue = queue;
+ m_logger = logger;
+ m_state = state;
+ }
+
+
//-------------------------------------------------------------------------------
+ // StateMachine
+
//-------------------------------------------------------------------------------
+
+ private Logger getLogger()
+ {
+ return m_logger;
+ }
+
+ /**
+ * Add a state change listener to the state machine.
+ * @param listener the state listener
+ */
+ public void addStateListener( final StateListener listener )
+ {
+ if( null == listener )
+ {
+ throw new NullPointerException( "listener" );
+ }
+ checkDisposed();
+ synchronized( m_lock )
+ {
+ m_listeners.put( listener, null );
+ }
+ }
+
+ /**
+ * Remove a state listener from the state machine.
+ * @param listener the state listener
+ */
+ public void removeStateListener( final StateListener listener )
+ {
+ if( null == listener )
+ {
+ throw new NullPointerException( "listener" );
+ }
+ checkDisposed();
+ synchronized( m_lock )
+ {
+ m_listeners.remove( listener );
+ }
+ }
+
+ public EventListener[] getEventListeners()
+ {
+ return getStateListeners();
+ }
+
+ private StateListener[] getStateListeners()
+ {
+ checkDisposed();
+ synchronized( m_lock )
+ {
+ return (StateListener[]) m_listeners.keySet().toArray( new
StateListener[0] );
+ }
+ }
+
+ public void processEvent( EventObject event )
+ {
+ StateListener[] listeners = getStateListeners();
+ for( int i=0; i < listeners.length; i++ )
+ {
+ StateListener listener = listeners[i];
+ if( event instanceof StateEvent )
+ {
+ try
+ {
+ StateEvent e = (StateEvent) event;
+ listener.stateChanged( e );
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "StateListener notification error.";
+ getLogger().error( error, e );
+ }
+ }
+ }
+ }
+
+ /**
+ * Return the current state.
+ * @return the current state
+ */
+ public State getState()
+ {
+ checkDisposed();
+ synchronized( m_state )
+ {
+ return m_state;
+ }
+ }
+
+ /**
+ * Locate and return the most immediate initialization action defined
relative to
+ * the current state. If an action is located within the current state
it will be
+ * return otherwise the search will continue up the state graph until
either an
+ * action is located or no further parent state is available in which
case a null
+ * value is returned.
+ *
+ * @return the initialization action or null if no action declared
+ */
+ public Action getInitializationAction()
+ {
+ checkDisposed();
+ try
+ {
+ return getAction( m_state, Trigger.INITIALIZATION );
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Unexpected error during resolution of initialization
actions.";
+ throw new IntegrityRuntimeException( error, e );
+ }
+ }
+
+ /**
+ * Locate and return the most immediate termination action defined
relative to
+ * the current state. If an action is located within the current state
it will be
+ * return otherwise the search will continue up the state graph until
either an
+ * action is located or no further parent state is available in which
case a null
+ * value is returned.
+ *
+ * @return the termination action or null if no action declared
+ */
+ public Action getTerminationAction()
+ {
+ checkDisposed();
+ try
+ {
+ return getAction( m_state, Trigger.TERMINATION );
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Unexpected error during resolution of termination actions.";
+ throw new IntegrityRuntimeException( error, e );
+ }
+ }
+
+ /**
+ * Invoke initialization of the supplied object using the initialization
action
+ * declared under the current state path.
+ *
+ * @param object the object to initialize
+ * @return the state established as a sidee effect of the initialization
+ * @exception InvocationTargetException if an invocation error occurs as
a
+ * result of initialization
+ */
+ public State initialize( Object object ) throws InvocationTargetException
+ {
+ checkDisposed();
+ ArrayList visited = new ArrayList();
+ try
+ {
+ State result = initialize( visited, object );
+ m_active = true;
+ return result;
+ }
+ catch( UnknownTransitionException e )
+ {
+ final String error =
+ "Internal state machine error raised due to an unresolved
transition.";
+ throw new IntegrityRuntimeException( error, e );
+ }
+ catch( UnknownOperationException e )
+ {
+ final String error =
+ "Internal state machine error raised due to an unresolved
operation.";
+ throw new IntegrityRuntimeException( error, e );
+ }
+ catch( InvocationTargetException e )
+ {
+ throw e;
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Unexpected error during state-machine initialization.";
+ throw new IntegrityRuntimeException( error, e );
+ }
+ }
+
+ /**
+ * Execute a named operation on the supplied object.
+ * @param name an operation name
+ * @param object the target object
+ * @param args operation arguments
+ * @return the result of operation invocation
+ * @exception UnknownOperationException if the operation is unknown
+ * @exception InvocationTargetException if an invocation error occurs as
a
+ * result of operation execution
+ */
+ public Object execute( String name, Object object, Object[] args )
+ throws UnknownOperationException, InvocationTargetException
+ {
+ checkDisposed();
+ Operation operation = getOperation( getState(), name );
+ return execute( operation, object, args );
+ }
+
+ /**
+ * Invoke a management method on the supplied object.
+ * @param object the target object
+ * @param method the method name
+ * @param args method parameter arguments
+ * @return the return value
+ * @exception IllegalStateException if the method is recognized but not
available
+ * @exception UnknownOperationException if the operation is unknown
+ * @exception InvocationTargetException if an invocation error occurs as
a
+ * result of operation execution
+ */
+ public Object invoke( Object object, String method, Object[] args )
+ throws UnknownOperationException, InvocationTargetException,
IllegalStateException
+ {
+ checkDisposed();
+
+ // TODO: validate exposure of declaring interface
+
+ try
+ {
+ Expression expression = new Expression( object, method, args );
+ return expression.getValue();
+ }
+ catch( InvocationTargetException e )
+ {
+ throw e;
+ }
+ catch( Exception e )
+ {
+ throw new InvocationTargetException( e );
+ }
+ }
+
+ /**
+ * Apply a named transition to the target object.
+ * @param name the transition name
+ * @param object the object against which any transition handler action
are to be applied
+ * @return the state established by the application of the transition
+ * @exception UnknownTransitionException if the transition is unknown
+ * @exception InvocationTargetException if an invocation error occurs as
a
+ * result of transition invocation
+ */
+ public State apply( String name, Object object )
+ throws UnknownTransitionException, InvocationTargetException
+ {
+ checkDisposed();
+ synchronized( m_state )
+ {
+ Transition transition = getTransition( m_state, name );
+ return apply( transition, object );
+ }
+ }
+
+ /**
+ * Return all of the available transitions relative to the current state.
+ * @return the available transitions
+ */
+ public Transition[] getTransitions()
+ {
+ checkDisposed();
+ Hashtable table = new Hashtable();
+ State[] states = m_state.getStatePath();
+ for( int i=( states.length-1 ); i>-1; i-- )
+ {
+ State state = states[i];
+ Transition[] transitions = state.getTransitions();
+ for( int j=0; j<transitions.length; j++ )
+ {
+ Transition transition = transitions[j];
+ String name = transition.getName();
+ if( null == table.get( name ) )
+ {
+ table.put( name, transition );
+ }
+ }
+ }
+ return (Transition[]) table.values().toArray( new Transition[0] );
+ }
+
+ /**
+ * Return all of the available operations relative to the current state.
+ * @return the available operations
+ */
+ public Operation[] getOperations()
+ {
+ checkDisposed();
+ Hashtable table = new Hashtable();
+ State[] states = m_state.getStatePath();
+ for( int i=( states.length-1 ); i>-1; i-- )
+ {
+ State state = states[i];
+ Operation[] operations = state.getOperations();
+ for( int j=0; j<operations.length; j++ )
+ {
+ Operation operation = operations[j];
+ String name = operation.getName();
+ if( null == table.get( name ) )
+ {
+ table.put( name, operation );
+ }
+ }
+ }
+ return (Operation[]) table.values().toArray( new Operation[0] );
+ }
+
+ /**
+ * Return all of the available interfaces relative to the current state.
+ * @return the available interface declarations
+ */
+ public Interface[] getInterfaces()
+ {
+ checkDisposed();
+ Hashtable table = new Hashtable();
+ State[] states = m_state.getStatePath();
+ for( int i=( states.length-1 ); i>-1; i-- )
+ {
+ State state = states[i];
+ Interface[] interfaces = state.getInterfaces();
+ for( int j=0; j<interfaces.length; j++ )
+ {
+ Interface data = interfaces[j];
+ String name = data.getName();
+ if( null == table.get( name ) )
+ {
+ table.put( name, data );
+ }
+ }
+ }
+ return (Interface[]) table.values().toArray( new Interface[0] );
+ }
+
+ /**
+ * Invoke termination of the supplied object using the termination action
+ * declared under the current state path.
+ *
+ * @param object the object to terminate
+ * @return the state established as a side-effect of the termination
+ */
+ public State terminate( Object object )
+ {
+ checkDisposed();
+ ArrayList visited = new ArrayList();
+ try
+ {
+ State result = terminate( visited, object );
+ m_active = false;
+ return result;
+ }
+ catch( Throwable e )
+ {
+ e.printStackTrace();
+ return getState();
+ }
+ }
+
+ /**
+ * Returns the active status of the state machine.
+ * @return TRUE if the state machine has invoked initialization and
+ * termination has not been performed otherwise FALSE
+ */
+ public boolean isActive()
+ {
+ return m_active;
+ }
+
+ /**
+ * Dispose of the state machine.
+ */
+ public void dispose()
+ {
+ synchronized( m_lock )
+ {
+ StateListener[] listeners = getStateListeners();
+ for( int i=0; i<listeners.length; i++ )
+ {
+ StateListener listener = listeners[i];
+ removeStateListener( listener );
+ }
+ }
+ m_disposed = true;
+ m_state = null;
+ }
+
+
//-------------------------------------------------------------------------------
+ // implementation
+
//-------------------------------------------------------------------------------
+
+ private State initialize( List list, Object object ) throws Exception
+ {
+ Action action = getInitializationAction();
+ if( null == action )
+ {
+ return m_state;
+ }
+ else if( list.contains( action ) )
+ {
+ return m_state;
+ }
+ else
+ {
+ list.add( action );
+ if( action instanceof Operation )
+ {
+ Operation operation = (Operation) action;
+ execute( operation, object, new Object[0] );
+ return m_state;
+ }
+ else if( action instanceof Transition )
+ {
+ Transition transition = (Transition) action;
+ State current = getState();
+ State result = apply( transition, object );
+ if( !current.equals( result ) )
+ {
+ return initialize( list, object );
+ }
+ else
+ {
+ return getState();
+ }
+ }
+ else
+ {
+ final String error = "Unrecognized action: " + action;
+ throw new IllegalStateException( error );
+ }
+ }
+ }
+
+ private Object execute( Operation operation, Object object, Object[]
args ) throws InvocationTargetException
+ {
+ if( null == object )
+ {
+ return null;
+ }
+
+ String method = getMethodName( operation );
+
+ try
+ {
+ Expression expression = new Expression( object, method, args );
+ return expression.getValue();
+ }
+ catch( InvocationTargetException e )
+ {
+ throw e;
+ }
+ catch( Exception e )
+ {
+ throw new InvocationTargetException( e );
+ }
+ }
+
+ private State terminate( List list, Object object ) throws Exception
+ {
+ Action action = getTerminationAction();
+ if( null == action )
+ {
+ return m_state;
+ }
+ else if( list.contains( action ) )
+ {
+ return m_state;
+ }
+ else
+ {
+ if( action instanceof Operation )
+ {
+ Operation operation = (Operation) action;
+ execute( operation, object, new Object[0] );
+ return m_state;
+ }
+ else if( action instanceof Transition )
+ {
+ Transition transition = (Transition) action;
+ State current = getState();
+ State result = apply( transition, object );
+ if( !current.equals( result ) )
+ {
+ return terminate( list, object );
+ }
+ else
+ {
+ return getState();
+ }
+ }
+ else
+ {
+ final String error = "Unrecognized action: " + action;
+ throw new IllegalStateException( error );
+ }
+ }
+ }
+
+ private State apply( Transition transition, Object object ) throws
InvocationTargetException
+ {
+ synchronized( m_state )
+ {
+ State context = transition.getState();
+ String target = transition.getTargetName();
+ State state = getState( context, target );
+ Operation operation = transition.getOperation();
+ if( null != operation )
+ {
+ execute( operation, object, new Object[0] ); // TODO: add
resolved values as args
+ }
+ setState( state );
+ return state;
+ }
+ }
+
+ private void execute( URI handler, Object object ) throws
InvocationTargetException
+ {
+ if( null == object )
+ {
+ return;
+ }
+ String scheme = handler.getScheme();
+ if( "method".equals( scheme ) )
+ {
+ String methodName = handler.getSchemeSpecificPart();
+ Statement statement = new Statement( object, methodName, new
Object[0] );
+ try
+ {
+ statement.execute();
+ }
+ catch( InvocationTargetException e )
+ {
+ throw e;
+ }
+ catch( Exception e )
+ {
+ throw new InvocationTargetException( e );
+ }
+ }
+ else
+ {
+ final String error =
+ "Operation scheme not recognized."
+ + "\nScheme: " + scheme
+ + "\nURI: " + handler;
+ throw new IllegalArgumentException( error );
+ }
+ }
+
+ private void setState( final State state )
+ {
+ synchronized( m_state )
+ {
+ if( m_state != state )
+ {
+ final State oldState = m_state;
+ m_state = state;
+
+ final StateEvent event = new StateEvent( this, oldState,
state );
+ m_queue.enqueueEvent( event );
+ }
+ }
+ }
+
+ private Action getAction( State state, TriggerEvent category )
+ throws UnknownTransitionException, UnknownOperationException
+ {
+ Trigger[] triggers = state.getTriggers();
+ for( int i=0; i<triggers.length; i++ )
+ {
+ Trigger trigger = triggers[i];
+ if( trigger.getEvent().equals( category ) )
+ {
+ Action action = trigger.getAction();
+ if( action instanceof ApplyAction )
+ {
+ ApplyAction apply = (ApplyAction) action;
+ String id = apply.getID();
+ return getTransition( state, id );
+ }
+ else if( action instanceof ExecAction )
+ {
+ ExecAction exec = (ExecAction) action;
+ String id = exec.getID();
+ return getOperation( state, id );
+ }
+ else
+ {
+ return action;
+ }
+ }
+ }
+ State parent = state.getParent();
+ if( null != parent )
+ {
+ return getAction( parent, category );
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private Transition getTransition( State state, String name ) throws
UnknownTransitionException
+ {
+ Transition[] transitions = state.getTransitions();
+ for( int i=0; i<transitions.length; i++ )
+ {
+ Transition transition = transitions[i];
+ if( name.equals( transition.getName() ) )
+ {
+ return transition;
+ }
+ }
+ State parent = state.getParent();
+ if( null == parent )
+ {
+ final String error =
+ "Unable to resolve a transition named ["
+ + name
+ + "] relative to the state ["
+ + state.getName()
+ + "].";
+ throw new UnknownTransitionException( error );
+ }
+ else
+ {
+ try
+ {
+ return getTransition( parent, name );
+ }
+ catch( UnknownTransitionException e )
+ {
+ final String error =
+ "Unable to resolve a transition named ["
+ + name
+ + "] relative to the current state ["
+ + state
+ + "].";
+ throw new UnknownTransitionException( error );
+ }
+ }
+ }
+
+ private Operation getOperation( State state, String name ) throws
UnknownOperationException
+ {
+ Operation[] operations = state.getOperations();
+ for( int i=0; i<operations.length; i++ )
+ {
+ Operation operation = operations[i];
+ if( name.equals( operation.getName() ) )
+ {
+ return operation;
+ }
+ }
+ State parent = state.getParent();
+ if( null == parent )
+ {
+ throw new UnknownOperationException( name );
+ }
+ else
+ {
+ return getOperation( parent, name );
+ }
+ }
+
+
//-------------------------------------------------------------------------------
+ // static internals used to validate the integrity of a state graph
+
//-------------------------------------------------------------------------------
+
+ private static void validateState( State state )
+ {
+ Trigger[] triggers = state.getTriggers();
+ validateTriggers( state, triggers );
+ Transition[] transitions = state.getTransitions();
+ validateTransitions( state, transitions );
+ Operation[] operations = state.getOperations();
+ validateOperations( state, operations );
+ State[] states = state.getStates();
+ validateStates( state, states );
+ }
+
+ private static void validateTransitions( State state, Transition[]
transitions )
+ {
+ for( int i=0; i<transitions.length; i++ )
+ {
+ Transition transition = transitions[i];
+ validateTransition( state, transition );
+ }
+ }
+
+ private static void validateOperations( State state, Operation[]
operations )
+ {
+ for( int i=0; i<operations.length; i++ )
+ {
+ Operation operation = operations[i];
+ validateOperation( state, operation );
+ }
+ }
+
+ private static void validateTriggers( State state, Trigger[] triggers )
+ {
+ for( int i=0; i<triggers.length; i++ )
+ {
+ Trigger trigger = triggers[i];
+ validateTrigger( state, trigger );
+ }
+ }
+
+ private static void validateStates( State state, State[] states )
+ {
+ for( int i=0; i<states.length; i++ )
+ {
+ State s = states[i];
+ validateState( s );
+ }
+ }
+
+ private static void validateTrigger( State state, Trigger trigger )
+ {
+ TriggerEvent event = trigger.getEvent();
+ Action action = trigger.getAction();
+ if( action instanceof Transition )
+ {
+ Transition transition = (Transition) action;
+ validateTransition( state, transition );
+ }
+ else if( action instanceof Operation )
+ {
+ Operation operation = (Operation) action;
+ validateOperation( state, operation );
+ }
+ else if( action instanceof ApplyAction )
+ {
+ ApplyAction apply = (ApplyAction) action;
+ String id = apply.getID();
+ validateTransition( state, id );
+ }
+ else if( action instanceof ExecAction )
+ {
+ ExecAction exec = (ExecAction) action;
+ String id = exec.getID();
+ validateOperation( state, id );
+ }
+ }
+
+ private static void validateTransition( State state, String id )
+ {
+ //System.out.println( "# v/transition: " + id );
+ }
+
+ private static void validateTransition( State state, Transition
transition )
+ {
+ String target = transition.getTargetName();
+ State s = getState( state, target );
+ if( null == state )
+ {
+ final String error =
+ "Transition target ["
+ + target
+ + "] does not exist relative to state ["
+ + state;
+ throw new IllegalStateException( error );
+ }
+ }
+
+ private static void validateOperation( State state, String id )
+ {
+ //System.out.println( "# v/operation: " + operation );
+ }
+
+ private static void validateOperation( State state, Operation operation )
+ {
+ //System.out.println( "# v/operation: " + operation );
+ }
+
+ private static State getState( State state, String target )
+ {
+ if( target.startsWith( "/" ) )
+ {
+ //
+ // its an absolute target
+ //
+
+ String spec = target.substring( 1 );
+ State root = state.getStatePath()[0];
+ return getState( root, spec );
+ }
+ else if( target.startsWith( "../" ) )
+ {
+ //
+ // its relative to the state's parent
+ //
+
+ String spec = target.substring( 3 );
+ State parent = state.getParent();
+ if( null != parent )
+ {
+ return getState( parent, spec );
+ }
+ else
+ {
+ final String error =
+ "Invalid relative reference ["
+ + spec
+ + "] passed to root state.";
+ throw new IllegalArgumentException( error );
+ }
+ }
+ else if( target.indexOf( "/" ) > -1 )
+ {
+ //
+ // its a composition address
+ //
+
+ int index = target.indexOf( "/" );
+ String base = target.substring( 0, index );
+ String remainder = target.substring( index + 1 );
+ State s = getState( state, base );
+ return getState( s, remainder );
+ }
+ else
+ {
+ //
+ // its a name relative to the supplied state
+ //
+
+ State[] states = state.getStates();
+ for( int i=0; i<states.length; i++ )
+ {
+ State s = states[i];
+ if( target.equals( s.getName() ) )
+ {
+ return s;
+ }
+ }
+ final String error =
+ "Requested target state ["
+ + target
+ + "] does not exist within the state ["
+ + state.getName()
+ + "].";
+ throw new IllegalArgumentException( error );
+ }
+ }
+
+ private void checkDisposed() throws IllegalStateException
+ {
+ if( m_disposed )
+ {
+ final String error =
+ "Instance has been disposed.";
+ throw new IllegalStateException( error );
+ }
+ }
+
+ private String getMethodName( Operation operation )
+ {
+ if( null != operation.getMethodName() )
+ {
+ return operation.getMethodName();
+ }
+
+ //
+ // otherwise resolve it using java beans style getXxxx
+ //
+
+ String name = operation.getName();
+ int n = name.length();
+ if( n == 0 )
+ {
+ throw new IllegalArgumentException( "Operation name is empty." );
+ }
+ else if( n == 1 )
+ {
+ return "get" + name.toUpperCase();
+ }
+ else
+ {
+ return "get"
+ + name.substring( 0, 1 ).toUpperCase()
+ + name.substring( 1 );
+ }
+ }
+
+ private static URI createURI( String path ) throws Exception
+ {
+ if( null == path )
+ {
+ return null;
+ }
+ else
+ {
+ return new URI( path );
+ }
+ }
+
+}

Copied:
trunk/main/metro/runtime/src/test/net/dpml/metro/DefaultStateMachineTestCase.java
(from rev 1513,
trunk/main/metro/state/impl/src/test/net/dpml/state/test/DefaultStateMachineTestCase.java)
===================================================================
---
trunk/main/metro/state/impl/src/test/net/dpml/state/test/DefaultStateMachineTestCase.java
2006-06-19 03:26:47 UTC (rev 1513)
+++
trunk/main/metro/runtime/src/test/net/dpml/metro/DefaultStateMachineTestCase.java
2006-06-20 05:13:57 UTC (rev 1515)
@@ -0,0 +1,294 @@
+/*
+ * 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.metro.runtime;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import net.dpml.state.State;
+import net.dpml.state.Transition;
+import net.dpml.state.Operation;
+import net.dpml.state.Interface;
+import net.dpml.state.Trigger;
+import net.dpml.state.Action;
+import net.dpml.state.impl.StateDecoder;
+
+import net.dpml.metro.runtime.DefaultStateMachine;
+
+import net.dpml.util.EventQueue;
+import net.dpml.util.Logger;
+import net.dpml.util.DefaultLogger;
+
+/**
+ * Default state machine test-case.
+ *
+ * @author <a href="http://www.dpml.net";>The Digital Product Meta Library</a>
+ */
+public class DefaultStateMachineTestCase extends AbstractEncodingTestCase
+{
+ private State m_state;
+ private EventQueue m_queue;
+ private DefaultStateMachine m_machine;
+ private Logger m_logger;
+
+ /**
+ * Testcase setup.
+ * @exception Exception if a setup error occurs
+ */
+ public void setUp() throws Exception
+ {
+ String testPath = System.getProperty( "project.test.dir" );
+ File test = new File( testPath );
+ File example = new File( test, "example.xgraph" );
+ try
+ {
+ StateDecoder builder = new StateDecoder();
+ m_state = builder.loadState( example.toURI() );
+ m_logger = new DefaultLogger( "test" );
+ m_queue = new EventQueue( m_logger );
+ m_machine = new DefaultStateMachine( m_queue, m_logger, m_state
);
+ }
+ catch( Throwable e )
+ {
+ e.printStackTrace();
+ fail( e.toString() );
+ }
+ }
+
+ /**
+ * List the state graph.
+ * @exception Exception if an error occurs
+ */
+ public void testAudit() throws Exception
+ {
+ audit( m_state );
+ }
+
+ /**
+ * Test state machine validation function.
+ * @exception Exception if an error occurs
+ */
+ public void testValidation() throws Exception
+ {
+ DefaultStateMachine.validate( m_state );
+ }
+
+ /**
+ * Test state machine initialization and termination internal state
integrity.
+ * @exception Exception if an error occurs
+ */
+ public void testExecution() throws Exception
+ {
+ // check that the termination action is null
+
+ Action termination = m_machine.getTerminationAction();
+ assertNull( "root-termination", termination );
+
+ // check that the initialization action is correct
+
+ Action action = m_machine.getInitializationAction();
+ if( action instanceof Transition )
+ {
+ Transition transition = (Transition) action;
+ String name = transition.getName();
+ assertEquals( "init-transition-name", "init", name );
+ }
+ else
+ {
+ fail( "Root initialization action is not a transition." );
+ }
+
+ // initialize the state
+
+ State state = m_machine.initialize( null );
+ assertEquals( "post-init-state", "started", state.getName() );
+ State machineState = m_machine.getState();
+ assertEquals( "machine-state", "started", machineState.getName() );
+
+ if( action != m_machine.getInitializationAction() )
+ {
+ fail(
+ "Unexpected initialization action ["
+ + m_machine.getInitializationAction()
+ + "] declared by statemachine." );
+ }
+
+ // check that the termination action has changed to the overridden
'stop' transition
+
+ termination = m_machine.getTerminationAction();
+ assertNotNull( "termination-in-start", termination );
+ assertEquals( "action-is-stop", "stop", termination.getName() );
+
+ //
+ // test if the 'stop' transition is accessible
+ //
+
+ Transition[] transitions = m_machine.getTransitions();
+ assertEquals( "started-transition-count", 1, transitions.length );
+ Transition stop = transitions[0];
+ assertEquals( "stop-transition-name", "stop", stop.getName() );
+
+ //
+ // test available operations
+ //
+
+ Operation[] operations = m_machine.getOperations();
+ assertEquals( "started-operation-count", 1, operations.length );
+ Operation audit = operations[0];
+ assertEquals( "audit-operation-name", "audit", audit.getName() );
+
+ //
+ // apply the stop transition
+ //
+
+ m_machine.apply( stop.getName(), null );
+ assertEquals( "stopped-state-name", "stopped",
m_machine.getState().getName() );
+
+ //
+ // restart
+ //
+
+ m_machine.apply( "start", null );
+ assertEquals( "re-started-state-name", "started",
m_machine.getState().getName() );
+
+ //
+ // terminate
+ //
+
+ m_machine.terminate( null );
+ assertEquals( "terminated-state-name", "terminated",
m_machine.getState().getName() );
+ }
+
+ /**
+ * Test illegal attempt to initialize a disposed state machine.
+ * @exception Exception if an error occurs
+ */
+ public void testInitializationInDisposed() throws Exception
+ {
+ m_machine.dispose();
+ try
+ {
+ m_machine.initialize( null );
+ fail( "disposed machine allowed initialization" );
+ }
+ catch( IllegalStateException e )
+ {
+ // success
+ }
+ }
+
+ /**
+ * Test illegal attempt to terminate a disposed state machine.
+ * @exception Exception if an error occurs
+ */
+ public void testTerminationInDisposed() throws Exception
+ {
+ m_machine.dispose();
+ try
+ {
+ m_machine.terminate( null );
+ fail( "disposed machine allowed termination" );
+ }
+ catch( IllegalStateException e )
+ {
+ // success
+ }
+ }
+
+ /**
+ * Test encoding of a state graph.
+ * @exception Exception if an error occurs
+ */
+ public void testEncoding() throws Exception
+ {
+ Object state = executeEncodingTest( m_state );
+ }
+
+ private void audit( State state )
+ {
+ ArrayList list = new ArrayList();
+ audit( list, state, "" );
+ System.out.println( "" + "# -------------------" );
+ }
+
+ private void audit( List visited, State state, String pad )
+ {
+ if( visited.contains( state ) )
+ {
+ return;
+ }
+ else
+ {
+ visited.add( state );
+ }
+ System.out.println( pad + "# -------------------" );
+ System.out.println( pad + "# state: [" + state.getName() + "]" );
+ Trigger[] triggers = state.getTriggers();
+ for( int i=0; i<triggers.length; i++ )
+ {
+ Trigger trigger = triggers[i];
+ System.out.println(
+ pad + "# trigger "
+ + "(" + ( i+1 ) + "): ["
+ + trigger.toString()
+ + "]" );
+ }
+ Transition[] transitions = state.getTransitions();
+ for( int i=0; i<transitions.length; i++ )
+ {
+ Transition transition = transitions[i];
+ System.out.println(
+ pad + "# transition "
+ + "(" + ( i+1 ) + "): ["
+ + transition.getName()
+ + "] --> [" + transition.getTargetName()
+ + "]" );
+ }
+ Interface[] classes = state.getInterfaces();
+ for( int i=0; i<classes.length; i++ )
+ {
+ Interface interfaceDef = classes[i];
+ System.out.println(
+ pad + "# interface "
+ + "(" + ( i+1 ) + "): ["
+ + interfaceDef.getClassname()
+ + "]" );
+ }
+ Operation[] operations = state.getOperations();
+ for( int i=0; i<operations.length; i++ )
+ {
+ Operation operation = operations[i];
+ System.out.println(
+ pad + "# operation "
+ + "(" + ( i+1 ) + "): ["
+ + operation.getName()
+ + "]" );
+ }
+ State[] states = state.getStates();
+ for( int i=0; i<states.length; i++ )
+ {
+ State s = states[i];
+ audit( visited, s, pad + " " );
+ }
+ }
+}
+
+
+

Copied: trunk/main/metro/state/api/src/main/net/dpml/state/ApplyAction.java
(from rev 1512,
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/ApplyAction.java)
===================================================================
--- trunk/main/metro/state/impl/src/main/net/dpml/state/impl/ApplyAction.java
2006-06-08 08:10:50 UTC (rev 1512)
+++ trunk/main/metro/state/api/src/main/net/dpml/state/ApplyAction.java
2006-06-20 05:13:57 UTC (rev 1515)
@@ -0,0 +1,105 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+
+import net.dpml.state.Action;
+
+/**
+ * Default implementation of delegating action.
+ *
+ * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
+ * @version @PROJECT-VERSION@
+ */
+public class ApplyAction implements Action, Serializable
+{
+ private final String m_id;
+
+ /**
+ * Creation of a new apply action.
+ * @param id transition name
+ */
+ public ApplyAction( final String id )
+ {
+ if( null == id )
+ {
+ throw new NullPointerException( "id" );
+ }
+ m_id = id;
+ }
+
+ /**
+ * Return the action name.
+ * @return the name
+ */
+ public String getName()
+ {
+ return "apply:"+ m_id;
+ }
+
+ /**
+ * Return the id of the transition to apply.
+ * @return the transition id
+ */
+ public String getID()
+ {
+ return m_id;
+ }
+
+ /**
+ * Compare this object to another for equality.
+ * @param other the other object
+ * @return true if the object is equal to this object
+ */
+ public boolean equals( Object other )
+ {
+ if( null == other )
+ {
+ return false;
+ }
+ else if( other instanceof ApplyAction )
+ {
+ ApplyAction action = (ApplyAction) other;
+ return m_id.equals( action.getID() );
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Compute the hashcode for this instance.
+ * @return the hashcode value
+ */
+ public int hashCode()
+ {
+ return m_id.hashCode();
+ }
+
+ /**
+ * Return a string representation of the instance.
+ * @return the string value
+ */
+ public String toString()
+ {
+ return "apply:" + m_id;
+ }
+}

Copied:
trunk/main/metro/state/api/src/main/net/dpml/state/DefaultInterface.java
(from rev 1512,
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultInterface.java)

Copied:
trunk/main/metro/state/api/src/main/net/dpml/state/DefaultOperation.java
(from rev 1512,
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultOperation.java)

Copied: trunk/main/metro/state/api/src/main/net/dpml/state/DefaultState.java
(from rev 1512,
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultState.java)

Copied:
trunk/main/metro/state/api/src/main/net/dpml/state/DefaultTransition.java
(from rev 1512,
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultTransition.java)

Copied:
trunk/main/metro/state/api/src/main/net/dpml/state/DefaultTrigger.java (from
rev 1512,
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultTrigger.java)

Copied: trunk/main/metro/state/api/src/main/net/dpml/state/ExecAction.java
(from rev 1512,
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/ExecAction.java)

Copied: trunk/main/metro/state/api/src/main/net/dpml/state/StateDecoder.java
(from rev 1512,
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/StateDecoder.java)

Copied: trunk/main/metro/state/api/src/main/net/dpml/state/StateEncoder.java
(from rev 1512,
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/StateEncoder.java)

Copied: trunk/main/metro/state/api/src/test/net/dpml/state/EmptyTestCase.java
(from rev 1514,
trunk/main/metro/state/impl/src/test/net/dpml/state/EmptyTestCase.java)

Copied:
trunk/main/metro/state/api/src/test/net/dpml/state/TransitionTestCase.java
(from rev 1514,
trunk/main/metro/state/impl/src/test/net/dpml/state/TransitionTestCase.java)

Deleted:
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/ApplyAction.java
===================================================================
--- trunk/main/metro/state/impl/src/main/net/dpml/state/impl/ApplyAction.java
2006-06-20 05:11:03 UTC (rev 1514)
+++ trunk/main/metro/state/impl/src/main/net/dpml/state/impl/ApplyAction.java
2006-06-20 05:13:57 UTC (rev 1515)
@@ -1,105 +0,0 @@
-/*
- * 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.io.Serializable;
-
-import net.dpml.state.Action;
-
-/**
- * Default implementation of delegating action.
- *
- * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
- * @version @PROJECT-VERSION@
- */
-public class ApplyAction implements Action, Serializable
-{
- private final String m_id;
-
- /**
- * Creation of a new apply action.
- * @param id transition name
- */
- public ApplyAction( final String id )
- {
- if( null == id )
- {
- throw new NullPointerException( "id" );
- }
- m_id = id;
- }
-
- /**
- * Return the action name.
- * @return the name
- */
- public String getName()
- {
- return "apply:"+ m_id;
- }
-
- /**
- * Return the id of the transition to apply.
- * @return the transition id
- */
- public String getID()
- {
- return m_id;
- }
-
- /**
- * Compare this object to another for equality.
- * @param other the other object
- * @return true if the object is equal to this object
- */
- public boolean equals( Object other )
- {
- if( null == other )
- {
- return false;
- }
- else if( other instanceof ApplyAction )
- {
- ApplyAction action = (ApplyAction) other;
- return m_id.equals( action.getID() );
- }
- else
- {
- return false;
- }
- }
-
- /**
- * Compute the hashcode for this instance.
- * @return the hashcode value
- */
- public int hashCode()
- {
- return m_id.hashCode();
- }
-
- /**
- * Return a string representation of the instance.
- * @return the string value
- */
- public String toString()
- {
- return "apply:" + m_id;
- }
-}

Deleted:
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultInterface.java
===================================================================
---
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultInterface.java
2006-06-20 05:11:03 UTC (rev 1514)
+++
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultInterface.java
2006-06-20 05:13:57 UTC (rev 1515)
@@ -1,109 +0,0 @@
-/*
- * 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.io.Serializable;
-
-import net.dpml.state.Interface;
-
-/**
- * Default implementation of an operation.
- *
- * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
- * @version @PROJECT-VERSION@
- */
-public class DefaultInterface implements Interface, Serializable
-{
- private final String m_classname;
-
- /**
- * Creation of a new interface declaration.
- * @param classname the overriding method name
- * @exception NullPointerException if the operation name is null
- */
- public DefaultInterface( String classname ) throws NullPointerException
- {
- if( null == classname )
- {
- throw new NullPointerException( "classname" );
- }
- m_classname = classname;
- }
-
- /**
- * Overriden method returning the interface classname.
- * @return the name (interface classname)
- * @see #getClassname()
- */
- public String getName()
- {
- return getClassname();
- }
-
- /**
- * Return the interface classname.
- * @return the classname
- */
- public String getClassname()
- {
- return m_classname;
- }
-
- /**
- * Return a string representation of the instance.
- * @return the string value
- */
- public String toString()
- {
- return "interface:" + m_classname;
- }
-
- /**
- * Compare this object to another for equality.
- * @param other the other object
- * @return true if the object is equal to this object
- */
- public boolean equals( Object other )
- {
- if( null == other )
- {
- return false;
- }
- else if( other instanceof DefaultInterface )
- {
- DefaultInterface description = (DefaultInterface) other;
- return m_classname.equals( description.m_classname );
- }
- else
- {
- return false;
- }
- }
-
- /**
- * Compute the hashcode for this instance.
- * @return the hashcode value
- */
- public int hashCode()
- {
- int hash = getClass().hashCode();
- hash ^= m_classname.hashCode();
- return hash;
- }
-}

Deleted:
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultOperation.java
===================================================================
---
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultOperation.java
2006-06-20 05:11:03 UTC (rev 1514)
+++
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultOperation.java
2006-06-20 05:13:57 UTC (rev 1515)
@@ -1,139 +0,0 @@
-/*
- * 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.io.Serializable;
-
-import net.dpml.state.Operation;
-
-/**
- * Default implementation of an operation.
- *
- * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
- * @version @PROJECT-VERSION@
- */
-public class DefaultOperation implements Operation, Serializable
-{
- private final String m_name;
- private final String m_method;
-
- /**
- * Creation of a new operation.
- * @param name the operation name
- * @exception NullPointerException if the operation name is null
- */
- public DefaultOperation( final String name ) throws NullPointerException
- {
- this( name, null );
- }
-
- /**
- * Creation of a new operation.
- * @param name the operation name
- * @param method the overriding method name
- * @exception NullPointerException if the operation name is null
- */
- public DefaultOperation( final String name, String method ) throws
NullPointerException
- {
- if( null == name )
- {
- throw new NullPointerException( "name" );
- }
- m_name = name;
- m_method = method;
- }
-
- /**
- * Return the action name.
- * @return the name
- */
- public String getName()
- {
- return m_name;
- }
-
- /**
- * Return the optional overriding method name. If the
- * value returned is null the method shall be assumed to be the
- * equivalent of "get[Name]().
- * @return the operation method name
- */
- public String getMethodName()
- {
- return m_method;
- }
-
- /**
- * Return a string representation of the instance.
- * @return the string value
- */
- public String toString()
- {
- return "operation:" + m_name;
- }
-
- /**
- * Compare this object to another for equality.
- * @param other the other object
- * @return true if the object is equal to this object
- */
- public boolean equals( Object other )
- {
- if( null == other )
- {
- return false;
- }
- else if( other instanceof DefaultOperation )
- {
- DefaultOperation operation = (DefaultOperation) other;
-
- if( !m_name.equals( operation.getName() ) )
- {
- return false;
- }
- else if( null == m_method )
- {
- return null == operation.m_method;
- }
- else
- {
- return m_method.equals( operation.m_method );
- }
- }
- else
- {
- return false;
- }
- }
-
- /**
- * Compute the hashcode for this instance.
- * @return the hashcode value
- */
- public int hashCode()
- {
- int hash = getClass().hashCode();
- hash ^= m_name.hashCode();
- if( null != m_method )
- {
- hash ^= m_method.hashCode();
- }
- return hash;
- }
-}

Deleted:
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultState.java
===================================================================
---
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultState.java
2006-06-20 05:11:03 UTC (rev 1514)
+++
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultState.java
2006-06-20 05:13:57 UTC (rev 1515)
@@ -1,379 +0,0 @@
-/*
- * 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.io.Serializable;
-import java.util.Arrays;
-
-import net.dpml.state.State;
-import net.dpml.state.Transition;
-import net.dpml.state.Interface;
-import net.dpml.state.Operation;
-import net.dpml.state.Trigger;
-import net.dpml.state.Action;
-
-/**
- * Default implementation of an application state descriptor.
- *
- * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
- * @version @PROJECT-VERSION@
- */
-public class DefaultState implements State, Serializable
-{
- private final String m_name;
- private final Transition[] m_transitions;
- private final Operation[] m_operations;
- private final Interface[] m_interfaces;
- private final State[] m_states;
- private final Trigger[] m_triggers;
- private final boolean m_terminal;
-
- private transient State m_parent;
-
- /**
- * Creation of a new state.
- */
- public DefaultState()
- {
- this( "root" );
- }
-
- /**
- * Creation of a new state.
- * @param name the state name
- */
- public DefaultState( final String name )
- {
- this( name, new Trigger[0], new Transition[0], new Interface[0], new
Operation[0], new State[0], true );
- }
-
- /**
- * Creation of a new non-terminal state.
- * @param name the state name
- * @param triggers an array of triggers
- * @param transitions an array of state transitions
- * @param interfaces an array of management interface declarations
- * @param operations an array of operations
- * @param states an array of substates
- */
- public DefaultState(
- final String name, final Trigger[] triggers, final Transition[]
transitions,
- final Interface[] interfaces, final Operation[] operations, final
State[] states )
- {
- this( name, triggers, transitions, interfaces, operations, states,
false );
- }
-
- /**
- * Creation of a new state.
- * @param name the state name
- * @param triggers an array of triggers
- * @param transitions an array of state transitions
- * @param interfaces an array of management interface declarations
- * @param operations an array of operations
- * @param states an array of substates
- * @param terminal the terminal flag
- */
- public DefaultState(
- final String name, final Trigger[] triggers, final Transition[]
transitions,
- final Interface[] interfaces, final Operation[] operations, final
State[] states, boolean terminal )
- {
- if( null == name )
- {
- throw new NullPointerException( "name" );
- }
-
- for( int i=0; i<operations.length; i++ )
- {
- Operation operation = operations[i];
- if( null == operation )
- {
- throw new NullPointerException( "operation/" + i );
- }
- }
-
- m_name = name;
- m_triggers = triggers;
- m_transitions = transitions;
- m_operations = operations;
- m_interfaces = interfaces;
- m_states = states;
- m_terminal = terminal;
-
- for( int i=0; i<transitions.length; i++ )
- {
- Transition transition = transitions[i];
- if( null == transition )
- {
- throw new NullPointerException( "transition/" + i );
- }
- transition.setState( this );
- }
-
- for( int i=0; i<triggers.length; i++ )
- {
- Trigger trigger = triggers[i];
- if( null == trigger )
- {
- throw new NullPointerException( "trigger/" + i );
- }
- Action action = trigger.getAction();
- if( action instanceof Transition )
- {
- Transition transition = (Transition) action;
- transition.setState( this );
- }
- }
-
- for( int i=0; i<interfaces.length; i++ )
- {
- Interface description = interfaces[i];
- if( null == description )
- {
- throw new NullPointerException( "interface/" + i );
- }
- }
-
- for( int i=0; i<states.length; i++ )
- {
- State state = states[i];
- if( null == state )
- {
- throw new NullPointerException( "state/ " + i );
- }
- state.setParent( this );
- }
- }
-
- /**
- * Return the parent state to this state or null if this is the root of a
- * state graph.
- * @return the parent state
- */
- public State getParent()
- {
- return m_parent;
- }
-
- /**
- * Set the parent state.
- * @param state the parent state
- */
- public void setParent( State state )
- {
- if( null == m_parent )
- {
- m_parent = state;
- }
- else
- {
- final String error =
- "Illegal attempt to reassign parent.";
- throw new IllegalStateException( error );
- }
- }
-
- /**
- * Return the name of the state.
- * @return the state name
- */
- public String getName()
- {
- return m_name;
- }
-
- /**
- * Return the array of triggers associated with the state.
- * @return the trigger array
- */
- public Trigger[] getTriggers()
- {
- return m_triggers;
- }
-
- /**
- * Return the state path. The path is composed of a sequence of states
- * from the root to this state.
- * @return the state path
- */
- public State[] getStatePath()
- {
- if( null == m_parent )
- {
- return new State[]{this};
- }
- else
- {
- State[] path = m_parent.getStatePath();
- State[] result = new State[ path.length + 1 ];
- System.arraycopy( path, 0, result, 0, path.length );
- result[ path.length ] = this;
- return result;
- }
- }
-
- /**
- * Return the substates within this state.
- * @return the substate array
- */
- public State[] getStates()
- {
- return m_states;
- }
-
- /**
- * Return the array of transtions associated with the state.
- * @return the transition array
- */
- public Transition[] getTransitions()
- {
- return m_transitions;
- }
-
- /**
- * Return the array of operations associated with the state.
- * @return the operation array
- */
- public Operation[] getOperations()
- {
- return m_operations;
- }
-
- /**
- * Return the array of management interfaces associated with the state.
- * @return the interfaces array
- */
- public Interface[] getInterfaces()
- {
- return m_interfaces;
- }
-
- /**
- * Return the terminal flag.
- * @return true if terminal
- */
- public boolean getTerminal()
- {
- return isTerminal();
- }
-
- /**
- * Test is the state is a terminal state.
- * @return true if terminal
- */
- public boolean isTerminal()
- {
- return m_terminal;
- }
-
- /**
- * Return a string representation of the instance.
- * @return the string value
- */
- public String toString()
- {
- StringBuffer buffer = new StringBuffer();
- State[] path = getStatePath();
- for( int i=0; i<path.length; i++ )
- {
- State state = path[i];
- if( i>0 )
- {
- buffer.append( "/" );
- }
- buffer.append( state.getName() );
- }
- return buffer.toString();
- //return "[" + m_name + "]";
- }
-
- /**
- * Compare this object to another for equality.
- * @param other the other object
- * @return true if the object is equal to this object
- */
- public boolean equals( Object other )
- {
- if( null == other )
- {
- return false;
- }
- else if( other instanceof DefaultState )
- {
- DefaultState state = (DefaultState) other;
- if( !m_name.equals( state.getName() ) )
- {
- return false;
- }
- else if( m_terminal != state.isTerminal() )
- {
- return false;
- }
- else if( !Arrays.equals( m_triggers, state.getTriggers() ) )
- {
- return false;
- }
- else if( !Arrays.equals( m_transitions, state.getTransitions() )
)
- {
- return false;
- }
- else if( !Arrays.equals( m_operations, state.getOperations() ) )
- {
- return false;
- }
- else
- {
- return Arrays.equals( m_states, state.getStates() );
- }
- }
- else
- {
- return false;
- }
- }
-
- /**
- * Compute the hashcode for this instance.
- * @return the hashcode value
- */
- public int hashCode()
- {
- if( null == m_parent )
- {
- return m_name.hashCode();
- }
- else
- {
- int hash = m_parent.hashCode();
- hash ^= m_name.hashCode();
- return hash;
- }
- }
-
- private boolean equals( Object a, Object b )
- {
- if( null == a )
- {
- return null == b;
- }
- else
- {
- return a.equals( b );
- }
- }
-}

Deleted:
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultStateMachine.java
===================================================================
---
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultStateMachine.java
2006-06-20 05:11:03 UTC (rev 1514)
+++
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultStateMachine.java
2006-06-20 05:13:57 UTC (rev 1515)
@@ -1,1005 +0,0 @@
-/*
- * 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.beans.Expression;
-import java.beans.Statement;
-import java.beans.PropertyChangeSupport;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeEvent;
-import java.lang.reflect.InvocationTargetException;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.WeakHashMap;
-import java.util.EventObject;
-import java.util.EventListener;
-import java.rmi.RemoteException;
-
-import net.dpml.state.State;
-import net.dpml.state.Transition;
-import net.dpml.state.Operation;
-import net.dpml.state.Interface;
-import net.dpml.state.Trigger;
-import net.dpml.state.Trigger.TriggerEvent;
-import net.dpml.state.Action;
-import net.dpml.state.StateMachine;
-import net.dpml.state.UnknownOperationException;
-import net.dpml.state.UnknownTransitionException;
-import net.dpml.state.IntegrityRuntimeException;
-import net.dpml.state.StateListener;
-import net.dpml.state.StateEvent;
-
-import net.dpml.util.Logger;
-import net.dpml.util.UnicastEventSource;
-import net.dpml.util.EventQueue;
-import net.dpml.util.EventHandler;
-
-/**
- * Default state-machine implementation.
- *
- * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
- * @version @PROJECT-VERSION@
- */
-public class DefaultStateMachine implements StateMachine, EventHandler
-{
- /**
- * Constant name used to reference a state change in a property event.
- */
- public static final String PROPERTY_NAME = "state";
-
- /**
- * Validate the state integrity.
- * @param state the state to validate
- */
- public static void validate( State state )
- {
- validateState( state );
- }
-
-
//-------------------------------------------------------------------------------
- // state
-
//-------------------------------------------------------------------------------
-
- //private final PropertyChangeSupport m_support;
-
- private State m_state;
- private boolean m_active = false;
- private boolean m_disposed = false;
-
- private final Object m_lock = new Object();
-
- private final EventQueue m_queue;
-
- private final WeakHashMap m_listeners = new WeakHashMap();
-
- private final Logger m_logger;
-
-
//-------------------------------------------------------------------------------
- // constructor
-
//-------------------------------------------------------------------------------
-
- /**
- * Creation of a new state machine using a state graph.
- * @param state the state graph
- */
- public DefaultStateMachine( EventQueue queue, Logger logger, State state
) throws RemoteException
- {
- m_queue = queue;
- m_logger = logger;
- m_state = state;
- }
-
-
//-------------------------------------------------------------------------------
- // StateMachine
-
//-------------------------------------------------------------------------------
-
- private Logger getLogger()
- {
- return m_logger;
- }
-
- /**
- * Add a state change listener to the state machine.
- * @param listener the state listener
- */
- public void addStateListener( final StateListener listener )
- {
- if( null == listener )
- {
- throw new NullPointerException( "listener" );
- }
- checkDisposed();
- synchronized( m_lock )
- {
- m_listeners.put( listener, null );
- }
- }
-
- /**
- * Remove a state listener from the state machine.
- * @param listener the state listener
- */
- public void removeStateListener( final StateListener listener )
- {
- if( null == listener )
- {
- throw new NullPointerException( "listener" );
- }
- checkDisposed();
- synchronized( m_lock )
- {
- m_listeners.remove( listener );
- }
- }
-
- public EventListener[] getEventListeners()
- {
- return getStateListeners();
- }
-
- private StateListener[] getStateListeners()
- {
- checkDisposed();
- synchronized( m_lock )
- {
- return (StateListener[]) m_listeners.keySet().toArray( new
StateListener[0] );
- }
- }
-
- public void processEvent( EventObject event )
- {
- StateListener[] listeners = getStateListeners();
- for( int i=0; i < listeners.length; i++ )
- {
- StateListener listener = listeners[i];
- if( event instanceof StateEvent )
- {
- try
- {
- StateEvent e = (StateEvent) event;
- listener.stateChanged( e );
- }
- catch( Throwable e )
- {
- final String error =
- "StateListener notification error.";
- getLogger().error( error, e );
- }
- }
- }
- }
-
- /**
- * Return the current state.
- * @return the current state
- */
- public State getState()
- {
- checkDisposed();
- synchronized( m_state )
- {
- return m_state;
- }
- }
-
- /**
- * Locate and return the most immediate initialization action defined
relative to
- * the current state. If an action is located within the current state
it will be
- * return otherwise the search will continue up the state graph until
either an
- * action is located or no further parent state is available in which
case a null
- * value is returned.
- *
- * @return the initialization action or null if no action declared
- */
- public Action getInitializationAction()
- {
- checkDisposed();
- try
- {
- return getAction( m_state, Trigger.INITIALIZATION );
- }
- catch( Throwable e )
- {
- final String error =
- "Unexpected error during resolution of initialization
actions.";
- throw new IntegrityRuntimeException( error, e );
- }
- }
-
- /**
- * Locate and return the most immediate termination action defined
relative to
- * the current state. If an action is located within the current state
it will be
- * return otherwise the search will continue up the state graph until
either an
- * action is located or no further parent state is available in which
case a null
- * value is returned.
- *
- * @return the termination action or null if no action declared
- */
- public Action getTerminationAction()
- {
- checkDisposed();
- try
- {
- return getAction( m_state, Trigger.TERMINATION );
- }
- catch( Throwable e )
- {
- final String error =
- "Unexpected error during resolution of termination actions.";
- throw new IntegrityRuntimeException( error, e );
- }
- }
-
- /**
- * Invoke initialization of the supplied object using the initialization
action
- * declared under the current state path.
- *
- * @param object the object to initialize
- * @return the state established as a sidee effect of the initialization
- * @exception InvocationTargetException if an invocation error occurs as
a
- * result of initialization
- */
- public State initialize( Object object ) throws InvocationTargetException
- {
- checkDisposed();
- ArrayList visited = new ArrayList();
- try
- {
- State result = initialize( visited, object );
- m_active = true;
- return result;
- }
- catch( UnknownTransitionException e )
- {
- final String error =
- "Internal state machine error raised due to an unresolved
transition.";
- throw new IntegrityRuntimeException( error, e );
- }
- catch( UnknownOperationException e )
- {
- final String error =
- "Internal state machine error raised due to an unresolved
operation.";
- throw new IntegrityRuntimeException( error, e );
- }
- catch( InvocationTargetException e )
- {
- throw e;
- }
- catch( Throwable e )
- {
- final String error =
- "Unexpected error during state-machine initialization.";
- throw new IntegrityRuntimeException( error, e );
- }
- }
-
- /**
- * Execute a named operation on the supplied object.
- * @param name an operation name
- * @param object the target object
- * @param args operation arguments
- * @return the result of operation invocation
- * @exception UnknownOperationException if the operation is unknown
- * @exception InvocationTargetException if an invocation error occurs as
a
- * result of operation execution
- */
- public Object execute( String name, Object object, Object[] args )
- throws UnknownOperationException, InvocationTargetException
- {
- checkDisposed();
- Operation operation = getOperation( getState(), name );
- return execute( operation, object, args );
- }
-
- /**
- * Invoke a management method on the supplied object.
- * @param object the target object
- * @param method the method name
- * @param args method parameter arguments
- * @return the return value
- * @exception IllegalStateException if the method is recognized but not
available
- * @exception UnknownOperationException if the operation is unknown
- * @exception InvocationTargetException if an invocation error occurs as
a
- * result of operation execution
- */
- public Object invoke( Object object, String method, Object[] args )
- throws UnknownOperationException, InvocationTargetException,
IllegalStateException
- {
- checkDisposed();
-
- // TODO: validate exposure of declaring interface
-
- try
- {
- Expression expression = new Expression( object, method, args );
- return expression.getValue();
- }
- catch( InvocationTargetException e )
- {
- throw e;
- }
- catch( Exception e )
- {
- throw new InvocationTargetException( e );
- }
- }
-
- /**
- * Apply a named transition to the target object.
- * @param name the transition name
- * @param object the object against which any transition handler action
are to be applied
- * @return the state established by the application of the transition
- * @exception UnknownTransitionException if the transition is unknown
- * @exception InvocationTargetException if an invocation error occurs as
a
- * result of transition invocation
- */
- public State apply( String name, Object object )
- throws UnknownTransitionException, InvocationTargetException
- {
- checkDisposed();
- synchronized( m_state )
- {
- Transition transition = getTransition( m_state, name );
- return apply( transition, object );
- }
- }
-
- /**
- * Return all of the available transitions relative to the current state.
- * @return the available transitions
- */
- public Transition[] getTransitions()
- {
- checkDisposed();
- Hashtable table = new Hashtable();
- State[] states = m_state.getStatePath();
- for( int i=( states.length-1 ); i>-1; i-- )
- {
- State state = states[i];
- Transition[] transitions = state.getTransitions();
- for( int j=0; j<transitions.length; j++ )
- {
- Transition transition = transitions[j];
- String name = transition.getName();
- if( null == table.get( name ) )
- {
- table.put( name, transition );
- }
- }
- }
- return (Transition[]) table.values().toArray( new Transition[0] );
- }
-
- /**
- * Return all of the available operations relative to the current state.
- * @return the available operations
- */
- public Operation[] getOperations()
- {
- checkDisposed();
- Hashtable table = new Hashtable();
- State[] states = m_state.getStatePath();
- for( int i=( states.length-1 ); i>-1; i-- )
- {
- State state = states[i];
- Operation[] operations = state.getOperations();
- for( int j=0; j<operations.length; j++ )
- {
- Operation operation = operations[j];
- String name = operation.getName();
- if( null == table.get( name ) )
- {
- table.put( name, operation );
- }
- }
- }
- return (Operation[]) table.values().toArray( new Operation[0] );
- }
-
- /**
- * Return all of the available interfaces relative to the current state.
- * @return the available interface declarations
- */
- public Interface[] getInterfaces()
- {
- checkDisposed();
- Hashtable table = new Hashtable();
- State[] states = m_state.getStatePath();
- for( int i=( states.length-1 ); i>-1; i-- )
- {
- State state = states[i];
- Interface[] interfaces = state.getInterfaces();
- for( int j=0; j<interfaces.length; j++ )
- {
- Interface data = interfaces[j];
- String name = data.getName();
- if( null == table.get( name ) )
- {
- table.put( name, data );
- }
- }
- }
- return (Interface[]) table.values().toArray( new Interface[0] );
- }
-
- /**
- * Invoke termination of the supplied object using the termination action
- * declared under the current state path.
- *
- * @param object the object to terminate
- * @return the state established as a side-effect of the termination
- */
- public State terminate( Object object )
- {
- checkDisposed();
- ArrayList visited = new ArrayList();
- try
- {
- State result = terminate( visited, object );
- m_active = false;
- return result;
- }
- catch( Throwable e )
- {
- e.printStackTrace();
- return getState();
- }
- }
-
- /**
- * Returns the active status of the state machine.
- * @return TRUE if the state machine has invoked initialization and
- * termination has not been performed otherwise FALSE
- */
- public boolean isActive()
- {
- return m_active;
- }
-
- /**
- * Dispose of the state machine.
- */
- public void dispose()
- {
- synchronized( m_lock )
- {
- StateListener[] listeners = getStateListeners();
- for( int i=0; i<listeners.length; i++ )
- {
- StateListener listener = listeners[i];
- removeStateListener( listener );
- }
- }
- m_disposed = true;
- m_state = null;
- }
-
-
//-------------------------------------------------------------------------------
- // implementation
-
//-------------------------------------------------------------------------------
-
- private State initialize( List list, Object object ) throws Exception
- {
- Action action = getInitializationAction();
- if( null == action )
- {
- return m_state;
- }
- else if( list.contains( action ) )
- {
- return m_state;
- }
- else
- {
- list.add( action );
- if( action instanceof Operation )
- {
- Operation operation = (Operation) action;
- execute( operation, object, new Object[0] );
- return m_state;
- }
- else if( action instanceof Transition )
- {
- Transition transition = (Transition) action;
- State current = getState();
- State result = apply( transition, object );
- if( !current.equals( result ) )
- {
- return initialize( list, object );
- }
- else
- {
- return getState();
- }
- }
- else
- {
- final String error = "Unrecognized action: " + action;
- throw new IllegalStateException( error );
- }
- }
- }
-
- private Object execute( Operation operation, Object object, Object[]
args ) throws InvocationTargetException
- {
- if( null == object )
- {
- return null;
- }
-
- String method = getMethodName( operation );
-
- try
- {
- Expression expression = new Expression( object, method, args );
- return expression.getValue();
- }
- catch( InvocationTargetException e )
- {
- throw e;
- }
- catch( Exception e )
- {
- throw new InvocationTargetException( e );
- }
- }
-
- private State terminate( List list, Object object ) throws Exception
- {
- Action action = getTerminationAction();
- if( null == action )
- {
- return m_state;
- }
- else if( list.contains( action ) )
- {
- return m_state;
- }
- else
- {
- if( action instanceof Operation )
- {
- Operation operation = (Operation) action;
- execute( operation, object, new Object[0] );
- return m_state;
- }
- else if( action instanceof Transition )
- {
- Transition transition = (Transition) action;
- State current = getState();
- State result = apply( transition, object );
- if( !current.equals( result ) )
- {
- return terminate( list, object );
- }
- else
- {
- return getState();
- }
- }
- else
- {
- final String error = "Unrecognized action: " + action;
- throw new IllegalStateException( error );
- }
- }
- }
-
- private State apply( Transition transition, Object object ) throws
InvocationTargetException
- {
- synchronized( m_state )
- {
- State context = transition.getState();
- String target = transition.getTargetName();
- State state = getState( context, target );
- Operation operation = transition.getOperation();
- if( null != operation )
- {
- execute( operation, object, new Object[0] ); // TODO: add
resolved values as args
- }
- setState( state );
- return state;
- }
- }
-
- private void execute( URI handler, Object object ) throws
InvocationTargetException
- {
- if( null == object )
- {
- return;
- }
- String scheme = handler.getScheme();
- if( "method".equals( scheme ) )
- {
- String methodName = handler.getSchemeSpecificPart();
- Statement statement = new Statement( object, methodName, new
Object[0] );
- try
- {
- statement.execute();
- }
- catch( InvocationTargetException e )
- {
- throw e;
- }
- catch( Exception e )
- {
- throw new InvocationTargetException( e );
- }
- }
- else
- {
- final String error =
- "Operation scheme not recognized."
- + "\nScheme: " + scheme
- + "\nURI: " + handler;
- throw new IllegalArgumentException( error );
- }
- }
-
- private void setState( final State state )
- {
- synchronized( m_state )
- {
- if( m_state != state )
- {
- final State oldState = m_state;
- m_state = state;
-
- final StateEvent event = new StateEvent( this, oldState,
state );
- m_queue.enqueueEvent( event );
- }
- }
- }
-
- private Action getAction( State state, TriggerEvent category )
- throws UnknownTransitionException, UnknownOperationException
- {
- Trigger[] triggers = state.getTriggers();
- for( int i=0; i<triggers.length; i++ )
- {
- Trigger trigger = triggers[i];
- if( trigger.getEvent().equals( category ) )
- {
- Action action = trigger.getAction();
- if( action instanceof ApplyAction )
- {
- ApplyAction apply = (ApplyAction) action;
- String id = apply.getID();
- return getTransition( state, id );
- }
- else if( action instanceof ExecAction )
- {
- ExecAction exec = (ExecAction) action;
- String id = exec.getID();
- return getOperation( state, id );
- }
- else
- {
- return action;
- }
- }
- }
- State parent = state.getParent();
- if( null != parent )
- {
- return getAction( parent, category );
- }
- else
- {
- return null;
- }
- }
-
- private Transition getTransition( State state, String name ) throws
UnknownTransitionException
- {
- Transition[] transitions = state.getTransitions();
- for( int i=0; i<transitions.length; i++ )
- {
- Transition transition = transitions[i];
- if( name.equals( transition.getName() ) )
- {
- return transition;
- }
- }
- State parent = state.getParent();
- if( null == parent )
- {
- final String error =
- "Unable to resolve a transition named ["
- + name
- + "] relative to the state ["
- + state.getName()
- + "].";
- throw new UnknownTransitionException( error );
- }
- else
- {
- try
- {
- return getTransition( parent, name );
- }
- catch( UnknownTransitionException e )
- {
- final String error =
- "Unable to resolve a transition named ["
- + name
- + "] relative to the current state ["
- + state
- + "].";
- throw new UnknownTransitionException( error );
- }
- }
- }
-
- private Operation getOperation( State state, String name ) throws
UnknownOperationException
- {
- Operation[] operations = state.getOperations();
- for( int i=0; i<operations.length; i++ )
- {
- Operation operation = operations[i];
- if( name.equals( operation.getName() ) )
- {
- return operation;
- }
- }
- State parent = state.getParent();
- if( null == parent )
- {
- throw new UnknownOperationException( name );
- }
- else
- {
- return getOperation( parent, name );
- }
- }
-
-
//-------------------------------------------------------------------------------
- // static internals used to validate the integrity of a state graph
-
//-------------------------------------------------------------------------------
-
- private static void validateState( State state )
- {
- Trigger[] triggers = state.getTriggers();
- validateTriggers( state, triggers );
- Transition[] transitions = state.getTransitions();
- validateTransitions( state, transitions );
- Operation[] operations = state.getOperations();
- validateOperations( state, operations );
- State[] states = state.getStates();
- validateStates( state, states );
- }
-
- private static void validateTransitions( State state, Transition[]
transitions )
- {
- for( int i=0; i<transitions.length; i++ )
- {
- Transition transition = transitions[i];
- validateTransition( state, transition );
- }
- }
-
- private static void validateOperations( State state, Operation[]
operations )
- {
- for( int i=0; i<operations.length; i++ )
- {
- Operation operation = operations[i];
- validateOperation( state, operation );
- }
- }
-
- private static void validateTriggers( State state, Trigger[] triggers )
- {
- for( int i=0; i<triggers.length; i++ )
- {
- Trigger trigger = triggers[i];
- validateTrigger( state, trigger );
- }
- }
-
- private static void validateStates( State state, State[] states )
- {
- for( int i=0; i<states.length; i++ )
- {
- State s = states[i];
- validateState( s );
- }
- }
-
- private static void validateTrigger( State state, Trigger trigger )
- {
- TriggerEvent event = trigger.getEvent();
- Action action = trigger.getAction();
- if( action instanceof Transition )
- {
- Transition transition = (Transition) action;
- validateTransition( state, transition );
- }
- else if( action instanceof Operation )
- {
- Operation operation = (Operation) action;
- validateOperation( state, operation );
- }
- else if( action instanceof ApplyAction )
- {
- ApplyAction apply = (ApplyAction) action;
- String id = apply.getID();
- validateTransition( state, id );
- }
- else if( action instanceof ExecAction )
- {
- ExecAction exec = (ExecAction) action;
- String id = exec.getID();
- validateOperation( state, id );
- }
- }
-
- private static void validateTransition( State state, String id )
- {
- //System.out.println( "# v/transition: " + id );
- }
-
- private static void validateTransition( State state, Transition
transition )
- {
- String target = transition.getTargetName();
- State s = getState( state, target );
- if( null == state )
- {
- final String error =
- "Transition target ["
- + target
- + "] does not exist relative to state ["
- + state;
- throw new IllegalStateException( error );
- }
- }
-
- private static void validateOperation( State state, String id )
- {
- //System.out.println( "# v/operation: " + operation );
- }
-
- private static void validateOperation( State state, Operation operation )
- {
- //System.out.println( "# v/operation: " + operation );
- }
-
- private static State getState( State state, String target )
- {
- if( target.startsWith( "/" ) )
- {
- //
- // its an absolute target
- //
-
- String spec = target.substring( 1 );
- State root = state.getStatePath()[0];
- return getState( root, spec );
- }
- else if( target.startsWith( "../" ) )
- {
- //
- // its relative to the state's parent
- //
-
- String spec = target.substring( 3 );
- State parent = state.getParent();
- if( null != parent )
- {
- return getState( parent, spec );
- }
- else
- {
- final String error =
- "Invalid relative reference ["
- + spec
- + "] passed to root state.";
- throw new IllegalArgumentException( error );
- }
- }
- else if( target.indexOf( "/" ) > -1 )
- {
- //
- // its a composition address
- //
-
- int index = target.indexOf( "/" );
- String base = target.substring( 0, index );
- String remainder = target.substring( index + 1 );
- State s = getState( state, base );
- return getState( s, remainder );
- }
- else
- {
- //
- // its a name relative to the supplied state
- //
-
- State[] states = state.getStates();
- for( int i=0; i<states.length; i++ )
- {
- State s = states[i];
- if( target.equals( s.getName() ) )
- {
- return s;
- }
- }
- final String error =
- "Requested target state ["
- + target
- + "] does not exist within the state ["
- + state.getName()
- + "].";
- throw new IllegalArgumentException( error );
- }
- }
-
- private void checkDisposed() throws IllegalStateException
- {
- if( m_disposed )
- {
- final String error =
- "Instance has been disposed.";
- throw new IllegalStateException( error );
- }
- }
-
- private String getMethodName( Operation operation )
- {
- if( null != operation.getMethodName() )
- {
- return operation.getMethodName();
- }
-
- //
- // otherwise resolve it using java beans style getXxxx
- //
-
- String name = operation.getName();
- int n = name.length();
- if( n == 0 )
- {
- throw new IllegalArgumentException( "Operation name is empty." );
- }
- else if( n == 1 )
- {
- return "get" + name.toUpperCase();
- }
- else
- {
- return "get"
- + name.substring( 0, 1 ).toUpperCase()
- + name.substring( 1 );
- }
- }
-
- private static URI createURI( String path ) throws Exception
- {
- if( null == path )
- {
- return null;
- }
- else
- {
- return new URI( path );
- }
- }
-
-}

Deleted:
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultTransition.java
===================================================================
---
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultTransition.java
2006-06-20 05:11:03 UTC (rev 1514)
+++
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultTransition.java
2006-06-20 05:13:57 UTC (rev 1515)
@@ -1,203 +0,0 @@
-/*
- * 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.io.Serializable;
-
-import net.dpml.state.State;
-import net.dpml.state.Transition;
-import net.dpml.state.Operation;
-
-/**
- * Default implemention of a state transition descriptor.
- *
- * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
- * @version @PROJECT-VERSION@
- */
-public class DefaultTransition implements Transition, Serializable
-{
- private final String m_name;
- private final String m_target;
- private final Operation m_operation;
-
- private transient State m_state;
-
- /**
- * Creation of a new transition.
- * @param name the transition name
- * @param target the transit target state name
- */
- public DefaultTransition( final String name, final String target )
- {
- this( name, target, null );
- }
-
- /**
- * Creation of a new transition.
- * @param name the transition name
- * @param target the transit target state name
- * @param operation optional transition operation
- */
- public DefaultTransition( final String name, final String target, final
Operation operation )
- {
- if( null == name )
- {
- throw new NullPointerException( "name" );
- }
- if( null == target )
- {
- throw new NullPointerException( "target" );
- }
- m_name = name;
- m_target = target;
- m_operation = operation;
- }
-
- /**
- * Set the state that this transition is a part of.
- * @param state the owning state
- */
- public void setState( State state )
- {
- if( null == state )
- {
- throw new NullPointerException( "state" );
- }
- if( null == m_state )
- {
- m_state = state;
- }
- else
- {
- throw new IllegalStateException( "State already set." );
- }
- }
-
- /**
- * Return the state that this transition is a part of.
- * @return the owning state
- */
- public State getState()
- {
- if( null != m_state )
- {
- return m_state;
- }
- else
- {
- throw new IllegalStateException( "Enclosing state has not been
declared." );
- }
- }
-
- /**
- * Return the transition name
- * @return the name
- */
- public String getName()
- {
- return m_name;
- }
-
- /**
- * Return the transition target state name
- * @return the target state name
- */
- public String getTargetName()
- {
- return m_target;
- }
-
- /**
- * Return an operation associated with the transition.
- * @return a possibly null operation
- */
- public Operation getOperation()
- {
- return m_operation;
- }
-
- /**
- * Compare this object to another for equality.
- * @param other the other object
- * @return true if the object is equal to this object
- */
- public boolean equals( Object other )
- {
- if( null == other )
- {
- return false;
- }
- else if( other instanceof DefaultTransition )
- {
- DefaultTransition transition = (DefaultTransition) other;
- if( !m_name.equals( transition.getName() ) )
- {
- return false;
- }
- else if( !equals( m_target, transition.getTargetName() ) )
- {
- return false;
- }
- else
- {
- return equals( m_operation, transition.getOperation() );
- }
- }
- else
- {
- return false;
- }
- }
-
- /**
- * Compute the hashcode for this instance.
- * @return the hashcode value
- */
- public int hashCode()
- {
- int hash = m_name.hashCode();
- hash ^= m_target.hashCode();
- if( m_operation != null )
- {
- hash ^= m_operation.hashCode();
- }
- return hash;
- }
-
- private boolean equals( Object a, Object b )
- {
- if( null == a )
- {
- return null == b;
- }
- else
- {
- return a.equals( b );
- }
- }
-
- /**
- * Return a string representation of the instance.
- * @return the string value
- */
- public String toString()
- {
- return "transition:" + getName() + " (target=" + m_target + ")";
- }
-}

Deleted:
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultTrigger.java
===================================================================
---
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultTrigger.java
2006-06-20 05:11:03 UTC (rev 1514)
+++
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/DefaultTrigger.java
2006-06-20 05:13:57 UTC (rev 1515)
@@ -1,123 +0,0 @@
-/*
- * 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.io.Serializable;
-
-import net.dpml.state.Trigger;
-import net.dpml.state.Trigger.TriggerEvent;
-import net.dpml.state.Action;
-
-/**
- * Default implementation of trigger.
- *
- * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
- * @version @PROJECT-VERSION@
- */
-public class DefaultTrigger implements Trigger, Serializable
-{
- private final TriggerEvent m_event;
- private final Action m_action;
-
- /**
- * Creation of a new trigger.
- * @param event the trigger event constant
- * @param action the action fired by the trigger
- */
- public DefaultTrigger( final TriggerEvent event, final Action action )
- {
- if( null == event )
- {
- throw new NullPointerException( "event" );
- }
- if( null == action )
- {
- throw new NullPointerException( "action" );
- }
- m_event = event;
- m_action = action;
- }
-
- /**
- * Return the event enumneration that this trigger is associated with.
- * @return the triggering event class
- */
- public TriggerEvent getEvent()
- {
- return m_event;
- }
-
- /**
- * Return the actions that this trigger initiates.
- * @return the triggered action
- */
- public Action getAction()
- {
- return m_action;
- }
-
- /**
- * Compare this object to another for equality.
- * @param other the other object
- * @return true if the object is equal to this object
- */
- public boolean equals( Object other )
- {
- if( null == other )
- {
- return false;
- }
- else if( other instanceof DefaultTrigger )
- {
- DefaultTrigger trigger = (DefaultTrigger) other;
- if( !m_event.equals( trigger.getEvent() ) )
- {
- return false;
- }
- else
- {
- return m_action.equals( trigger.getAction() );
- }
- }
- else
- {
- return false;
- }
- }
-
- /**
- * Compute the hashcode for this instance.
- * @return the hashcode value
- */
- public int hashCode()
- {
- int hash = m_event.hashCode();
- hash ^= m_action.hashCode();
- return hash;
- }
-
- /**
- * Return a string representation of the instance.
- * @return the string value
- */
- public String toString()
- {
- return "trigger:" + m_event.getName();
- }
-}

Deleted:
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/ExecAction.java
===================================================================
--- trunk/main/metro/state/impl/src/main/net/dpml/state/impl/ExecAction.java
2006-06-20 05:11:03 UTC (rev 1514)
+++ trunk/main/metro/state/impl/src/main/net/dpml/state/impl/ExecAction.java
2006-06-20 05:13:57 UTC (rev 1515)
@@ -1,105 +0,0 @@
-/*
- * 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.io.Serializable;
-
-import net.dpml.state.Action;
-
-/**
- * Default implementation of delegating action.
- *
- * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
- * @version @PROJECT-VERSION@
- */
-public class ExecAction implements Action, Serializable
-{
- private final String m_id;
-
- /**
- * Creation of a new exec action.
- * @param id operation name
- */
- public ExecAction( final String id )
- {
- if( null == id )
- {
- throw new NullPointerException( "id" );
- }
- m_id = id;
- }
-
- /**
- * Return the action name.
- * @return the name
- */
- public String getName()
- {
- return "exec:" + m_id;
- }
-
- /**
- * Return the id of the transition to apply.
- * @return the transition id
- */
- public String getID()
- {
- return m_id;
- }
-
- /**
- * Compare this object to another for equality.
- * @param other the other object
- * @return true if the object is equal to this object
- */
- public boolean equals( Object other )
- {
- if( null == other )
- {
- return false;
- }
- else if( other instanceof ExecAction )
- {
- ExecAction action = (ExecAction) other;
- return m_id.equals( action.getID() );
- }
- else
- {
- return false;
- }
- }
-
- /**
- * Compute the hashcode for this instance.
- * @return the hashcode value
- */
- public int hashCode()
- {
- return m_id.hashCode();
- }
-
- /**
- * Return a string representation of the instance.
- * @return the string value
- */
- public String toString()
- {
- return "exec:" + m_id;
- }
-}

Deleted:
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/StateDecoder.java
===================================================================
---
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/StateDecoder.java
2006-06-20 05:11:03 UTC (rev 1514)
+++
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/StateDecoder.java
2006-06-20 05:13:57 UTC (rev 1515)
@@ -1,272 +0,0 @@
-/*
- * Copyright 2006 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.io.IOException;
-import java.net.URI;
-
-import javax.xml.XMLConstants;
-
-import net.dpml.state.State;
-import net.dpml.state.Action;
-import net.dpml.state.Trigger.TriggerEvent;
-import net.dpml.state.StateBuilderRuntimeException;
-
-import net.dpml.util.DOM3DocumentBuilder;
-
-import net.dpml.util.ElementHelper;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-/**
- * Construct a state graph.
- */
-public class StateDecoder
-{
- private static final String XML_HEADER =
- "<?xml version=\"1.0\"?>";
-
- private static final String STATE_SCHEMA_URN = "@STATE-XSD-URI@";
-
- private static final String STATE_HEADER =
- "<state xmlns=\""
- + STATE_SCHEMA_URN
- + "\""
- + "\n xmlns:xsi=\""
- + XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI
- + "\">";
-
- private static final String STATE_FOOTER = "</state>";
-
- private static final DOM3DocumentBuilder BUILDER = new
DOM3DocumentBuilder();
-
- /**
- * Load a state graph.
- * @param uri the graph uri
- * @return the constructed state graph
- * @exception IOException if an IO error occurs while reading the
- * graph data
- */
- public State loadState( URI uri ) throws IOException
- {
- if( null == uri )
- {
- throw new NullPointerException( "uri" );
- }
- try
- {
- final Document document = BUILDER.parse( uri );
- final Element root = document.getDocumentElement();
- return buildStateGraph( root );
- }
- catch( Throwable e )
- {
- final String error =
- "An error while attempting to load a state graph."
- + "\nURI: " + uri;
- IOException exception = new IOException( error );
- exception.initCause( e );
- throw exception;
- }
- }
-
- /**
- * Build a state graph.
- * @param element a DOM element representing the root of the state graph
- * @return the constructed state
- */
- public State buildStateGraph( Element element )
- {
- if( null == element )
- {
- throw new NullPointerException( "element" );
- }
-
- boolean terminal = ElementHelper.getBooleanAttribute( element,
"terminal" );
- DefaultTransition[] transitions = buildNestedTransitions( element );
- DefaultOperation[] operations = buildNestedOperations( element );
- DefaultInterface[] interfaces = buildNestedInterfaces( element );
- DefaultState[] states = buildNestedStates( 1, element );
- DefaultTrigger[] triggers = buildNestedTriggers( element );
- return new DefaultState(
- "root", triggers, transitions, interfaces, operations, states,
terminal );
- }
-
- private DefaultTransition[] buildNestedTransitions( Element element )
- {
- Element[] children = ElementHelper.getChildren( element,
"transition" );
- DefaultTransition[] transitions = new DefaultTransition[
children.length ];
- for( int i=0; i<children.length; i++ )
- {
- Element child = children[i];
- transitions[i] = buildTransition( child );
- }
- return transitions;
- }
-
- private DefaultOperation[] buildNestedOperations( Element element )
- {
- Element[] children = ElementHelper.getChildren( element, "operation"
);
- DefaultOperation[] operations = new DefaultOperation[
children.length ];
- for( int i=0; i<children.length; i++ )
- {
- Element child = children[i];
- operations[i] = buildOperation( child );
- }
- return operations;
- }
-
- private DefaultInterface[] buildNestedInterfaces( Element element )
- {
- Element[] children = ElementHelper.getChildren( element, "interface"
);
- DefaultInterface[] interfaces = new DefaultInterface[
children.length ];
- for( int i=0; i<children.length; i++ )
- {
- Element child = children[i];
- interfaces[i] = buildInterface( child );
- }
- return interfaces;
- }
-
- private DefaultState[] buildNestedStates( int n, Element element )
- {
- Element[] children = ElementHelper.getChildren( element, "state" );
- DefaultState[] states = new DefaultState[ children.length ];
- for( int i=0; i<children.length; i++ )
- {
- Element child = children[i];
- states[i] = buildState( n, child );
- }
- return states;
- }
-
- private DefaultTrigger[] buildNestedTriggers( Element element )
- {
- Element[] children = ElementHelper.getChildren( element, "trigger" );
- DefaultTrigger[] triggers = new DefaultTrigger[ children.length ];
- for( int i=0; i<children.length; i++ )
- {
- Element child = children[i];
- triggers[i] = buildTrigger( child );
- }
- return triggers;
- }
-
- private DefaultTransition buildTransition( Element element )
- {
- String name = ElementHelper.getAttribute( element, "name" );
- String target = ElementHelper.getAttribute( element, "target" );
- Element child = ElementHelper.getChild( element, "operation" );
- DefaultOperation operation = buildOperation( child );
- return new DefaultTransition( name, target, operation );
- }
-
- private DefaultOperation buildOperation( Element element )
- {
- if( null == element )
- {
- return null;
- }
- String name = ElementHelper.getAttribute( element, "name" );
- String method = ElementHelper.getAttribute( element, "method" );
- return new DefaultOperation( name, method );
- }
-
- private DefaultInterface buildInterface( Element element )
- {
- String classname = ElementHelper.getAttribute( element, "class" );
- return new DefaultInterface( classname );
- }
-
- private DefaultState buildState( int n, Element element )
- {
- String name = ElementHelper.getAttribute( element, "name" );
- boolean terminal = ElementHelper.getBooleanAttribute( element,
"terminal" );
- DefaultTransition[] transitions = buildNestedTransitions( element );
- DefaultOperation[] operations = buildNestedOperations( element );
- DefaultInterface[] interfaces = buildNestedInterfaces( element );
- DefaultState[] states = buildNestedStates( n+1, element );
- DefaultTrigger[] triggers = buildNestedTriggers( element );
- return new DefaultState(
- name, triggers, transitions, interfaces, operations, states,
terminal );
- }
-
- private DefaultTrigger buildTrigger( Element element )
- {
- String type = ElementHelper.getAttribute( element, "event" );
- TriggerEvent event = TriggerEvent.parse( type );
- Element child = getSingleNestedElement( element );
- Action action = buildAction( child );
- return new DefaultTrigger( event, action );
- }
-
- private Action buildAction( Element element )
- {
- String name = element.getTagName();
- if( name.equals( "transition" ) )
- {
- return buildTransition( element );
- }
- else if( name.equals( "operation" ) )
- {
- return buildOperation( element );
- }
- else if( name.equals( "apply" ) )
- {
- String id = ElementHelper.getAttribute( element, "id" );
- return new ApplyAction( id );
- }
- else if( name.equals( "exec" ) )
- {
- String id = ElementHelper.getAttribute( element, "id" );
- return new ExecAction( id );
- }
- else
- {
- final String error =
- "Illegal element name ["
- + name
- + "] supplied to action builder.";
- throw new StateBuilderRuntimeException( error );
- }
- }
-
- private Element getSingleNestedElement( Element parent )
- {
- if( null == parent )
- {
- throw new NullPointerException( "parent" );
- }
- else
- {
- Element[] children = ElementHelper.getChildren( parent );
- if( children.length == 1 )
- {
- return children[0];
- }
- else
- {
- final String error =
- "Parent element does not contain a single child.";
- throw new IllegalArgumentException( error );
- }
- }
- }
-}

Deleted:
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/StateEncoder.java
===================================================================
---
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/StateEncoder.java
2006-06-20 05:11:03 UTC (rev 1514)
+++
trunk/main/metro/state/impl/src/main/net/dpml/state/impl/StateEncoder.java
2006-06-20 05:13:57 UTC (rev 1515)
@@ -1,337 +0,0 @@
-/*
- * Copyright 2006 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.io.IOException;
-import java.io.OutputStream;
-import java.io.Writer;
-import java.io.OutputStreamWriter;
-
-import javax.xml.XMLConstants;
-
-import net.dpml.state.State;
-import net.dpml.state.Action;
-import net.dpml.state.Trigger.TriggerEvent;
-import net.dpml.state.Trigger;
-import net.dpml.state.Transition;
-import net.dpml.state.Operation;
-import net.dpml.state.Interface;
-
-/**
- * Construct a state graph.
- */
-public class StateEncoder
-{
- private static final String XML_HEADER =
- "<?xml version=\"1.0\"?>";
-
- private static final String STATE_SCHEMA_URN = "@STATE-XSD-URI@";
-
- /**
- * Externalize the part to XML.
- * @param state the state graph to externalize
- * @param output the output stream
- * @exception IOException if an IO error occurs
- */
- public void export( State state, OutputStream output ) throws IOException
- {
- final Writer writer = new OutputStreamWriter( output );
-
- writer.write( XML_HEADER );
- writer.write( "\n\n" );
- writer.write( "<state xmlns=\""
- + STATE_SCHEMA_URN
- + "\""
- + "\n xmlns:xsi=\""
- + XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI
- + "\"" );
- if( state.isTerminal() )
- {
- writer.write( " terminal=\"true\">" );
- }
- else
- {
- writer.write( ">" );
- }
- writer.write( "\n" );
- writeBody( writer, state, "" );
- writer.write( "\n" );
- writer.write( "\n</state>" );
- writer.write( "\n" );
- writer.flush();
- output.close();
- }
-
- /**
- * Write the state.
- * @param writer the stream writer
- * @param state the state to externalize
- * @param pad the pad offset
- * @exception IOException if an IO error occurs
- */
- public void writeState( Writer writer, State state, String pad ) throws
IOException
- {
- if( isEmpty( state ) )
- {
- return;
- }
- else
- {
- writer.write( "\n" + pad + "<state xmlns=\"" + STATE_SCHEMA_URN
+ "\"" );
- if( state.isTerminal() )
- {
- writer.write( " terminal=\"true\"" );
- }
- writer.write( ">" );
- writeBody( writer, state, pad + " " );
- writer.write( "\n" + pad + "</state>" );
- }
- }
-
- private void writeBody( Writer writer, State state, String pad ) throws
IOException
- {
- Trigger[] triggers = state.getTriggers();
- Transition[] transitions = state.getTransitions();
- Operation[] operations = state.getOperations();
- Interface[] interfaces = state.getInterfaces();
- State[] states = state.getStates();
-
- writeTriggers( writer, triggers, pad );
- writeTransitions( writer, transitions, pad );
- writeOperations( writer, operations, pad );
- writeInterfaces( writer, interfaces, pad );
- writeStates( writer, states, pad );
- }
-
- private void writeTriggers( Writer writer, Trigger[] triggers, String
pad ) throws IOException
- {
- if( triggers.length == 0 )
- {
- return;
- }
- else
- {
- for( int i=0; i<triggers.length; i++ )
- {
- Trigger trigger = triggers[i];
- writeTrigger( writer, trigger, pad );
- }
- }
- }
-
- private void writeTrigger( Writer writer, Trigger trigger, String pad )
throws IOException
- {
- TriggerEvent event = trigger.getEvent();
- writer.write( "\n" + pad + "<trigger event=\"" );
- writer.write( event.getName() );
- writer.write( "\">" );
- Action action = trigger.getAction();
- writeAction( writer, action, pad + " " );
- writer.write( "\n" + pad + "</trigger>" );
- }
-
- private void writeTransitions( Writer writer, Transition[] transitions,
String pad ) throws IOException
- {
- if( transitions.length == 0 )
- {
- return;
- }
- else
- {
- for( int i=0; i<transitions.length; i++ )
- {
- Transition transition = transitions[i];
- writeTransition( writer, transition, pad );
- }
- }
- }
-
- private void writeOperations( Writer writer, Operation[] operations,
String pad ) throws IOException
- {
- if( operations.length == 0 )
- {
- return;
- }
- else
- {
- for( int i=0; i<operations.length; i++ )
- {
- Operation operation = operations[i];
- writeOperation( writer, operation, pad );
- }
- }
- }
-
- private void writeInterfaces( Writer writer, Interface[] interfaces,
String pad ) throws IOException
- {
- if( interfaces.length == 0 )
- {
- return;
- }
- else
- {
- for( int i=0; i<interfaces.length; i++ )
- {
- Interface spec = interfaces[i];
- writeInterface( writer, spec, pad );
- }
- }
- }
-
- private void writeStates( Writer writer, State[] states, String pad )
throws IOException
- {
- if( states.length == 0 )
- {
- return;
- }
- else
- {
- for( int i=0; i<states.length; i++ )
- {
- State state = states[i];
- writeNestedState( writer, state, pad );
- }
- }
- }
-
- private void writeTransition( Writer writer, Transition transition,
String pad ) throws IOException
- {
- String name = transition.getName();
- String target = transition.getTargetName();
- writer.write( "\n" + pad + "<transition name=\"" + name + "\"
target=\"" + target + "\"" );
- Operation operation = transition.getOperation();
- if( null == operation )
- {
- writer.write( "/>" );
- }
- else
- {
- writer.write( ">" );
- writeOperation( writer, operation, pad + " " );
- writer.write( "\n" + pad + "</transition>" );
- }
- }
-
- private void writeOperation( Writer writer, Operation operation, String
pad ) throws IOException
- {
- String name = operation.getName();
- String method = operation.getMethodName();
- writer.write( "\n" + pad + "<operation name=\"" + name + "\"" );
- if( null != method )
- {
- writer.write( " method=\"" + method + "\"" );
- }
- writer.write( "/>" );
- }
-
- private void writeInterface( Writer writer, Interface spec, String pad )
throws IOException
- {
- String classname = spec.getClassname();
- writer.write( "\n" + pad + "<interface class=\"" + classname +
"\"/>" );
- }
-
- private void writeAction( Writer writer, Action action, String pad )
throws IOException
- {
- if( action instanceof Transition )
- {
- Transition transition = (Transition) action;
- writeTransition( writer, transition, pad );
- }
- else if( action instanceof Operation )
- {
- Operation operation = (Operation) action;
- writeOperation( writer, operation, pad );
- }
- else if( action instanceof Interface )
- {
- Interface spec = (Interface) action;
- writeInterface( writer, spec, pad );
- }
- else if( action instanceof ExecAction )
- {
- ExecAction exec = (ExecAction) action;
- writeExecAction( writer, exec, pad );
- }
- else if( action instanceof ApplyAction )
- {
- ApplyAction apply = (ApplyAction) action;
- writeApplyAction( writer, apply, pad );
- }
- else
- {
- final String error =
- "Unrecognized action class ["
- + action.getClass().getName()
- + "].";
- throw new IOException( error );
- }
- }
- private void writeExecAction( Writer writer, ExecAction action, String
pad ) throws IOException
- {
- String id = action.getID();
- writer.write( "\n" + pad + "<exec id=\"" + id + "\"/>" );
- }
-
- private void writeApplyAction( Writer writer, ApplyAction action, String
pad ) throws IOException
- {
- String id = action.getID();
- writer.write( "\n" + pad + "<apply id=\"" + id + "\"/>" );
- }
-
- private void writeNestedState( Writer writer, State state, String pad )
throws IOException
- {
- String name = state.getName();
- writer.write( "\n" + pad + "<state name=\"" + name + "\"" );
- if( state.isTerminal() )
- {
- writer.write( " terminal=\"true\">" );
- }
- else
- {
- writer.write( ">" );
- }
- writeBody( writer, state, pad + " " );
- writer.write( "\n" + pad + "</state>" );
- }
-
- private boolean isEmpty( State state )
- {
- if( state.getTriggers().length > 0 )
- {
- return false;
- }
- if( state.getTransitions().length > 0 )
- {
- return false;
- }
- if( state.getOperations().length > 0 )
- {
- return false;
- }
- if( state.getInterfaces().length > 0 )
- {
- return false;
- }
- if( state.getStates().length > 0 )
- {
- return false;
- }
- return true;
- }
-}

Deleted:
trunk/main/metro/state/impl/src/test/net/dpml/state/EmptyTestCase.java
===================================================================
--- trunk/main/metro/state/impl/src/test/net/dpml/state/EmptyTestCase.java
2006-06-20 05:11:03 UTC (rev 1514)
+++ trunk/main/metro/state/impl/src/test/net/dpml/state/EmptyTestCase.java
2006-06-20 05:13:57 UTC (rev 1515)
@@ -1,64 +0,0 @@
-/*
- * 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;
-
-import java.io.File;
-import java.net.URI;
-
-import net.dpml.state.impl.StateDecoder;
-
-import junit.framework.TestCase;
-
-/**
- * Default state machine test-case.
- *
- * @author <a href="http://www.dpml.net";>The Digital Product Meta Library</a>
- */
-public class EmptyTestCase extends TestCase
-{
- private StateDecoder m_decoder;
-
- /**
- * Testcase setup.
- * @exception Exception if a setup error occurs
- */
- public void setUp() throws Exception
- {
- m_decoder = new StateDecoder();
- }
-
- /**
- * List the state graph.
- * @exception Exception if an error occurs
- */
- public void testStateLoading() throws Exception
- {
- String testPath = System.getProperty( "project.test.dir" );
- File test = new File( testPath );
- File example = new File( test, "empty.xml" );
- URI uri = example.toURI();
- State state = m_decoder.loadState( uri );
- assertEquals( "substates", 0, state.getStates().length );
- assertEquals( "transitions", 0, state.getTransitions().length );
- assertEquals( "triggers", 0, state.getTriggers().length );
- }
-}
-
-
-

Deleted:
trunk/main/metro/state/impl/src/test/net/dpml/state/TransitionTestCase.java
===================================================================
---
trunk/main/metro/state/impl/src/test/net/dpml/state/TransitionTestCase.java
2006-06-20 05:11:03 UTC (rev 1514)
+++
trunk/main/metro/state/impl/src/test/net/dpml/state/TransitionTestCase.java
2006-06-20 05:13:57 UTC (rev 1515)
@@ -1,64 +0,0 @@
-/*
- * 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;
-
-import java.io.File;
-import java.net.URI;
-
-import net.dpml.state.impl.StateDecoder;
-
-import junit.framework.TestCase;
-
-/**
- * Default state machine test-case.
- *
- * @author <a href="http://www.dpml.net";>The Digital Product Meta Library</a>
- */
-public class TransitionTestCase extends TestCase
-{
- private StateDecoder m_decoder;
-
- /**
- * Testcase setup.
- * @exception Exception if a setup error occurs
- */
- public void setUp() throws Exception
- {
- m_decoder = new StateDecoder();
- }
-
- /**
- * List the state graph.
- * @exception Exception if an error occurs
- */
- public void testStateLoading() throws Exception
- {
- String testPath = System.getProperty( "project.test.dir" );
- File test = new File( testPath );
- File example = new File( test, "transition.xml" );
- URI uri = example.toURI();
- State state = m_decoder.loadState( uri );
- assertEquals( "substates", 0, state.getStates().length );
- assertEquals( "transitions", 3, state.getTransitions().length );
- assertEquals( "triggers", 0, state.getTriggers().length );
- }
-}
-
-
-

Deleted:
trunk/main/metro/state/impl/src/test/net/dpml/state/test/DefaultStateMachineTestCase.java
===================================================================
---
trunk/main/metro/state/impl/src/test/net/dpml/state/test/DefaultStateMachineTestCase.java
2006-06-20 05:11:03 UTC (rev 1514)
+++
trunk/main/metro/state/impl/src/test/net/dpml/state/test/DefaultStateMachineTestCase.java
2006-06-20 05:13:57 UTC (rev 1515)
@@ -1,293 +0,0 @@
-/*
- * 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.test;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-import net.dpml.state.State;
-import net.dpml.state.Transition;
-import net.dpml.state.Operation;
-import net.dpml.state.Interface;
-import net.dpml.state.Trigger;
-import net.dpml.state.Action;
-import net.dpml.state.impl.DefaultStateMachine;
-import net.dpml.state.impl.StateDecoder;
-
-import net.dpml.util.EventQueue;
-import net.dpml.util.Logger;
-import net.dpml.util.DefaultLogger;
-
-/**
- * Default state machine test-case.
- *
- * @author <a href="http://www.dpml.net";>The Digital Product Meta Library</a>
- */
-public class DefaultStateMachineTestCase extends AbstractEncodingTestCase
-{
- private State m_state;
- private EventQueue m_queue;
- private DefaultStateMachine m_machine;
- private Logger m_logger;
-
- /**
- * Testcase setup.
- * @exception Exception if a setup error occurs
- */
- public void setUp() throws Exception
- {
- String testPath = System.getProperty( "project.test.dir" );
- File test = new File( testPath );
- File example = new File( test, "example.xgraph" );
- try
- {
- StateDecoder builder = new StateDecoder();
- m_state = builder.loadState( example.toURI() );
- m_logger = new DefaultLogger( "test" );
- m_queue = new EventQueue( m_logger );
- m_machine = new DefaultStateMachine( m_queue, m_logger, m_state
);
- }
- catch( Throwable e )
- {
- e.printStackTrace();
- fail( e.toString() );
- }
- }
-
- /**
- * List the state graph.
- * @exception Exception if an error occurs
- */
- public void testAudit() throws Exception
- {
- audit( m_state );
- }
-
- /**
- * Test state machine validation function.
- * @exception Exception if an error occurs
- */
- public void testValidation() throws Exception
- {
- DefaultStateMachine.validate( m_state );
- }
-
- /**
- * Test state machine initialization and termination internal state
integrity.
- * @exception Exception if an error occurs
- */
- public void testExecution() throws Exception
- {
- // check that the termination action is null
-
- Action termination = m_machine.getTerminationAction();
- assertNull( "root-termination", termination );
-
- // check that the initialization action is correct
-
- Action action = m_machine.getInitializationAction();
- if( action instanceof Transition )
- {
- Transition transition = (Transition) action;
- String name = transition.getName();
- assertEquals( "init-transition-name", "init", name );
- }
- else
- {
- fail( "Root initialization action is not a transition." );
- }
-
- // initialize the state
-
- State state = m_machine.initialize( null );
- assertEquals( "post-init-state", "started", state.getName() );
- State machineState = m_machine.getState();
- assertEquals( "machine-state", "started", machineState.getName() );
-
- if( action != m_machine.getInitializationAction() )
- {
- fail(
- "Unexpected initialization action ["
- + m_machine.getInitializationAction()
- + "] declared by statemachine." );
- }
-
- // check that the termination action has changed to the overridden
'stop' transition
-
- termination = m_machine.getTerminationAction();
- assertNotNull( "termination-in-start", termination );
- assertEquals( "action-is-stop", "stop", termination.getName() );
-
- //
- // test if the 'stop' transition is accessible
- //
-
- Transition[] transitions = m_machine.getTransitions();
- assertEquals( "started-transition-count", 1, transitions.length );
- Transition stop = transitions[0];
- assertEquals( "stop-transition-name", "stop", stop.getName() );
-
- //
- // test available operations
- //
-
- Operation[] operations = m_machine.getOperations();
- assertEquals( "started-operation-count", 1, operations.length );
- Operation audit = operations[0];
- assertEquals( "audit-operation-name", "audit", audit.getName() );
-
- //
- // apply the stop transition
- //
-
- m_machine.apply( stop.getName(), null );
- assertEquals( "stopped-state-name", "stopped",
m_machine.getState().getName() );
-
- //
- // restart
- //
-
- m_machine.apply( "start", null );
- assertEquals( "re-started-state-name", "started",
m_machine.getState().getName() );
-
- //
- // terminate
- //
-
- m_machine.terminate( null );
- assertEquals( "terminated-state-name", "terminated",
m_machine.getState().getName() );
- }
-
- /**
- * Test illegal attempt to initialize a disposed state machine.
- * @exception Exception if an error occurs
- */
- public void testInitializationInDisposed() throws Exception
- {
- m_machine.dispose();
- try
- {
- m_machine.initialize( null );
- fail( "disposed machine allowed initialization" );
- }
- catch( IllegalStateException e )
- {
- // success
- }
- }
-
- /**
- * Test illegal attempt to terminate a disposed state machine.
- * @exception Exception if an error occurs
- */
- public void testTerminationInDisposed() throws Exception
- {
- m_machine.dispose();
- try
- {
- m_machine.terminate( null );
- fail( "disposed machine allowed termination" );
- }
- catch( IllegalStateException e )
- {
- // success
- }
- }
-
- /**
- * Test encoding of a state graph.
- * @exception Exception if an error occurs
- */
- public void testEncoding() throws Exception
- {
- Object state = executeEncodingTest( m_state );
- }
-
- private void audit( State state )
- {
- ArrayList list = new ArrayList();
- audit( list, state, "" );
- System.out.println( "" + "# -------------------" );
- }
-
- private void audit( List visited, State state, String pad )
- {
- if( visited.contains( state ) )
- {
- return;
- }
- else
- {
- visited.add( state );
- }
- System.out.println( pad + "# -------------------" );
- System.out.println( pad + "# state: [" + state.getName() + "]" );
- Trigger[] triggers = state.getTriggers();
- for( int i=0; i<triggers.length; i++ )
- {
- Trigger trigger = triggers[i];
- System.out.println(
- pad + "# trigger "
- + "(" + ( i+1 ) + "): ["
- + trigger.toString()
- + "]" );
- }
- Transition[] transitions = state.getTransitions();
- for( int i=0; i<transitions.length; i++ )
- {
- Transition transition = transitions[i];
- System.out.println(
- pad + "# transition "
- + "(" + ( i+1 ) + "): ["
- + transition.getName()
- + "] --> [" + transition.getTargetName()
- + "]" );
- }
- Interface[] classes = state.getInterfaces();
- for( int i=0; i<classes.length; i++ )
- {
- Interface interfaceDef = classes[i];
- System.out.println(
- pad + "# interface "
- + "(" + ( i+1 ) + "): ["
- + interfaceDef.getClassname()
- + "]" );
- }
- Operation[] operations = state.getOperations();
- for( int i=0; i<operations.length; i++ )
- {
- Operation operation = operations[i];
- System.out.println(
- pad + "# operation "
- + "(" + ( i+1 ) + "): ["
- + operation.getName()
- + "]" );
- }
- State[] states = state.getStates();
- for( int i=0; i<states.length; i++ )
- {
- State s = states[i];
- audit( visited, s, pad + " " );
- }
- }
-}
-
-
-




  • r1515 - in trunk/main/metro: . runtime/src/main/net/dpml/metro/runtime runtime/src/test/net/dpml/metro state/api/src/main/net/dpml/state state/api/src/test/net/dpml/state state/impl/src/main/net/dpml/state/impl state/impl/src/test/net/dpml/state state/impl/src/test/net/dpml/state/test, mcconnell at BerliOS, 06/20/2006

Archive powered by MHonArc 2.6.24.

Top of Page