MDF Model

Access to the MDF model is required in all areas which are not covered by the BswmdModel. This is the SystemDescription (non-Ecuc data) and details of the Ecuc model which are not covered by the BswmdModel.

The MDF model implements the raw AUTOSAR data model and is based on the AUTOSAR meta-model. For details about the MDF model, see chapter MDFModelRaw.

For more details concerning the methods mentioned in this chapter, you should also read the JavaDoc sections in the described interfaces and classes.

Reading the MDF Model

The mdfModel() methods provide entry points to start navigation through the MDF model. Client code can use the Closure overloads to navigate into the content of the found MDF objects. Inside the called closure the related MDF object is available as closure parameter.

The following types of entry points are provided here:

  • mdfModel(TypedAsrPath) searches an object with the specified AUTOSAR path
  • mdfModel(TypedDefRef) searches all objects with the specified definition
  • mdfModel(Class) searches all objects with the specified model type (meta class)
  • mdfModel(String) searches for model elements with by different properties, see for details.
  • mdfModel(MIObject, String) searches for model elements by giving a root element and a relative path, see for details.

When a closure is being used, the object found by mdfModel() is provided as parameter when this closure is called:

Navigate into an MDF object starting with an AUTOSAR path
code {
    // Create a type-safe AUTOSAR path for a MIVariableDataPrototype
    def asrPath =
        AsrPath.create("/PortInterfaces/PiSignal_Dummy/DeSignal_Dummy", MIVariableDataPrototype)

    // Use the Java-Style syntax
    def dataDefPropsMdf = mdfModel(asrPath).swDataDefProps

    // Or use the Closure syntax to navigate

    // Enter the MDF model tree starting at the object with this path
    mdfModel(asrPath) {
        // Parameter type is MIVariableDataPrototype:
        dataPrototype ->

            // Traverse down to the swDataDefProps
            dataPrototype.swDataDefProps.each {MISwDataDefProps props ->
                scriptLogger.info "Do something ..."
            }
    }

   saveProject()
}

The mdfModel() method itself returns the found object too. Retrieving the objects member (as property) is then possible directly using the returned object.

Naming of the interface classes to create the type safe AUTOSAR path is described in chapter MDFModelRaw.

An alternative is using a closure to navigate into the MDF object and access its member there:

Find an MDF object and retrieve some content data
// Get an MDF object and get its members directly
def obj = mdfModel(asrPath)     // Type MIVariableDataPrototype
def props = obj.swDataDefProps  // Type MISwDataDefProps

// Get an MDF object and get its members using a closure
def props2
def obj2 = mdfModel(asrPath) {
    props2 = swDataDefProps
}

// The results are the same
assert obj == obj2
assert props == props2

Closures can be nested to navigate deeply into the MDF model tree:

Navigating deeply into an MDF object with nested closures
mdfModel(asrPath) {
    int count = 0
    swDataDefProps.with {
        // swDataDefPropsVariant is a List<MISwDataDefPropsConditional>
        // Execute the following for ALL elements of this List
        List v = swDataDefPropsVariant.each {
            scriptLogger.info "Do something ..."
            count++
        }
    }
    assert count >= 1
}

When a member doesn't exist during navigation into a deep MDF model tree, the specified closure is not called:

Ignoring non-existing member closures
mdfModel(asrPath) {
    int count = 0
    assert adminData == null
    adminData?.with {
        count++
    }
    assert count == 0
}

Retrieving a Child by Shortname or Definition

There are multiple ways to retrieve children from an MDF model object, by the shortname or by its definition. The shortname can be used at the object with childByName() or at the child list with byName().

childByName

The childByName(MIARObject, String, Action) method calls the passed Action, if the request child exists. And returns the child MIReferrable below the specified object which has this relative AUTOSAR path (not starting with '/').

MIContainer canGeneral = ...
canGeneral.childByName("CanMainFunctionRWPeriods"){ child->
     //Do something
}

Lists containing Referrables

  • The method byName(String) retrieves the child with the shortname, or null, if no child exists with this shortname.
  • The method byName(String, Closure) retrieves the child with the shortname, or null, if no child exists with this shortname. Then the closure is executed with the child as closure parameter, if the child is not null. The child is finally returned.
  • The method byName(Class, String) retrieves the child with the shortname and type, or null, if no child exists with this shortname.
  • The method byName(Class, String, Closure) retrieves the child with the shortname and type, or null, if no child exists with this shortname. Then the closure is executed with the child as closure parameter, if the child is not null. The child is finally returned.
  • The method getAt(String) all members with this relative AUTOSAR path. Groovy also allows to write list["ShortnameToSearchFor"].

Retrieve child from list with byName()
// The asrPath points to an MISenderReceiverInterface
MISenderReceiverInterface prototype = mdfModel(asrPath)

// byName() with shortname
def data1 = prototype.withDataElement().byName("DeSignal_Dummy")
assert data1.name == "DeSignal_Dummy"

Lists containing Parameters and Containers

  • The method getAt(TypedDefRef) returns all children with the passed definition. Groovy also allows to write list[DefRef].

Reading the MDF Model by String

The method mdfModel(String) searches for model elements by multiple ways at once. The method evaluates the specified property in the following order, it will continue, if nothing was found:

  • AUTOSAR path, see mdfModel(AsrPath), if the path begins with an '/' and the model element is no definition object (MIParamConfMultiplicity)
    • Example: /ActiveEcuc/MyCan/MyContainer
  • ObjectLink, see AsrObjectLink, if the path begins with an '/' and the model element is no definition object (type MIParamConfMultiplicity)
    • Example: /ActiveEcuc/MyCan/MyContainer[0:ParameterDef]
  • Definition path, see mdfModel(DefRef), if the path begins with an '/'
    • Example: /MICROSAR/Can2
  • Relative path, see mdfModel(MIObject, String), the relative path may not start with an '/'. See for more details.
  • MICROSAR QUERY, if the path begins with "msrq:". The defined Microsar Query, filters the configuration elements
    by the given arbitrary filter code. The filter must be evaluable to a String, Boolean or Pattern. The Microsar Query can be used for modules, containers and parameters. See for more details.
  • AUTOSAR path relative to the ActiveEcuc package, if it does not begin with an '/'
    • Example: MyCan/MyContainer
  • Definition path as DefRef with wildcard ANY starting at the moduleConfiguration, if it does not begin with an '/'
    • Example: Can/CanGeneral
  • Definition path as DefRef with wildcards, if it does begin with a valid wildcard like /[ANY], see EDefRefWildcard.
    • Example: /[ANY]/Can/CanGeneral
  • Shortname of an MIARElement if the path does not contain any '/'.
    • Example: MyContainer

This method does not limit the search to the ActiveEcuC, so it can be used to retrieve any object with the path String.

Remark: Even in post-build selectable variant models this method expects to find at most one object because script code will never run in an unfiltered context.

Caution: This is a potentially slow operation, you should use other mdfModel() methods, if possible. Because this method must traverse the whole model in some cases.

Get elements with mdfModel(String)
def moduleCfg1 = mdfModel("/ActiveEcuC/Can").single
def moduleCfg2 = mdfModel("Can").single
def moduleCfg3 = mdfModel("/[ANY]/Can").single
def parameter  = mdfModel("/ActiveEcuc/MyCan/MyContainer[0:ParameterDef]").singleOrNull

Relative search - mdfModel(MIObject, String)

Retrieves model elements based on the root element. The system navigates relative to the model element based on the root element. The relative path may not start with an '/'. In case of a variant project the collection may have more than one entry.

Read definitions elements with a relative path using the mdfModel
// Required imports
import com.vector.cfg.model.access.AsrPath
import com.vector.cfg.model.mdf.model.autosar.ecucparamdef.MIContainerDef

scriptTask("mdfModel", DV_PROJECT){
    code {
        // Reading a definition element
        def asrPath = AsrPath.create("/MICROSAR/Can_CanoeemuCanoe/Can/CanConfigSet", MIContainerDef)
        def root = mdfModel(asrPath)
        def reqElem = mdfModel(root, "CanController/CanFilterMask").getFirst()
    }
}

Read activeEcuc elements with a relative path using the mdfModel
// Required imports
import com.vector.cfg.model.access.AsrPath
import com.vector.cfg.model.mdf.model.autosar.ecucdescription.MIContainer

scriptTask("mdfModel", DV_PROJECT){
    code {
        // Reading an activeEcuc element
        def asrPath = AsrPath.create("/ActiveEcuC/Can/CanConfigSet", MIContainer)
        def root = mdfModel(asrPath)
        def reqElem = mdfModel(root, "ECU_T_CTP_1_NWT_CTP_CANH_ak72ea5qpue3dstlfi5v43l2z_090525f9_Rx_Ext").getFirst()
    }
}

Msrq search - msrQuery(String path)

The method msrQuery(String) searches for model elements by using an arbitrary filter code as closure. The method evaluates the specified pattern and returns the matching model elements. If nothing was found, it returns an empty list. The input string defined as an MICROSAR QUERY, filters the configuration elements by the given arbitrary filter code. The arbitrary filter code must be defined inside of the { } . The filter code must be evaluable to a String, Boolean or Pattern. Examples:

  • /MICROSAR/Crc/CrcGeneral{ true }
  • /MICROSAR/Crc/CrcGeneral{ ~"[\\w]*[123l]\$" }
  • /MICROSAR/Crc/CrcGeneral{ "CrcGeneral" }
  • /MICROSAR/Crc/CrcGeneral{ it.getName() == "CrcGeneral" }
  • /MICROSAR/Crc/CrcGeneral{ elem -> elem.getName() == "CrcGeneral" }
  • /MICROSAR/Crc/CrcGeneral{ getName() == "CrcGeneral" }
  • /MICROSAR/Crc/CrcGeneral{ it.getName().contains("CrcGeneral") }
  • /[ANY]/Crc/CrcGeneral/{ true }

Writing the MDF Model

Writing to the MDF model can be done with the same mdfModel(AsrPath) API, but you have to call specific methods to modify the model objects. The methods are devided in the following use cases:

  • Change a simple property like Strings
  • Change or create a single child relateion (0:1)
  • Create a new child for a child list (0:*)
  • Update an existing child from a child list (0:*)

You have to open a transaction before you can modify the MDF model.

Simple Property Changes

The properties of MDF model object simply be changed by with the setter method of the model object. Simple setter exist for example for the types:

  • String
  • Enums
  • Integer
  • Double

Changing a simple property of an MIVariableDataPrototype
transaction{
    // The asrPath points to an MIVariableDataPrototype
    mdfModel(asrPath) { dataPrototype ->
        dataPrototype.category = "NewCategory"
    }
}

Creating single Child Members (0:1)

For single child members (0:1), the automation API provides and additional method for the getter get<Element>OrCreate() for convenient child object creation. The methods will create the element, instead of returning null.

Creating non-existing member by navigating into its content with OrCreate()
transaction{
    // The asrPath points to an MIVariableDataPrototype
    mdfModel(asrPath) {
        int count = 0
        assert adminData == null
        withAdminData().orCreate.with {
            count++
        }
        assert count == 1
        assert adminData != null
    }
}

If the compile time child type is not instatiatable, you have to provide the concrete type by get<Element>OrCreate(Class childType).

Creating child member by navigating into its content with OrCreate() with type
transaction{
    // The asrPath points to an MIVariableDataPrototype
    mdfModel(asrPath) {

        withIntroduction().getOrCreate(MIBlockLevelContent).with { docuBlock ->
            assert docuBlock instanceof MIBlockLevelContent
        }
    }
}

Creating and adding Child List Members (0:*)

For child list members, the automation API provides many createAndAdd() methods for convenient child object creation. These method will always create the element, regardless if the same element (e.g. same ShortName) already exists.

If you want to update element see the chapter mdfUpdateExistingElements.

Creating new members of child lists with createAndAdd() by type
transaction{
    // The asrPath points to an MIVariableDataPrototype
    mdfModel(asrPath) {
        assert adminData.sdg.empty

        adminData.with {
            withSdg().create{
                it.gid = "NewGidValue"
            }
        }

        assert adminData.sdg.first.gid == "NewGidValue"
    }
}

These methods are available --- but be aware that not all of these methods are available for all child lists. Adding parameters, for example, is only permitted in the parameter child list of an MIContainer instance.

All Lists:

  • The method createAndAdd() creates a new MDF object of the lists content type and appends it to this list. If the type is not instantiatable the method will thrown a ModelException. The new object is finally returned.
  • The method createAndAdd(Closure) creates a new MDF object of the lists content type and appends it to this list. If the type is not instantiatable the method will thrown a ModelException. Then the closure is executed with the new object as closure parameter. The new object is finally returned.
  • The method createAndAdd(Class) creates a new MDF object of the specified type and appends it to this list. The new object is finally returned.
  • The method createAndAdd(Class, Closure) creates a new MDF object of the specified type and appends it to this list. Then the closure is executed with the new object as closure parameter. The new object is finally returned.
  • The method createAndAdd(Class, Integer) creates a new MDF object of the specified type and inserts it to this list at the specified index position. The new object is finally returned.
  • The method createAndAdd(Class, Integer, Closure) creates a new MDF object of the specified type and inserts it to this list at the specified index position. Then the closure is executed with the new object as closure parameter. The new object is finally returned.

Lists containing Referrables

  • The method createAndAdd(String) creates a new child with the specified shortname and appends it to this list. The new object is finally returned. The used type is the lists content type. If the type is not instantiatable the method will thrown a ModelException.
  • The method createAndAdd(String, Closure) creates a new MIReferrable with the specified shortname and appends it to this list. Then the closure is executed with the new object as closure parameter. The new object is finally returned. The used type is the lists content type. If the type is not instantiatable the method will thrown a ModelException.
  • The method createAndAdd(Class, String) creates a new MIReferrable with the specified type and shortname and appends it to this list. The new object is finally returned.
  • The method createAndAdd(Class, String, Closure) creates a new MIReferrable with the specified type and shortname and appends it to this list. Then the closure is executed with the new object as closure parameter. The new object is finally returned.
  • The method createAndAdd(Class, String, Integer) creates a new MIReferrable with the specified type and shortname and inserts it to this list at the specified index position. The new object is finally returned.
  • The method createAndAdd(Class, String, Integer, Closure) creates a new MIReferrable with the specified type and shortname and inserts it to this list at the specified index position. Then the closure is executed with the new object as closure parameter. The new object is finally returned.

Lists containing Parameters and Containers

  • The method createAndAdd(TypedDefRef) creates a new Ecuc object (container or parameter) with the specified definition and appends it to this list. The new object is finally returned.
  • The method createAndAdd(TypedDefRef, Closure) creates a new Ecuc object (container or parameter) with the specified definition and appends it to this list. Then the closure is executed with the new object as closure parameter. The new object is finally returned.
  • The method createAndAdd(TypedDefRef, Integer) creates a new Ecuc object (container or parameter) with the specified definition and inserts it to this list at the specified index position. The new object is finally returned.
  • The method createAndAdd(TypedDefRef, Integer, Closure) creates a new Ecuc object (container or parameter) with the specified definition and inserts it to this list at the specified index position. Then the closure is executed with the new object as closure parameter. The new object is finally returned.
  • The method byDefOrCreate(TypedDefRef) retrieves the child with the passed definition, if the child exists and has a definition multiplicity of 0:1 or 1:1. Otherwise a new child is created. The definition and shortname (using the definition name) are automatically set before returning the new child. So this method will always create a new child if the upper multiplicity is greater than 1.

Lists containing Containers

  • The method createAndAdd(TypedDefRef, String) creates a new container with the specified definition and shortname and appends it to this list. The new container is finally returned.
  • The method createAndAdd(TypedDefRef, String, Closure) creates a new container with the specified definition and shortname and appends it to this list. Then the closure is executed with the new container as closure parameter. The new container is finally returned.
  • The method createAndAdd(TypedDefRef, String, Integer) creates a new container with the specified definition and shortname and inserts it to this list at the specified index position. The new container is finally returned.
  • The method createAndAdd(TypedDefRef, String, Integer, Closure) creates a new container with the specified definition and shortname and inserts it to this list at the specified index position. Then the closure is executed with the new container as closure parameter. The new container is finally returned.

Updating existing Elements

For child list members, the automation API provides many byNameOrCreate() methods for convenient child object update and creation on demand. These method will create the element if id does not exists, or return the existing element.

Updating existing members of child lists with byNameOrCreate() by type
transaction{
    // The path points to an MISenderReceiverInterface
    mdfModel(asrPath) { MISenderReceiverInterface sendRecIf ->
        def dataElementRelation = sendRecIf.withDataElement()

        def dataElement = dataElementRelation.byNameOrCreate("MyDataElement")
        dataElement.name = "NewName"

        def dataElement2 = dataElementRelation.byNameOrCreate("NewName")

        assert dataElement == dataElement2
    }
}

These methods are available --- but be aware that not all of these methods are available for all child lists. Updating container, for example, is only permitted in the parameter child list of an MIContainer instance.

Lists containing Referrables

  • The method byNameOrCreate(String) retrieves the child with the passed shortname, or creates the child, if it does not exist. The shortname is automatically set before returning the new child.
  • The method byNameOrCreate(String,Closure) retrieves the child with the passed shortname, or creates the child, if it does not exist. The shortname is automatically set before returning the new child. Then the closure is executed with the child as closure parameter. The child is finally returned.
  • The method byNameOrCreate(Class, String) retrieves the child with the passed type and shortname, or creates the child, if it does not exist. The shortname is automatically set before returning the new child.
  • The method byNameOrCreate(Class, String,Closure) retrieves the child with the passed type and shortname, or creates the child, if it does not exist. The shortname is automatically set before returning the new child. Then the closure is executed with the child as closure parameter. The child is finally returned.

Lists containing Containers

  • The method byNameOrCreate(TypedDefRef, String) retrieves the child with the passed definition and shortname, or creates the child, if it does not exist. The definition and shortname are automatically set before returning the new child.
  • The method byNameOrCreate(TypedDefRef, String, Closure) retrieves the child with the passed definition and shortname, or creates the child, if it does not exist. The definition and shortname are automatically set before returning the new child. Then the closure is executed with the child as closure parameter. The child is finally returned.

Deleting Model Objects

The method delete(MIObject) deletes the specified object from the model. This method must be called inside a transaction because it changes the model content.

Special case: If this method is being called on an active module configuration, it actually calls IOperations.deactivateModuleConfiguration(MIModuleConfiguration) to deactivate the module correctly.

Delete a parameter instance
// MIParameterValue param = ...

transaction {
    assert !param.isDeleted()
    param.delete()
    assert param.isDeleted()
}

The method moRemove() does the same as delete(). For details about model object deletion and access to deleted objects, read section deletingModelObjects ff.

IsDeleted

The isDeleted(MIObject) method returns true if the specified object has been deleted (removed) from the MDF model, or is invisible in the current active IModelView.

MIObject obj = ...
if (!obj.isDeleted()) {
    work with obj ...
}

Note: The return value is dependent on the current active thread and the current active IModelView in this thread!

The method moIsRemoved() does the same as isDeleted().

Duplicating Model Objects

The duplicate() method copies (clones) a complete MDF model sub-tree and adds it as child below the same parent.

  • The source object must have a parent. The clone will be added to the same MDF feature below the same parent then
  • AUTOSAR UUIDs will not be cloned. The clone will contain new UUIDs to guarantee unambiguousness
This method can clone any model sub-tree, also see IOperations.deepClone(MIObject, MIObject) for details.

Note: This operation must be executed inside of a transaction.

Remarks: Use this method with care on referrable objects. When calling this method on a referrable, then the name must be changed immediately afterward. But be aware that on renaming all existing references will be changed as well and point to the new referrable object.

Duplicates a container under the same parent
// MIContainer container = ...
transaction {
   def newCont = container.duplicate()
   // The duplicated container newCont
}

Special properties and extensions

asrPath

The getAsrPath(MIReferrable) method returns the AUTOSAR path of the specified object.

MIContainer canGeneral = ...
AsrPath path = canGeneral.asrPath
See chapter AsrPath for more details about AsrPaths.

The getAsrObjectLink(MIARObject) method returns the AsrObjectLink of the specified object.

MIParameterValue param = ...
AsrObjectLink link = param.asrObjectLink
See chapter AsrObjectLink for more details about AsrObjectLinks.

defRef

The getDefRef() method returns the DefRef of the model object.

MIParameterValue param = ...
DefRef defRef = param.defRef

The MIParameterValue.setDefRef(DefRef) method sets the definition of this parameter to the defRef.

MIParameterValue param = ...
DefRef newDefinition = ...
param.defRef = newDefinition

If the specified DefRef has a wildcard, the parameter must have a parent to calculate the absolute definition path - otherwise a ModelCeHasNoParentException will be thrown.

If it has no wildcard and no parent, the absolute definition path of the defRef will be used.

If the parameter has a parent or and parents definition does not match the defRefs parent definition, this method fails with InconsistentParentDefinitionException.

The MIContainer.setDefRef(DefRef) method sets the definition of this container to the defRef.

See chapter defRef for more details about DefRefs.

ceState

The CeState is an object which aggregates states of a related MDF object. Client code can e.g. check with the CeState if an Ecuc object has a related pre-configuration value.

The getCeState(MIObject) method returns the CeState of the specified model object.

MIParameterValue param = ...
IParameterStatePublished state = param.ceState

See chapter ceState for more details about the CeState.

ceState - User-defined Flag

The method isUserDefined() returns true, if the ecuc configuration element like parameters is flagged as user-defined.

MIParameterValue param = ...
def flag = param.ceState.userDefined

The method setUserDefined(boolean) sets or removes the user-defined flag of an ecuc parameter.

Note: This method must be executed inside a transaction because it modifies the model state.

MIParameterValue param = ...
transaction {
  param.ceState.userDefined = true
}

EcuConfigurationAccess and EcucDefinitionAccess

The Groovy automation interface also provides special access methods for Ecuc elements (module configurations, container and parameter) to the

The getEcucDefinition() method returns the IEcucDefinition of the model object.

MIParameterValue param = ...
IEcucDefinition definition = param.ecucDefinition

The getEcuConfiguration() method returns the IEcucHasDefinition of the model object.

MIParameterValue param = ...
IEcucHasDefinition cfg = param.ecuConfiguration

These methods are the same as for bswmd model objects.

Reverse Reference Resolution - ReferencesPointingToMe

You can resolve all references in the MDF model in the reverse direction, so you can start at a reference target and navigate to all references which point to the reference target.

referencesPointingToMe

The getReferencesPointingToMe() method returns all reference parameters in the active ecuc pointing to specified target (MIReferrable) object. It returns an empty collection if the target object is invisible or removed.

The getReferencesPointingToMe(DefRef) method returns all reference parameters in the active ecuc with the specified definition (DefRef) pointing to the specified target (MIReferrable) object. It returns an empty collection if the target object is invisible, removed or the specified definition is null.

referencesPointingToMe sample
List<MIReferenceValue> refs = container.referencesPointingToMe
//Or
DefRef refDefRef = // DefRef to reference parameter
def refByDef = container.getReferencesPointingToMe(refDefRef)

systemDescriptionObjectsPointingToMe

The method getSystemDescriptionObjectsPointingToMe() returns all objects located in the system description which are parent objects of references pointing to the specified target. It returns an empty collection if the object is invisible or removed.

systemDescriptionObjectsPointingToMe sample
List<MIObject> references =
        systemDescElement.systemDescriptionObjectsPointingToMe

Derived Containers

The MIHasContainer.getDerived() method provides access to derived container information. The method returns a IDerivedElementInfo object corresponding to the model element.

The IDerivedElementInfo can be used to retrieve information about element or delete it:

  • getRemovedDerivedSubContainers(): Retrieves the removed children, which could be used to restore them the children
  • isDerived(): returns true if the element is derived
  • delete(): deletes the element regardless if it is derived or not

Derived Container API access
container.derived.isDerived()
// Or
container.derived {
     boolean isDerivedFlag = isDerived()
     def removedList = getRemovedDerivedSubContainers()
}

Deletion of Derived Containers

The method delete() deletes the MIContainer regardless, if it is derived or not. This method behaves as follows:

  • If the container is a derived container it calls the derived container deletion operation to delete it.
  • All other containers with be deleted by means of MIObject.deleteFromModel().

Delete a derived container unconditionally
transaction {
    container.derived.delete()
}

AUTOSAR Root Object

The getAUTOSAR() method returns the AUTOSAR root object (the root object of the MDF model tree of AUTOSAR data).

MIAUTOSAR root = AUTOSAR

ActiveEcuC

The activeEcuc access methods provide access to the module configurations of the Ecuc model.

Get the active Ecuc and all module configurations
// Get the modules as Collection<MIModuleConfiguration>
Collection modules = activeEcuc.allModules

Iterate over all module configurations
// Iterate over all module configurations
activeEcuc {
    int count = 0
    allModules.each { moduleCfg ->
        count++
    }
    assert count > 1
}

Get module configurations by definition
activeEcuc {
    // Parameter type is IActiveEcuc
    ecuc ->

    def defRef = DefRef.create(EDefRefWildcard.AUTOSAR, "EcuC")

    // Get the modules as Collection<MIModuleConfiguration>
    Collection foundModules = ecuc.modules(defRef)
    assert !foundModules.empty
}

DefRef based Access to Containers and Parameters

The Groovy automation interface for the MDF model provides some overloaded access methods for

  • MIModuleConfiguration.getSubContainer()
  • MIContainer.getSubContainer()
  • MIContainer.getParameter()

to offer convenient filtering access to the subContainer and parameter child lists.

Get subContainers and parameters by definition
activeEcuc {
    // Parameter type is IActiveEcuc
    ecuc ->

    def module = ecuc.modules(EcuC.DefRef).first

    // Get containers as List<MIContainer>
    def containers = module.subContainer(EcucGeneral.DefRef)

    // Get parameters as List<MIParameterValue>
    def cpuType = containers.first.parameter(CPUType.DefRef)

    assert cpuType.size() == 1
}

Ecuc Parameter and Reference Value Access

The Groovy automation interface also provides special access methods for Ecuc parameter values. These methods are implemented as extensions of the Ecuc parameter and value types and can therefore be called directly at the parameter or reference instance.

Value Checks

  • MIParameterValue.hasValue() returns true if the parameter (or reference) has a value.

  • MINumericalValue.containsBoolean() returns true if the parameter value contains a valid boolean with the same semantic as IEcucModelAccess.containsBoolean(MINumericalValue).

    Call this method in advance to guarantee that MINumericalValueVariationPoint.getAsBoolean() doesn't lead to errors.

  • MINumericalValue.containsInteger() returns true if the parameter value contains a valid integer with the same semantic as IEcucModelAccess.containsInteger(MINumericalValue).

    Call this method in advance to guarantee that MINumericalValueVariationPoint.getAsInteger() doesn't lead to errors.

  • MINumericalValue.containsDouble() returns true if the parameter value contains a valid double (AUTOSAR float) with the same semantic as IEcucModelAccess.containsFloat(MINumericalValue).

    Call this method in advance to guarantee that MINumericalValueVariationPoint.getAsDouble() doesn't lead to errors.

Check parameter values
// MINumericalValue param = ...

if (!param.hasValue()) {
    scriptLogger.warn "The parameter has no value!"
}

if (param.containsInteger()) {
    int value = param.value.asInteger
}

Parameters

  • MINumericalValueVariationPoint.getAsLong() returns the value as native long.

    Throws Throws [ArithmeticException] if the value will not exactly fit in a <code>long if the value string doesn't represent an integer value.
    Throws long if the value will not exactly fit in a long.

  • MINumericalValueVariationPoint.getAsInteger() returns the value as native int.

    Throws Throws [ArithmeticException] if the value will not exactly fit in an <code>int if the value string doesn't represent an integer value.
    Throws int if the value will not exactly fit in an int.

  • MINumericalValueVariationPoint.getAsBigInteger() returns the value as BigInteger.

    Throws NumberFormatException if the value string doesn't represent an integer value.

  • MINumericalValueVariationPoint.getAsDouble() returns the value as Double.

    Throws NumberFormatException if the value string doesn't represent a float value.

  • MINumericalValueVariationPoint.getAsBoolean() returns the value as Boolean.

    Throws NumberFormatException if the value doesn't represent a boolean value.

  • MITextualValue.asCustomEnum(Class) returns the value of the enum parameter as a custom enum literal. If the Class destClass implements the IEcucEnum interface, the literals are mapped via these information form the IEcucEnum interface. Read the JavaDoc of IEcucEnum for more details.

Get integer parameter value
// MINumericalValue param = ...
// MINumericalValueVariationPoint is the type of param.value

long longValue = param.value.asLong
assert longValue == 10

int intValue = param.value.asInteger
assert intValue == 10

BigInteger bigIntValue = param.value.asBigInteger
assert bigIntValue == BigInteger.valueOf(10)

Double doubleValue = param.value.asDouble
assert Math.abs(doubleValue-10.0) <= 0.0001

References

  • MIARRef#getAsAsrPath() returns the reference value as AUTOSAR path.

  • MIReferenceValue#getAsAsrPath() returns the reference value as AUTOSAR path.

  • MIReferenceValue.getRefTarget() returns the reference parameters target object (the object referenced by this parameter). It returns null if the target cannot be resolved or the reference parameter doesn't contain a value reference.

Get reference parameter value
// MIReferenceValue refParam = ...

def asrPath1 = refParam.asAsrPath
def asrPath2 = refParam.value.asAsrPath
assert asrPath1 == asrPath2

String pathString = refParam.value.value
assert asrPath1.autosarPathString == pathString

def target1 = refParam.refTarget
def target2 = refParam.value.refTarget
assert target1 == target2

Getting and Setting Formula Expression Values

The Groovy automation interface provides special methods to evaluate a formula expression and replace its content as well. These methods are implemented as extensions of the MIFormulaExpression and therefore they can be called directly at its instances.

Get Expression Value

  • The formula expression can contain a simple numeric literal, a boolean literal, or a more advanced expression that handles references to autosar model elements, arithmetic functions, special functions, and special values.

    Therefore, the method MIFormulaExpression.eval() is used to do the evaluation and return the result as IFormulaResult.

  • The IFormulaResult represents the evaluation result of a MIFormulaExpression. It contains the numeric value if the formula has been evaluated successfully or the ModelFormulaException if an error happened while evaluating the expression. This interface has the following convenient methods:

    • isEvaluated(): Returns True if the expression has been evaluated successfully, or False if an error has occurred.
    • getValue(): It is worthwhile to mention that formula expression always yields a numeric value. Thus, the numeric result of the evaluation will be mainly given using this method.
    • getAsBoolean(): If the provided formula expression is a condition, the result is expected to be boolean. Therefore, this method can be used to convert the numeric result to boolean. Zero is considered False, and any other value is considered True.
    • getAsFloat(): Returns the numeric value of the formula as double.
    • getAsBigDecimal(): Returns the numeric value of the formula as BigDecimal.
    • getAsInteger(): Returns the numeric value of the formula as integer:
      • First, if the origin value is of an integer type, it is returned as it is.
      • Second, if the origin value can be converted to integer without loss of any information, then it is converted and returned.
      • Otherwise, it throws NumberFormatException stating that 'The formula value is not an integer'.
    • getError(): Returns an Optional of ModelFormulaException. It will be empty if the formula has been evaluated successfully, or contains the error that occurred.

Evaluate formula expression
// arrayElement is MIImplementationDataTypeElement
// arraySizeOrCreate returns MIFormulaExpression
IFormulaResult evalResult = arrayElement.arraySizeOrCreate.eval()

if (evalResult.evaluated) {
    // Get the numeric value
    Number value = evalResult.value
    // Get the numeric value converted to other types
    boolean valueAsBoolean = evalResult.asBoolean
    BigInteger valueAsInteger = evalResult.asInteger
    double valueAsFloat = evalResult.asFloat
} else {
    ModelFormulaException exception = evalResult.error.get()
}

// This one line statement can also be used to provide quick access, but
// it will throw an exception if the expression was not evaluated successfully.
Number value = arrayElement.arraySizeOrCreate.eval().value

Set Expression Value

  • The method setValue(Number) replaces the content of the passed MIFormulaExpression by the provided numeric value.

    Throws NullPointerException if any of the parameters is null.

  • The method setValue(Boolean) replaces the content of the passed MIFormulaExpression by the string representation of the provided Boolean value.

    Throws NullPointerException if any of the parameters is null.

Important Note: These operations must run within a unit of work. The client code is responsible for opening the transaction before calling these two methods.

Set formula expression value
transaction {
    // arrayElement is MIImplementationDataTypeElement
    // arraySizeOrCreate returns MIFormulaExpression
    arrayElement.arraySizeOrCreate.setValue(5)
}