EAL (Executable Action Language) is the action language for MDriven developers who need an OCL expression to change data, control application flow, or invoke runtime operations.
What EAL is
EAL extends OCL with imperative operations. OCL evaluates expressions and constraints; EAL performs work from those expressions.
For example, this EAL action assigns three values in sequence:
self.SomeDateTime := DateTime.Now;
self.SomeInt := 27;
self.SomeString := self.SomeDateTime.ToString('yyyy-MM-dd')EAL is also referred to as Extended Action Language in earlier MDriven documentation. Both names refer to the action language described on this page.
You can use EAL to:
- Assign attribute values.
- Create and delete objects.
- Add, remove, and clear collection members.
- Save, refresh, search, and re-query persistent data.
- Navigate ViewModel user interfaces and execute actions.
- Trigger state-machine behavior.
- Call REST endpoints and transform JSON or XML.
Where EAL runs
You write EAL where MDriven expects an executable expression:
- An action's ExecuteExpression.
- A ViewModel column's execute expression.
- A class method implementation.
- A state machine effect.
- An action's ExpressionAfterModalOk when a modal ViewModel closes with OK.
Actions have a context, and that context determines what the EAL expression can access.
| Action type | EAL context | Example |
|---|---|---|
| Global action | No current object context. Start from a model class. | Order.allinstances
|
| Context action | ViewModel context variables, including variables named vCurrent_TheViewModelClassName.
|
Act on the object currently selected in a ViewModel grid. |
| Class action | An object of the action's class, available as self.
|
self.Status := 'Approved'
|
A ViewModel context follows the user's selections in its grids. For example, a context action can use its current variable to update the order that the user selected.
Write assignments and sequences
Use := to assign a value. Use = to compare values.
self.Status := 'Approved'Use a semicolon (;) between statements when an action must perform more than one operation.
self.IsProcessed := true;
self.ProcessedAt := DateTime.NowThe semicolon must be between statements. Do not end an EAL expression with a semicolon. For example, 'a string';0 has an integer result, but 'a string';0; is invalid because the parser expects another statement after the final separator.
Change objects and collections
EAL adds object lifecycle and collection operations that are not available to read-only OCL expressions.
| Task | EAL operation | Example |
|---|---|---|
| Create an object | Create
|
Thing.Create
|
| Delete an object | delete
|
Delete an object that is no longer needed in the current action. |
| Remove an object reference | setToNull
|
Set an optional association end to no value. |
| Add a collection member | add
|
Add a selected product to an order's product collection. |
| Remove a collection member | remove
|
Remove a product from that collection. |
| Empty a collection | clear
|
Clear all temporary selections before rebuilding them. |
You can also use insertAt, removeAt, and addReturnIndexOf0 when the collection position matters.
Control flow
Use EAL flow operations to decide what runs and to process collection members. The available operations include whentrue, whenfalse, and foreach.
Use assignments with control flow when an action needs to update the model based on a condition. For example, an action can assign a result only after a validation expression evaluates successfully.
Persist and update data
EAL provides persistence operations including Save, Refresh, Search, and ReQuery.
Use these operations when the action must store changes, retrieve data, or update its data scope. For example, an action that changes an order can use Save to persist the changed order.
EAL can control ViewModel and UI behavior with operations such as Navigate, NavigateUrl, ExecuteAction, ShowActionMenuForCurrentInNesting, ExecuteFetchHints, ExecutePS, and ExecuteQueryPlan.
For example, use NavigateUrl when an action must open a URL after completing its model work.
An action can also bring up a ViewModel-defined UI. Its ViewModelRootObjectExpression supplies the root object for that ViewModel. If the expression is empty, the opened ViewModel has no assigned root object; this is appropriate for a UI that searches persistent storage.
When ViewModelIsModal is enabled, the runtime adds OK and Cancel buttons. Selecting Cancel closes the dialog without further action. Selecting OK executes ExpressionAfterModalOk when that expression is defined; it runs as EAL in the same action context.
State machines, server execution, and integration
EAL can invoke stateMachineTrigger and stateMachineForceMode for state-machine behavior.
For server and remote operations, EAL includes RunServerSideViewModelNow, SuspectExternalUpdateInvalidate, and Remote Turnkey session operations such as RemoteTurnkeyConnectGetSessionKey and RemoteTurnkeyExecuteAction.
For external communication, use RestGet, RestPost, RestPut, RestPatch, and RestDelete. Data import, export, and transformation operations include ApplyTaJson, MergeTaJson, JSonToObjects, XmlToObjects, ViewModelAsJSon, ViewModelAsXml, ImportTabSepData, XsltTransformXml, and transform.
Keep action code separate from action availability
An action's ExecuteExpression is EAL and can have side effects, such as changing an attribute or creating an object.
An action's EnableExpression is OCL, not EAL. It must return a Boolean value and cannot change domain objects. Use it to decide whether the user can execute the action.
For example, enable a Delete action only while the current object is in the Deletable state:
self.oclIsInState(#Deletable)Call an overridden base implementation
When a class overrides a method, use self.base to call the superclass implementation. This follows the same pattern as a C# base call.
self.base.OnCreateFor example, if both RootClass.OnCreate and Person.OnCreate add initialization behavior, calling self.base.OnCreate from Person.OnCreate runs the root-class behavior as part of creating a Person.
Validate dynamically stored expressions
ScriptEvalCheck validates an OCL expression stored as text before you evaluate it. It checks syntax, verifies the expected return type, and validates the expression against the current model context. It does not execute the expression or change data.
The following action validates an Order's DynamicFormula as a Decimal expression. If validation succeeds, it evaluates the formula and stores the result; otherwise, it stores the validation error.
let validationInfo = self.ScriptEvalCheck(false, Decimal, self.DynamicFormula) in
(
if validationInfo = 'ok' then
self.FormulaResult := self.ScriptEval(false, Decimal, self.DynamicFormula).asstring
else
self.FormulaResult := validationInfo
endif
)In this example, self.Total * 0.10 can fail type validation when Total is Decimal and 0.10 is Double. Use self.Total * 0.10.ToDecimal to align the types.
