autosar_data_abstraction/software_component/
mode.rs1use std::str::FromStr;
2
3use crate::{
4 AbstractionElement, ArPackage, AutosarAbstractionError, Element, IdentifiableAbstractionElement,
5 abstraction_element, get_reference_parents, software_component::SwcModeSwitchEvent,
6};
7use autosar_data::ElementName;
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash)]
13pub struct ModeDeclarationGroup(Element);
14abstraction_element!(ModeDeclarationGroup, ModeDeclarationGroup);
15impl IdentifiableAbstractionElement for ModeDeclarationGroup {}
16
17impl ModeDeclarationGroup {
18 pub(crate) fn new(
20 name: &str,
21 package: &ArPackage,
22 category: Option<ModeDeclarationGroupCategory>,
23 ) -> Result<Self, AutosarAbstractionError> {
24 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
25 let mode_declaration_group_elem = elements.create_named_sub_element(ElementName::ModeDeclarationGroup, name)?;
26 let mode_declaration_group = Self(mode_declaration_group_elem);
27
28 mode_declaration_group.set_category(category)?;
29
30 Ok(mode_declaration_group)
31 }
32
33 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
35 for mode_declaration in self.mode_declarations() {
36 mode_declaration.remove(deep)?;
37 }
38 AbstractionElement::remove(self, deep)
39 }
40
41 pub fn set_category(&self, category: Option<ModeDeclarationGroupCategory>) -> Result<(), AutosarAbstractionError> {
43 if let Some(category) = category {
44 self.element()
45 .get_or_create_sub_element(ElementName::Category)?
46 .set_character_data(category.to_string())?;
47 } else {
48 let _ = self.element().remove_sub_element_kind(ElementName::Category);
49 }
50 Ok(())
51 }
52
53 #[must_use]
55 pub fn category(&self) -> Option<ModeDeclarationGroupCategory> {
56 let category = self
57 .element()
58 .get_sub_element(ElementName::Category)?
59 .character_data()?
60 .string_value()?;
61 ModeDeclarationGroupCategory::from_str(&category).ok()
62 }
63
64 pub fn create_mode_declaration(&self, name: &str) -> Result<ModeDeclaration, AutosarAbstractionError> {
66 let mode_declarations = self
67 .element()
68 .get_or_create_sub_element(ElementName::ModeDeclarations)?;
69 ModeDeclaration::new(name, &mode_declarations)
70 }
71
72 pub fn mode_declarations(&self) -> impl Iterator<Item = ModeDeclaration> + Send + use<> {
74 self.element()
75 .get_sub_element(ElementName::ModeDeclarations)
76 .into_iter()
77 .flat_map(|mode_declarations| mode_declarations.sub_elements())
78 .filter_map(|elem| ModeDeclaration::try_from(elem).ok())
79 }
80
81 pub fn set_initial_mode(&self, mode_declaration: &ModeDeclaration) -> Result<(), AutosarAbstractionError> {
86 if mode_declaration.element().named_parent()?.as_ref() != Some(self.element()) {
87 return Err(AutosarAbstractionError::InvalidParameter(
88 "Mode declaration is not part of the mode declaration group".to_string(),
89 ));
90 }
91 self.element()
92 .get_or_create_sub_element(ElementName::InitialModeRef)?
93 .set_reference_target(mode_declaration.element())?;
94 Ok(())
95 }
96
97 #[must_use]
99 pub fn initial_mode(&self) -> Option<ModeDeclaration> {
100 self.element()
101 .get_sub_element(ElementName::InitialModeRef)
102 .and_then(|elem| elem.get_reference_target().ok())
103 .and_then(|target| ModeDeclaration::try_from(target).ok())
104 }
105
106 pub fn set_on_transition_value(&self, value: Option<u64>) -> Result<(), AutosarAbstractionError> {
108 if let Some(value) = value {
109 self.element()
110 .get_or_create_sub_element(ElementName::OnTransitionValue)?
111 .set_character_data(value)?;
112 } else {
113 let _ = self.element().remove_sub_element_kind(ElementName::OnTransitionValue);
114 }
115 Ok(())
116 }
117
118 #[must_use]
120 pub fn on_transition_value(&self) -> Option<u64> {
121 self.element()
122 .get_sub_element(ElementName::OnTransitionValue)?
123 .character_data()?
124 .parse_integer()
125 }
126}
127
128#[derive(Debug, Clone, PartialEq, Eq, Hash)]
131pub enum ModeDeclarationGroupCategory {
133 AlphabeticOrder,
135 ExplicitOrder,
138}
139
140impl std::fmt::Display for ModeDeclarationGroupCategory {
141 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
142 match self {
143 ModeDeclarationGroupCategory::AlphabeticOrder => f.write_str("ALPHABETIC_ORDER"),
144 ModeDeclarationGroupCategory::ExplicitOrder => f.write_str("EXPLICIT_ORDER"),
145 }
146 }
147}
148
149impl std::str::FromStr for ModeDeclarationGroupCategory {
150 type Err = AutosarAbstractionError;
151
152 fn from_str(s: &str) -> Result<Self, Self::Err> {
153 match s {
154 "ALPHABETIC_ORDER" => Ok(ModeDeclarationGroupCategory::AlphabeticOrder),
155 "EXPLICIT_ORDER" => Ok(ModeDeclarationGroupCategory::ExplicitOrder),
156 _ => Err(AutosarAbstractionError::ValueConversionError {
157 value: s.to_string(),
158 dest: "ModeDeclarationGroupCategory".to_string(),
159 }),
160 }
161 }
162}
163
164#[derive(Debug, Clone, PartialEq, Eq, Hash)]
168pub struct ModeDeclaration(Element);
169abstraction_element!(ModeDeclaration, ModeDeclaration);
170impl IdentifiableAbstractionElement for ModeDeclaration {}
171
172impl ModeDeclaration {
173 fn new(name: &str, parent_element: &Element) -> Result<Self, AutosarAbstractionError> {
175 let mode_declaration = parent_element.create_named_sub_element(ElementName::ModeDeclaration, name)?;
176 Ok(Self(mode_declaration))
177 }
178
179 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
181 let ref_parents = get_reference_parents(self.element())?;
182
183 AbstractionElement::remove(self, deep)?;
184
185 for (named_parent, _parent) in ref_parents {
186 if named_parent.element_name() == ElementName::SwcModeSwitchEvent
187 && let Ok(swc_mode_switch_event) = SwcModeSwitchEvent::try_from(named_parent)
188 {
189 swc_mode_switch_event.remove(deep)?;
190 }
191 }
192
193 Ok(())
194 }
195
196 pub fn set_value(&self, value: Option<u64>) -> Result<(), AutosarAbstractionError> {
198 if let Some(value) = value {
199 self.element()
200 .get_or_create_sub_element(ElementName::Value)?
201 .set_character_data(value)?;
202 } else {
203 let _ = self.element().remove_sub_element_kind(ElementName::Value);
204 }
205 Ok(())
206 }
207
208 #[must_use]
210 pub fn value(&self) -> Option<u64> {
211 self.element()
212 .get_sub_element(ElementName::Value)?
213 .character_data()?
214 .parse_integer()
215 }
216
217 pub fn mode_declaration_group(&self) -> Result<ModeDeclarationGroup, AutosarAbstractionError> {
219 let Some(parent) = self.element().named_parent()? else {
220 return Err(AutosarAbstractionError::InvalidParameter(
221 "Mode declaration has no parent".to_string(),
222 ));
223 };
224 ModeDeclarationGroup::try_from(parent)
225 }
226}
227
228#[cfg(test)]
231mod test {
232 use super::*;
233 use crate::{
234 AutosarModelAbstraction,
235 software_component::{AbstractSwComponentType, AtomicSwComponentType, ModeActivationKind},
236 };
237 use autosar_data::AutosarVersion;
238
239 #[test]
240 fn mode_declaration_group() {
241 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
242 let package = model.get_or_create_package("/Pkg").unwrap();
243 let mode_declaration_group = package.create_mode_declaration_group("test_group", None).unwrap();
244
245 assert_eq!(mode_declaration_group.category(), None);
246 assert_eq!(mode_declaration_group.name().unwrap(), "test_group");
247
248 mode_declaration_group
249 .set_category(Some(ModeDeclarationGroupCategory::ExplicitOrder))
250 .unwrap();
251 assert_eq!(
252 mode_declaration_group.category(),
253 Some(ModeDeclarationGroupCategory::ExplicitOrder)
254 );
255 mode_declaration_group
256 .set_category(Some(ModeDeclarationGroupCategory::AlphabeticOrder))
257 .unwrap();
258 assert_eq!(
259 mode_declaration_group.category(),
260 Some(ModeDeclarationGroupCategory::AlphabeticOrder)
261 );
262
263 assert_eq!(mode_declaration_group.on_transition_value(), None);
264 mode_declaration_group.set_on_transition_value(Some(42)).unwrap();
265 assert_eq!(mode_declaration_group.on_transition_value(), Some(42));
266 mode_declaration_group.set_on_transition_value(None).unwrap();
267 assert_eq!(mode_declaration_group.on_transition_value(), None);
268
269 let mode_declaration = mode_declaration_group.create_mode_declaration("test_mode").unwrap();
270 mode_declaration.set_value(Some(1)).unwrap();
271 assert_eq!(mode_declaration.value(), Some(1));
272
273 assert_eq!(mode_declaration_group.mode_declarations().count(), 1);
274
275 mode_declaration_group.set_initial_mode(&mode_declaration).unwrap();
276 assert_eq!(mode_declaration_group.initial_mode().unwrap(), mode_declaration);
277
278 let mode_declaration_group_2 = package.create_mode_declaration_group("test_group_2", None).unwrap();
279 mode_declaration_group_2
280 .set_initial_mode(&mode_declaration)
281 .unwrap_err(); }
283
284 #[test]
285 fn remove_mode_declaration() {
286 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
287 let package = model.get_or_create_package("/Pkg").unwrap();
288
289 let mode_declaration_group = package.create_mode_declaration_group("test_group", None).unwrap();
291 let mode_declaration = mode_declaration_group.create_mode_declaration("test_mode").unwrap();
292
293 let mode_switch_interface = package.create_mode_switch_interface("TestModeSwitchInterface").unwrap();
295 let _mode_if_group = mode_switch_interface
296 .create_mode_group("ModeDeclarationGroup", &mode_declaration_group)
297 .unwrap();
298
299 let swc_type = package.create_application_sw_component_type("TestSwcType").unwrap();
301 let port = swc_type.create_r_port("RPort", &mode_switch_interface).unwrap();
302
303 let ib = swc_type.create_swc_internal_behavior("InternalBehavior").unwrap();
305 let runnable = ib.create_runnable_entity("RunnableEntity").unwrap();
306 let _swc_mode_switch_event = ib
307 .create_mode_switch_event(
308 "ModeSwitchEvent",
309 &runnable,
310 ModeActivationKind::OnEntry,
311 &port,
312 &mode_declaration,
313 None,
314 )
315 .unwrap();
316
317 assert_eq!(mode_declaration_group.mode_declarations().count(), 1);
318
319 mode_declaration.remove(true).unwrap();
320
321 assert_eq!(mode_declaration_group.mode_declarations().count(), 0);
323 assert_eq!(ib.events().count(), 0);
325 }
326}