import { log, TransitionKind, Region, Transition } from '.'; import { Transaction } from './Transaction'; import { Constructor, Predicate } from '@steelbreeze/types'; /** * Represents an element within a state machine model hierarchy that can be the source or target of a transition. * Vertices are contained within regions. */ export abstract class Vertex { /** The parent region of the vertex. */ abstract parent: Region | undefined; /** * The transitions originating from this vertex. * @internal * @hidden */ readonly outgoing: Array = []; /** * Creates a new instance of the vertex class. * @param name The name of the vertex. * @param parent The parent region of this vertex. */ protected constructor(public readonly name: string) { log.write(() => `Created ${this}`, log.Create); } /** * Creates a new transition at this vertex triggered by an event of a specific type. * @param TTrigger The type of the triggering event; note that this can be derived from the type parameter. * @param type The type (class name) of the triggering event. * @returns Returns a new typed transition. A typed transition being one whose guard condition and behaviour will accept a parameter of the same type specified. */ public on(type: Constructor): Transition { return new Transition(this).on(type); } /** * Creates a new transition at this vertex with a guard condition. * @param TTrigger The type of the triggering event. * @param guard The guard condition to determine if the transition should be traversed. * @returns Returns a new transition; if TTrigger is specified, a typed transition will be returned. */ public when(guard: Predicate): Transition { return new Transition(this).when(guard); } /** * Creates a new transition from this vertex to the target vertex. * @param TTrigger The type of the triggering event that the guard will evaluate. * @param target The target of the transition. * @param kind The kind of the transition, specifying its behaviour. * @returns Returns a new transition; if TTrigger is specified, a typed transition will be returned. */ public to(target: Vertex, kind: TransitionKind = TransitionKind.External): Transition { return new Transition(this).to(target, kind); } /** * Tests the vertex to see if it part of the the active state configuration of a particular state machine instance. * @param transaction The current transaction being executed. * @returns Returns true if this vertex is active in the specified instance. * @internal * @hidden */ isActive(transaction: Transaction): boolean { return !this.parent || transaction.getVertex(this.parent) === this; } /** * Evaluates a trigger event at this vertex to determine if it will trigger an outgoing transition. * @param transaction The current transaction being executed. * @param deepHistory True if deep history semantics are in play. * @param trigger The trigger event. * @returns Returns true if one of outgoing transitions guard conditions passed. * @internal * @hidden */ evaluate(transaction: Transaction, deepHistory: boolean, trigger: any): boolean { const transition = this.getTransition(trigger); if (transition) { transition.traverse(transaction, deepHistory, trigger); } return !!transition; } /** * Selects an outgoing transition from this vertex based on the trigger event. * @param trigger The trigger event. * @returns Returns a transition or undefined if none were found. * @internal * @hidden */ getTransition(trigger: any): Transition | undefined { return this.outgoing.find(transition => transition.evaluate(trigger)); } /** * Enters an element during a state transition. * @param transaction The current transaction being executed. * @param deepHistory Flag used to denote deep history semantics are in force at the time of entry. * @param trigger The event that triggered the state transition. * @param next The next element to enter in a non-cascaded entry, driven by external transitions. * @internal * @hidden */ abstract doEnter(transaction: Transaction, deepHistory: boolean, trigger: any, next: Region | Vertex | undefined): void; /** * Exits an element during a state transition. * @param transaction The current transaction being executed. * @param deepHistory Flag used to denote deep history semantics are in force at the time of exit. * @param trigger The event that triggered the state transition. * @internal * @hidden */ abstract doExit(transaction: Transaction, deepHistory: boolean, trigger: any): void; /** * Returns the element in string form; the fully qualified name of the element. */ public toString(): string { return this.parent ? `${this.parent}.${this.name}` : this.name; } }