Class Interpreter
The Interpreter reads workflow definitions in YAML or JSON format and executes them by invoking actions on registered actors. Workflows are represented as a matrix of states and actions, where each row defines state transitions and the actions to execute during those transitions.
This class maintains the current execution state, including the current
row and state, and coordinates with an IIActorSystem to invoke
actor methods dynamically.
- Author:
- devteam@scivics-lab.com
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classBuilder for constructing Interpreter instances. -
Field Summary
FieldsModifier and TypeFieldDescriptionprotected MatrixCodeprotected Stringprotected intprotected Loggerprotected IIActorRef<?> Reference to the actor executing this interpreter (for Unix-style path resolution).protected IIActorSystemprotected StringBase directory for resolving relative workflow file paths. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionaction()Executes the actions in the current row of the workflow matrix.addToAccumulator(String type, String data) Adds a result to the accumulator actor in the system.addToAccumulator(String accumulatorName, String type, String data) Adds a result to a named accumulator actor in the system.Applies an action to existing child actors (with wildcard support).Calls a subworkflow by creating a child interpreter, executing it, and removing it.execCode()Executes the loaded workflow code.protected List<IIActorRef<?>> findMatchingActors(String pattern) Finds all actors in the system matching a wildcard pattern.protected List<IIActorRef<?>> findMatchingChildActors(String pattern) Finds child actors matching a wildcard pattern.protected voidFinds the first step whose from-state pattern matches the current state.protected StringgenerateChildName(String workflowFile) Generates a unique child actor name for subworkflow execution.getCode()Returns the currently loaded workflow code.Gets the current state of the interpreter.intGets the current step index.getToState(Vertex vertex) Gets the to-state from a vertex.Gets the base directory for resolving relative workflow file paths.booleanChecks if workflow code is loaded.protected InputStreamloadWorkflowFromClasspath(String workflowFile) Loads a workflow from the classpath.booleanmatchesCurrentState(Vertex vertex) Checks if a vertex's from-state matches the current state.protected booleanmatchesStatePattern(String pattern, String state) Checks if a state pattern matches a given state value.protected voidonEnterVertex(Vertex vertex) Hook method called when entering a vertex during workflow execution.voidreadJson(InputStream jsonInput) Reads and parses a workflow definition from a JSON input stream.voidreadXml(InputStream xmlInput) Reads and parses a workflow definition from an XML input stream.voidreadYaml(InputStream yamlInput) Reads and parses a workflow definition from a YAML input stream.voidReads and parses a workflow definition from a YAML file.voidReads and parses a workflow definition from a YAML file with overlay applied.protected voidremoveChildActor(String childName) Removes a child actor from the system and parent-child relationship.voidreset()Resets the interpreter to its initial state.Executes the workflow until reaching the "end" state.runUntilEnd(int maxIterations) Executes the workflow until reaching the "end" state with a custom iteration limit.runWorkflow(String workflowFile) Loads and runs a workflow file to completion.runWorkflow(String workflowFile, int maxIterations) Loads and runs a workflow file to completion with custom iteration limit.voidsetCode(MatrixCode code) Sets the workflow code directly (for testing purposes).voidsetSelfActorRef(IIActorRef<?> actorRef) Sets the reference to the actor executing this interpreter.voidsetWorkflowBaseDir(String baseDir) Sets the base directory for resolving relative workflow file paths.voidtransitionTo(String toState) Transitions to a new state and finds the next matching row.
-
Field Details
-
logger
-
code
-
currentVertexIndex
protected int currentVertexIndex -
currentState
-
system
-
selfActorRef
Reference to the actor executing this interpreter (for Unix-style path resolution). When this interpreter is running inside an actor (e.g., Node extends Interpreter), this field holds a reference to that actor, enabling relative path resolution like "." (self), ".." (parent), "../sibling" (sibling actors), etc. -
workflowBaseDir
Base directory for resolving relative workflow file paths. When set, runWorkflow will look for files relative to this directory.
-
-
Constructor Details
-
Interpreter
public Interpreter()
-
-
Method Details
-
action
Executes the actions in the current row of the workflow matrix.For each action in the current row, this method retrieves the corresponding actor(s) from the system and invokes the specified action by name with the provided arguments.
Supports Unix-style actor path resolution when
selfActorRefis set:.orthis- self (the current interpreter's actor)..- parent actor./*- all children../*- all siblings../sibling- specific sibling by name../web*- siblings matching wildcard pattern
If
selfActorRefis not set, falls back to absolute actor name lookup.Supports both legacy
argument(String) and newarguments(List/Map) formats. Ifargumentsis present, it is converted to JSON array format before passing to the actor.- Returns:
- an
ActionResultindicating success or failure
-
getCode
Returns the currently loaded workflow code.- Returns:
- the
MatrixCoderepresenting the workflow
-
setCode
Sets the workflow code directly (for testing purposes).- Parameters:
code- the workflow code to set
-
readYaml
Reads and parses a workflow definition from a YAML input stream.- Parameters:
yamlInput- the YAML input stream containing the workflow definition
-
readYaml
Reads and parses a workflow definition from a YAML file.- Parameters:
yamlPath- the path to the YAML file containing the workflow definition- Throws:
IOException- if the file cannot be read
-
readYaml
Reads and parses a workflow definition from a YAML file with overlay applied.This method applies the overlay configuration from the specified directory to the base workflow before loading. The overlay can modify vertices, add new steps, substitute variables, and apply name transformations.
Example usage:
interpreter.readYaml( Path.of("workflows/base/main-workflow.yaml"), Path.of("workflows/overlays/production") );- Parameters:
yamlPath- the path to the base YAML workflow fileoverlayDir- the directory containing overlay-conf.yaml- Throws:
IOException- if files cannot be read- Since:
- 2.9.0
-
readJson
Reads and parses a workflow definition from a JSON input stream.- Parameters:
jsonInput- the JSON input stream containing the workflow definition- Throws:
IOException- if an I/O error occurs during parsing
-
readXml
public void readXml(InputStream xmlInput) throws IOException, ParserConfigurationException, SAXException Reads and parses a workflow definition from an XML input stream.The XML format follows this structure:
<workflow name="workflow-name"> <steps> <transition from="state1" to="state2"> <action actor="actorName" method="methodName">argument</action> </transition> </steps> </workflow>- Parameters:
xmlInput- the XML input stream containing the workflow definition- Throws:
IOException- if an I/O error occurs during parsingParserConfigurationException- if the XML parser cannot be configuredSAXException- if the XML is malformed
-
execCode
Executes the loaded workflow code.This method implements finite automaton semantics:
- Find a step whose from-state matches the current state
- Execute the actions in that step
- If any action returns false, skip to the next step and retry
- If all actions succeed, transition to the to-state
This enables conditional branching: multiple steps can have the same from-state, and the first one whose actions all succeed will be taken.
- Returns:
- an
ActionResultindicating success or failure
-
runUntilEnd
Executes the workflow until reaching the "end" state.This method provides a self-contained way to run workflows that have a defined termination state. The workflow author defines transitions to the "end" state in the YAML file, and this method handles the execution loop automatically.
The method repeatedly calls
execCode()until:- The current state becomes "end" (success)
- An action returns failure (error)
- No matching state transition is found (error)
- Maximum iterations exceeded (error - prevents infinite loops)
Usage Example:
// YAML workflow with "end" state: // steps: // - states: ["0", "1"] // actions: // - actor: worker // method: process // - states: ["1", "end"] // actions: // - actor: worker // method: finish Interpreter interpreter = new Interpreter.Builder() .loggerName("workflow") .team(system) .build(); interpreter.readYaml(workflowStream); ActionResult result = interpreter.runUntilEnd(); if (result.isSuccess()) { System.out.println("Workflow completed successfully"); } else { System.out.println("Workflow failed: " + result.getResult()); }- Returns:
- an
ActionResultwith success=true if "end" state reached, or success=false with error message if workflow failed - Since:
- 2.8.0
- See Also:
-
runWorkflow
Loads and runs a workflow file to completion.This is a convenience method that combines loading a workflow and running it until the "end" state is reached. The workflow file is reloaded each time this method is called, ensuring fresh state.
The method:
- Resets the interpreter state
- Loads the workflow from classpath or file system
- Runs until "end" state is reached
- Parameters:
workflowFile- the workflow file path (YAML or JSON)- Returns:
- ActionResult with success=true if completed, false otherwise
- Since:
- 2.8.0
-
runWorkflow
Loads and runs a workflow file to completion with custom iteration limit.- Parameters:
workflowFile- the workflow file path (YAML or JSON)maxIterations- maximum number of state transitions allowed- Returns:
- ActionResult with success=true if completed, false otherwise
- Since:
- 2.8.0
-
runUntilEnd
Executes the workflow until reaching the "end" state with a custom iteration limit.This method runs the workflow with the following termination conditions:
- Success: current state becomes "end" (automaton accepted)
- Failure: an action fails and no alternative row matches the current state
- Failure: maxIterations exceeded without reaching "end" (automaton did not accept)
- Parameters:
maxIterations- maximum number of state transitions allowed- Returns:
- an
ActionResultwith success=true if "end" state reached, or success=false with error message if workflow failed or iterations exceeded - Since:
- 2.8.0
- See Also:
-
hasCodeLoaded
public boolean hasCodeLoaded()Checks if workflow code is loaded.- Returns:
- true if code is loaded and has at least one step
-
matchesCurrentState
Checks if a vertex's from-state matches the current state.A vertex matches if it has at least 2 states (from and to) and the from-state pattern (index 0) matches the interpreter's current state.
Supported state patterns:
- Exact match:
"1"- matches only state "1" - Wildcard:
"*"- matches any state - Negation:
"!end"- matches any state except "end" - OR condition:
"1|2|3"- matches "1", "2", or "3" - Numeric comparison:
">=1","<=5",">1","<5"
- Parameters:
vertex- the vertex to check- Returns:
- true if the vertex's from-state pattern matches current state
- Exact match:
-
matchesStatePattern
Checks if a state pattern matches a given state value.Supported patterns:
- Exact match: "1" matches only "1"
- Wildcard: "*" matches any state
- Negation: "!end" matches anything except "end"
- OR condition: "1|2|3" matches "1", "2", or "3"
- Numeric comparison: ">=1", "<5" etc.
- JEXL expression: "jexl:state >= 5 && state < 10"
- Parameters:
pattern- the state pattern (may contain wildcards, operators, etc.)state- the actual state value to match against- Returns:
- true if the pattern matches the state
-
getToState
Gets the to-state from a vertex.- Parameters:
vertex- the vertex containing the state transition- Returns:
- the to-state (second element), or null if not present
-
transitionTo
Transitions to a new state and finds the next matching row.This method:
- Updates the current state to the specified to-state
- Searches for the first step whose from-state matches the new current state
- Updates currentVertexIndex to point to that step
- Parameters:
toState- the state to transition to
-
findNextMatchingVertex
protected void findNextMatchingVertex()Finds the first step whose from-state pattern matches the current state.Searches from the beginning of the steps list and updates currentVertexIndex to the index of the first matching step. Supports state patterns including wildcards, negations, and numeric comparisons.
-
getCurrentState
Gets the current state of the interpreter.- Returns:
- the current state string
-
getCurrentVertexIndex
public int getCurrentVertexIndex()Gets the current step index.- Returns:
- the current step index
-
reset
public void reset()Resets the interpreter to its initial state.This method resets the execution state of the interpreter, allowing it to be reused for executing a new workflow without creating a new instance. The following state is reset:
- Current row index is reset to 0
- Current state is reset to "0" (initial state)
- Loaded workflow code is cleared
The following state is preserved:
- Logger instance
- Actor system reference
This method is primarily used by
ReusableSubWorkflowCallerto reuse a single Interpreter instance across multiple sub-workflow calls, reducing object allocation overhead.Usage Example:
Interpreter interpreter = new Interpreter.Builder() .loggerName("workflow") .team(system) .build(); // First workflow execution interpreter.readYaml(workflow1); while (true) { ActionResult result = interpreter.execCode(); if (result.getResult().contains("end")) break; } // Reset and reuse for second workflow interpreter.reset(); interpreter.readYaml(workflow2); while (true) { ActionResult result = interpreter.execCode(); if (result.getResult().contains("end")) break; }- Since:
- 2.5.0
- See Also:
-
onEnterVertex
Hook method called when entering a vertex during workflow execution.This method is called just before executing the actions of a matching vertex. Subclasses can override this method to provide custom behavior such as logging, visualization, or debugging output.
The default implementation does nothing.
- Parameters:
vertex- the vertex being entered- Since:
- 2.9.0
-
setSelfActorRef
Sets the reference to the actor executing this interpreter.This method is called by IIActorRef implementations to establish the link between the interpreter and its actor wrapper, enabling Unix-style path resolution within workflows.
- Parameters:
actorRef- the actor reference wrapping this interpreter
-
setWorkflowBaseDir
Sets the base directory for resolving relative workflow file paths.- Parameters:
baseDir- the directory path
-
getWorkflowBaseDir
Gets the base directory for resolving relative workflow file paths.- Returns:
- the directory path, or null if not set
-
generateChildName
Generates a unique child actor name for subworkflow execution.The name format is:
subwf-{workflowName}-{timestamp}-{random}Example:
subwf-user-validation-1735812345678-04821The combination of timestamp and random number ensures collision-free naming even under parallel invocation or nested subworkflows.
- Parameters:
workflowFile- the workflow file name (e.g., "user-validation.yaml")- Returns:
- a unique child actor name
- Since:
- 2.9.0
-
call
Calls a subworkflow by creating a child interpreter, executing it, and removing it.This method implements the 4-step subworkflow pattern:
- createChild — Create a child InterpreterIIAR and register it
- loadWorkflow — Load the YAML workflow into the child interpreter
- runUntilEnd — Execute the subworkflow until "end" state
- removeChild — Remove the child actor (always executed via finally)
The child interpreter shares the same
IIActorSystemas the parent, so all registered actors are accessible from the subworkflow.Usage in YAML:
- states: ["0", "1"] actions: - actor: this method: call arguments: ["sub-workflow.yaml"]- Parameters:
workflowFile- the workflow file name to execute- Returns:
- ActionResult indicating success or failure
- Since:
- 2.9.0
-
loadWorkflowFromClasspath
Loads a workflow from the classpath.Searches for the workflow in the following locations:
/workflows/{workflowFile}/{workflowFile}
- Parameters:
workflowFile- the workflow file name- Returns:
- InputStream for the workflow, or null if not found
-
removeChildActor
Removes a child actor from the system and parent-child relationship.- Parameters:
childName- the name of the child actor to remove
-
apply
Applies an action to existing child actors (with wildcard support).Unlike
call(String)which creates and deletes child actors, this method operates on existing child actors without removing them.Supports wildcard patterns for actor names:
*— all child actorsSpecies-*— child actors starting with "Species-"*-worker— child actors ending with "-worker"node-*-primary— child actors matching the pattern
Usage in YAML:
- actor: this method: apply arguments: - actor: "Species-*" method: mutate arguments: [0.05, 0.02, 0.5]- Parameters:
actionDefinition- JSON string containing actor, method, and arguments- Returns:
- ActionResult indicating success or failure
- Since:
- 2.9.0
-
findMatchingActors
Finds all actors in the system matching a wildcard pattern.This method searches all registered actors in the IIActorSystem, not just child actors of the current interpreter.
- Parameters:
pattern- the pattern (exact name or wildcard like "Species-*")- Returns:
- list of matching actors
- Since:
- 2.9.0
-
findMatchingChildActors
Finds child actors matching a wildcard pattern.- Parameters:
pattern- the pattern (exact name or wildcard like "Species-*")- Returns:
- list of matching child actors
-
addToAccumulator
Adds a result to the accumulator actor in the system.This is a convenience method for child workflows to report results back to an accumulator. It looks up the accumulator actor by name (default: "accumulator") and calls its "add" action.
Usage in YAML:
- states: ["0", "1"] actions: - actor: this method: addToAccumulator arguments: type: "cpu" data: "Intel Xeon E5-2680"- Parameters:
type- the type of result (e.g., "cpu", "memory")data- the result data- Returns:
- ActionResult indicating success or failure
- Since:
- 2.8.0
-
addToAccumulator
Adds a result to a named accumulator actor in the system.- Parameters:
accumulatorName- the name of the accumulator actortype- the type of result (e.g., "cpu", "memory")data- the result data- Returns:
- ActionResult indicating success or failure
- Since:
- 2.8.0
-