Executable Model Example: Finite State Machine¶
As an example, this description re-implements the Finite State Machine (FSM) example as described in the ALE tutorial page. ALE is a domain specific language designed for EMF Java that provides (_extracted from the ALE homepage_):
Metamodel extension: The very same mechanism can be used to extend existing Ecore metamodels and insert new features (eg. attributes) in a non-intrusive way
Executable metamodeling: Re-open existing EClasses to insert new methods with their implementations
Interpreted: Just run the behavior on a model directly in your modeling environment
Extensible: If ALE doesn’t fit your needs, register classes as services and invoke them inside your implementations of EOperations.
PyEcore provides the exact same capability to use ALE in a Python environment. You can find more information about how to add behavior to your metamodel in the “Adding Behavior: Executable Models” section of the advanced User Documentation.
The following gives you the full code for the FSM example of the ALE tutorial page, but in a pure Python style using PyEcore. The script:
opens the FSM Ecore metamodel from a remote location
registers the FSM Ecore metamodel in the metamodel registry
defines additional behavior for each metaclass from the FSM Ecore metamodel
defines an entry point
opens a FSM XMI model from a remote location
executes the loaded metamodel
from pyecore.resources.resource import HttpURI, ResourceSet
from pyecore.utils import DynamicEPackage
from pyecore.ecore import EcoreUtils
import pyecore.behavior as behavior
# Load metamodel
rset = ResourceSet()
uri = HttpURI('https://raw.githubusercontent.com/gemoc/ale-lang/master/'
'examples/minifsm/model/MiniFsm.ecore')
package_root = rset.get_resource(uri).contents[0]
rset.metamodel_registry[package_root.nsURI] = package_root
fsm = DynamicEPackage(package_root)
# Code for each overridden/added method
@fsm.Transition.behavior
def is_activated(self):
return (self.fsm.currentEvent == self.event
and self.incoming == self.fsm.currentState)
@fsm.State.behavior
def execute(self):
print('Execute', self.name)
@fsm.FSM.behavior
def handle(self, event):
print('Handle', event)
self.currentEvent = event
self.currentState = [t for t in self.transitions
if t.is_activated()][0].outgoing
@fsm.FSM.behavior
@behavior.main
def entry_point(self):
print('Start')
events = ['event1', 'event2']
self.currentState = [s for s in self.states
if isinstance(s, fsm.Initial)][0]
self.currentState.execute()
for event in events:
self.handle(event)
self.currentState.execute()
print('End')
# Load the model
uri = HttpURI('https://raw.githubusercontent.com/gemoc/ale-lang/master/'
'examples/minifsm/model/FSM.xmi')
resource = rset.get_resource(uri)
root = resource.contents[0]
# Execute the model
behavior.run(root)