1use crate::{
2 AbstractionElement, ArPackage, AutosarAbstractionError, Element, IdentifiableAbstractionElement,
3 abstraction_element,
4 datatype::{AbstractAutosarDataType, AutosarDataType, ValueSpecification},
5 software_component::ModeDeclarationGroup,
6};
7use autosar_data::ElementName;
8
9mod clientserver;
10mod senderreceiver;
11
12pub use clientserver::*;
13pub use senderreceiver::*;
14
15#[derive(Debug, Clone, PartialEq, Eq, Hash)]
21pub struct ModeSwitchInterface(Element);
22abstraction_element!(ModeSwitchInterface, ModeSwitchInterface);
23impl IdentifiableAbstractionElement for ModeSwitchInterface {}
24impl AbstractPortInterface for ModeSwitchInterface {}
25
26impl ModeSwitchInterface {
27 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
29 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
30 let mode_switch_interface = elements.create_named_sub_element(ElementName::ModeSwitchInterface, name)?;
31
32 Ok(Self(mode_switch_interface))
33 }
34
35 pub fn create_mode_group(
39 &self,
40 name: &str,
41 mode_declaration_group: &ModeDeclarationGroup,
42 ) -> Result<ModeGroup, AutosarAbstractionError> {
43 ModeGroup::new(name, self.element(), mode_declaration_group)
44 }
45
46 #[must_use]
48 pub fn mode_group(&self) -> Option<ModeGroup> {
49 let mode_group_elem = self.element().get_sub_element(ElementName::ModeGroup)?;
50 ModeGroup::try_from(mode_group_elem).ok()
51 }
52}
53
54#[derive(Debug, Clone, PartialEq, Eq, Hash)]
60pub struct ModeGroup(Element);
61abstraction_element!(ModeGroup, ModeGroup);
62impl IdentifiableAbstractionElement for ModeGroup {}
63
64impl ModeGroup {
65 fn new(
67 name: &str,
68 parent_element: &Element,
69 mode_declaration_group: &ModeDeclarationGroup,
70 ) -> Result<Self, AutosarAbstractionError> {
71 let mode_group_elem = parent_element.create_named_sub_element(ElementName::ModeGroup, name)?;
72 let mode_group = Self(mode_group_elem);
73 mode_group.set_mode_declaration_group(mode_declaration_group)?;
74
75 Ok(mode_group)
76 }
77
78 pub fn set_mode_declaration_group(
80 &self,
81 mode_declaration_group: &ModeDeclarationGroup,
82 ) -> Result<(), AutosarAbstractionError> {
83 self.element()
84 .get_or_create_sub_element(ElementName::TypeTref)?
85 .set_reference_target(mode_declaration_group.element())?;
86 Ok(())
87 }
88
89 #[must_use]
91 pub fn mode_declaration_group(&self) -> Option<ModeDeclarationGroup> {
92 let mode_declaration_group_elem = self
93 .element()
94 .get_sub_element(ElementName::TypeTref)?
95 .get_reference_target()
96 .ok()?;
97 ModeDeclarationGroup::try_from(mode_declaration_group_elem).ok()
98 }
99}
100
101#[derive(Debug, Clone, PartialEq, Eq, Hash)]
107pub struct ParameterInterface(Element);
108abstraction_element!(ParameterInterface, ParameterInterface);
109impl IdentifiableAbstractionElement for ParameterInterface {}
110impl AbstractPortInterface for ParameterInterface {}
111
112impl ParameterInterface {
113 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
115 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
116 let parameter_interface = elements.create_named_sub_element(ElementName::ParameterInterface, name)?;
117
118 Ok(Self(parameter_interface))
119 }
120
121 pub fn create_parameter<T: AbstractAutosarDataType>(
123 &self,
124 name: &str,
125 data_type: &T,
126 ) -> Result<ParameterDataPrototype, AutosarAbstractionError> {
127 let parameters = self.element().get_or_create_sub_element(ElementName::Parameters)?;
128 ParameterDataPrototype::new(name, ¶meters, data_type)
129 }
130
131 pub fn parameters(&self) -> impl Iterator<Item = ParameterDataPrototype> + Send + 'static {
133 self.element()
134 .get_sub_element(ElementName::Parameters)
135 .into_iter()
136 .flat_map(|parameters| parameters.sub_elements())
137 .filter_map(|param| ParameterDataPrototype::try_from(param).ok())
138 }
139}
140
141#[derive(Debug, Clone, PartialEq, Eq, Hash)]
147pub struct ParameterDataPrototype(Element);
148abstraction_element!(ParameterDataPrototype, ParameterDataPrototype);
149impl IdentifiableAbstractionElement for ParameterDataPrototype {}
150
151impl ParameterDataPrototype {
152 fn new<T: AbstractAutosarDataType>(
154 name: &str,
155 parent_element: &Element,
156 data_type: &T,
157 ) -> Result<Self, AutosarAbstractionError> {
158 let pdp = parent_element.create_named_sub_element(ElementName::ParameterDataPrototype, name)?;
159
160 let pdp = Self(pdp);
161 pdp.set_data_type(data_type)?;
162
163 Ok(pdp)
164 }
165
166 pub fn set_init_value<T: Into<ValueSpecification>>(
168 &self,
169 value_spec: Option<T>,
170 ) -> Result<(), AutosarAbstractionError> {
171 if let Some(value_spec) = value_spec {
172 let value_spec: ValueSpecification = value_spec.into();
173 let init_value_elem = self.element().get_or_create_sub_element(ElementName::InitValue)?;
174 value_spec.store(&init_value_elem)?;
175 } else {
176 let _ = self.element().remove_sub_element_kind(ElementName::InitValue);
177 }
178 Ok(())
179 }
180
181 #[must_use]
183 pub fn init_value(&self) -> Option<ValueSpecification> {
184 let init_value_elem = self
185 .element()
186 .get_sub_element(ElementName::InitValue)?
187 .get_sub_element_at(0)?;
188 ValueSpecification::load(&init_value_elem)
189 }
190
191 pub fn interface(&self) -> Result<ParameterInterface, AutosarAbstractionError> {
193 let named_parent = self.element().named_parent()?.unwrap();
194 ParameterInterface::try_from(named_parent)
195 }
196
197 pub fn set_data_type<T: AbstractAutosarDataType>(&self, data_type: &T) -> Result<(), AutosarAbstractionError> {
199 self.element()
200 .get_or_create_sub_element(ElementName::TypeTref)?
201 .set_reference_target(data_type.element())?;
202 Ok(())
203 }
204
205 #[must_use]
207 pub fn data_type(&self) -> Option<AutosarDataType> {
208 let type_tref = self.element().get_sub_element(ElementName::TypeTref)?;
209 AutosarDataType::try_from(type_tref.get_reference_target().ok()?).ok()
210 }
211}
212
213#[derive(Debug, Clone, PartialEq, Eq, Hash)]
219pub struct NvDataInterface(Element);
220abstraction_element!(NvDataInterface, NvDataInterface);
221impl IdentifiableAbstractionElement for NvDataInterface {}
222impl AbstractPortInterface for NvDataInterface {}
223
224impl NvDataInterface {
225 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
227 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
228 let nv_data_interface = elements.create_named_sub_element(ElementName::NvDataInterface, name)?;
229
230 Ok(Self(nv_data_interface))
231 }
232}
233
234#[derive(Debug, Clone, PartialEq, Eq, Hash)]
240pub struct TriggerInterface(Element);
241abstraction_element!(TriggerInterface, TriggerInterface);
242impl IdentifiableAbstractionElement for TriggerInterface {}
243impl AbstractPortInterface for TriggerInterface {}
244
245impl TriggerInterface {
246 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
248 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
249 let trigger_interface = elements.create_named_sub_element(ElementName::TriggerInterface, name)?;
250
251 Ok(Self(trigger_interface))
252 }
253}
254
255pub trait AbstractPortInterface: AbstractionElement {
259 fn set_is_service(&self, is_service: Option<bool>) -> Result<(), AutosarAbstractionError> {
261 if let Some(is_service) = is_service {
262 self.element()
263 .get_or_create_sub_element(ElementName::IsService)?
264 .set_character_data(is_service)?;
265 } else {
266 let _ = self.element().remove_sub_element_kind(ElementName::IsService);
267 }
268 Ok(())
269 }
270
271 #[must_use]
273 fn is_service(&self) -> Option<bool> {
274 self.element()
275 .get_sub_element(ElementName::IsService)
276 .and_then(|elem| elem.character_data())
277 .and_then(|cdata| cdata.parse_bool())
278 }
279}
280
281#[derive(Debug, Clone, PartialEq, Eq, Hash)]
285pub enum PortInterface {
286 SenderReceiverInterface(SenderReceiverInterface),
288 ClientServerInterface(ClientServerInterface),
290 ModeSwitchInterface(ModeSwitchInterface),
292 ParameterInterface(ParameterInterface),
294 NvDataInterface(NvDataInterface),
296 TriggerInterface(TriggerInterface),
298}
299
300impl AbstractionElement for PortInterface {
301 fn element(&self) -> &Element {
302 match self {
303 PortInterface::SenderReceiverInterface(sender_receiver_interface) => sender_receiver_interface.element(),
304 PortInterface::ClientServerInterface(client_server_interface) => client_server_interface.element(),
305 PortInterface::ModeSwitchInterface(mode_switch_interface) => mode_switch_interface.element(),
306 PortInterface::ParameterInterface(parameter_interface) => parameter_interface.element(),
307 PortInterface::NvDataInterface(nv_data_interface) => nv_data_interface.element(),
308 PortInterface::TriggerInterface(trigger_interface) => trigger_interface.element(),
309 }
310 }
311}
312
313impl IdentifiableAbstractionElement for PortInterface {}
314impl AbstractPortInterface for PortInterface {}
315
316impl TryFrom<Element> for PortInterface {
317 type Error = AutosarAbstractionError;
318
319 fn try_from(element: Element) -> Result<Self, Self::Error> {
320 match element.element_name() {
321 ElementName::SenderReceiverInterface => {
322 Ok(PortInterface::SenderReceiverInterface(SenderReceiverInterface(element)))
323 }
324 ElementName::ClientServerInterface => {
325 Ok(PortInterface::ClientServerInterface(ClientServerInterface(element)))
326 }
327 ElementName::ModeSwitchInterface => Ok(PortInterface::ModeSwitchInterface(ModeSwitchInterface(element))),
328 ElementName::ParameterInterface => Ok(PortInterface::ParameterInterface(ParameterInterface(element))),
329 ElementName::NvDataInterface => Ok(PortInterface::NvDataInterface(NvDataInterface(element))),
330 ElementName::TriggerInterface => Ok(PortInterface::TriggerInterface(TriggerInterface(element))),
331 _ => Err(AutosarAbstractionError::ConversionError {
332 element,
333 dest: "PortInterface".to_string(),
334 }),
335 }
336 }
337}
338
339#[cfg(test)]
342mod test {
343 use super::*;
344 use crate::{
345 AutosarModelAbstraction,
346 datatype::{BaseTypeEncoding, ImplementationDataTypeSettings, TextValueSpecification},
347 software_component::AbstractSwComponentType,
348 };
349 use autosar_data::AutosarVersion;
350
351 #[test]
352 fn test_interfaces() {
353 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
354 let package = model.get_or_create_package("/package").unwrap();
355
356 let sender_receiver_interface = package
357 .create_sender_receiver_interface("sender_receiver_interface")
358 .unwrap();
359 let client_server_interface = package
360 .create_client_server_interface("client_server_interface")
361 .unwrap();
362 let mode_switch_interface = package.create_mode_switch_interface("mode_switch_interface").unwrap();
363 let parameter_interface = package.create_parameter_interface("parameter_interface").unwrap();
364 let nv_data_interface = package.create_nv_data_interface("nv_data_interface").unwrap();
365 let trigger_interface = package.create_trigger_interface("trigger_interface").unwrap();
366
367 let composition = package.create_composition_sw_component_type("composition").unwrap();
368
369 let port_1 = composition.create_p_port("port_1", &sender_receiver_interface).unwrap();
370 assert!(matches!(
371 port_1.port_interface(),
372 Ok(PortInterface::SenderReceiverInterface(interface)) if interface == sender_receiver_interface
373 ));
374 assert_eq!(
375 port_1.port_interface().unwrap().element(),
376 sender_receiver_interface.element()
377 );
378
379 let port_2 = composition.create_p_port("port_2", &client_server_interface).unwrap();
380 assert!(matches!(
381 port_2.port_interface(),
382 Ok(PortInterface::ClientServerInterface(interface)) if interface == client_server_interface
383 ));
384 assert_eq!(
385 port_2.port_interface().unwrap().element(),
386 client_server_interface.element()
387 );
388
389 let port_3 = composition.create_p_port("port_3", &mode_switch_interface).unwrap();
390 assert!(matches!(
391 port_3.port_interface(),
392 Ok(PortInterface::ModeSwitchInterface(interface)) if interface == mode_switch_interface
393 ));
394 assert_eq!(
395 port_3.port_interface().unwrap().element(),
396 mode_switch_interface.element()
397 );
398
399 let port_4 = composition.create_p_port("port_4", ¶meter_interface).unwrap();
400 assert!(matches!(
401 port_4.port_interface(),
402 Ok(PortInterface::ParameterInterface(interface)) if interface == parameter_interface
403 ));
404 assert_eq!(
405 port_4.port_interface().unwrap().element(),
406 parameter_interface.element()
407 );
408
409 let port_5 = composition.create_p_port("port_5", &nv_data_interface).unwrap();
410 assert!(matches!(
411 port_5.port_interface(),
412 Ok(PortInterface::NvDataInterface(interface)) if interface == nv_data_interface
413 ));
414 assert_eq!(port_5.port_interface().unwrap().element(), nv_data_interface.element());
415
416 let port_6 = composition.create_p_port("port_6", &trigger_interface).unwrap();
417 assert!(matches!(
418 port_6.port_interface(),
419 Ok(PortInterface::TriggerInterface(interface)) if interface == trigger_interface
420 ));
421 assert_eq!(port_6.port_interface().unwrap().element(), trigger_interface.element());
422 }
423
424 #[test]
425 fn parameter_interface() {
426 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
427 let package = model.get_or_create_package("/package").unwrap();
428
429 let parameter_interface = package.create_parameter_interface("parameter_interface").unwrap();
430 let base_type = package
431 .create_sw_base_type("base", 32, BaseTypeEncoding::None, None, None, None)
432 .unwrap();
433 let datatype = package
434 .create_implementation_data_type(&ImplementationDataTypeSettings::Value {
435 name: "ImplementationValue".to_string(),
436 base_type: base_type.clone(),
437 compu_method: None,
438 data_constraint: None,
439 })
440 .unwrap();
441
442 let parameter = parameter_interface.create_parameter("parameter", &datatype).unwrap();
443 assert_eq!(parameter.name().as_deref().unwrap(), "parameter");
444
445 assert_eq!(parameter_interface.parameters().count(), 1);
446
447 assert_eq!(parameter.interface().unwrap(), parameter_interface);
448 assert_eq!(
449 parameter.data_type().unwrap(),
450 AutosarDataType::ImplementationDataType(datatype)
451 );
452
453 parameter_interface.set_is_service(Some(true)).unwrap();
454 assert_eq!(parameter_interface.is_service(), Some(true));
455 parameter_interface.set_is_service(None).unwrap();
456 assert_eq!(parameter_interface.is_service(), None);
457
458 let value_spec = TextValueSpecification {
459 label: None,
460 value: "42".to_string(),
461 };
462 parameter.set_init_value(Some(value_spec)).unwrap();
463 assert_eq!(
464 parameter.init_value().unwrap(),
465 TextValueSpecification {
466 label: None,
467 value: "42".to_string()
468 }
469 .into()
470 );
471 }
472
473 #[test]
474 fn mode_switch_interface() {
475 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
476 let package = model.get_or_create_package("/package").unwrap();
477
478 let mode_declaration_group = package
479 .create_mode_declaration_group("mode_declaration_group", None)
480 .unwrap();
481
482 let mode_switch_interface = package.create_mode_switch_interface("mode_switch_interface").unwrap();
483 mode_switch_interface.set_is_service(Some(true)).unwrap();
484 assert_eq!(mode_switch_interface.is_service(), Some(true));
485 mode_switch_interface.set_is_service(None).unwrap();
486 assert_eq!(mode_switch_interface.is_service(), None);
487
488 let mode_group = mode_switch_interface
489 .create_mode_group("mode_group", &mode_declaration_group)
490 .unwrap();
491 assert_eq!(mode_switch_interface.mode_group().unwrap(), mode_group);
492 assert_eq!(mode_group.mode_declaration_group().unwrap(), mode_declaration_group);
493 }
494}