autosar_data_abstraction/software_component/internal_behavior/
mod.rs

1use crate::{
2    AbstractionElement, AutosarAbstractionError, Element, IdentifiableAbstractionElement, abstraction_element,
3    datatype::DataTypeMappingSet,
4    software_component::{
5        ClientServerOperation, ModeDeclaration, ModeGroup, PPortPrototype, PortPrototype, RPortPrototype,
6        SwComponentType, VariableDataPrototype,
7    },
8};
9use autosar_data::ElementName;
10
11mod rte_event;
12
13pub use rte_event::*;
14
15//##################################################################
16
17/// The `SwcInternalBehavior` of a software component type describes the
18/// details that are needed to generate the RTE.
19#[derive(Debug, Clone, PartialEq, Eq, Hash)]
20pub struct SwcInternalBehavior(Element);
21abstraction_element!(SwcInternalBehavior, SwcInternalBehavior);
22impl IdentifiableAbstractionElement for SwcInternalBehavior {}
23
24impl SwcInternalBehavior {
25    pub(crate) fn new(name: &str, parent: &Element) -> Result<Self, AutosarAbstractionError> {
26        let swc_internal_behavior = parent.create_named_sub_element(ElementName::SwcInternalBehavior, name)?;
27
28        Ok(Self(swc_internal_behavior))
29    }
30
31    /// remove the `SwcInternalBehavior` from the model
32    pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
33        // remove all events
34        for event in self.events() {
35            event.remove(deep)?;
36        }
37
38        // remove all runnable entities
39        for runnable in self.runnable_entities() {
40            runnable.remove(deep)?;
41        }
42
43        AbstractionElement::remove(self, deep)
44    }
45
46    /// Get the software component type that contains the `SwcInternalBehavior`
47    #[must_use]
48    pub fn sw_component_type(&self) -> Option<SwComponentType> {
49        let parent = self.element().named_parent().ok()??;
50        SwComponentType::try_from(parent).ok()
51    }
52
53    /// Create a new `RunnableEntity` in the `SwcInternalBehavior`
54    pub fn create_runnable_entity(&self, name: &str) -> Result<RunnableEntity, AutosarAbstractionError> {
55        let runnalbles_elem = self.element().get_or_create_sub_element(ElementName::Runnables)?;
56        RunnableEntity::new(name, &runnalbles_elem)
57    }
58
59    /// Get an iterator over all `RunnableEntities` in the `SwcInternalBehavior`
60    pub fn runnable_entities(&self) -> impl Iterator<Item = RunnableEntity> + Send + use<> {
61        self.element()
62            .get_sub_element(ElementName::Runnables)
63            .into_iter()
64            .flat_map(|runnables| runnables.sub_elements())
65            .filter_map(|elem| RunnableEntity::try_from(elem).ok())
66    }
67
68    /// Add a reference to a `DataTypeMappingSet` to the `SwcInternalBehavior`
69    pub fn add_data_type_mapping_set(
70        &self,
71        data_type_mapping_set: &DataTypeMappingSet,
72    ) -> Result<(), AutosarAbstractionError> {
73        self.element()
74            .get_or_create_sub_element(ElementName::DataTypeMappingRefs)?
75            .create_sub_element(ElementName::DataTypeMappingRef)?
76            .set_reference_target(data_type_mapping_set.element())?;
77        Ok(())
78    }
79
80    /// create an iterator over all `DataTypeMappingSet` references in the `SwcInternalBehavior`
81    pub fn data_type_mapping_sets(&self) -> impl Iterator<Item = DataTypeMappingSet> + Send + use<> {
82        self.element()
83            .get_sub_element(ElementName::DataTypeMappingRefs)
84            .into_iter()
85            .flat_map(|refs| {
86                refs.sub_elements()
87                    .filter_map(|elem| elem.get_reference_target().ok())
88                    .filter_map(|elem| DataTypeMappingSet::try_from(elem).ok())
89            })
90    }
91
92    /// Create a new `InitEvent` in the `SwcInternalBehavior`
93    pub fn create_init_event(
94        &self,
95        name: &str,
96        runnable: &RunnableEntity,
97    ) -> Result<InitEvent, AutosarAbstractionError> {
98        let events = self.element().get_or_create_sub_element(ElementName::Events)?;
99        InitEvent::new(name, &events, runnable)
100    }
101
102    /// Create a new `OperationInvokedEvent` in the `SwcInternalBehavior` when a server operation is invoked
103    pub fn create_operation_invoked_event(
104        &self,
105        name: &str,
106        runnable: &RunnableEntity,
107        client_server_operation: &ClientServerOperation,
108        context_p_port: &PPortPrototype,
109    ) -> Result<OperationInvokedEvent, AutosarAbstractionError> {
110        let events = self.element().get_or_create_sub_element(ElementName::Events)?;
111        OperationInvokedEvent::new(name, &events, runnable, client_server_operation, context_p_port)
112    }
113
114    /// Create a timing event that triggers a runnable in the `SwcInternalBehavior` based on a timer
115    pub fn create_timing_event(
116        &self,
117        name: &str,
118        runnable: &RunnableEntity,
119        period: f64,
120    ) -> Result<TimingEvent, AutosarAbstractionError> {
121        let events = self.element().get_or_create_sub_element(ElementName::Events)?;
122        TimingEvent::new(name, &events, runnable, period)
123    }
124
125    /// create a background event that triggers a runnable in the `SwcInternalBehavior` for background processing
126    pub fn create_background_event(
127        &self,
128        name: &str,
129        runnable: &RunnableEntity,
130    ) -> Result<BackgroundEvent, AutosarAbstractionError> {
131        let events = self.element().get_or_create_sub_element(ElementName::Events)?;
132        BackgroundEvent::new(name, &events, runnable)
133    }
134
135    /// create a data received event that triggers a runnable in the `SwcInternalBehavior` when data is received
136    pub fn create_data_received_event<T: Into<PortPrototype> + Clone>(
137        &self,
138        name: &str,
139        runnable: &RunnableEntity,
140        variable_data_prototype: &VariableDataPrototype,
141        context_port: &T,
142    ) -> Result<DataReceivedEvent, AutosarAbstractionError> {
143        let events = self.element().get_or_create_sub_element(ElementName::Events)?;
144        DataReceivedEvent::new(name, &events, runnable, variable_data_prototype, context_port)
145    }
146
147    /// create an os task execution event that triggers a runnable in the `SwcInternalBehavior` every time the task is executed
148    pub fn create_os_task_execution_event(
149        &self,
150        name: &str,
151        runnable: &RunnableEntity,
152    ) -> Result<OsTaskExecutionEvent, AutosarAbstractionError> {
153        let events = self.element().get_or_create_sub_element(ElementName::Events)?;
154        OsTaskExecutionEvent::new(name, &events, runnable)
155    }
156
157    /// create a mode switch event that triggers a runnable in the `SwcInternalBehavior` when the mode is switched
158    pub fn create_mode_switch_event<T: Into<PortPrototype> + Clone>(
159        &self,
160        name: &str,
161        runnable: &RunnableEntity,
162        activation: ModeActivationKind,
163        context_port: &T,
164        mode_declaration: &ModeDeclaration,
165        second_mode_declaration: Option<&ModeDeclaration>,
166    ) -> Result<SwcModeSwitchEvent, AutosarAbstractionError> {
167        let events = self.element().get_or_create_sub_element(ElementName::Events)?;
168        SwcModeSwitchEvent::new(
169            name,
170            &events,
171            runnable,
172            activation,
173            context_port,
174            mode_declaration,
175            second_mode_declaration,
176        )
177    }
178
179    /// create an iterator over all events in the `SwcInternalBehavior`
180    pub fn events(&self) -> impl Iterator<Item = RTEEvent> + Send + use<> {
181        self.element()
182            .get_sub_element(ElementName::Events)
183            .into_iter()
184            .flat_map(|events| events.sub_elements())
185            .filter_map(|elem| RTEEvent::try_from(elem).ok())
186    }
187}
188
189//##################################################################
190
191/// A `RunnableEntity` is a function that can be executed by the RTE
192#[derive(Debug, Clone, PartialEq, Eq, Hash)]
193pub struct RunnableEntity(Element);
194abstraction_element!(RunnableEntity, RunnableEntity);
195impl IdentifiableAbstractionElement for RunnableEntity {}
196
197impl RunnableEntity {
198    pub(crate) fn new(name: &str, parent: &Element) -> Result<Self, AutosarAbstractionError> {
199        let runnable_entity = parent.create_named_sub_element(ElementName::RunnableEntity, name)?;
200
201        Ok(Self(runnable_entity))
202    }
203
204    /// remove the `RunnableEntity` from the model
205    pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
206        let event_list = self.events();
207
208        AbstractionElement::remove(self, deep)?;
209
210        for event in event_list {
211            event.remove(deep)?;
212        }
213
214        Ok(())
215    }
216
217    /// Get the `SwcInternalBehavior` that contains the `RunnableEntity`
218    #[must_use]
219    pub fn swc_internal_behavior(&self) -> Option<SwcInternalBehavior> {
220        let parent = self.element().named_parent().ok()??;
221        SwcInternalBehavior::try_from(parent).ok()
222    }
223
224    /// List all events that can trigger the `RunnableEntity`
225    #[must_use]
226    pub fn events(&self) -> Vec<RTEEvent> {
227        let model_result = self.element().model();
228        let path_result = self.element().path();
229        if let (Ok(model), Ok(path)) = (model_result, path_result) {
230            model
231                .get_references_to(&path)
232                .iter()
233                .filter_map(|e| {
234                    e.upgrade()
235                        .and_then(|ref_elem| ref_elem.named_parent().ok().flatten())
236                        .and_then(|elem| RTEEvent::try_from(elem).ok())
237                })
238                .collect()
239        } else {
240            vec![]
241        }
242    }
243
244    /// add implicit read access to a data element of a sender-receiver `PortPrototype`
245    ///
246    /// this results in `Rte_IRead_<port>_<data_element>` being generated
247    pub fn create_data_read_access<T: Into<PortPrototype> + Clone>(
248        &self,
249        name: &str,
250        data_element: &VariableDataPrototype,
251        context_port: &T,
252    ) -> Result<VariableAccess, AutosarAbstractionError> {
253        let data_accesses = self.element().get_or_create_sub_element(ElementName::DataReadAccesss)?;
254        VariableAccess::new(name, &data_accesses, data_element, &context_port.clone().into())
255    }
256
257    /// iterate over all data read accesses
258    pub fn data_read_accesses(&self) -> impl Iterator<Item = VariableAccess> + Send + use<> {
259        self.element()
260            .get_sub_element(ElementName::DataReadAccesss)
261            .into_iter()
262            .flat_map(|data_accesses| data_accesses.sub_elements())
263            .filter_map(|elem| VariableAccess::try_from(elem).ok())
264    }
265
266    /// add implicit write access to a data element of a sender-receiver `PortPrototype`
267    ///
268    /// this results in `Rte_IWrite_<port>_<data_element>` being generated
269    pub fn create_data_write_access<T: Into<PortPrototype> + Clone>(
270        &self,
271        name: &str,
272        data_element: &VariableDataPrototype,
273        context_port: &T,
274    ) -> Result<VariableAccess, AutosarAbstractionError> {
275        let data_accesses = self
276            .element()
277            .get_or_create_sub_element(ElementName::DataWriteAccesss)?;
278        VariableAccess::new(name, &data_accesses, data_element, &context_port.clone().into())
279    }
280
281    /// iterate over all data write accesses
282    pub fn data_write_accesses(&self) -> impl Iterator<Item = VariableAccess> + Send + use<> {
283        self.element()
284            .get_sub_element(ElementName::DataWriteAccesss)
285            .into_iter()
286            .flat_map(|data_accesses| data_accesses.sub_elements())
287            .filter_map(|elem| VariableAccess::try_from(elem).ok())
288    }
289
290    /// add a data send point to a data element of a sender-receiver `PortPrototype`
291    pub fn create_data_send_point<T: Into<PortPrototype> + Clone>(
292        &self,
293        name: &str,
294        data_element: &VariableDataPrototype,
295        context_port: &T,
296    ) -> Result<VariableAccess, AutosarAbstractionError> {
297        let data_accesses = self.element().get_or_create_sub_element(ElementName::DataSendPoints)?;
298        VariableAccess::new(name, &data_accesses, data_element, &context_port.clone().into())
299    }
300
301    /// iterate over all data send points
302    pub fn data_send_points(&self) -> impl Iterator<Item = VariableAccess> + Send + use<> {
303        self.element()
304            .get_sub_element(ElementName::DataSendPoints)
305            .into_iter()
306            .flat_map(|data_accesses| data_accesses.sub_elements())
307            .filter_map(|elem| VariableAccess::try_from(elem).ok())
308    }
309
310    /// add explicit read access by argument to a data element of a sender-receiver `PortPrototype`
311    ///
312    /// this results in `Rte_Read_<port>_<data_element>(DataType* data)` being generated
313    pub fn create_data_receive_point_by_argument<T: Into<PortPrototype> + Clone>(
314        &self,
315        name: &str,
316        data_element: &VariableDataPrototype,
317        context_port: &T,
318    ) -> Result<VariableAccess, AutosarAbstractionError> {
319        let data_accesses = self
320            .element()
321            .get_or_create_sub_element(ElementName::DataReceivePointByArguments)?;
322        VariableAccess::new(name, &data_accesses, data_element, &context_port.clone().into())
323    }
324
325    /// iterate over all data receive points by argument
326    pub fn data_receive_points_by_argument(&self) -> impl Iterator<Item = VariableAccess> + Send + use<> {
327        self.element()
328            .get_sub_element(ElementName::DataReceivePointByArguments)
329            .into_iter()
330            .flat_map(|data_accesses| data_accesses.sub_elements())
331            .filter_map(|elem| VariableAccess::try_from(elem).ok())
332    }
333
334    /// add explicit read access by value to a data element of a sender-receiver `PortPrototype`
335    pub fn create_data_receive_point_by_value<T: Into<PortPrototype> + Clone>(
336        &self,
337        name: &str,
338        data_element: &VariableDataPrototype,
339        context_port: &T,
340    ) -> Result<VariableAccess, AutosarAbstractionError> {
341        let data_accesses = self
342            .element()
343            .get_or_create_sub_element(ElementName::DataReceivePointByValues)?;
344        VariableAccess::new(name, &data_accesses, data_element, &context_port.clone().into())
345    }
346
347    /// iterate over all data receive points by value
348    pub fn data_receive_points_by_value(&self) -> impl Iterator<Item = VariableAccess> + Send + use<> {
349        self.element()
350            .get_sub_element(ElementName::DataReceivePointByValues)
351            .into_iter()
352            .flat_map(|data_accesses| data_accesses.sub_elements())
353            .filter_map(|elem| VariableAccess::try_from(elem).ok())
354    }
355
356    /// create a synchronous server call point that allows the runnable to call a server operation
357    pub fn create_synchronous_server_call_point(
358        &self,
359        name: &str,
360        client_server_operation: &ClientServerOperation,
361        context_r_port: &RPortPrototype,
362    ) -> Result<SynchronousServerCallPoint, AutosarAbstractionError> {
363        let server_call_points = self
364            .element()
365            .get_or_create_sub_element(ElementName::ServerCallPoints)?;
366        SynchronousServerCallPoint::new(name, &server_call_points, client_server_operation, context_r_port)
367    }
368
369    /// iterate over all synchronous server call points
370    pub fn synchronous_server_call_points(&self) -> impl Iterator<Item = SynchronousServerCallPoint> + Send + use<> {
371        self.element()
372            .get_sub_element(ElementName::ServerCallPoints)
373            .into_iter()
374            .flat_map(|server_call_points| server_call_points.sub_elements())
375            .filter_map(|elem| SynchronousServerCallPoint::try_from(elem).ok())
376    }
377
378    /// create a mode access point that allows the runnable to access the current mode of a ModeDeclarationGroup
379    pub fn create_mode_access_point<T: Into<PortPrototype> + Clone>(
380        &self,
381        name: &str,
382        mode_group: &ModeGroup,
383        context_port: &T,
384    ) -> Result<ModeAccessPoint, AutosarAbstractionError> {
385        let mode_access_points = self
386            .element()
387            .get_or_create_sub_element(ElementName::ModeAccessPoints)?;
388        ModeAccessPoint::new(name, &mode_access_points, mode_group, &context_port.clone().into())
389    }
390
391    /// iterate over all mode access points
392    pub fn mode_access_points(&self) -> impl Iterator<Item = ModeAccessPoint> + Send + use<> {
393        self.element()
394            .get_sub_element(ElementName::ModeAccessPoints)
395            .into_iter()
396            .flat_map(|mode_access_points| mode_access_points.sub_elements())
397            .filter_map(|elem| ModeAccessPoint::try_from(elem).ok())
398    }
399
400    /// create a mode switch point that allows the runnable to switch modes in a ModeDeclarationGroup
401    pub fn create_mode_switch_point<T: Into<PortPrototype> + Clone>(
402        &self,
403        name: &str,
404        mode_group: &ModeGroup,
405        context_port: &T,
406    ) -> Result<ModeSwitchPoint, AutosarAbstractionError> {
407        let mode_switch_points = self
408            .element()
409            .get_or_create_sub_element(ElementName::ModeSwitchPoints)?;
410        ModeSwitchPoint::new(name, &mode_switch_points, mode_group, context_port)
411    }
412
413    /// iterate over all mode switch points
414    pub fn mode_switch_points(&self) -> impl Iterator<Item = ModeSwitchPoint> + Send + use<> {
415        self.element()
416            .get_sub_element(ElementName::ModeSwitchPoints)
417            .into_iter()
418            .flat_map(|mode_switch_points| mode_switch_points.sub_elements())
419            .filter_map(|elem| ModeSwitchPoint::try_from(elem).ok())
420    }
421}
422
423//##################################################################
424
425/// A `VariableAccess` allows a `RunnableEntity` to access a variable in various contexts
426#[derive(Debug, Clone, PartialEq, Eq, Hash)]
427pub struct VariableAccess(Element);
428abstraction_element!(VariableAccess, VariableAccess);
429impl IdentifiableAbstractionElement for VariableAccess {}
430
431impl VariableAccess {
432    pub(crate) fn new(
433        name: &str,
434        parent: &Element,
435        data_element: &VariableDataPrototype,
436        context_port: &PortPrototype,
437    ) -> Result<Self, AutosarAbstractionError> {
438        let variable_access = parent.create_named_sub_element(ElementName::VariableAccess, name)?;
439        let variable_access = Self(variable_access);
440        variable_access.set_accessed_variable(data_element, context_port)?;
441
442        Ok(variable_access)
443    }
444
445    /// Set the accessed variable
446    pub fn set_accessed_variable(
447        &self,
448        data_element: &VariableDataPrototype,
449        context_port: &PortPrototype,
450    ) -> Result<(), AutosarAbstractionError> {
451        // remove the old accessed variable
452        let _ = self.element().remove_sub_element_kind(ElementName::AccessedVariable);
453        let accessed_variable = self.element().create_sub_element(ElementName::AccessedVariable)?;
454        let autosar_variable_iref = accessed_variable.create_sub_element(ElementName::AutosarVariableIref)?;
455
456        autosar_variable_iref
457            .create_sub_element(ElementName::TargetDataPrototypeRef)?
458            .set_reference_target(data_element.element())?;
459        autosar_variable_iref
460            .create_sub_element(ElementName::PortPrototypeRef)?
461            .set_reference_target(context_port.element())?;
462        Ok(())
463    }
464
465    /// Get the accessed variable
466    #[must_use]
467    pub fn accessed_variable(&self) -> Option<(VariableDataPrototype, PortPrototype)> {
468        let accessed_variable = self.element().get_sub_element(ElementName::AccessedVariable)?;
469        let autosar_variable_iref = accessed_variable.get_sub_element(ElementName::AutosarVariableIref)?;
470        let data_prototype_ref = autosar_variable_iref.get_sub_element(ElementName::TargetDataPrototypeRef)?;
471        let port_prototype_ref = autosar_variable_iref.get_sub_element(ElementName::PortPrototypeRef)?;
472
473        let data_prototype = VariableDataPrototype::try_from(data_prototype_ref.get_reference_target().ok()?).ok()?;
474        let port_prototype = PortPrototype::try_from(port_prototype_ref.get_reference_target().ok()?).ok()?;
475
476        Some((data_prototype, port_prototype))
477    }
478
479    /// Get the `RunnableEntity` that contains the `VariableAccess`
480    #[must_use]
481    pub fn runnable_entity(&self) -> Option<RunnableEntity> {
482        let parent = self.element().named_parent().ok()??;
483        RunnableEntity::try_from(parent).ok()
484    }
485}
486
487//##################################################################
488
489/// A `SynchronousServerCallPoint` allows a `RunnableEntity` to call a server operation synchronously
490#[derive(Debug, Clone, PartialEq, Eq, Hash)]
491pub struct SynchronousServerCallPoint(Element);
492abstraction_element!(SynchronousServerCallPoint, SynchronousServerCallPoint);
493impl IdentifiableAbstractionElement for SynchronousServerCallPoint {}
494
495impl SynchronousServerCallPoint {
496    pub(crate) fn new(
497        name: &str,
498        parent: &Element,
499        client_server_operation: &ClientServerOperation,
500        context_r_port: &RPortPrototype,
501    ) -> Result<Self, AutosarAbstractionError> {
502        let synchronous_server_call_point =
503            parent.create_named_sub_element(ElementName::SynchronousServerCallPoint, name)?;
504        let synchronous_server_call_point = Self(synchronous_server_call_point);
505        synchronous_server_call_point.set_client_server_operation(client_server_operation, context_r_port)?;
506
507        Ok(synchronous_server_call_point)
508    }
509
510    /// Set the client server operation
511    pub fn set_client_server_operation(
512        &self,
513        client_server_operation: &ClientServerOperation,
514        context_r_port: &RPortPrototype,
515    ) -> Result<(), AutosarAbstractionError> {
516        // remove the old client server operation
517        let _ = self.element().remove_sub_element_kind(ElementName::OperationIref);
518        let operation_iref = self.element().create_sub_element(ElementName::OperationIref)?;
519
520        operation_iref
521            .create_sub_element(ElementName::TargetRequiredOperationRef)?
522            .set_reference_target(client_server_operation.element())?;
523        operation_iref
524            .create_sub_element(ElementName::ContextRPortRef)?
525            .set_reference_target(context_r_port.element())?;
526        Ok(())
527    }
528
529    /// Get the client server operation
530    #[must_use]
531    pub fn client_server_operation(&self) -> Option<(ClientServerOperation, RPortPrototype)> {
532        let operation_iref = self.element().get_sub_element(ElementName::OperationIref)?;
533        let required_operation_ref = operation_iref.get_sub_element(ElementName::TargetRequiredOperationRef)?;
534        let context_r_port_ref = operation_iref.get_sub_element(ElementName::ContextRPortRef)?;
535
536        let client_server_operation =
537            ClientServerOperation::try_from(required_operation_ref.get_reference_target().ok()?).ok()?;
538        let context_r_port = RPortPrototype::try_from(context_r_port_ref.get_reference_target().ok()?).ok()?;
539
540        Some((client_server_operation, context_r_port))
541    }
542
543    /// Get the `RunnableEntity` that contains the `SynchronousServerCallPoint`
544    #[must_use]
545    pub fn runnable_entity(&self) -> Option<RunnableEntity> {
546        let parent = self.element().named_parent().ok()??;
547        RunnableEntity::try_from(parent).ok()
548    }
549}
550
551//##################################################################
552
553/// A `ModeAccessPoint`provides the ability to access the current mode of a ModeDeclarationGroup
554#[derive(Debug, Clone, PartialEq, Eq, Hash)]
555pub struct ModeAccessPoint(Element);
556abstraction_element!(ModeAccessPoint, ModeAccessPoint);
557
558// not identifiable, but it has an Ident element instead
559impl IdentifiableAbstractionElement for ModeAccessPoint {
560    fn name(&self) -> Option<String> {
561        self.element()
562            .get_sub_element(ElementName::Ident)
563            .and_then(|elem| elem.item_name())
564    }
565
566    /// set the name of the mode access point
567    fn set_name(&self, name: &str) -> Result<(), AutosarAbstractionError> {
568        // rename an existing Ident element or create a new one
569        if let Some(ident_elem) = self.element().get_sub_element(ElementName::Ident) {
570            ident_elem.set_item_name(name)?;
571        } else {
572            self.element().create_named_sub_element(ElementName::Ident, name)?;
573        }
574        Ok(())
575    }
576}
577
578impl ModeAccessPoint {
579    pub(crate) fn new<T: Into<PortPrototype> + Clone>(
580        name: &str,
581        parent: &Element,
582        mode_group: &ModeGroup,
583        context_port: &T,
584    ) -> Result<Self, AutosarAbstractionError> {
585        let mode_access_point = parent.create_sub_element(ElementName::ModeAccessPoint)?;
586        let mode_access_point = Self(mode_access_point);
587        mode_access_point.set_name(name)?;
588        mode_access_point.set_mode_group(mode_group, context_port)?;
589
590        Ok(mode_access_point)
591    }
592
593    /// Set the mode group and context port for the mode access point
594    pub fn set_mode_group<T: Into<PortPrototype> + Clone>(
595        &self,
596        mode_group: &ModeGroup,
597        context_port: &T,
598    ) -> Result<(), AutosarAbstractionError> {
599        let context_port = context_port.clone().into();
600        // remove the old mode group iref
601        let _ = self.element().remove_sub_element_kind(ElementName::ModeGroupIref);
602        let mode_group_iref = self.element().create_sub_element(ElementName::ModeGroupIref)?;
603
604        let context_port_elem = context_port.element();
605        match context_port {
606            PortPrototype::R(_) | PortPrototype::PR(_) => {
607                let r_ref_container =
608                    mode_group_iref.create_sub_element(ElementName::RModeGroupInAtomicSwcInstanceRef)?;
609                r_ref_container
610                    .create_sub_element(ElementName::ContextRPortRef)?
611                    .set_reference_target(context_port_elem)?;
612                r_ref_container
613                    .create_sub_element(ElementName::TargetModeGroupRef)?
614                    .set_reference_target(mode_group.element())?;
615            }
616            PortPrototype::P(_) => {
617                let p_ref_container =
618                    mode_group_iref.create_sub_element(ElementName::PModeGroupInAtomicSwcInstanceRef)?;
619                p_ref_container
620                    .create_sub_element(ElementName::ContextPPortRef)?
621                    .set_reference_target(context_port_elem)?;
622                p_ref_container
623                    .create_sub_element(ElementName::TargetModeGroupRef)?
624                    .set_reference_target(mode_group.element())?;
625            }
626        }
627
628        Ok(())
629    }
630
631    /// Get the mode group and context port for the mode access point
632    #[must_use]
633    pub fn mode_group(&self) -> Option<(ModeGroup, PortPrototype)> {
634        let mode_group_iref = self.element().get_sub_element(ElementName::ModeGroupIref)?;
635
636        // Determine the context port reference based on the mode group reference type
637        if let Some(r_ref_container) = mode_group_iref.get_sub_element(ElementName::RModeGroupInAtomicSwcInstanceRef) {
638            let context_r_port = r_ref_container
639                .get_sub_element(ElementName::ContextRPortRef)?
640                .get_reference_target()
641                .ok()?;
642            let mode_group = r_ref_container
643                .get_sub_element(ElementName::TargetModeGroupRef)?
644                .get_reference_target()
645                .ok()?;
646            Some((
647                ModeGroup::try_from(mode_group).ok()?,
648                PortPrototype::try_from(context_r_port).ok()?,
649            ))
650        } else if let Some(p_ref_container) =
651            mode_group_iref.get_sub_element(ElementName::PModeGroupInAtomicSwcInstanceRef)
652        {
653            let context_p_port = p_ref_container
654                .get_sub_element(ElementName::ContextPPortRef)?
655                .get_reference_target()
656                .ok()?;
657            let mode_group = p_ref_container
658                .get_sub_element(ElementName::TargetModeGroupRef)?
659                .get_reference_target()
660                .ok()?;
661            Some((
662                ModeGroup::try_from(mode_group).ok()?,
663                PortPrototype::try_from(context_p_port).ok()?,
664            ))
665        } else {
666            None
667        }
668    }
669
670    /// Get the `RunnableEntity` that contains the `ModeAccessPoint`
671    #[must_use]
672    pub fn runnable_entity(&self) -> Option<RunnableEntity> {
673        let parent = self.element().named_parent().ok()??;
674        RunnableEntity::try_from(parent).ok()
675    }
676}
677
678//##################################################################
679
680/// A `ModeSwitchPoint` allows a `RunnableEntity` to switch modes in a ModeDeclarationGroup
681#[derive(Debug, Clone, PartialEq, Eq, Hash)]
682pub struct ModeSwitchPoint(Element);
683abstraction_element!(ModeSwitchPoint, ModeSwitchPoint);
684impl IdentifiableAbstractionElement for ModeSwitchPoint {}
685
686impl ModeSwitchPoint {
687    pub(crate) fn new<T: Into<PortPrototype> + Clone>(
688        name: &str,
689        parent: &Element,
690        mode_group: &ModeGroup,
691        context_port: &T,
692    ) -> Result<Self, AutosarAbstractionError> {
693        let mode_switch_point = parent.create_named_sub_element(ElementName::ModeSwitchPoint, name)?;
694        let mode_switch_point = Self(mode_switch_point);
695        mode_switch_point.set_mode_group(mode_group, context_port)?;
696
697        Ok(mode_switch_point)
698    }
699
700    /// Set the mode group and context port for the mode switch point
701    pub fn set_mode_group<T: Into<PortPrototype> + Clone>(
702        &self,
703        mode_group: &ModeGroup,
704        context_port: &T,
705    ) -> Result<(), AutosarAbstractionError> {
706        let context_port = context_port.clone().into();
707        if matches!(context_port, PortPrototype::R(_)) {
708            return Err(AutosarAbstractionError::InvalidParameter(
709                "ModeSwitchPoint context_port cannot be an R port".to_string(),
710            ));
711        }
712
713        // remove the old mode group iref
714        let _ = self.element().remove_sub_element_kind(ElementName::ModeGroupIref);
715        let mode_group_iref = self.element().create_sub_element(ElementName::ModeGroupIref)?;
716
717        mode_group_iref
718            .create_sub_element(ElementName::TargetModeGroupRef)?
719            .set_reference_target(mode_group.element())?;
720        mode_group_iref
721            .create_sub_element(ElementName::ContextPPortRef)?
722            .set_reference_target(context_port.element())?;
723
724        Ok(())
725    }
726
727    /// Get the mode group and context port for the mode switch point
728    #[must_use]
729    pub fn mode_group(&self) -> Option<(ModeGroup, PortPrototype)> {
730        let mode_group_iref = self.element().get_sub_element(ElementName::ModeGroupIref)?;
731        let mode_group = mode_group_iref
732            .get_sub_element(ElementName::TargetModeGroupRef)?
733            .get_reference_target()
734            .ok()?;
735        let context_port = mode_group_iref
736            .get_sub_element(ElementName::ContextPPortRef)?
737            .get_reference_target()
738            .ok()?;
739
740        let mode_declaration = ModeGroup::try_from(mode_group).ok()?;
741        let context_port = PortPrototype::try_from(context_port).ok()?;
742
743        Some((mode_declaration, context_port))
744    }
745
746    /// Get the `RunnableEntity` that contains the `ModeSwitchPoint`
747    #[must_use]
748    pub fn runnable_entity(&self) -> Option<RunnableEntity> {
749        let parent = self.element().named_parent().ok()??;
750        RunnableEntity::try_from(parent).ok()
751    }
752}
753
754//##################################################################
755
756#[cfg(test)]
757mod test {
758    use super::*;
759    use crate::{
760        AbstractionElement, AutosarModelAbstraction,
761        datatype::ApplicationPrimitiveCategory,
762        software_component::{AbstractRTEEvent, AbstractSwComponentType, AtomicSwComponentType},
763    };
764    use autosar_data::{AutosarVersion, EnumItem};
765
766    #[test]
767    fn swc_internal_behavior() {
768        let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
769        let package = model.get_or_create_package("/package").unwrap();
770
771        // create a client-server interface
772        let client_server_interface = package.create_client_server_interface("ClientServerInterface").unwrap();
773        let operation = client_server_interface.create_operation("TestOperation").unwrap();
774
775        // create a software component type with an internal behavior
776        let app_swc = package
777            .create_application_sw_component_type("AppSwComponentType")
778            .unwrap();
779        let p_port = app_swc.create_p_port("p_port", &client_server_interface).unwrap();
780        let swc_internal_behavior = app_swc
781            .create_swc_internal_behavior("AppSwComponentType_InternalBehavior")
782            .unwrap();
783        assert_eq!(app_swc.swc_internal_behaviors().count(), 1);
784        assert_eq!(swc_internal_behavior.sw_component_type().unwrap(), app_swc.into());
785
786        // create two runnable entities
787        let runnable1 = swc_internal_behavior.create_runnable_entity("Runnable1").unwrap();
788        assert_eq!(runnable1.swc_internal_behavior().unwrap(), swc_internal_behavior);
789        let runnable2 = swc_internal_behavior.create_runnable_entity("Runnable2").unwrap();
790        assert_eq!(swc_internal_behavior.runnable_entities().count(), 2);
791
792        // create an init event, which triggers runnable1
793        let init_event = swc_internal_behavior
794            .create_init_event("InitEvent", &runnable1)
795            .unwrap();
796        assert_eq!(init_event.runnable_entity().unwrap(), runnable1);
797
798        // create an operation invoked event, which triggers runnable1
799        let op_invoked_event = swc_internal_behavior
800            .create_operation_invoked_event("OpInvokedEvent", &runnable1, &operation, &p_port)
801            .unwrap();
802        let (op_invoked_event_operation, context_p_port) = op_invoked_event.client_server_operation().unwrap();
803        assert_eq!(op_invoked_event_operation, operation);
804        assert_eq!(context_p_port, p_port);
805        assert_eq!(op_invoked_event.runnable_entity().unwrap(), runnable1);
806
807        // create a background event, which triggers runnable1
808        let background_event = swc_internal_behavior
809            .create_background_event("BackgroundEvent", &runnable1)
810            .unwrap();
811        assert_eq!(background_event.runnable_entity().unwrap(), runnable1);
812
813        // create an os task execution event, which triggers runnable1
814        let os_task_execution_event = swc_internal_behavior
815            .create_os_task_execution_event("OsTaskExecutionEvent", &runnable1)
816            .unwrap();
817        assert_eq!(os_task_execution_event.runnable_entity().unwrap(), runnable1);
818
819        // create a timing event, which triggers runnable2
820        let timing_event = swc_internal_behavior
821            .create_timing_event("TimingEvent", &runnable2, 0.1)
822            .unwrap();
823        assert_eq!(timing_event.period().unwrap(), 0.1);
824        assert_eq!(timing_event.runnable_entity().unwrap(), runnable2);
825        assert_eq!(timing_event.swc_internal_behavior().unwrap(), swc_internal_behavior);
826
827        // there should be 3 events in the swc_internal_behavior
828        assert_eq!(swc_internal_behavior.events().count(), 5);
829        // iterate over all events and check if they are the same as the ones we created
830        let mut events_iter = swc_internal_behavior.events();
831        assert_eq!(events_iter.next().unwrap().element(), init_event.element());
832        assert_eq!(events_iter.next().unwrap().element(), op_invoked_event.element());
833        assert_eq!(events_iter.next().unwrap().element(), background_event.element());
834        assert_eq!(events_iter.next().unwrap().element(), os_task_execution_event.element());
835        assert_eq!(events_iter.next().unwrap().element(), timing_event.element());
836
837        // runnable1 should be triggered by 4 events
838        assert_eq!(runnable1.events().len(), 4);
839        // runnable2 should be triggered by 1 event
840        assert_eq!(runnable2.events().len(), 1);
841
842        // add a data type mapping set to the swc_internal_behavior
843        let data_type_mapping_set = package.create_data_type_mapping_set("MappingSet").unwrap();
844        swc_internal_behavior
845            .add_data_type_mapping_set(&data_type_mapping_set)
846            .unwrap();
847        assert_eq!(swc_internal_behavior.data_type_mapping_sets().count(), 1);
848    }
849
850    #[test]
851    fn mode_switch_event() {
852        let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
853        let package = model.get_or_create_package("/package").unwrap();
854
855        // create a software component type with an internal behavior
856        let app_swc = package
857            .create_application_sw_component_type("AppSwComponentType")
858            .unwrap();
859        let swc_internal_behavior = app_swc
860            .create_swc_internal_behavior("AppSwComponentType_InternalBehavior")
861            .unwrap();
862        assert_eq!(app_swc.swc_internal_behaviors().count(), 1);
863        assert_eq!(
864            swc_internal_behavior.sw_component_type().unwrap(),
865            app_swc.clone().into()
866        );
867
868        // create a mode declaration group and a mode switch interface
869        let mode_declaration_group = package
870            .create_mode_declaration_group("ModeDeclarationGroup", None)
871            .unwrap();
872        let mode_declaration_1 = mode_declaration_group
873            .create_mode_declaration("ModeDeclaration1")
874            .unwrap();
875        let mode_declaration_2 = mode_declaration_group
876            .create_mode_declaration("ModeDeclaration2")
877            .unwrap();
878        let mode_switch_interface = package.create_mode_switch_interface("ModeSwitchInterface").unwrap();
879        let r_port = app_swc.create_r_port("r_port", &mode_switch_interface).unwrap();
880
881        let mode_declaration_group2 = package
882            .create_mode_declaration_group("ModeDeclarationGroup2", None)
883            .unwrap();
884        let mode_declaration_g2 = mode_declaration_group2
885            .create_mode_declaration("ModeDeclaratio_g2")
886            .unwrap();
887
888        //  create a second port for the error path test which does not have a mode switch interface
889        let client_server_interface = package.create_client_server_interface("ClientServerInterface").unwrap();
890        let bad_port = app_swc.create_r_port("bad_port", &client_server_interface).unwrap();
891
892        // create a runnable entity
893        let runnable = swc_internal_behavior.create_runnable_entity("Runnable1").unwrap();
894        assert_eq!(runnable.swc_internal_behavior().unwrap(), swc_internal_behavior);
895
896        // error case: create a mode switch event with a port that does not have a mode switch interface
897        let result = swc_internal_behavior.create_mode_switch_event(
898            "ModeSwitchEvent",
899            &runnable,
900            ModeActivationKind::OnEntry,
901            &bad_port,
902            &mode_declaration_g2,
903            None,
904        );
905        assert!(result.is_err());
906
907        // error case: the mode switch interface does not contain a mode group
908        let result = swc_internal_behavior.create_mode_switch_event(
909            "ModeSwitchEvent",
910            &runnable,
911            ModeActivationKind::OnEntry,
912            &r_port,
913            &mode_declaration_1,
914            Some(&mode_declaration_2),
915        );
916        assert!(result.is_err());
917
918        // create the mode group in the mode switch interface
919        mode_switch_interface
920            .create_mode_group("mode_group", &mode_declaration_group)
921            .unwrap();
922
923        // error case: create a mode switch event with a mode_declaration that is not part of the mode declaration group
924        let result = swc_internal_behavior.create_mode_switch_event(
925            "ModeSwitchEvent",
926            &runnable,
927            ModeActivationKind::OnEntry,
928            &r_port,
929            &mode_declaration_g2,
930            None,
931        );
932        assert!(result.is_err());
933
934        // correct: create a mode switch event with a mode_declaration that is part of the mode declaration group
935        let mode_switch_event = swc_internal_behavior
936            .create_mode_switch_event(
937                "ModeSwitchEvent",
938                &runnable,
939                ModeActivationKind::OnEntry,
940                &r_port,
941                &mode_declaration_1,
942                Some(&mode_declaration_2),
943            )
944            .unwrap();
945        assert_eq!(mode_switch_event.runnable_entity().unwrap(), runnable);
946
947        assert_eq!(runnable.events().len(), 1);
948
949        let (mode_decls, context_port) = mode_switch_event.mode_declarations().unwrap();
950        assert_eq!(context_port, r_port.into());
951        assert_eq!(mode_decls.len(), 2);
952        assert_eq!(mode_decls[0], mode_declaration_1);
953        assert_eq!(mode_decls[1], mode_declaration_2);
954
955        // check the mode activation kind
956        mode_switch_event
957            .set_mode_activation_kind(ModeActivationKind::OnEntry)
958            .unwrap();
959        assert_eq!(
960            mode_switch_event.mode_activation_kind().unwrap(),
961            ModeActivationKind::OnEntry
962        );
963        mode_switch_event
964            .set_mode_activation_kind(ModeActivationKind::OnExit)
965            .unwrap();
966        assert_eq!(
967            mode_switch_event.mode_activation_kind().unwrap(),
968            ModeActivationKind::OnExit
969        );
970        mode_switch_event
971            .set_mode_activation_kind(ModeActivationKind::OnTransition)
972            .unwrap();
973        assert_eq!(
974            mode_switch_event.mode_activation_kind().unwrap(),
975            ModeActivationKind::OnTransition
976        );
977
978        // mode activation kind error case
979        let activation_kind = ModeActivationKind::try_from(EnumItem::Opaque);
980        assert!(activation_kind.is_err());
981    }
982
983    #[test]
984    fn data_received_event() {
985        let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
986        let package = model.get_or_create_package("/package").unwrap();
987
988        // create a sender receiver interface with a variable
989        let sender_receiver_interface = package
990            .create_sender_receiver_interface("SenderReceiverInterface")
991            .unwrap();
992        let app_data_type = package
993            .create_application_primitive_data_type("uint32", ApplicationPrimitiveCategory::Value, None, None, None)
994            .unwrap();
995        let variable_data_prototype = sender_receiver_interface
996            .create_data_element("data", &app_data_type)
997            .unwrap();
998
999        // create a software component type with an internal behavior
1000        let app_swc = package
1001            .create_application_sw_component_type("AppSwComponentType")
1002            .unwrap();
1003        let r_port = app_swc.create_r_port("r_port", &sender_receiver_interface).unwrap();
1004        let swc_internal_behavior = app_swc
1005            .create_swc_internal_behavior("AppSwComponentType_InternalBehavior")
1006            .unwrap();
1007        assert_eq!(app_swc.swc_internal_behaviors().count(), 1);
1008        assert_eq!(
1009            swc_internal_behavior.sw_component_type().unwrap(),
1010            app_swc.clone().into()
1011        );
1012
1013        // create a p-port using the sender-receiver interface
1014        let p_port = app_swc.create_p_port("p_port", &sender_receiver_interface).unwrap();
1015
1016        // create a port using a client-server interface
1017        let client_server_interface = package.create_client_server_interface("ClientServerInterface").unwrap();
1018        let cs_port = app_swc.create_r_port("cs_port", &client_server_interface).unwrap();
1019
1020        // create a runnable entity
1021        let runnable = swc_internal_behavior.create_runnable_entity("Runnable1").unwrap();
1022        assert_eq!(runnable.swc_internal_behavior().unwrap(), swc_internal_behavior);
1023
1024        // error case: create a data received event with a port that does not have a sender-receiver interface
1025        let result = swc_internal_behavior.create_data_received_event(
1026            "DataReceivedEvent",
1027            &runnable,
1028            &variable_data_prototype,
1029            &cs_port,
1030        );
1031        assert!(result.is_err());
1032
1033        // error case: can't create a data received event with a p-port
1034        let result = swc_internal_behavior.create_data_received_event(
1035            "DataReceivedEvent",
1036            &runnable,
1037            &variable_data_prototype,
1038            &p_port,
1039        );
1040        assert!(result.is_err());
1041
1042        // create a data received event, which triggers runnable
1043        let data_received_event = swc_internal_behavior
1044            .create_data_received_event("DataReceivedEvent", &runnable, &variable_data_prototype, &r_port)
1045            .unwrap();
1046        assert_eq!(data_received_event.runnable_entity().unwrap(), runnable);
1047
1048        let (data_element, context_port) = data_received_event.variable_data_prototype().unwrap();
1049        assert_eq!(data_element, variable_data_prototype);
1050        assert_eq!(context_port, r_port.into());
1051        assert_eq!(data_received_event.runnable_entity().unwrap(), runnable);
1052    }
1053
1054    #[test]
1055    fn variable_access() {
1056        let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1057        let package = model.get_or_create_package("/package").unwrap();
1058
1059        // create a sender receiver interface with a variable
1060        let sender_receiver_interface = package
1061            .create_sender_receiver_interface("SenderReceiverInterface")
1062            .unwrap();
1063        let app_data_type = package
1064            .create_application_primitive_data_type("uint32", ApplicationPrimitiveCategory::Value, None, None, None)
1065            .unwrap();
1066        let variable_data_prototype = sender_receiver_interface
1067            .create_data_element("data", &app_data_type)
1068            .unwrap();
1069
1070        // create a software component type with an internal behavior
1071        let app_swc = package
1072            .create_application_sw_component_type("AppSwComponentType")
1073            .unwrap();
1074        let r_port = app_swc.create_r_port("r_port", &sender_receiver_interface).unwrap();
1075        let p_port = app_swc.create_p_port("p_port", &sender_receiver_interface).unwrap();
1076        let swc_internal_behavior = app_swc
1077            .create_swc_internal_behavior("AppSwComponentType_InternalBehavior")
1078            .unwrap();
1079        assert_eq!(app_swc.swc_internal_behaviors().count(), 1);
1080        assert_eq!(
1081            swc_internal_behavior.sw_component_type().unwrap(),
1082            app_swc.clone().into()
1083        );
1084
1085        // create a runnable entity
1086        let runnable = swc_internal_behavior.create_runnable_entity("Runnable").unwrap();
1087        assert_eq!(runnable.swc_internal_behavior().unwrap(), swc_internal_behavior);
1088
1089        // create a variable access for read access
1090        let variable_access = runnable
1091            .create_data_read_access("DataReadAccess", &variable_data_prototype, &r_port)
1092            .unwrap();
1093        assert_eq!(variable_access.runnable_entity().unwrap(), runnable);
1094        assert_eq!(variable_access.accessed_variable().unwrap().0, variable_data_prototype);
1095        assert_eq!(runnable.data_read_accesses().count(), 1);
1096
1097        // create a variable access for write access
1098        let variable_access = runnable
1099            .create_data_write_access("DataWriteAccess", &variable_data_prototype, &p_port)
1100            .unwrap();
1101        assert_eq!(variable_access.runnable_entity().unwrap(), runnable);
1102        assert_eq!(variable_access.accessed_variable().unwrap().0, variable_data_prototype);
1103        assert_eq!(runnable.data_write_accesses().count(), 1);
1104
1105        // create a variable access for send point
1106        let variable_access = runnable
1107            .create_data_send_point("DataSendPoint", &variable_data_prototype, &p_port)
1108            .unwrap();
1109        assert_eq!(variable_access.runnable_entity().unwrap(), runnable);
1110        assert_eq!(variable_access.accessed_variable().unwrap().0, variable_data_prototype);
1111        assert_eq!(runnable.data_send_points().count(), 1);
1112
1113        // create a variable access for receive point by argument
1114        let variable_access = runnable
1115            .create_data_receive_point_by_argument("DataReceivePointByArgument", &variable_data_prototype, &r_port)
1116            .unwrap();
1117        assert_eq!(variable_access.runnable_entity().unwrap(), runnable);
1118        assert_eq!(variable_access.accessed_variable().unwrap().0, variable_data_prototype);
1119        assert_eq!(runnable.data_receive_points_by_argument().count(), 1);
1120
1121        // create a variable access for receive point by value
1122        let variable_access = runnable
1123            .create_data_receive_point_by_value("DataReceivePointByValue", &variable_data_prototype, &r_port)
1124            .unwrap();
1125        assert_eq!(variable_access.runnable_entity().unwrap(), runnable);
1126        assert_eq!(variable_access.accessed_variable().unwrap().0, variable_data_prototype);
1127        assert_eq!(runnable.data_receive_points_by_value().count(), 1);
1128    }
1129
1130    #[test]
1131    fn synchronous_server_call_point() {
1132        let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1133        let package = model.get_or_create_package("/package").unwrap();
1134
1135        // create a client-server interface
1136        let client_server_interface = package.create_client_server_interface("ClientServerInterface").unwrap();
1137        let operation = client_server_interface.create_operation("TestOperation").unwrap();
1138
1139        // create a software component type with an internal behavior
1140        let app_swc = package
1141            .create_application_sw_component_type("AppSwComponentType")
1142            .unwrap();
1143        let r_port = app_swc.create_r_port("r_port", &client_server_interface).unwrap();
1144        let swc_internal_behavior = app_swc
1145            .create_swc_internal_behavior("AppSwComponentType_InternalBehavior")
1146            .unwrap();
1147        assert_eq!(app_swc.swc_internal_behaviors().count(), 1);
1148        assert_eq!(
1149            swc_internal_behavior.sw_component_type().unwrap(),
1150            app_swc.clone().into()
1151        );
1152
1153        // create a runnable entity
1154        let runnable = swc_internal_behavior.create_runnable_entity("Runnable1").unwrap();
1155        assert_eq!(runnable.swc_internal_behavior().unwrap(), swc_internal_behavior);
1156
1157        // create a synchronous server call point
1158        let synchronous_server_call_point = runnable
1159            .create_synchronous_server_call_point("SynchronousServerCallPoint", &operation, &r_port)
1160            .unwrap();
1161        assert_eq!(synchronous_server_call_point.runnable_entity().unwrap(), runnable);
1162        assert_eq!(
1163            synchronous_server_call_point.client_server_operation().unwrap().0,
1164            operation
1165        );
1166        assert_eq!(runnable.synchronous_server_call_points().count(), 1);
1167    }
1168
1169    #[test]
1170    fn mode_access_point() {
1171        let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1172        let package = model.get_or_create_package("/package").unwrap();
1173
1174        // create a mode declaration group
1175        let mode_declaration_group = package
1176            .create_mode_declaration_group("ModeDeclarationGroup", None)
1177            .unwrap();
1178        // create a mode switch interface
1179        let mode_switch_interface = package.create_mode_switch_interface("ModeSwitchInterface").unwrap();
1180        // create a mode group in the mode switch interface
1181        let mode_group = mode_switch_interface
1182            .create_mode_group("mode_group", &mode_declaration_group)
1183            .unwrap();
1184
1185        // create a software component type with an internal behavior
1186        let app_swc = package
1187            .create_application_sw_component_type("AppSwComponentType")
1188            .unwrap();
1189        let r_port = app_swc.create_r_port("r_port", &mode_switch_interface).unwrap();
1190        let p_port = app_swc.create_p_port("p_port", &mode_switch_interface).unwrap();
1191        let swc_internal_behavior = app_swc
1192            .create_swc_internal_behavior("AppSwComponentType_InternalBehavior")
1193            .unwrap();
1194        assert_eq!(app_swc.swc_internal_behaviors().count(), 1);
1195        assert_eq!(
1196            swc_internal_behavior.sw_component_type().unwrap(),
1197            app_swc.clone().into()
1198        );
1199
1200        // create a runnable entity
1201        let runnable = swc_internal_behavior.create_runnable_entity("Runnable1").unwrap();
1202        assert_eq!(runnable.swc_internal_behavior().unwrap(), swc_internal_behavior);
1203
1204        // create a mode access point
1205        let mode_access_point_r = runnable
1206            .create_mode_access_point("ModeAccessPoint", &mode_group, &r_port)
1207            .unwrap();
1208        assert_eq!(mode_access_point_r.name(), Some("ModeAccessPoint".to_string()));
1209        let mode_access_point_p = runnable
1210            .create_mode_access_point("ModeAccessPointP", &mode_group, &p_port)
1211            .unwrap();
1212        assert_eq!(mode_access_point_p.name(), Some("ModeAccessPointP".to_string()));
1213        assert_eq!(mode_access_point_r.runnable_entity().unwrap(), runnable);
1214        assert_eq!(mode_access_point_p.runnable_entity().unwrap(), runnable);
1215        assert_eq!(mode_access_point_r.mode_group().unwrap().0, mode_group);
1216        assert_eq!(mode_access_point_p.mode_group().unwrap().0, mode_group);
1217        assert_eq!(mode_access_point_r.mode_group().unwrap().1, r_port.into());
1218        assert_eq!(mode_access_point_p.mode_group().unwrap().1, p_port.into());
1219        assert_eq!(runnable.mode_access_points().count(), 2);
1220    }
1221
1222    #[test]
1223    fn test_mode_switch_point() {
1224        let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1225        let package = model.get_or_create_package("/package").unwrap();
1226
1227        // create a mode declaration group
1228        let mode_declaration_group = package
1229            .create_mode_declaration_group("ModeDeclarationGroup", None)
1230            .unwrap();
1231        // create a mode switch interface
1232        let mode_switch_interface = package.create_mode_switch_interface("ModeSwitchInterface").unwrap();
1233        // create a mode group in the mode switch interface
1234        let mode_group = mode_switch_interface
1235            .create_mode_group("mode_group", &mode_declaration_group)
1236            .unwrap();
1237
1238        // create a software component type with an internal behavior
1239        let app_swc = package
1240            .create_application_sw_component_type("AppSwComponentType")
1241            .unwrap();
1242        let p_port = app_swc.create_p_port("p_port", &mode_switch_interface).unwrap();
1243        let swc_internal_behavior = app_swc
1244            .create_swc_internal_behavior("AppSwComponentType_InternalBehavior")
1245            .unwrap();
1246        assert_eq!(app_swc.swc_internal_behaviors().count(), 1);
1247        assert_eq!(
1248            swc_internal_behavior.sw_component_type().unwrap(),
1249            app_swc.clone().into()
1250        );
1251
1252        // create a runnable entity
1253        let runnable = swc_internal_behavior.create_runnable_entity("Runnable1").unwrap();
1254        assert_eq!(runnable.swc_internal_behavior().unwrap(), swc_internal_behavior);
1255
1256        // create a mode switch point
1257        let mode_switch_point = runnable
1258            .create_mode_switch_point("ModeSwitchPoint", &mode_group, &p_port)
1259            .unwrap();
1260        assert_eq!(mode_switch_point.runnable_entity().unwrap(), runnable);
1261        assert_eq!(mode_switch_point.mode_group().unwrap().0, mode_group);
1262        assert_eq!(mode_switch_point.mode_group().unwrap().1, p_port.into());
1263        assert_eq!(runnable.mode_switch_points().count(), 1);
1264    }
1265
1266    #[test]
1267    fn remove_runnable_entity() {
1268        let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1269        let package = model.get_or_create_package("/package").unwrap();
1270
1271        // create a software component type with an internal behavior
1272        let app_swc = package
1273            .create_application_sw_component_type("AppSwComponentType")
1274            .unwrap();
1275        let swc_internal_behavior = app_swc
1276            .create_swc_internal_behavior("AppSwComponentType_InternalBehavior")
1277            .unwrap();
1278        assert_eq!(app_swc.swc_internal_behaviors().count(), 1);
1279        assert_eq!(
1280            swc_internal_behavior.sw_component_type().unwrap(),
1281            app_swc.clone().into()
1282        );
1283
1284        // create a runnable entity
1285        let runnable = swc_internal_behavior.create_runnable_entity("Runnable1").unwrap();
1286        assert_eq!(runnable.swc_internal_behavior().unwrap(), swc_internal_behavior);
1287        assert_eq!(swc_internal_behavior.runnable_entities().count(), 1);
1288
1289        // create an init event, which triggers runnable
1290        let init_event = swc_internal_behavior.create_init_event("InitEvent", &runnable).unwrap();
1291        assert_eq!(init_event.runnable_entity().unwrap(), runnable);
1292
1293        // remove the runnable entity
1294        runnable.remove(true).unwrap();
1295        assert_eq!(swc_internal_behavior.runnable_entities().count(), 0);
1296        // check that the init event has also been removed
1297        assert_eq!(swc_internal_behavior.events().count(), 0);
1298    }
1299}