diff --git a/examples/xml/template/demo_system/factory.py b/examples/xml/template/demo_system/factory.py
index 6f793e5..2e85b9b 100644
--- a/examples/xml/template/demo_system/factory.py
+++ b/examples/xml/template/demo_system/factory.py
@@ -1,9 +1,11 @@
"""
Example template classes
"""
+from typing import Callable
import autosar.xml.template as ar_template
import autosar.xml.element as ar_element
import autosar.xml.enumeration as ar_enum
+from autosar.xml.template import TemplateBase
import autosar.xml.workspace as ar_workspace
@@ -24,7 +26,11 @@ def __init__(self,
self.encoding = encoding
self.native_declaration = native_declaration
- def apply(self, package: ar_element.Package, workspace: ar_workspace.Workspace, **kwargs) -> ar_element.SwBaseType:
+ def create(self,
+ element_ref: str,
+ workspace: ar_workspace.Workspace,
+ dependencies: dict[str, ar_element.ARElement] | None,
+ **kwargs) -> ar_element.SwBaseType:
"""
Factory method for SwBaseType
"""
@@ -33,7 +39,7 @@ def apply(self, package: ar_element.Package, workspace: ar_workspace.Workspace,
size=self.bit_size,
encoding=self.encoding,
native_declaration=self.native_declaration)
- package.append(elem)
+
return elem
@@ -51,15 +57,15 @@ def __init__(self,
self.lower_limit = lower_limit
self.upper_limit = upper_limit
- def apply(self,
- package: ar_element.Package,
- workspace: ar_workspace.Workspace,
- **kwargs) -> ar_element.DataConstraint:
+ def create(self,
+ element_ref: str,
+ workspace: ar_workspace.Workspace,
+ dependencies: dict[str, ar_element.ARElement] | None,
+ **kwargs) -> ar_element.DataConstraint:
"""
Factory method
"""
elem = ar_element.DataConstraint.make_internal(self.element_name, self.lower_limit, self.upper_limit)
- package.append(elem)
return elem
@@ -80,10 +86,11 @@ def __init__(self,
self.auto_label = auto_label
self.desc = desc
- def apply(self,
- package: ar_element.Package,
- workspace: ar_workspace.Workspace,
- **kwargs) -> ar_element.CompuMethod:
+ def create(self,
+ element_ref: str,
+ workspace: ar_workspace.Workspace,
+ dependencies: dict[str, ar_element.ARElement] | None,
+ **kwargs) -> ar_element.CompuMethod:
"""
Factory method
"""
@@ -92,7 +99,6 @@ def apply(self,
desc=self.desc,
category=self.category,
int_to_phys=computation)
- package.append(elem)
return elem
@@ -126,7 +132,11 @@ def __init__(self,
self.calibration_access = calibration_access
self.type_emitter = type_emitter
- def apply(self, package: ar_element.Package, workspace: ar_workspace.Workspace, **kwargs) -> ar_element.SwBaseType:
+ def create(self,
+ element_ref: str,
+ workspace: ar_workspace.Workspace,
+ dependencies: dict[str, ar_element.ARElement] | None,
+ **kwargs) -> ar_element.ImplementationDataType:
"""
Factory method
"""
@@ -143,7 +153,6 @@ def apply(self, package: ar_element.Package, workspace: ar_workspace.Workspace,
category=self.category,
sw_data_def_props=sw_data_def_props,
type_emitter=self.type_emitter)
- package.append(elem)
return elem
@@ -195,8 +204,11 @@ def _create_compu_method(self,
value_table: list[str]) -> ar_template.ElementTemplate:
return CompuMethodEnumTemplate(element_name + suffix, namespace_name, value_table, auto_label=False)
- def apply(self, package: ar_element.Package,
- workspace: ar_workspace.Workspace, **kwargs) -> ar_element.ImplementationDataType:
+ def create(self,
+ element_ref: str,
+ workspace: ar_workspace.Workspace,
+ dependencies: dict[str, ar_element.ARElement] | None,
+ **kwargs) -> ar_element.ImplementationDataType:
"""
Factory method
"""
@@ -212,7 +224,6 @@ def apply(self, package: ar_element.Package,
desc=self.desc,
category=self.category,
sw_data_def_props=sw_data_def_props)
- package.append(elem)
return elem
@@ -230,15 +241,20 @@ def __init__(self,
self.mode_declarations = list(mode_declarations)
self.initial_mode_name = initial_mode_name
- def apply(self, package: ar_element.Package, workspace: ar_workspace.Workspace, **kwargs) -> ar_element.SwBaseType:
+ def create(self,
+ element_ref: str,
+ workspace: ar_workspace.Workspace,
+ dependencies: dict[str, ar_element.ARElement] | None,
+ **kwargs) -> ar_element.ModeDeclarationGroup:
"""
Factory method for SwBaseType
"""
- elem = ar_element.ModeDeclarationGroup(name=self.element_name,
- mode_declarations=self.mode_declarations)
- package.append(elem)
+ initial_mode_ref = None
if self.initial_mode_name is not None:
- elem.initial_mode_ref = elem.find(self.initial_mode_name).ref()
+ initial_mode_ref = '/'.join([element_ref, self.initial_mode_name])
+ elem = ar_element.ModeDeclarationGroup(name=self.element_name,
+ mode_declarations=self.mode_declarations,
+ initial_mode_ref=initial_mode_ref)
return elem
@@ -259,11 +275,43 @@ def __init__(self,
self.mode_declaration_group = mode_declaration_group
self.is_service = is_service
- def apply(self, package: ar_element.Package, workspace: ar_workspace.Workspace, **kwargs) -> ar_element.SwBaseType:
+ def create(self,
+ element_ref: str,
+ workspace: ar_workspace.Workspace,
+ dependencies: dict[str, ar_element.ARElement] | None,
+ **kwargs) -> ar_element.ModeSwitchInterface:
"""
Element creation method
"""
elem = ar_element.ModeSwitchInterface(self.element_name, is_service=self.is_service)
elem.create_mode_group(self.mode_group_name, self.mode_declaration_group.ref(workspace))
- package.append(elem)
+ return elem
+
+
+CreateFuncType = Callable[[str, ar_workspace.Workspace, dict[str, ar_element.ARElement] | None],
+ ar_element.PortInterface]
+
+
+class GenericPortInterfaceTemplate(ar_template.ElementTemplate):
+ """
+ Generic element template
+ """
+
+ def __init__(self,
+ element_name: str,
+ namespace_name: str,
+ create_func: CreateFuncType,
+ depends: list[TemplateBase] | None = None) -> None:
+ super().__init__(element_name, namespace_name, ar_enum.PackageRole.PORT_INTERFACE, depends)
+ self.create_func = create_func
+
+ def create(self,
+ element_ref: str,
+ workspace: ar_workspace.Workspace,
+ dependencies: dict[str, ar_element.ARElement] | None,
+ **kwargs) -> ar_element.PortInterface:
+ """
+ Create method
+ """
+ elem = self.create_func(element_ref, workspace, dependencies, **kwargs)
return elem
diff --git a/examples/xml/template/demo_system/portinterface.py b/examples/xml/template/demo_system/portinterface.py
index 0666575..710417d 100644
--- a/examples/xml/template/demo_system/portinterface.py
+++ b/examples/xml/template/demo_system/portinterface.py
@@ -5,8 +5,27 @@
# pylint: disable=C0103, C0301
+import autosar.xml.element as ar_element
+import autosar.xml.workspace as ar_workspace
from . import factory, mode
NAMESPACE = "Default"
EcuM_CurrentMode = factory.ModeSwitchInterfaceTemplate("EcuM_CurrentMode", NAMESPACE, mode.EcuM_Mode, "currentMode", is_service=True)
+
+
+def create_NvMService_interface(element_ref: str,
+ _1: ar_workspace.Workspace,
+ _2: dict[str, ar_element.ARElement] | None,
+ **_3) -> ar_element.ClientServerInterface:
+ """
+ Create NvmService interface
+ """
+
+ interface = ar_element.ClientServerInterface("NvMService_I", is_service=True)
+ e_not_ok = interface.create_possible_error("E_NOT_OK", 1)
+ interface.create_operation("EraseBlock", possible_error_refs=element_ref + "/" + e_not_ok.name)
+ return interface
+
+
+NvMService_I = factory.GenericPortInterfaceTemplate("NvMService_I", NAMESPACE, create_NvMService_interface)
diff --git a/examples/xml/template/generate_xml.py b/examples/xml/template/generate_xml.py
index 751d1d8..525947f 100644
--- a/examples/xml/template/generate_xml.py
+++ b/examples/xml/template/generate_xml.py
@@ -71,6 +71,7 @@ def apply_portinterfaces(workspace: ar_workspace.Workspace):
Applies mode templates
"""
workspace.apply(portinterface.EcuM_CurrentMode)
+ workspace.apply(portinterface.NvMService_I)
def main():
diff --git a/examples/xml/template/generated/PortInterfaces.arxml b/examples/xml/template/generated/PortInterfaces.arxml
index d6b5962..df587a5 100644
--- a/examples/xml/template/generated/PortInterfaces.arxml
+++ b/examples/xml/template/generated/PortInterfaces.arxml
@@ -41,6 +41,24 @@
/ModeDclrGroups/EcuM_Mode
+
+ NvMService_I
+ true
+
+
+ EraseBlock
+
+ /PortInterfaces/NvMService_I/E_NOT_OK
+
+
+
+
+
+ E_NOT_OK
+ 1
+
+
+
diff --git a/src/autosar/xml/element.py b/src/autosar/xml/element.py
index 9d985d7..d2612f9 100644
--- a/src/autosar/xml/element.py
+++ b/src/autosar/xml/element.py
@@ -3386,6 +3386,9 @@ def __init__(self,
self._assign_optional_strict("error_code", error_code, int)
+PossibleErrorRefsTypes = ApplicationErrorRef | list[ApplicationErrorRef] | str | list[str]
+
+
class ClientServerOperation(Identifiable):
"""
Complex type AR:CLIENT-SERVER-OPERATION
@@ -3397,7 +3400,7 @@ def __init__(self,
arguments: ArgumentDataPrototype | list[ArgumentDataPrototype] | None = None,
diag_arg_integrity: bool | None = None,
fire_and_forget: bool | None = None,
- possible_error_refs: ApplicationErrorRef | list[ApplicationErrorRef] | None = None,
+ possible_error_refs: PossibleErrorRefsTypes | None = None,
**kwargs) -> None:
super().__init__(name, **kwargs)
self.arguments: list[ArgumentDataPrototype] = [] # .ARGUMENTS
@@ -3422,7 +3425,9 @@ def __init__(self,
if possible_error_refs is not None:
if isinstance(possible_error_refs, ApplicationErrorRef):
- self.append_argument(arguments)
+ self.append_possible_error_ref(possible_error_refs)
+ elif isinstance(possible_error_refs, str):
+ self.append_possible_error_ref(ApplicationErrorRef(possible_error_refs))
elif isinstance(possible_error_refs, list):
for possible_error_ref in possible_error_refs:
self.append_possible_error_ref(possible_error_ref)
diff --git a/src/autosar/xml/template.py b/src/autosar/xml/template.py
index e7dae64..a16cf44 100644
--- a/src/autosar/xml/template.py
+++ b/src/autosar/xml/template.py
@@ -51,19 +51,26 @@ def __init__(self,
self.depends = depends
@abstractmethod
- def apply(self, package: Package, workspace: Workspace, **kwargs) -> ar_element.ARElement:
+ def create(self,
+ element_ref: str,
+ workspace: Workspace,
+ dependencies: dict[str, ar_element.ARElement] | None,
+ **kwargs) -> ar_element.ARElement:
"""
- This apply method shall solely focus on creating the
- new element and return it. The workspace will handle the rest.
+ Element creation method.
The workspace will automatically do the following:
- * Make sure any dependencies have been created (optional)
+ Before call:
+
+ * Make sure any (optional) dependencies have been created
* Make sure the necessary package has been created
* Make sure the element doesn't already exists
- It's up to the implementer of the apply-method to call package.append to add the newly
- created element
+ After call:
+
+ * Appends the returned element to the package
+
"""
def ref(self, workspace: Workspace) -> str:
diff --git a/src/autosar/xml/workspace.py b/src/autosar/xml/workspace.py
index 02da03c..f94b8ec 100644
--- a/src/autosar/xml/workspace.py
+++ b/src/autosar/xml/workspace.py
@@ -180,18 +180,27 @@ def _apply_element_template(self, template: ar_template.ElementTemplate, kwargs:
created element
"""
if template.depends is not None:
- self._create_dependencies(template.depends)
+ depends_map = self._create_dependencies(template.depends)
+ else:
+ depends_map = None
package_ref = self.get_package_ref_by_role(template.namespace_name, template.package_role)
package: ar_element.Package = self.make_packages(package_ref)
if isinstance(package, ar_element.Package):
elem = package.find(template.element_name)
if elem is None:
- elem = template.apply(package, self, **kwargs)
+ element_ref = package_ref + "/" + template.element_name
+ elem = template.create(element_ref, self, depends_map, **kwargs)
+ assert isinstance(elem, ar_element.ARElement)
+ package.append(elem)
return elem
raise TypeError(f"Expected Package, got {str(type(package))}")
- def _create_dependencies(self, dependencies: list[ar_template.TemplateBase]) -> list[Any]:
- items = []
+ def _create_dependencies(self, dependencies: list[ar_template.TemplateBase]
+ ) -> dict[str, ar_element.ARElement]:
+ item_map = {}
for dependency in dependencies:
- items.append(self.apply(dependency))
- return items
+ elem = self.apply(dependency)
+ assert isinstance(elem, ar_element.ARElement)
+ assert hasattr(elem, "ref")
+ item_map[str(elem.ref())] = elem
+ return item_map
diff --git a/tests/xml/test_template.py b/tests/xml/test_template.py
index 56222c8..cf40a3a 100644
--- a/tests/xml/test_template.py
+++ b/tests/xml/test_template.py
@@ -28,7 +28,11 @@ def __init__(self,
self.encoding = encoding
self.native_declaration = native_declaration
- def apply(self, package: ar_element.Package, _: ar_workspace.Workspace, **kwargs) -> ar_element.SwBaseType:
+ def create(self,
+ _1: str,
+ _2: ar_workspace.Workspace,
+ _3: dict[str, ar_element.ARElement] | None,
+ **kwargs) -> ar_element.SwBaseType:
"""
Template method
"""
@@ -37,7 +41,6 @@ def apply(self, package: ar_element.Package, _: ar_workspace.Workspace, **kwargs
size=self.bit_size,
encoding=self.encoding,
native_declaration=self.native_declaration)
- package.append(elem)
return elem
@@ -55,12 +58,15 @@ def __init__(self,
self.lower_limit = lower_limit
self.upper_limit = upper_limit
- def apply(self, package: ar_element.Package, _: ar_workspace.Workspace, **kwargs) -> ar_element.DataConstraint:
+ def create(self,
+ _1: str,
+ _2: ar_workspace.Workspace,
+ _3: dict[str, ar_element.ARElement] | None,
+ **kwargs) -> ar_element.DataConstraint:
"""
Create new internal data constraint
"""
elem = ar_element.DataConstraint.make_internal(self.element_name, self.lower_limit, self.upper_limit)
- package.append(elem)
return elem
@@ -85,7 +91,11 @@ def __init__(self,
self.data_constraint = data_constraint
self.calibration_access = calibration_access
- def apply(self, package: ar_element.Package, workspace: ar_workspace.Workspace, **kwargs) -> ar_element.SwBaseType:
+ def create(self,
+ _1: str,
+ workspace: ar_workspace.Workspace,
+ _2: dict[str, ar_element.ARElement] | None,
+ **kwargs) -> ar_element.SwBaseType:
"""
Template method
"""
@@ -99,7 +109,6 @@ def apply(self, package: ar_element.Package, workspace: ar_workspace.Workspace,
desc=self.desc,
category=self.category,
sw_data_def_props=sw_data_def_props)
- package.append(elem)
return elem