Code Generator API

With YAKINDU Statecharts 4.0, the way the client API is generated slightly changed. These incompatible changes were introduced to have a more concise Application Programming Interface. This chapter explains in detail how to migrate client code to the new generated API.

Migrating all Code Generators

Out events

The default API to access out events changed. In 3.x releases out events must be checked using event isRaised() methods. With release 4 an observable based notification API is the default. The 3.x compatible API can be generated using the new generator feature in your sgen files.


feature OutEventAPI {
	getters = true
	observables = false
}

This feature is available in all code generators and observables can be used together with the old style API.

Migrating the C Code Generator

Changed generator options

  • The inEventQueue parameter from the GeneratorOptions feature has been removed and replaced by the new model annotation @EventBuffering(inEvents = true, ...)
  • The already deprecated maxIdentifierLength parameter from the IdentifierSettings feature has been removed. If you want to generate code for compilers with identifier length restrictions you should add the @CShortIdentifier annotation to your model instead.

Changed file names

The generated source and header files use the name of the statechart as it is defined without upper casing the first letter. In case your statechart uses time events or defines operations, an additional header is generated. We changed the suffix of this header from Required to _required:


Before:	StatechartRequired.h
After:	statechart_required.h


Accessing events and variables within in default interface

We removed the Iface suffix from all operations that access variables, events and operations that are declared within an interface. This can be migrated by simply removing the Iface suffix:


Before:	coffeeMachineIface_raise_userEvent(handle);
After:	coffeeMachine_raise_userEvent(handle);


Accessing events and variables within named interfaces

We removed the Iface prefix of the named interfaces. Assume an interface User with an event on_button:


Before:	coffeeMachineIfaceHeater_raise_overheated(handle);
After:	coffeeMachine_heater_raise_overheated(handle);


Changed Lifecycle Functions

We changed the lifecycle functions runCycle, isStateActive, isActive and isFinal to have a consistent naming convention for the generated C API. Same holds for setTimer, unsetTimer and raiseTimeEvent functions in case time triggers are used.


Before:	coffeeMachine_runCycle(handle);
After:	coffeeMachine_run_cycle(handle);

Before:	coffeeMachine_isStateActive(handle, ...);
After:	coffeeMachine_is_state_active(handle, ...);

Before:	coffeeMachine_isActive(handle);
After:	coffeeMachine_is_active(handle);

Before:	coffeeMachine_iFinal(handle);
After:	coffeeMachine_is_final(handle);

Before:	coffeeMachine_setTimer(handle, ...);
After:	coffeeMachine_set_timer(handle, ...);

Before:	coffeeMachine_unsetTimer(handle, ...);
After:	coffeeMachine_unset_timer(handle, ...);

Before:	coffeeMachine_raiseTimeEvent(handle, ...);
After:	coffeeMachine_raise_time_event(handle, ...);


Migrating the C++ Code Generator

Changed generator options

  • The inEventQueue parameter from the GeneratorOptions feature has been removed and replaced by the new model annotation @EventBuffering(inEvents = true, ...)
  • The already deprecated maxIdentifierLength parameter from the IdentifierSettings feature has been removed. If you want to generate code for compilers with identifier length restrictions you should add the @CShortIdentifier annotation to your model instead.
  • The API feature with the checkUnimplementedOCBs parameter has been removed. If you want to check if the state machine is set up properly, we introduced a new _ bool check()_ method that can be used like this:

CoffeeMachine* coffeeMachine = new CoffeeMachine()
coffeeMachine->init()
if(! coffeeMachine->check()) {
 cout << "something has not been set" << endl;
 return -1;
}


Changed file names, new interfaces and namespaces

State machine classes inherit from a StatemachineInterface. This is now declared in the header sc_statemachine.h under the namespace sc. A state machine does not declare an init() function anymore. The initialization is done in the class constructor instead. The runCycle method is also not part of the generic interface anymore.

State machines that run with the @CycleBased execution scheme now inherit from the CycleBasedInterface which declares a public runCycle() function.

State machines that use time triggers inherit from TimedInterface instead of TimedStatemachineInterface. This interface declares functions to set a timer service which are called setTimerService(TimerServiceInterface) / getTimerService() instead of setTimer(TimerInterface) / getTimer(). The former TimerInterface was renamed accordingly to TimerServiceInterface. Both, the TimedInterface and the TimerServiceInterface are declared in the header file sc_timer.h under the namespace sc::timer:

namespace sc {
namespace timer {

class TimedInterface {
	public:
		virtual void setTimerService(sc::timer::TimerServiceInterface* timerService) = 0;
		virtual sc::timer::TimerServiceInterface* getTimerService() = 0;
		...
};
class TimerServiceInterface { ... };

Accessing events and variables

We removed the underscore in favor of camelCase notation for all getter/setter and raise methods. Assume a default interface with an event userEvent.


Before:	coffeeMachine->raise_userEvent(lastEvent);
After:	coffeeMachine->raiseUserEvent(lastEvent);

Accessing events and variables within named interfaces

We removed the getSCI prefix_ from the state machine. Assuming an interface called Light with a variable called on:


Before: 	coffeeMachine.getSCI_Heater()->raise_overheated()
After: 	coffeeMachine.heater()->raiseOverheated()

Migrating the Java Code Generator

Changed generator options

We have removed some parameters from the GeneralFeatures feature:

  • The inEventQueue parameter has been removed and replaced by the new model annotation @EventBuffering(inEvents = true, ...)
  • The deprecated UseJavaIntForInteger parameter has been removed.
  • The deprecated features RunnableWrapper and SynchronizedWrapper have been removed and replaced by the parameters runnable and synchronized.

Moreover, the InterfaceObserverSupport parameter has been replaced by the new OutEventAPI feature. In order to react on out events you just need to subscribe an observer on the out event observables which are generated for you by default. As the expected observer interface only declares one function, you can simply use lambda expressions like this to react on out events:


coffeeMachine.heater().getTemperatureReached().subscribe((value) -> System.out.println("Set temperature is " + value + "."));

If you are using the event getter functions isRaisedEvent() and getEventValue(), you need to enable their generation with the parameter getters in the OutEventAPI feature.

The Naming feature now contains two more options:

  • The parameter typeName allows to define the name for the generated state machine class.
  • The parameter libraryPackage allows to define a package for library files like the generic interfaces. The default package name is com.yakindu.core.
  • We removed the parameter implementationSuffix in favor of typeName.
  • The parameter basePackage works as before.

The state machine is generated into the package as defined by the basePackage parameter and/or the statechart’s namespace. If none of the two is defined, the state machine is generated into the default package. In that case, the generator model will contain a warning.

Changed file names and new interfaces

We do not add a Statemachine suffix for state machine classes anymore.

State machine classes inherit from an IStatemachine interface as before. This interface does not declare an init() function anymore. The initialization is done in the class constructor instead. The runCycle method is also not part of the generic interface anymore.

State machines that run with the @CycleBased execution scheme now inherit from the ICycleBased interface which declares a public runCycle() function.

State machine classes do not inherit from a statechart specific interface anymore which reflected the statechart’s definition section.

State machines that use time triggers inherit from ITimed interface instead of ITimerCallback. The ITimed interface declares a function to set a timer service, and the callback function to raise a time event. The timer service interface is also renamed from ITimer to ITimerService.

public interface ITimed {
	public void raiseTimeEvent(int eventID);
	public void setTimerService(ITimerService timerService);
}


Accessing events and variables within in default interface

We removed the getInterface prefix from the state machine. Assuming an interface called User with an event called operate:


Before: 	coffeeMachine.getInterfaceHeater().raiseOverheated();
After: 	coffeeMachine.heater().raiseOverheated();

Accessing events and variables within named interfaces

We removed the getInterface() getter for the default interface. You can access all events and variables that are defined within the default interface directly from the state machine instance now:


Before: 	coffeeMachine.getInterface().raiseUserEvent())
After: 	coffeeMachine.raiseUserEvent()