
p. 

==<div style="counter-reset: h1 7 h2 6">==

h2(#codegen_java_code_generator). Java code generator

h3(#codegen_java_code_generator_features). Java code generator features

==<!-- Start sgen_feature_naming -->==

h4(#codegen_java_naming_feature). Naming feature

The *Naming* feature allows the configuration of package names for the generated classes (and interfaces) as well as a prefix and/or a suffix for their names.

It is an _optional_ feature and has the following parameters:

* _basePackage_ (String, required): Package name for the generated Java classes
* _implementationSuffix_ (String, optional): Name suffix for the implementing classes

==<div class="example">==

Example:

bc. feature Naming {
    basePackage = "org.ourproject.sct"
    implementationSuffix = "Impl"
}

==</div>==

==<!-- End sgen_feature_naming -->==



==<!-- Start sgen_feature_synchronizedwrapper -->==

h4(#codegen_java_synchronizedwrapper_feature). SynchronizedWrapper feature

The *SynchronizedWrapper* feature generates a synchronized wrapper for the state machine. This is an additional Java class providing thread-safe access to the generated state machine implementation. As the wrapper adds thread safety any number of client threads may call the state machine.

It is an _optional_ feature and has the following parameters:

* _namePrefix_ (String, optional): Name prefix for the generated wrapper class
* _nameSuffix_ (String, optional): Name suffix for the generated wrapper class

==<div class="example">==

Example:

bc. feature SynchronizedWrapper {
    namePrefix = "Synchronized"
    nameSuffix = "Wrapper"
}

==</div>==

==<!-- End sgen_feature_synchronizedwrapper -->==



==<!-- Start sgen_feature_runnablewrapper -->==

h4(#codegen_java_runnablewrapper_feature). RunnableWrapper feature

The *RunnableWrapper* feature generates a runnable wrapper for the state machine. This is an additional Java class providing a thread-safe wrapper for the generated state machine implementation. In addition to the specific state machine interface it implements the _Runnable_ interface and can be executed in a thread. It implements an event queue and event-driven execution semantics. As the wrapper adds thread safety any number of client threads may call the state machine.

It is an _optional_ feature and has the following parameters:

* _namePrefix_ (String, optional): Name prefix for the generated wrapper class
* _nameSuffix_ (String, optional): Name suffix for the generated wrapper class

==<div class="example">==

Example:

bc. feature RunnableWrapper {
    namePrefix = "Runnable"
    nameSuffix = "Wrapper"
}

==</div>==

==<!-- End sgen_feature_runnablewrapper -->==



==<!-- Start sgen_feature_generalfeatures -->==

h4(#codegen_java_generalfeatures). GeneralFeatures feature

The *GeneralFeatures* feature allows to configure additional services to be generated along with the state machine. Per default, all parameters are _false_, meaning to disable the corresponding features, respectively.

*GeneralFeatures* is an _optional_ feature and has the following parameters:

* _InterfaceObserverSupport_ (Boolean, optional): Enables/disables the generation of listener interfaces for the state machine.
* _RuntimeService_ (Boolean, optional): Enables/disables the generation of a runtime service that triggers the run cycle of a cycle-based state machine.
* _TimerService_ (Boolean, optional): Enables/disables the generation of a timer service implementation using _java.util.Timer_.

==<div class="example">==

Example:

bc. feature GeneralFeatures {
    InterfaceObserverSupport = true
    RuntimeService = true
    TimerService = true
}

==</div>==

==<!-- End sgen_feature_generalfeatures -->==




h3(#codegen_java_specification_of_java_code). Specification of Java code

In order to describe the API specifications of the code generated by the YAKINDU Java generator, the explanations below are using the _Traffic Light_ sample state machine, see "figure &quot;The _Traffic Light_ sample statechart model&quot;":#codegen_java_fig_the_traffic_light_sample_statechart_model. It models a pedestrian crossing with push-button operated traffic lights ("pelican crossing").

p(#codegen_java_fig_the_traffic_light_sample_statechart_model). 
!(full)images/docu_TrafficLight.png(The _Traffic Light_ sample statechart model)!

p=. The _Traffic Light_ sample statechart model

###. You can find the Java sample project _"Traffic Light (Java)":https://github.com/Yakindu/examples/tree/master/traffic_light_java_ in the "YAKINDU Statechart Tools examples repository":https://github.com/Yakindu/examples. The Java example contains statechart, SGen model, graphical widgets, and some glue code to connect the generated code with the widgets. The graphical widgets are based on SWT.

###. To execute the Java example, run the file _CrossingDemoCycleBased.java_ as "Java Application" from the Eclipse _Run As_ context menu.



h4(#codegen_java_generated_code_files). Generated code files

Generally you will find generated code at the places specified in the SGen model, see "section &quot;Outlet&quot;":../user-guide/code_generation_intro.html#codegen_outlet_feature for details.

In the case of the traffic light example, you will find the generated code in the _src-gen_ folder.

The package _org.yakindu.sct.examples.trafficlight.cyclebased_ contains the general state machine interfaces and classes. They are needed by each particular state machine and are independend from concrete ones.



h4(#codegen_java_the_state_machine_interface). The state machine interface

Each generated state machine implements the _IStatemachine_ interface:

bc.. 
package org.yakindu.sct.examples.trafficlight;

/**
 * Basic interface for state machines.
 */
public interface IStatemachine {

	/**
	 * Initializes the state machine. Used to initialize internal variables etc.
	 */
	public void init();

	/**
	 * Enters the state machine. Sets the state machine into a defined state.
	 */
	public void enter();

	/**
	 * Exits the state machine. Leaves the state machine with a defined state.
	 */
	public void exit();

	/**
	 * Checks whether the state machine is active. 
	 * A state machine is active if it has been entered. It is inactive if it has not been entered at all or if it has been exited.
	 */
	public boolean isActive();

	/**
	 * Checks whether all active states are final. 
	 * If there are no active states then the state machine is considered being incative. In this case this method returns <code>false</code>.
	 */
	public boolean isFinal();

	/**
	* Start a run-to-completion cycle.
	*/
	public void runCycle();
}


h5(#codegen_java_fundamental_statechart_methods). Fundamental statechart methods

The generated code contains fundamental methods to initialize, enter, and exit a state machine, as well as a method to execute a run-to-completion step.

The _IStatemachine_ interface specifies the four methods _init()_, _enter()_, _exit()_, and _runCycle()_.

<ul><li><p>The _init()_ method is used to initialize the internal objects of the state machine right after its instantiation. Variables are initialized to their respective default values. If the statechart defines any initialized variables, these initializations are also done in the _init()_ method.</p></li><li><p>The _enter()_ method must be called to enter the state machine. It brings the state machine to a well-defined state.</p></li><li><p>The _exit()_ method is used to leave a state machine statefully. If for example a history state is used in one of the top regions, the last active state is stored and the state machine is left via _exit()_. Re-entering it via _enter()_ continues to work with the saved state.</p></li><li><p>The _runCycle()_ method is used to trigger a run-to-completion step in which the state machine evaluates arising events and computes possible state changes. Somewhat simplified, a run-to-completion cycle consists of the following steps:</p><ol style="list-style-type: decimal;"><li><p>Clear the list of outgoing events.</p></li><li><p>Check whether any events have occurred which are leading to a state change.</p></li><li><p>If a state change has to be done:</p><ol style="list-style-type: decimal;"><li><p>Make the present state inactive.</p></li><li><p>Execute exit actions of the present state.</p></li><li><p>Save history state, if necessary.</p></li><li><p>Execute transition actions, if any.</p></li><li><p>Execute entry actions of the new state.</p></li><li><p>Make the new state active.</p></li></ol></li><li><p>Clear the list of incoming events.</p></li></ol></li></ul>


h4(#codegen_java_time_controlled_state_machines). Time-controlled state machines

If a statechart uses timing functionality, additional classes are generated.

The traffic light example uses timing funtionality, namely _after_ clauses. To support time-controlled behavior, the interfaces _ITimerCallback_ and _ITimer_ are generated. Like _IStatemachine_, they are independend of any particular state machine and are generated in the _libraryTargetFolder_ directory, if specified. See "section &quot;Outlet&quot;":../user-guide/code_generation_intro.html#codegen_outlet_feature for details.

The generated state machine class implements the _ITimerCallback_ and has a property _timer_ of type _ITimer_. The client code must provide an _ITimer_ implementation to the state machine by calling the latter's _setTimer()_ method.

Here's an example showing how to create a new instance of the state machine (here: class _MyTimedStatemachine_), create a new instance of a timer (here: class _MyTimer_), set the latter on the former, and start the state machine by entering it:

bc. MyTimedStatemachine sm = new MyTimedStatemachine();
sm.setTimer(new MyTimer());
sm.enter(); // Enter the state machine


Timer functions generally depend on the hardware target used, therefore the proper time handling has to be implemented by the developer. In principle, for each hardware target a dedicated timer service class implementing the _ITimer_ interface has to be developed.



h4(#codegen_java_default_timer_implementation). Default timer implementation

However, upon request the Java code generator can create a default implementation of the _ITimer_ interface, and in many cases it will be sufficient. This implementation is based on _java.util.Timer_ and _java.util.TimerTask_ and should be compatible with the Oracle JVM or the OpenJDK JVM.

To generate the default timer service class, set the _TimerService_ feature in the SGen model to _true_. Example:

bc.. 
GeneratorModel for yakindu::java {

    statechart MyStateMachine {

        /* … */

        feature GeneralFeatures {
            TimerService = true
        }

    }
}

p. The generated class is named _TimerService_ and looks like this:

bc.. 
package org.yakindu.sct.examples.trafficlight;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Default timer service implementation.
 *
 */
public class TimerService implements ITimer {

	private final Timer timer = new Timer();
	
	private final List<TimeEventTask> timerTaskList = new ArrayList<TimeEventTask>();
	
	private final Lock lock = new ReentrantLock();
	
	/**
	 * Timer task that reflects a time event. It's internally used by
	 * {@link TimerService}.
	 *
	 */
	private class TimeEventTask extends TimerTask {
	
		private ITimerCallback callback;
	
		int eventID;
	
		/**
		 * Constructor for a time event.
		 *
		 * @param callback
		 *            : Set to {@code true} if event should be repeated
		 *            periodically.
		 *
		 * @param eventID
		 *            : Index position within the state machine's timeEvent
		 *            array.
		 */
		public TimeEventTask(ITimerCallback callback, int eventID) {
			this.callback = callback;
			this.eventID = eventID;
		}
	
		public void run() {
			callback.timeElapsed(eventID);
		}
	
		public boolean equals(Object obj) {
			if (obj instanceof TimeEventTask) {
				return ((TimeEventTask) obj).callback.equals(callback)
						&& ((TimeEventTask) obj).eventID == eventID;
			}
			return super.equals(obj);
		}
	}
	
	public void setTimer(final ITimerCallback callback, final int eventID,
			long time, boolean isPeriodic) {
	
		// Create a new TimerTask for given event and store it.
		TimeEventTask timerTask = new TimeEventTask(callback, eventID);
		lock.lock();
		timerTaskList.add(timerTask);
	
		// start scheduling the timer
		if (isPeriodic) {
			timer.scheduleAtFixedRate(timerTask, time, time);
		} else {
			timer.schedule(timerTask, time);
		}
		lock.unlock();
	}
	
	public void unsetTimer(ITimerCallback callback, int eventID) {
		lock.lock();
		int index = timerTaskList.indexOf(new TimeEventTask(callback, eventID));
		if (index != -1) {
			timerTaskList.get(index).cancel();
			timer.purge();
			timerTaskList.remove(index);
		}
		lock.unlock();
	}
	
	/**
	 * Cancel timer service. Use this to end possible timing threads and free
	 * memory resources.
	 */
	public void cancel() {
		lock.lock();
		timer.cancel();
		timer.purge();
		lock.unlock();
	}
}


h4(#codegen_java_timer_service). Timer service

A timer service must implement the _ITimer_ interface and must be able to maintain a number of time events and the timers associated with them. A time event is identified by a numeric ID.

If suitable, an application can use the default timer service class _TimerService_, see "section &quot;Default timer implementation&quot;":#codegen_java_default_timer_implementation for details.

The _ITimer_ interface looks like this:

bc.. 
package org.yakindu.sct.examples.trafficlight;

/**
 * Interface a timer has to implement. Use to implement your own timer
 * service.
 * 
 */
public interface ITimer {

	/**
	 * Starts the timing for a given time event id.
	 * 
	 * @param callback
	 * 			  : The target callback where the time event has to be raised.
	 * 
	 * @param eventID
	 *            : The eventID the timer should use if timed out.
	 *            
	 * @param time
	 *            : Time in milliseconds after the given time event should be
	 *            triggered
	 *            
	 * @param isPeriodic
	 * 			  : Set to true if the time event should be triggered periodically
	 */
	public void setTimer(ITimerCallback callback, int eventID, long time, boolean isPeriodic);

	/**
	 * Unset a time event.
	 * 
	 * @param callback
	 * 			: The target callback for which the time event has to be unset.
	 * 
	 * @param eventID
	 * 			: The time event id.
	 */
	public void unsetTimer(ITimerCallback callback, int eventID);
}


h5(#codegen_java_method_settimer). Method setTimer

A state machine calls the _setTimer(ITimerCallback callback, int eventID, long time, boolean isPeriodic)_ method to tell the timer service that it has to start a timer for the given _eventID_. The _time_ parameter specifies the number of milliseconds until the timer expires. When this period of time has elapsed, the timer service must raise the time event by calling the method _public void timeElapsed(int eventID)_ on the _ITimerCallback_ specified by the _callback_ parameter, i.e., usually the state machine.

It is important to keep the execution of the _setTimer()_ method short and use it only to start a timer thread, a hardware timer interrupt, or the like. Avoid any time-consuming operations like extensive computations, _Thread.sleep(…)_, waiting, etc. Otherwise the state machine execution might hang within the timer service or might not show the expected runtime behavior.

If the parameter _isPeriodic_ is _false_, the timer service raises the time event only once. If _isPeriodic_ is _true_, the timer service raises the time event every _time_ milliseconds.

h5(#codegen_java_method_unsettimer). Method unsetTimer

If the state machine calls the _unsetTimer(ITimerCallback callback, int eventID)_ method the timer service must unset the timer for the given _eventID_, i.e., the time event will not be raised.



h4(#codegen_java_raising_time_events_on_a_state_machine). Raising time events on a state machine

If a statechart is using time events, the generated Java state machine class not only implements the _IStatemachine_ interface, but it also implements the _ITimerCallback_ interface. _ITimerCallback_ is defined as follows. It specifies a single method: _public void timeElapsed(int eventID)_.

bc.. 
package org.yakindu.sct.examples.trafficlight;

/**
* Interface for state machines which use timed event triggers.
*/
public interface ITimerCallback {
	
	/**
	* Callback method if a time event occurred.
	* 
	* @param eventID
	* 			:The id of the occurred event.
	*/
	public void timeElapsed(int eventID);
}


h5(#codegen_java_method_timeelapsed). Method timeElapsed

It is the timer service's responsibility to actually raise a time event on a state machine. To do so, the timer service calls the state machine's _timeElapsed()_ method and supplies the time event's _eventID_ as a parameter. The state machine recognizes the time event and will process it during the next run cycle.

You can conclude that in order to process time events without too much latency, the runtime environment has to call the state machine's _runCycle()_ method as frequently as needed. Consider for example a time event which is raised by the timer service after 500 ms. However, if the runtime environment calls the state machine's _runCycle()_ method with a frequency of once per 1000 ms only, the event will quite likely not be processed at the correct points in time.



h4(#codegen_java_runtime_service). Runtime service

The _RuntimeService_ class maintains all state machines that are expected to execute run-to-completion steps periodically. A client application can retrieve the _RuntimeService_ singleton using _RuntimeService.getInstance()_. It can then pause, resume or cancel all state machines that are poised to run at a specified intervall.

bq. *Please note:* To enable this feature, set the _RuntimeService_ parameter of *GeneralFeatures* to _true_, see "Java: General Features":#codegen_java_generalfeatures.



h4(#codegen_java_accessing_interfaces_variables_and_events). Accessing interfaces, variables and events

The client code can read and write state machine variables and raise state machine events. In a YAKINDU statechart, variables and events are contained in so-called _interfaces_. There can be at most one default, unnamed interface plus zero or more named interfaces. In the generated Java code, these interfaces can be found as inner interface of the interface specifying the state machine. The outer interface's name is derived from the statechart's name while the inner interfaces' names are derived from the respective names of the statechart interfaces.

Let's have a look at the following sample statechart interface declaration:

bc. interface Sample:
    var a:boolean
    in event evA:boolean
    out event evB:integer


The generated interface code looks like this:

bc.. 
package org.yakindu.scr.defaultsm;
import org.yakindu.scr.IStatemachine;

public interface IDefaultSMStatemachine extends IStatemachine {
	public interface SCISample {
		public void raiseEvA(boolean value);
		public boolean isRaisedEvB();
		public long getEvBValue();
		public boolean getA();
		public void setA(boolean value);

	}

	public SCISample getSCISample();

}

p. A statechart interface is generated as an inner Java interface within the state machine interface. The Java interface's name is derived from the statechart interface's name by prepending the string @SCI@.

A special case is the unnamed statechart interface: It is generated as the Java interface _SCInterface_.

An incoming event _evA:boolean_ is generated as the raise method _raiseEvA(boolean value)_. Since the event is of type _boolean_ the method has a _boolean_ parameter.

For an outgoing event _evB:integer_ the methods _boolean isRaisedEvB()_ and _long getEvBValue()_ are generated. The former can be used to determine whether the event has been raised by the state machine or not. The latter serves to query the value of the event.

For variables, the code generator creates getter and setter methods, here _boolean getA()_ and _void setA(boolean value)_.

The code generator also creates appropriately-named getter methods in the enclosing interface, which can be used to acquire the nested interfaces, here: _SCISample getSCISample()_.

The nesting interface is implemented by the generated state machine source code. Each nested interface is implemented as an internal class of the state machine class. The latter holds instances of the nested interface implementations and provides them via getter methods. Have a look at the source code generated for the _Sample_ interface:

bc.. 
package org.yakindu.scr.defaultsm;

public class DefaultSMStatemachine implements IDefaultSMStatemachine {

	protected class SCISampleImpl implements SCISample {

		private boolean evA;

		private boolean evAValue;

		public void raiseEvA(boolean value) {
			evA = true;
			evAValue = value;
		}

		protected boolean getEvAValue() {
			if (!evA)
				throw new IllegalStateException("Illegal event value access. Event EvA is not raised!");
			return evAValue;
		}

		private boolean evB;

		private long evBValue;

		public boolean isRaisedEvB() {
			return evB;
		}

		protected void raiseEvB(long value) {
			evB = true;
			evBValue = value;
		}

		public long getEvBValue() {
			if (!evB)
				throw new IllegalStateException("Illegal event value access. Event EvB is not raised!");
			return evBValue;
		}

		private boolean a;

		public boolean getA() {
			return a;
		}

		public void setA(boolean value) {
			this.a = value;
		}

		protected void clearEvents() {
			evA = false;
		}

		protected void clearOutEvents() {
			evB = false;
		}
	}

	protected SCISampleImpl sCISample;

	private boolean initialized = false;

	public enum State {
		main_region_MyState, $NullState$
	};

	private final State[] stateVector = new State[1];

	private int nextStateIndex;

	public DefaultSMStatemachine() {

		sCISample = new SCISampleImpl();
	}

	public void init() {
		this.initialized = true;
		for (int i = 0; i < 1; i++) {
			stateVector[i] = State.$NullState$;
		}

		clearEvents();
		clearOutEvents();

		sCISample.setA(false);
	}

	public void enter() {
		if (!initialized)
			throw new IllegalStateException(
					"The state machine needs to be initialized first by calling the init() function.");

		enterSequence_main_region_default();
	}

	public void exit() {
		exitSequence_main_region();
	}

	/**
	 * @see IStatemachine#isActive()
	 */
	public boolean isActive() {

		return stateVector[0] != State.$NullState$;
	}

	/** 
	* Always returns 'false' since this state machine can never become final.
	*
	 * @see IStatemachine#isFinal() 
	 */
	public boolean isFinal() {
		return false;
	}

	/**
	* This method resets the incoming events (time events included).
	*/
	protected void clearEvents() {
		sCISample.clearEvents();

	}

	/**
	* This method resets the outgoing events.
	*/
	protected void clearOutEvents() {
		sCISample.clearOutEvents();
	}

	/**
	* Returns true if the given state is currently active otherwise false.
	*/
	public boolean isStateActive(State state) {
		switch (state) {
			case main_region_MyState :
				return stateVector[0] == State.main_region_MyState;
			default :
				return false;
		}
	}

	public SCISample getSCISample() {
		return sCISample;
	}

	/* 'default' enter sequence for state MyState */
	private void enterSequence_main_region_MyState_default() {
		nextStateIndex = 0;
		stateVector[0] = State.main_region_MyState;
	}

	/* 'default' enter sequence for region main region */
	private void enterSequence_main_region_default() {
		react_main_region__entry_Default();
	}

	/* Default exit sequence for state MyState */
	private void exitSequence_main_region_MyState() {
		nextStateIndex = 0;
		stateVector[0] = State.$NullState$;
	}

	/* Default exit sequence for region main region */
	private void exitSequence_main_region() {
		switch (stateVector[0]) {
			case main_region_MyState :
				exitSequence_main_region_MyState();
				break;

			default :
				break;
		}
	}

	/* The reactions of state MyState. */
	private void react_main_region_MyState() {
	}

	/* Default react sequence for initial entry  */
	private void react_main_region__entry_Default() {
		enterSequence_main_region_MyState_default();
	}

	public void runCycle() {
		if (!initialized)
			throw new IllegalStateException(
					"The state machine needs to be initialized first by calling the init() function.");

		clearOutEvents();

		for (nextStateIndex = 0; nextStateIndex < stateVector.length; nextStateIndex++) {

			switch (stateVector[nextStateIndex]) {
				case main_region_MyState :
					react_main_region_MyState();
					break;
				default :
					// $NullState$
			}
		}

		clearEvents();
	}
}

p. The value of an event can be accessed only if the event has been processed in a run-to-completion step. Otherwise an _IllegalStateException_ will be thrown.


h4(#codegen_java_interface_observers). Interface observers

If the general feature _InterfaceObserverSupport_ is enabled in the SGen model, the generated interfaces will support the registration of observers.

Enabling the _InterfaceObserverSupport_ feature looks like this in the _.sgen_ file:

bc. feature GeneralFeatures {
    InterfaceObserverSupport = true
}

Now the generated code has additional features:

bc.. 
package org.yakindu.scr.defaultsm;
import java.util.List;
import org.yakindu.scr.IStatemachine;

public interface IDefaultSMStatemachine extends IStatemachine {
	public interface SCISample {
		public void raiseEvA(boolean value);
		public boolean isRaisedEvB();
		public long getEvBValue();
		public boolean getA();
		public void setA(boolean value);
		public List<SCISampleListener> getListeners();

	}

	public interface SCISampleListener {
		public void onEvBRaised(long value);
	}

	public SCISample getSCISample();

}

p. An additional listener interface is generated, here _SCISampleListener_. It contains a callback method for each outgoing event. Here it is a single one: _void onEvBRaised(long value)_.

The client code has to provide an implementation of the listener interface. A listener method gets called by the state machine when it raises an outgoing event.

To register or unregister a listener, use the _getListeners()_ method of the nesting interface. This method returns a _java.util.List_ parameterized with the appropriate listener type. Initially this list is empty. Add or remove listeners as needed.

A callback method specified by the listener interface should complete its operations quickly, because otherwise the state machine execution might be delayed for too long, potentially leading to unexpected runtime behavior.


h4(#codegen_java_operation_callback). Operation callbacks

YAKINDU Statechart Tools support _operations_ that are executed by a state machine as actions, but are implemented by client-side code. The figure below shows a sample statechart using an operation:

!images/docu_operationExample.png(Specifying an operation callback in the model)!

p=. Specifying an operation callback in the model

Let's have a look at the generated code:

bc.. 
package org.yakindu.scr.defaultsm;
import java.util.List;
import org.yakindu.scr.IStatemachine;

public interface IDefaultSMStatemachine extends IStatemachine {
	public interface SCISample {
		public void raiseEvA(boolean value);
		public boolean isRaisedEvB();
		public long getEvBValue();
		public boolean getA();
		public void setA(boolean value);
		public List<SCISampleListener> getListeners();

		public void setSCISampleOperationCallback(SCISampleOperationCallback operationCallback);
	}

	public interface SCISampleListener {
		public void onEvBRaised(long value);
	}

	public interface SCISampleOperationCallback {
		public long myOperation(long p1, boolean p2);
	}

	public SCISample getSCISample();

}

p. An additional interface _SCISampleOperationCallback_ specifying the method _public long myOperation(long p1, boolean p2)_ has been generated. The client code has to

* provide an implementation of this interface and
* pass an instance of it to the state machine via the _setSCISampleOperationCallback(SCISampleOperationCallback operationCallback)_ method.

Here's some sample code that passes an implementation of the operation to a state machine, and then executes the latter:

bc.. 
public static void main(String[] args) {
    DefaultSMStatemachine statemachine = new DefaultSMStatemachine();

    SCISampleOperationCallback callback = new SCISampleOperationCallback() {

        @Override
        public long myOperation(long p1, boolean p2) {
            // Your operation code should be placed here;
            return 0;
        }
    };

    statemachine.getSCISample().setSCISampleOperationCallback(callback);

    statemachine.init();
    statemachine.enter();
    statemachine.runCycle();
}



h4(#codegen_java_integrating_generated_code). Integrating generated code

To get a clue how to integrate a generated Java state machine with your project, have a look at the _CrossingDemoCycleBased_ class and its abstract superclass _CrossingDemoBase_. The _main()_ method is in _CrossingDemoCycleBased_:

bc.. 
public static void main(String[] args) {

    new CrossingDemoCycleBased().runTrafficLight();
}

p. A new instance of the class is created and the method _runTrafficLight()_ is called. This method can be found in the superclass:

bc.. 
public void runTrafficLight() {

        setUpAndRunStatemachine();
        createUIContent();

        shell.open();
        while (!shell.isDisposed()) {
            // update traffic lights
            readStatemachineOutput();

            crossing.repaint();

            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }

        tearDownStatemachine();
}

p. This method sets up the state machine and creates the GUI content. In a _while_ loop it reads the content of the state machine and repaints the GUI. If the user exits the GUI shell, the loop terminates and the state machine is torn down. The really interesting methods are _setUpAndRunStatemachine()_, _readStatemachineOutput()_, and _tearDownStatemachine()_:

bc.. 
protected void setUpAndRunStatemachine() {

    statemachine = new TrafficLightStatemachine();
    statemachine.setTimerService(new TimerService());
    statemachine.init();
    statemachine.enter();

    RuntimeService.getInstance().registerStatemachine(statemachine, 100);
}

p. First a new instance of the generated state machine is created. Since the traffic light statechart uses timing clauses, it is provided with a timer service, here with the default implementation of the _ITimerService_ interface. In the next steps the state machine is initialized and entered. After the _enter()_ method has been executed, the machine is in a defined state.

Finally the state machine is passed to the runtime service. This service executes the _runCycle()_ method of the state machine every 100 ms, that is the state machine executes a run-to-completion step every 100 ms.

bc. protected void readStatemachineOutput() {
    trafficLightFigure.setRed(statemachine.getSCITrafficLight()
            .getRed());
    trafficLightFigure.setYellow(statemachine.getSCITrafficLight()
            .getYellow());
    trafficLightFigure.setGreen(statemachine.getSCITrafficLight()
            .getGreen());
        pedestrianLightFigure.setWhite(statemachine.getSCIPedestrian()
            .getRequest());
    pedestrianLightFigure.setRed(statemachine.getSCIPedestrian()
            .getRed());
    pedestrianLightFigure.setGreen(statemachine.getSCIPedestrian()
            .getGreen());
}

The generated code contains getters and setters for each variable and event. So it's easy to read values from or write values to a state machine, raise events, or ask the state machine whether outgoing events have been raised during the last run-to-completion step. Within the _readStatemachineOutput()_ method, these methods are used to get the lights values from the state machine and set them to the UI elements. The methods _pedestrianRequestButtonClicked()_ and _onOffButtonClicked()_ raise some events.

bq. *Hint:* When outgoing events are raised within the state machine, they remain active until the next run-to-completion step is started.

bc. @Override
protected void tearDownStatemachine() {
    // End TimerHandler and RuntimeService.
    statemachine.getTimerService().cancel();
    RuntimeService.getInstance().cancelTimer();
}

If the UI thread has been terminated by the user, the state machine will be shut down. It is necessary to explicitly end the timer service. Finally the runtime service is cancelled.



h4(#codegen_java_simulating_operations_with_custom_java_code). Simulating operations with custom Java code

To simulate a model with operations it is possible to use custom Java code that mocks the desired behavior or even to simulate against an existing Java backend. For this purpose it is required to provide one or more custom Java classes having a method with a matching signature.

!images/docu_java_simulating_operation_010_statechart_with_operation.png(A statechart model with an operation)!

p=. A statechart model with an operation

To simulate the statechart above, a new Java class must be created matching the method signature defined in the statechart. This class must be placed onto the classpath of the statecharts project.

YAKINDU Statechart Tools' default types are mapped to Java types as follows:

table{border:1px solid black}.
|*YSCT type* |  |*Java type*  |
|integer|→|long|
|real|→|double|
|boolean|→|boolean|
|string|→|String|
|void|→|void| 
 
bc. 
package example;
public class Calculator {
   public long add(long param1, long param2) {
      return param1 + param2;
   }
}

This custom class can be passed to Eclipse's run configuration as an _Operation Class_, see the figure below. It is possible to specify multiple Java classes, separated by comma.

When the simulation is executed, the variable _result_ gets the value 2.

!images/docu_java_simulating_operation_020_run_configuration.png(Configuring an operations class)!

p=. Configuring an operations class

==</div>==
