autosar_data_abstraction/software_component/
mode.rs1use std::str::FromStr;
2
3use crate::{
4 AbstractionElement, ArPackage, AutosarAbstractionError, Element, IdentifiableAbstractionElement,
5 abstraction_element,
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 set_category(&self, category: Option<ModeDeclarationGroupCategory>) -> Result<(), AutosarAbstractionError> {
35 if let Some(category) = category {
36 self.element()
37 .get_or_create_sub_element(ElementName::Category)?
38 .set_character_data(category.to_string())?;
39 } else {
40 let _ = self.element().remove_sub_element_kind(ElementName::Category);
41 }
42 Ok(())
43 }
44
45 #[must_use]
47 pub fn category(&self) -> Option<ModeDeclarationGroupCategory> {
48 let category = self
49 .element()
50 .get_sub_element(ElementName::Category)?
51 .character_data()?
52 .string_value()?;
53 ModeDeclarationGroupCategory::from_str(&category).ok()
54 }
55
56 pub fn create_mode_declaration(&self, name: &str) -> Result<ModeDeclaration, AutosarAbstractionError> {
58 let mode_declarations = self
59 .element()
60 .get_or_create_sub_element(ElementName::ModeDeclarations)?;
61 ModeDeclaration::new(name, &mode_declarations)
62 }
63
64 pub fn mode_declarations(&self) -> impl Iterator<Item = ModeDeclaration> + Send + 'static {
66 self.element()
67 .get_sub_element(ElementName::ModeDeclarations)
68 .into_iter()
69 .flat_map(|mode_declarations| mode_declarations.sub_elements())
70 .filter_map(|elem| ModeDeclaration::try_from(elem).ok())
71 }
72
73 pub fn set_initial_mode(&self, mode_declaration: &ModeDeclaration) -> Result<(), AutosarAbstractionError> {
78 if mode_declaration.element().named_parent()?.as_ref() != Some(self.element()) {
79 return Err(AutosarAbstractionError::InvalidParameter(
80 "Mode declaration is not part of the mode declaration group".to_string(),
81 ));
82 }
83 self.element()
84 .get_or_create_sub_element(ElementName::InitialModeRef)?
85 .set_reference_target(mode_declaration.element())?;
86 Ok(())
87 }
88
89 #[must_use]
91 pub fn initial_mode(&self) -> Option<ModeDeclaration> {
92 self.element()
93 .get_sub_element(ElementName::InitialModeRef)
94 .and_then(|elem| elem.get_reference_target().ok())
95 .and_then(|target| ModeDeclaration::try_from(target).ok())
96 }
97
98 pub fn set_on_transition_value(&self, value: Option<u64>) -> Result<(), AutosarAbstractionError> {
100 if let Some(value) = value {
101 self.element()
102 .get_or_create_sub_element(ElementName::OnTransitionValue)?
103 .set_character_data(value)?;
104 } else {
105 let _ = self.element().remove_sub_element_kind(ElementName::OnTransitionValue);
106 }
107 Ok(())
108 }
109
110 #[must_use]
112 pub fn on_transition_value(&self) -> Option<u64> {
113 self.element()
114 .get_sub_element(ElementName::OnTransitionValue)?
115 .character_data()?
116 .parse_integer()
117 }
118}
119
120#[derive(Debug, Clone, PartialEq, Eq, Hash)]
123pub enum ModeDeclarationGroupCategory {
125 AlphabeticOrder,
127 ExplicitOrder,
130}
131
132impl std::fmt::Display for ModeDeclarationGroupCategory {
133 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
134 match self {
135 ModeDeclarationGroupCategory::AlphabeticOrder => f.write_str("ALPHABETIC_ORDER"),
136 ModeDeclarationGroupCategory::ExplicitOrder => f.write_str("EXPLICIT_ORDER"),
137 }
138 }
139}
140
141impl std::str::FromStr for ModeDeclarationGroupCategory {
142 type Err = AutosarAbstractionError;
143
144 fn from_str(s: &str) -> Result<Self, Self::Err> {
145 match s {
146 "ALPHABETIC_ORDER" => Ok(ModeDeclarationGroupCategory::AlphabeticOrder),
147 "EXPLICIT_ORDER" => Ok(ModeDeclarationGroupCategory::ExplicitOrder),
148 _ => Err(AutosarAbstractionError::ValueConversionError {
149 value: s.to_string(),
150 dest: "ModeDeclarationGroupCategory".to_string(),
151 }),
152 }
153 }
154}
155
156#[derive(Debug, Clone, PartialEq, Eq, Hash)]
160pub struct ModeDeclaration(Element);
161abstraction_element!(ModeDeclaration, ModeDeclaration);
162impl IdentifiableAbstractionElement for ModeDeclaration {}
163
164impl ModeDeclaration {
165 fn new(name: &str, parent_element: &Element) -> Result<Self, AutosarAbstractionError> {
167 let mode_declaration = parent_element.create_named_sub_element(ElementName::ModeDeclaration, name)?;
168 Ok(Self(mode_declaration))
169 }
170
171 pub fn set_value(&self, value: Option<u64>) -> Result<(), AutosarAbstractionError> {
173 if let Some(value) = value {
174 self.element()
175 .get_or_create_sub_element(ElementName::Value)?
176 .set_character_data(value)?;
177 } else {
178 let _ = self.element().remove_sub_element_kind(ElementName::Value);
179 }
180 Ok(())
181 }
182
183 #[must_use]
185 pub fn value(&self) -> Option<u64> {
186 self.element()
187 .get_sub_element(ElementName::Value)?
188 .character_data()?
189 .parse_integer()
190 }
191
192 pub fn mode_declaration_group(&self) -> Result<ModeDeclarationGroup, AutosarAbstractionError> {
194 let Some(parent) = self.element().named_parent()? else {
195 return Err(AutosarAbstractionError::InvalidParameter(
196 "Mode declaration has no parent".to_string(),
197 ));
198 };
199 ModeDeclarationGroup::try_from(parent)
200 }
201}
202
203#[cfg(test)]
206mod test {
207 use super::*;
208 use crate::AutosarModelAbstraction;
209 use autosar_data::AutosarVersion;
210
211 #[test]
212 fn mode_declaration_group() {
213 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
214 let package = model.get_or_create_package("/Pkg").unwrap();
215 let mode_declaration_group = package.create_mode_declaration_group("test_group", None).unwrap();
216
217 assert_eq!(mode_declaration_group.category(), None);
218 assert_eq!(mode_declaration_group.name().unwrap(), "test_group");
219
220 mode_declaration_group
221 .set_category(Some(ModeDeclarationGroupCategory::ExplicitOrder))
222 .unwrap();
223 assert_eq!(
224 mode_declaration_group.category(),
225 Some(ModeDeclarationGroupCategory::ExplicitOrder)
226 );
227 mode_declaration_group
228 .set_category(Some(ModeDeclarationGroupCategory::AlphabeticOrder))
229 .unwrap();
230 assert_eq!(
231 mode_declaration_group.category(),
232 Some(ModeDeclarationGroupCategory::AlphabeticOrder)
233 );
234
235 assert_eq!(mode_declaration_group.on_transition_value(), None);
236 mode_declaration_group.set_on_transition_value(Some(42)).unwrap();
237 assert_eq!(mode_declaration_group.on_transition_value(), Some(42));
238 mode_declaration_group.set_on_transition_value(None).unwrap();
239 assert_eq!(mode_declaration_group.on_transition_value(), None);
240
241 let mode_declaration = mode_declaration_group.create_mode_declaration("test_mode").unwrap();
242 mode_declaration.set_value(Some(1)).unwrap();
243 assert_eq!(mode_declaration.value(), Some(1));
244
245 assert_eq!(mode_declaration_group.mode_declarations().count(), 1);
246
247 mode_declaration_group.set_initial_mode(&mode_declaration).unwrap();
248 assert_eq!(mode_declaration_group.initial_mode().unwrap(), mode_declaration);
249
250 let mode_declaration_group_2 = package.create_mode_declaration_group("test_group_2", None).unwrap();
251 mode_declaration_group_2
252 .set_initial_mode(&mode_declaration)
253 .unwrap_err(); }
255}