use crate::{action::ActionType, Action, Context, Event, Guard, IntoAction, IntoGuard};
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Transition {
pub source: String,
pub target: Option<String>,
pub event: String,
pub guard: Option<Guard>,
pub actions: Vec<Action>,
#[serde(default = "uuid::Uuid::new_v4")]
pub(crate) id: uuid::Uuid,
}
impl Transition {
pub fn new(
source: impl Into<String>,
event: impl Into<String>,
target: impl Into<String>,
) -> Self {
Self {
source: source.into(),
target: Some(target.into()),
event: event.into(),
guard: None,
actions: Vec::new(),
id: uuid::Uuid::new_v4(),
}
}
pub fn self_transition(state: impl Into<String>, event: impl Into<String>) -> Self {
let state = state.into();
Self {
source: state.clone(),
target: Some(state),
event: event.into(),
guard: None,
actions: Vec::new(),
id: uuid::Uuid::new_v4(),
}
}
pub fn internal_transition(state: impl Into<String>, event: impl Into<String>) -> Self {
Self {
source: state.into(),
target: None,
event: event.into(),
guard: None,
actions: Vec::new(),
id: uuid::Uuid::new_v4(),
}
}
pub fn with_guard<G: IntoGuard>(&mut self, guard: G) -> &mut Self {
self.guard = Some(guard.into_guard());
self
}
pub fn with_action<A: IntoAction>(&mut self, action: A) -> &mut Self {
self.actions
.push(action.into_action(ActionType::Transition));
self
}
pub fn matches_event(&self, event: &Event) -> bool {
self.event == event.event_type || self.event == crate::event::WILDCARD_EVENT
}
pub fn is_enabled(&self, context: &Context, event: &Event) -> bool {
self.matches_event(event)
&& match &self.guard {
Some(guard) => guard.evaluate(context, event),
None => true,
}
}
pub fn execute_actions(&self, context: &mut Context, event: &Event) {
for action in &self.actions {
action.execute(context, event);
}
}
}
impl fmt::Display for Transition {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.target {
Some(target) => write!(f, "{} -- {} --> {}", self.source, self.event, target),
None => write!(f, "{} -- {} (internal)", self.source, self.event),
}
}
}