diff options
Diffstat (limited to 'src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm')
13 files changed, 996 insertions, 0 deletions
diff --git a/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/Action.java b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/Action.java new file mode 100644 index 0000000..296602e --- /dev/null +++ b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/Action.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.corba.se.spi.orbutil.fsm; + +/** + * Description goes here + * + * @author Ken Cavanaugh + */ +public interface Action +{ + /** Called by the state engine to perform an action + * before a state transition takes place. The FSM is + * passed so that the Action may set the next state in + * cases when that is required. FSM and Input together + * allow actions to be written that depend on the state and + * input, but this should generally be avoided, as the + * reason for a state machine in the first place is to cleanly + * separate the actions and control flow. Note that an + * action should complete in a timely manner. If the state machine + * is used for concurrency control with multiple threads, the + * action must not allow multiple threads to run simultaneously + * in the state machine, as the state could be corrupted. + * Any exception thrown by the Action for the transition + * will be propagated to doIt. + * @param fsm the state machine causing this action. + * @param in the input that caused the transition. + */ + public void doIt( FSM fsm, Input in ) ; +} + +// end of Action.java diff --git a/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/ActionBase.java b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/ActionBase.java new file mode 100644 index 0000000..5b590eb --- /dev/null +++ b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/ActionBase.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.corba.se.spi.orbutil.fsm ; + +import com.sun.corba.se.impl.orbutil.fsm.NameBase ; + +public abstract class ActionBase extends NameBase implements Action { + public ActionBase( String name ) { super( name ) ; } +} diff --git a/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/FSM.java b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/FSM.java new file mode 100644 index 0000000..4ca832f --- /dev/null +++ b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/FSM.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.corba.se.spi.orbutil.fsm ; + +/** + * An FSM is used to represent an instance of a finite state machine + * which has a transition function represented by an instance of + * StateEngine. An instance of an FSM may be created either by calling + * StateEngine.makeFSM( startState ) on a state engine, or by extending FSMImpl and + * using a constructor. Using FSMImpl as a base class is convenient if + * additional state is associated with the FSM beyond that encoded + * by the current state. This is especially convenient if an action + * needs some additional information. For example, counters are best + * handled by special actions rather than encoding a bounded counter + * in a state machine. It is also possible to create a class that + * implements the FSM interface by delegating to an FSM instance + * created by StateEngine.makeFSM. + * + * @author Ken Cavanaugh + */ +public interface FSM +{ + /** Get the current state of this FSM. + */ + public State getState() ; + + /** Perform the action and transition to the next state based + * on the current state of the FSM and the input. + */ + public void doIt( Input in ) ; +} + +// end of FSM.java diff --git a/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/FSMImpl.java b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/FSMImpl.java new file mode 100644 index 0000000..1674eba --- /dev/null +++ b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/FSMImpl.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.corba.se.spi.orbutil.fsm ; + +import java.util.Set ; +import java.util.HashSet ; + +import com.sun.corba.se.spi.orbutil.fsm.Input ; +import com.sun.corba.se.spi.orbutil.fsm.StateEngine ; +import com.sun.corba.se.impl.orbutil.fsm.StateEngineImpl ; +import com.sun.corba.se.impl.orbutil.ORBUtility ; +import com.sun.corba.se.spi.orbutil.fsm.FSM ; + +/** + * This is the main class that represents an instance of a state machine + * using a state engine. It may be used as a base class, in which case + * the guards and actions have access to the derived class. + * + * @author Ken Cavanaugh + */ +public class FSMImpl implements FSM +{ + private boolean debug ; + private State state ; + private StateEngineImpl stateEngine ; + + /** Create an instance of an FSM using the StateEngine + * in a particular start state. + */ + public FSMImpl( StateEngine se, State startState ) + { + this( se, startState, false ) ; + } + + public FSMImpl( StateEngine se, State startState, boolean debug ) + { + state = startState ; + stateEngine = (StateEngineImpl)se ; + this.debug = debug ; + } + + /** Return the current state. + */ + public State getState() + { + return state ; + } + + /** Perform the transition for the given input in the current state. This proceeds as follows: + * <p>Let S be the current state of the FSM. + * If there are guarded actions for S with input in, evaluate their guards successively until + * all have been evaluted, or one returns a non-DISABLED Result. + * <ol> + * <li>If a DEFERED result is returned, retry the input + * <li>If a ENABLED result is returned, the action for the guarded action + * is the current action + * <li>Otherwise there is no enabled action. If S has a default action and next state, use them; otherwise + * use the state engine default action (the next state is always the current state). + * </ol> + * After the action is available, the transition proceeds as follows: + * <ol> + * <li>If the next state is not the current state, execute the current state postAction method. + * <li>Execute the action. + * <li>If the next state is not the current state, execute the next state preAction method. + * <li>Set the current state to the next state. + * </ol> + */ + public void doIt( Input in ) + { + stateEngine.doIt( this, in, debug ) ; + } + + // Methods for use only by StateEngineImpl + + public void internalSetState( State nextState ) + { + if (debug) { + ORBUtility.dprint( this, "Calling internalSetState with nextState = " + + nextState ) ; + } + + state = nextState ; + + if (debug) { + ORBUtility.dprint( this, "Exiting internalSetState with state = " + + state ) ; + } + } +} + +// end of FSMImpl.java diff --git a/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/FSMTest.java b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/FSMTest.java new file mode 100644 index 0000000..1f3f36d --- /dev/null +++ b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/FSMTest.java @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.corba.se.spi.orbutil.fsm ; + +import com.sun.corba.se.spi.orbutil.fsm.Input ; +import com.sun.corba.se.spi.orbutil.fsm.Action ; +import com.sun.corba.se.spi.orbutil.fsm.Guard ; +import com.sun.corba.se.spi.orbutil.fsm.StateEngine ; +import com.sun.corba.se.spi.orbutil.fsm.StateImpl ; +import com.sun.corba.se.spi.orbutil.fsm.StateEngineFactory ; +import com.sun.corba.se.spi.orbutil.fsm.FSM ; + +class TestInput { + TestInput( Input value, String msg ) + { + this.value = value ; + this.msg = msg ; + } + + public String toString() + { + return "Input " + value + " : " + msg ; + } + + public Input getInput() + { + return value ; + } + + Input value ; + String msg ; +} + +class TestAction1 implements Action +{ + public void doIt( FSM fsm, Input in ) + { + System.out.println( "TestAction1:" ) ; + System.out.println( "\tlabel = " + label ) ; + System.out.println( "\toldState = " + oldState ) ; + System.out.println( "\tnewState = " + newState ) ; + if (label != in) + throw new Error( "Unexcepted Input " + in ) ; + if (oldState != fsm.getState()) + throw new Error( "Unexpected old State " + fsm.getState() ) ; + } + + public TestAction1( State oldState, Input label, State newState ) + { + this.oldState = oldState ; + this.newState = newState ; + this.label = label ; + } + + private State oldState ; + private Input label ; + private State newState ; +} + +class TestAction2 implements Action +{ + private State oldState ; + private State newState ; + + public void doIt( FSM fsm, Input in ) + { + System.out.println( "TestAction2:" ) ; + System.out.println( "\toldState = " + oldState ) ; + System.out.println( "\tnewState = " + newState ) ; + System.out.println( "\tinput = " + in ) ; + if (oldState != fsm.getState()) + throw new Error( "Unexpected old State " + fsm.getState() ) ; + } + + public TestAction2( State oldState, State newState ) + { + this.oldState = oldState ; + this.newState = newState ; + } +} + +class TestAction3 implements Action { + private State oldState ; + private Input label ; + + public void doIt( FSM fsm, Input in ) + { + System.out.println( "TestAction1:" ) ; + System.out.println( "\tlabel = " + label ) ; + System.out.println( "\toldState = " + oldState ) ; + if (label != in) + throw new Error( "Unexcepted Input " + in ) ; + } + + public TestAction3( State oldState, Input label ) + { + this.oldState = oldState ; + this.label = label ; + } +} + +class NegateGuard implements Guard { + Guard guard ; + + public NegateGuard( Guard guard ) + { + this.guard = guard ; + } + + public Guard.Result evaluate( FSM fsm, Input in ) + { + return guard.evaluate( fsm, in ).complement() ; + } +} + +class MyFSM extends FSMImpl { + public MyFSM( StateEngine se ) + { + super( se, FSMTest.STATE1 ) ; + } + + public int counter = 0 ; +} + +public class FSMTest { + public static final State STATE1 = new StateImpl( "1" ) ; + public static final State STATE2 = new StateImpl( "2" ) ; + public static final State STATE3 = new StateImpl( "3" ) ; + public static final State STATE4 = new StateImpl( "4" ) ; + + public static final Input INPUT1 = new InputImpl( "1" ) ; + public static final Input INPUT2 = new InputImpl( "2" ) ; + public static final Input INPUT3 = new InputImpl( "3" ) ; + public static final Input INPUT4 = new InputImpl( "4" ) ; + + private Guard counterGuard = new Guard() { + public Guard.Result evaluate( FSM fsm, Input in ) + { + MyFSM mfsm = (MyFSM) fsm ; + return Guard.Result.convert( mfsm.counter < 3 ) ; + } + } ; + + private static void add1( StateEngine se, State oldState, Input in, State newState ) + { + se.add( oldState, in, new TestAction1( oldState, in, newState ), newState ) ; + } + + private static void add2( StateEngine se, State oldState, State newState ) + { + se.setDefault( oldState, new TestAction2( oldState, newState ), newState ) ; + } + + public static void main( String[] args ) + { + TestAction3 ta3 = new TestAction3( STATE3, INPUT1 ) ; + + StateEngine se = StateEngineFactory.create() ; + add1( se, STATE1, INPUT1, STATE1 ) ; + add2( se, STATE1, STATE2 ) ; + + add1( se, STATE2, INPUT1, STATE2 ) ; + add1( se, STATE2, INPUT2, STATE2 ) ; + add1( se, STATE2, INPUT3, STATE1 ) ; + add1( se, STATE2, INPUT4, STATE3 ) ; + + se.add( STATE3, INPUT1, ta3, STATE3 ) ; + se.add( STATE3, INPUT1, ta3, STATE4 ) ; + add1( se, STATE3, INPUT2, STATE1 ) ; + add1( se, STATE3, INPUT3, STATE2 ) ; + add1( se, STATE3, INPUT4, STATE2 ) ; + + MyFSM fsm = new MyFSM( se ) ; + TestInput in11 = new TestInput( INPUT1, "1.1" ) ; + TestInput in12 = new TestInput( INPUT1, "1.2" ) ; + TestInput in21 = new TestInput( INPUT2, "2.1" ) ; + TestInput in22 = new TestInput( INPUT2, "2.2" ) ; + TestInput in31 = new TestInput( INPUT3, "3.1" ) ; + TestInput in32 = new TestInput( INPUT3, "3.2" ) ; + TestInput in33 = new TestInput( INPUT3, "3.3" ) ; + TestInput in41 = new TestInput( INPUT4, "4.1" ) ; + + fsm.doIt( in11.getInput() ) ; + fsm.doIt( in12.getInput() ) ; + fsm.doIt( in41.getInput() ) ; + fsm.doIt( in11.getInput() ) ; + fsm.doIt( in22.getInput() ) ; + fsm.doIt( in31.getInput() ) ; + fsm.doIt( in33.getInput() ) ; + fsm.doIt( in41.getInput() ) ; + fsm.doIt( in41.getInput() ) ; + fsm.doIt( in41.getInput() ) ; + fsm.doIt( in22.getInput() ) ; + fsm.doIt( in32.getInput() ) ; + fsm.doIt( in41.getInput() ) ; + fsm.doIt( in11.getInput() ) ; + fsm.doIt( in12.getInput() ) ; + fsm.doIt( in11.getInput() ) ; + fsm.doIt( in11.getInput() ) ; + fsm.doIt( in11.getInput() ) ; + fsm.doIt( in11.getInput() ) ; + fsm.doIt( in11.getInput() ) ; + } +} diff --git a/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/Guard.java b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/Guard.java new file mode 100644 index 0000000..2fd467c --- /dev/null +++ b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/Guard.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.corba.se.spi.orbutil.fsm; + +/** + * + * @author Ken Cavanaugh + */ +public interface Guard +{ + public static final class Complement extends GuardBase { + private Guard guard ; + + public Complement( GuardBase guard ) + { + super( "not(" + guard.getName() + ")" ) ; + this.guard = guard ; + } + + public Result evaluate( FSM fsm, Input in ) + { + return guard.evaluate( fsm, in ).complement() ; + } + } + + public static final class Result { + private String name ; + + private Result( String name ) + { + this.name = name ; + } + + public static Result convert( boolean res ) + { + return res ? ENABLED : DISABLED ; + } + + public Result complement() + { + if (this == ENABLED) + return DISABLED ; + else if (this == DISABLED) + return ENABLED ; + else + return DEFERED ; + } + + public String toString() + { + return "Guard.Result[" + name + "]" ; + } + + public static final Result ENABLED = new Result( "ENABLED" ) ; + public static final Result DISABLED = new Result( "DISABLED" ) ; + public static final Result DEFERED = new Result( "DEFERED" ) ; + } + + /** Called by the state engine to determine whether a + * transition is enabled, defered, or disabled. + * The result is interpreted as follows: + * <ul> + * <li>ENABLED if the transition is ready to proceed + * <li>DISABLED if the transition is not ready to proceed + * <li>DEFERED if the action associated with the transition + * is to be deferred. This means that the input will not be + * acted upon, but rather it will be saved for later execution. + * Typically this is implemented using a CondVar wait, and the + * blocked thread represents the defered input. The defered + * input is retried when the thread runs again. + * </ul> + * + * @param fsm is the state machine causing this action. + * @param in is the input that caused the transition. + */ + public Result evaluate( FSM fsm, Input in ) ; +} + +// end of Action.java diff --git a/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/GuardBase.java b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/GuardBase.java new file mode 100644 index 0000000..b84abb9 --- /dev/null +++ b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/GuardBase.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.corba.se.spi.orbutil.fsm ; + +import com.sun.corba.se.impl.orbutil.fsm.NameBase ; + +public abstract class GuardBase extends NameBase implements Guard { + public GuardBase( String name ) { super( name ) ; } +} diff --git a/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/Input.java b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/Input.java new file mode 100644 index 0000000..9f39958 --- /dev/null +++ b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/Input.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.corba.se.spi.orbutil.fsm; + +/** + * This interface must be implemented by any class that is used as + * an input to a FSM. The FSM only needs the identity of this + * object, so all that is really needs is the default equals implementation. + * The toString() method should also be overridden to give a concise + * description or name of the input. + * + * @author Ken Cavanaugh + */ +public interface Input +{ +} + +// end of Input.java diff --git a/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/InputImpl.java b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/InputImpl.java new file mode 100644 index 0000000..28bbe86 --- /dev/null +++ b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/InputImpl.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.corba.se.spi.orbutil.fsm ; + +import com.sun.corba.se.impl.orbutil.fsm.NameBase ; + +public class InputImpl extends NameBase implements Input { + public InputImpl( String name ) { super( name ) ; } +} diff --git a/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/State.java b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/State.java new file mode 100644 index 0000000..53ea514 --- /dev/null +++ b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/State.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.corba.se.spi.orbutil.fsm ; + +/** + * This interface must be implemented by any class that is used as + * a state in a FSM. The FSM only needs the identity of this + * object, so all that is really needs is the default equals implementation. + * The toString() method should also be overridden to give a concise + * description or name of the state. The StateImpl class handles this. + * <P> + * Pre- and post- actions are taken only on completed transitions between + * different states. Assume that the FSM is in state A, and the FSM will + * transition to state B under input I with action X. If A != B and X completes + * successfully, then after X completes execution, A.postAction is executed, + * followed by B.preAction. + * + * @author Ken Cavanaugh + */ +public interface State +{ + /** Method that defines action that occurs whenever this state is entered. + * Any exceptions thrown by this method are ignored. + */ + void preAction( FSM fsm ) ; + + /** Method that defines action that occurs whenever this state is exited. + * Any exceptions thrown by this method are ignored. + */ + void postAction( FSM fsm ) ; +} + +// end of State.java diff --git a/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/StateEngine.java b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/StateEngine.java new file mode 100644 index 0000000..e9d8624 --- /dev/null +++ b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/StateEngine.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.corba.se.spi.orbutil.fsm; + +/** + * A StateEngine defines the state transition function for a + * finite state machine (FSM). A FSM always has a current state. + * In response to an Input, the FSM performs an Action and + * makes a transition to a new state. Note that any object can + * be used as an input if it supports the Input interface. + * For example, a protocol message may be an input. The FSM + * uses only the result of calling getLabel on the Input to + * drive the transition. + * <p> + * The function can be non-deterministic + * in that the same input may cause transitions to different new + * states from the current state. In this case, the action that + * is executed for the transition must set the correct new state. + * + * @author Ken Cavanaugh + */ +public interface StateEngine +{ + /** Add a new transition (old,in,guard,act,new) to the state engine. + * Multiple calls to add with the same old and in are permitted, + * in which case only a transition in which the guard evaluates to + * true will be taken. If no such transition is enabled, a default + * will be taken. If more than one transition is enabled, one will + * be chosen arbitrarily. + * This method can only be called before done(). An attempt to + * call it after done() results in an IllegalStateException. + */ + public StateEngine add( State oldState, Input input, Guard guard, + Action action, State newState ) throws IllegalStateException ; + + /** Add a transition with a guard that always evaluates to true. + */ + public StateEngine add( State oldState, Input input, + Action action, State newState ) throws IllegalStateException ; + + /** Set the default transition and action for a state. + * This transition will be used if no more specific transition was + * defined for the actual input. Repeated calls to this method + * simply change the default. + * This method can only be called before done(). An attempt to + * call it after done() results in an IllegalStateException. + */ + public StateEngine setDefault( State oldState, Action action, State newState ) + throws IllegalStateException ; + + /** Equivalent to setDefault( oldState, act, newState ) where act is an + * action that does nothing. + */ + public StateEngine setDefault( State oldState, State newState ) + throws IllegalStateException ; + + /** Euaivalent to setDefault( oldState, oldState ) + */ + public StateEngine setDefault( State oldState ) + throws IllegalStateException ; + + /** Set the default action used in this state engine. This is the + * action that is called whenever there is no applicable transition. + * Normally this would simply flag an error. This method can only + * be called before done(). An attempt to + * call it after done() results in an IllegalStateException. + */ + public void setDefaultAction( Action act ) throws IllegalStateException ; + + /** Called after all transitions have been added to the state engine. + * This provides an opportunity for the implementation to optimize + * its representation before the state engine is used. This method + * may only be called once. An attempt to call it more than once + * results in an IllegalStateException. + */ + public void done() throws IllegalStateException ; + + /** Create an instance of a FSM that uses this state engine. + * The initial state of the FSM will be the stateState specified + * here. This method can only be called after done(). An attempt + * to call it before done results in an IllegalStateException. + */ + public FSM makeFSM( State startState ) throws IllegalStateException ; +} + +// end of StateEngine.java diff --git a/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/StateEngineFactory.java b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/StateEngineFactory.java new file mode 100644 index 0000000..d2e8f2b --- /dev/null +++ b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/StateEngineFactory.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.corba.se.spi.orbutil.fsm; + +import com.sun.corba.se.impl.orbutil.fsm.StateEngineImpl ; + +/** + * Factory for creating the standard state machine implementation. + * + * @author Ken Cavanaugh + */ +public class StateEngineFactory { + private StateEngineFactory() {} + + public static StateEngine create() + { + return new StateEngineImpl() ; + } +} diff --git a/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/StateImpl.java b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/StateImpl.java new file mode 100644 index 0000000..49df29a --- /dev/null +++ b/src/java.corba/share/classes/com/sun/corba/se/spi/orbutil/fsm/StateImpl.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.corba.se.spi.orbutil.fsm ; + +import com.sun.corba.se.impl.orbutil.fsm.NameBase ; + +import java.util.Map ; +import java.util.HashMap ; +import java.util.Set ; +import java.util.HashSet ; + +import com.sun.corba.se.impl.orbutil.fsm.GuardedAction ; +import com.sun.corba.se.impl.orbutil.fsm.NameBase ; + +/** Base class for all states in a StateEngine. This must be used +* as the base class for all states in transitions added to a StateEngine. +*/ +public class StateImpl extends NameBase implements State { + private Action defaultAction ; + private State defaultNextState ; + private Map inputToGuardedActions ; + + public StateImpl( String name ) + { + super( name ) ; + defaultAction = null ; + inputToGuardedActions = new HashMap() ; + } + + public void preAction( FSM fsm ) + { + } + + public void postAction( FSM fsm ) + { + } + + // Methods for use only by StateEngineImpl. + + public State getDefaultNextState() + { + return defaultNextState ; + } + + public void setDefaultNextState( State defaultNextState ) + { + this.defaultNextState = defaultNextState ; + } + + public Action getDefaultAction() + { + return defaultAction ; + } + + public void setDefaultAction( Action defaultAction ) + { + this.defaultAction = defaultAction ; + } + + public void addGuardedAction( Input in, GuardedAction ga ) + { + Set gas = (Set)inputToGuardedActions.get( in ) ; + if (gas == null) { + gas = new HashSet() ; + inputToGuardedActions.put( in, gas ) ; + } + + gas.add( ga ) ; + } + + public Set getGuardedActions( Input in ) + { + return (Set)inputToGuardedActions.get( in ) ; + } +} |