All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.coos.javaframe.CompositeState Maven / Gradle / Ivy

/**
 * COOS - Connected Objects Operating System (www.connectedobjects.org).
 *
 * Copyright (C) 2009 Telenor ASA and Tellu AS. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 *
 * You may also contact one of the following for additional information:
 * Telenor ASA, Snaroyveien 30, N-1331 Fornebu, Norway (www.telenor.no)
 * Tellu AS, Hagalokkveien 13, N-1383 Asker, Norway (www.tellu.no)
 */
package org.coos.javaframe;

import org.coos.javaframe.messages.ActorMsg;

import java.util.Enumeration;
import java.util.Hashtable;

/**
 * CompositeState is a {@link State} with inner States. A CompositeState has 1
 * or more entry and exit ports that connects the CompositeState to its
 * environment. The ports are identified by an entry index or an exit index
 * (int). A CompositeState may have a default entry port (not identified by an
 * index).
 * 
 * @author Knut Eilif Husa, Tellu AS
 * @author Dag Belsnes
 */
public abstract class CompositeState extends State {

	public StateMachine curfsm;

	/**
	 * CompositeState constructor with user supplied name.
	 * 
	 * @param sn
	 *            The name of this CompositeState.
	 */
	public CompositeState(String sn, CompositeState cs) {
		super(sn, cs);
	}

	/**
	 * Sets the state name equal the class name, minus the suffux "CS"; This
	 * constructor is called from SM classes
	 */
	public CompositeState(String s) {
		super(s, null);
	}

	public Hashtable children = new Hashtable();

	// public AFPropertyMsg pm = null;

	// ####################################################################
	// Utilities to be used within the transitions, that is inside the
	// methods enterState(), execTrans(), and outofInnerCompositeState()
	// (see below).

	/**
	 * Leave this CompositeState through a given exit port. The method is to be
	 * used within the methods execTrans() or outofInnerCompositeState().
	 * 
	 * @param exitNo
	 *            Index of the exit port.
	 * @param curfsm
	 *            The current StateMachine.
	 */
	protected void exitState(int exitNo, StateMachine curfsm) {
		curfsm.exitStateIsDone = true;
		// exit(curfsm); will be run after all execTrans has been called in the
		// class hiarchi
		curfsm.setCurrentState(enclosingState);
		enclosingState.outofInnerCompositeState(this, exitNo, curfsm);
	}

	/**
	 * Execute the exit() method for states beginning from currentState up to
	 * (but not including) this CompositeState. The method is to be used within
	 * the method execTrans(). An performExit flag in StateMachine is set to
	 * enable check of inkonsistent use of nextstate and performExit in the
	 * transistion. If this method has been called before during the same
	 * transition, the call should be ignored
	 * 
	 * @param curfsm
	 *            The current StateMachine.
	 */
	protected void performExit(StateMachine curfsm) {
		if (curfsm.performExitIsDone) {
			return;
		}

		State st = curfsm.getCurrentState();
		curfsm.performExitIsDone = true;

		do {
			st.exit(curfsm); // execute exit method
			st = st.enclosingState;
		} while (this != st);

		curfsm.setCurrentState(this);
	}

	/**
	 * Execute exit() from currentState up to (but not including) this
	 * CompositeState. The method is to be used within the method execTrans() of
	 * RoleCS type. An performExit flag in StateMachine is set to enable check
	 * of inkonsistent use of nextstate and performExit in the transistion. If
	 * this method has been called before during the same transition, the call
	 * should be ignored
	 * 
	 * @param curfsm
	 *            The current StateMachine.
	 */
	protected void performExit(StateMachine curfsm, CompositeState cs) {
		if (curfsm.performExitIsDone) {
			return;
		}

		// Asume that enclosing state is not part of RoleCS, illegal use but OK
		// to run original performExit method
		if (curfsm.getScheduler().isTraceOn()) {
			curfsm.trace
					.traceWarning("Method performExit() is called with illegal Composite state, not of RoleCS type ");
		}

		if (curfsm.performExitIsDone) {
			if (curfsm.getScheduler().isTraceOn()) {
				curfsm.trace
						.traceWarning("Method sameState() is not allowed to be called, when performExit() is already called");
			}
		} else {
			curfsm.sameStateIsDone = true;
			curfsm.nextState = null;
		}
	}

	/**
	 * Remain in the same State of the StateMachine. The method is to be used
	 * within the method execTrans(). Notice that entry() of this State will not
	 * be executed. That means performExit() should neither have been called.
	 * 
	 * @param curfsm
	 *            The current StateMachine.
	 */
	protected void sameState(StateMachine curfsm) {
		if (curfsm.performExitIsDone) {
			if (curfsm.getScheduler().isTraceOn()) {
				curfsm.trace
						.traceWarning("Method sameState() is not allowed to be called, when performExit() is already called");
			}
		} else {
			curfsm.sameStateIsDone = true;
			curfsm.nextState = null;
		}
	}

	/**
	 * The received ActorMsg is not to be consumed and handled in this State and
	 * the ActorMsg is saved in order to be handled later in another State. The
	 * method is to be used within the method execTrans().
	 * 
	 * @param sig
	 *            The ActorMsg that will be saved (assumed to be != null).
	 * @param curfsm
	 *            The StateMachine that conceptually performs this operation
	 *            (assumed to be != null).
	 */
	protected void save(ActorMsg sig, StateMachine curfsm) {
		curfsm.saveDone = true;

		if (!curfsm.sameStateIsDone && !curfsm.performExitIsDone) {
			curfsm.saveQueue.addMessage(sig); // put signal into the save queue

			if (curfsm.getScheduler().isTraceOn()) {
				curfsm.trace.traceTask("Input signal saved");
			}
		} else {
			if (curfsm.getScheduler().isTraceOn()) {
				curfsm.trace.traceWarning("Method save(): Signal " + sig
						+ " not saved, because the input signal has already triggered a transition");
			}
		}
	}

	/**
	 * Finds the chilren state based on its id
	 * 
	 * @param sn
	 *            The id of the State to be looked for
	 * @return Reference to the state that is equal to the ID, otherwise it is
	 *         null
	 */
	public State findCurrentState(String sn) {
		State st = (State) children.get(sn);

		// This state does not contain this state. Ask all states below
		if (st == null) {
			Enumeration en = children.elements();

			while (en.hasMoreElements()) {
				State state = (State) en.nextElement();
				st = state.findCurrentState(sn);

				if (st != null) {
					return st;
				}
			}
		}

		return st;
	}

	/**
	 * outputs a {@link org.coos.javaframe.messages.Message} to a given (local).
	 * The method is to be used within the method enterState(), execTrans(), or
	 * outofInnerCompositeState().
	 * 
	 * @param sig
	 *            The ActorMsg to be sent.
	 * @param curfsm
	 *            The StateMachine that is conceptually performing this
	 *            operation.
	 */

	// ####################################################################
	// Methods that has to be written for each non-abstract specialization
	// of CompositeState.

	/**
	 * Enter this CompositeState through a given entry port. enterState links
	 * the given entry port with an inner State based on the value of the entry
	 * index. It may also contain optional user transition code. Note:
	 * enterState has two versions 
* - with entry port index
* - without entry port index (entry through the default entry port).
* For each CompositeState class at least one of the enterState methods has * to be redefined. NB: enterState is called from user transition code. * * @param enterNo * Index of the entry port. * @param curfsm * The current StateMachine. */ public void enterState(int enterNo, StateMachine curfsm) { throw new IllegalStateException("This method must be overriden!"); } /** * Enter this CompositeState through the default entry port. enterState * links the default entry port with an inner State. It may also contain * optional user transition code. NB: enterState is called from user * transition code. * * @param curfsm * The current StateMachine. */ public void enterState(StateMachine curfsm) { throw new IllegalStateException("This method must be overriden!"); } /** * Execute transition (if defined) for ActorMsg sig and State st. For each * CompositeState class execTrans has to be defined. It defines the * transitions (and saves) handled by its inner States (not included those * inside inner CompositeStates). NB: execTrans is not called from user * code. * * @param sig * The consumed ActorMsg. * @param st * The State to search for defined transition. * @param curfsm * The performing StateMachine. */ public abstract void execTrans(ActorMsg sig, State st, StateMachine curfsm); /** * Executes linking code when an inner CompositeState leaves through a given * exit port. For each CompositeState class with inner CompositeStates the * operation outofInnerCompositeState has to be defined. It will link the * given exit port with an inner singular State, the entry port of an inner * CompositeState, or an exit port of this CompositeState. NB: * outofInnerCompositeState is not called from user code. * * @param cs * The inner CompositeState that is leaving. * @param exNo * Index of the exit port of the inner CompositeState. * @param curfsm * The current StateMachine. */ public void outofInnerCompositeState(CompositeState cs, int exNo, StateMachine curfsm) { } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy