rl_model/model/
resource.rs

1use super::*;
2use crate::parser::{Position, RlError};
3use std::collections::HashMap;
4
5#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Default)]
6pub struct ResourceId(pub usize);
7impl Id for ResourceId {
8    fn index(&self) -> usize {
9        self.0
10    }
11}
12
13#[derive(Debug, Clone)]
14pub struct Resource {
15    id: ResourceId,
16    name: String,
17    states: Vec<State>,
18    initial: Reference<StateId>,
19    transitions: Transitions,
20    position: Option<Position>,
21}
22
23impl Resource {
24    pub fn new<S: Into<String>>(name: S, position: Option<Position>) -> Self {
25        let id = ResourceId::default();
26        let name = name.into();
27        Self {
28            id,
29            name,
30            states: Vec::new(),
31            initial: Reference::Unresolved("?".into(), None),
32            transitions: Transitions::All,
33            position,
34        }
35    }
36
37    //---------- State ----------
38
39    pub fn states(&self) -> &Vec<State> {
40        &self.states
41    }
42
43    pub fn add_state(&mut self, mut state: State) -> StateId {
44        let id = StateId(self.id, self.states.len());
45        state.set_id(id);
46        self.states.push(state);
47        id
48    }
49
50    pub fn get_state(&self, id: StateId) -> Option<&State> {
51        let StateId(resource_id, state_id) = id;
52        if self.id != resource_id {
53            None
54        } else {
55            self.states.get(state_id)
56        }
57    }
58
59    pub fn initial(&self) -> StateId {
60        self.initial.resolved()
61    }
62
63    pub fn set_initial(&mut self, state: Reference<StateId>) {
64        self.initial = state;
65    }
66
67    pub fn state_map(&self) -> HashMap<String, StateId> {
68        let mut map = HashMap::new();
69        for x in self.states.iter() {
70            map.insert(x.name().into(), x.id());
71        }
72        map
73    }
74
75    pub fn get_state_from_name(&self, name: &str) -> Option<&State> {
76        for x in self.states.iter() {
77            if x.name() == name {
78                return Some(x);
79            }
80        }
81        None
82    }
83
84    //---------- Transition ----------
85
86    pub fn transitions(&self) -> &Transitions {
87        &self.transitions
88    }
89
90    pub fn set_transitions(&mut self, transitions: Transitions) {
91        self.transitions = transitions;
92    }
93
94    pub fn transitions_list(&self) -> Vec<Transition> {
95        match self.transitions() {
96            Transitions::All => {
97                let mut transitions = vec![];
98                for src in self.states.iter() {
99                    let r_src = Reference::Resolved(src.id());
100                    for dst in self.states.iter() {
101                        let r_dst = Reference::Resolved(dst.id());
102                        if src.id() != dst.id() {
103                            transitions.push(Transition::new(r_src.clone(), r_dst.clone()));
104                        }
105                    }
106                }
107                transitions
108            }
109            Transitions::List(transitions) => transitions.clone(),
110        }
111    }
112
113    //---------- Duplicate ----------
114
115    pub fn names(&self) -> Vec<(String, Option<Position>)> {
116        let mut v = Vec::new();
117        for x in self.states.iter() {
118            v.push((x.name().into(), x.position()))
119        }
120        v
121    }
122
123    //---------- Resolve ----------
124
125    pub fn resolve_state(&mut self) -> Result<(), RlError> {
126        let map = self.state_map();
127        self.resolve_initial_state(&map)?;
128        self.transitions.resolve(&map)?;
129        Ok(())
130    }
131
132    fn resolve_initial_state(&mut self, map: &HashMap<String, StateId>) -> Result<(), RlError> {
133        match &self.initial {
134            Reference::Unresolved(name, pos) => match map.get(name) {
135                Some(id) => {
136                    self.initial = Reference::Resolved(*id);
137                    Ok(())
138                }
139                None => Err(RlError::Resolve {
140                    element: format!("state '{}'", name),
141                    position: pos.clone(),
142                }),
143            },
144            Reference::Resolved(_) => Ok(()),
145        }
146    }
147}
148
149impl Named<ResourceId> for Resource {
150    fn id(&self) -> ResourceId {
151        self.id
152    }
153
154    fn set_id(&mut self, id: ResourceId) {
155        self.id = id;
156        for state in self.states.iter_mut() {
157            let StateId(_, index) = state.id();
158            state.set_id(StateId(id, index));
159        }
160    }
161
162    fn name(&self) -> &str {
163        &self.name
164    }
165
166    fn position(&self) -> Option<Position> {
167        self.position.clone()
168    }
169}
170
171//------------------------- Get From Id -------------------------
172
173impl GetFromId<StateId, State> for Resource {
174    fn get(&self, id: StateId) -> Option<&State> {
175        self.get_state(id)
176    }
177}
178
179//------------------------- ToLang -------------------------
180
181impl ToLang for Resource {
182    fn to_lang(&self, skillset: &Skillset) -> String {
183        let mut s = String::new();
184        s.push_str(&format!("\t\t{} {{\n", self.name));
185        // state
186        s.push_str("\t\t\tstate {");
187        for x in self.states.iter() {
188            s.push_str(&format!(" {}", x));
189        }
190        s.push_str(" }\n");
191        // initial
192        s.push_str(&format!(
193            "\t\t\tinitial {}\n",
194            self.initial.to_lang(skillset)
195        ));
196        // transitions
197        s.push_str(&self.transitions.to_lang(skillset));
198        //
199        s.push_str("\t\t}\n");
200        s
201    }
202}
203
204//------------------------- Display -------------------------
205
206impl std::fmt::Display for Resource {
207    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
208        write!(f, "{}", self.name())
209    }
210}