Runtime System Domain

The runtime system domain API is specifically designed to support runtime system related use cases. It is available from the IAutomationContext.IDomainApi (see IDomainApi) in the form of the IRuntimeSystemApi interface.

Remark: The runtime system domain API is designed to work on the flat extract of the System Description. Since the flat extract is now only created on demand, the API works on the flat-view of the structured extract

getRuntimeSystem() allows accessing the IRuntimeSystemApi like a property.

Accessing IRuntimeSystemApi as a property
scriptTask('taskName') {
  code {
    // IRuntimeSystemApi is available as "runtimeSystem" property
    def runtimeSystem = domain.runtimeSystem
  }
}

runtimeSystem(Transfomer) allows accessing the IRuntimeSystemApi in a scope-like way.

Accessing IRuntimeSystemApi in a scope-like way
scriptTask('taskName') {
  code {
    domain.runtimeSystem {
      // IRuntimeSystemApi is available inside this Closure
    }
  }
}

The access point for elements of the runtime system domain are the selections. They are most of the time your starting point and offer predicates to filter for elements which are relevant. These selections can be used to get the elements for further work, but they also offer direct methods for actions that can be performed for them.

As default the selection APIs select always from all elements, but you can also put elements into most selections and use predicates to filter them. The put methods helps you to transfer the elements from selection to selection and put newly created elements into the next selection to perform the next step of your workflow.

We will start by introducing each selection API and will then have a look on common use cases. Before starting to implement a use case it might be helpful to have a quick look into the chapters of the selections that are required for it. The objects such as communication element or component port used in the runtime system domain API are explained in the chapter of the corresponding selection API.

Component Port Selection

A component port (SIComponentPort) represents a port prototype and its corresponding component prototype, and in case of a delegation port the corresponding top level composition type (ECU Composition).

selectComponentPorts(Action) allows the selection of SIComponentPorts using predicates.

The component port selection can be used to select and filter component ports and either do further operations on them, such as connecting to other ports, terminating them or to just return a list of component ports with which you can continue working.

getComponentPorts() allows access to the single component ports in the IComponentPortSelection.

Component Port Predicates

To select component ports predicates can be provided to narrow down the result.

Per default the predicates are combined via logical AND. To realize other combinations, use the 'or','not' and 'and' predicates.

  • unconnected() matches unconnected component ports.
  • connected() matches connected component ports.
  • completed() matches component ports which are completed.

    A delegation port is completed if and only if the port is connected and each of the port's communication elements is either data mapped to a system signal or a system signal group or referenced by flat instance descriptors referring to cross sw cluster RTE implementation plug-ins.

    An inner port is completed if the port is connected or each of the port's communication elements is data mapped to a system signal or a system signal group. This means an inner port which is connected and data mapped is also completed.

  • notCompleted() matches component ports which are not completed.

    See completed() for the conditions a port has to meet to be a completed port.

  • terminated() matches terminated component ports.
  • notTerminated() matches non-terminated component ports.
  • senderReceiver() matches component ports whose port has a sender/receiver port interface.
  • clientServer() matches component ports whose port has a client/server port interface.
  • modeSwitch() matches component ports whose port has a mode-switch port interface.
  • nvData() matches component ports whose port has a NvData port interface.
  • parameter() matches component ports whose port has a parameter (calibration) port interface.
  • trigger() matches component ports whose port has a trigger port interface.
  • provided() matches provided component ports (p-port).
  • required() matches required component ports (r-port).
  • providedRequired() matches provided-required component ports (pr-port).
  • delegation() matches delegation ports (ports of the Ecu composition).
  • application() matches component ports whose port interface is an application port interface.
  • service() matches component ports whose port interface is an service port interface.
  • applicationComponent() matches component ports whose component type is an application component type. Application component types are all component types which are not service component types, as displayed in the ECU Software Components Editor, not ApplicationSwComponentTypes as defined by AUTOSAR.
  • serviceComponent() matches component ports whose component type is a service component type.
  • parameterComponent() matches component ports whose component type is a parameter component type.
  • nvBlockComponent() matches component ports whose component type is a nv block component type.
  • sensorActuatorComponent() matches component ports whose component type is a sensor actuator component type.
  • ioHwAbstractionComponent() matches component ports whose component type is a I/O hardware abstraction component type, also called EcuAbstractionSwComponentType.
  • complexDeviceDriverComponent() matches component ports whose component type is a complex device driver component type.
  • serviceProxyComponent() matches component ports whose component type is a service proxy component type.
  • name(String) matches component ports with the given port name.
  • names(Collection) matches component ports with the given port names. The order of the names is not relevant in any kind.
  • name(Pattern) matches component ports with the given port name pattern.
  • componentPortName(String) matches component ports with the given component port name.
    The component name and port name are separated by a dot, e.g. 'MySwc.MyApplicationPort', 'ECU Composition.MyDelegationPort'. See also SIComponentPort.getName().
  • componentPortNames(Collection) matches component ports with the given component port names.
    The component name and port name are separated by a dot, e.g. 'MySwc.MyApplicationPort', 'ECU Composition.MyDelegationPort'. See also SIComponentPort.getName().
    The order of the names is not relevant in any kind.
  • asrPath(String) matches component ports with the given port autosar path.
  • asrPath(Pattern) matches component ports with the given port autosar path pattern.
  • component(String) matches component ports with the given component name.
  • components(Collection) matches component ports with the given component names. The order of the names is not relevant in any kind.
  • component(Pattern) matches component ports with the given component name pattern.
  • componentAsrPath(String) matches the component ports with the given component autosar path.
  • componentAsrPath(Pattern) matches component ports with the given component autosar path pattern.
  • componentType(String) matches component ports whose component type's name equals the given component type name.
  • componentType(Pattern) matches component ports whose component type's name matches the given component type name pattern.
  • componentTypeAsrPath(String) matches the component ports whose component type's autosar path equals the given component type autosar path.
  • componentTypeAsrPath(Pattern) matches component ports whose component type's autosar path matches the given component type autosar path pattern.
  • portInterfaceMapping(String) matches component ports for whose port interfaces a port interface mapping with the given port interface mapping name exists.
  • portInterfaceMapping(Pattern) matches component ports for whose port interfaces a port interface mapping with the given port interface mapping name pattern exists.
  • portInterfaceMappingAsrPath(String) matches component ports for whose port interfaces a port interface mapping with the given port interface mapping autosar path exists.
  • portInterfaceMappingAsrPath(Pattern) matches component ports for whose port interfaces a port interface mapping with the given port interface mapping autosar path pattern exists.
  • originComponentPortName(String) matches component ports having an origin component port with the given originPortName. That means the port has an incomplete delegation connection in the structured extract to a composition port with the given originPortName.
  • originComponentPortNames(Collection) matches component ports having an origin component port with one of the given originPortNames. That means the port has an incomplete delegation connection in the structured extract to a composition port with one of the given originPortNames. The order of the names is not relevant in any kind.
  • originComponentPortName(Pattern) matches component ports having an origin component port with the given origin port name pattern. That means the port has an incomplete delegation connection in the structured extract to a composition port with the given origin port name pattern.
  • originComponentPortComponent(String) matches component ports having an origin component port with the given originComponentName. That means the port has an incomplete delegation connection in the structured extract to a composition port whose composition owner instance has the given originComponentName.
  • originComponentPortComponent(Pattern) matches component ports having an origin component port with the given origin component name pattern. That means the port has an incomplete delegation connection in the structured extract to a composition port whose composition owner instance has the given origin component name pattern.
  • hasInnerTopLevelDelegationOriginComponentPort() matches component ports which have an inner top level origin component port. That means the port in the structured extract has an incomplete delegation connection which ends at a composition that is instantiated directly inside the top level composition (ECU Composition).
  • diagnosticConnection() narrows down selection to component ports which are derived from diagnostic mappings. See IComponentPortSelector.hasDiagnosticConnection() for more details.

    diagnosticConnection() cannot be combined with and(Runnable),
    or(Runnable) and not(Runnable).
    If possible always prefer using diagnosticConnection() over hasDiagnosticConnection() which can be also combined with not(Runnable), and(Runnable) and or(Runnable) due to performance reasons.
  • hasDiagnosticConnection() matches component ports for which a corresponding diagnostic event port mapping, diagnostic FiM function mapping, diagnostic service data mapping or a diagnostic service sw mapping exists so that a connection to another port can be derived from this mapping.
  • diagnosticPortRole(EDiagnosticPortRole) matches component ports with the given EDiagnosticPortRole.
  • filterAdvanced(Predicate) matches component ports for which the given predicate results to true.
  • and(Runnable) combines the predicates inside the lambda with a logical AND.
  • or(Runnable) combines the predicates inside the lambda with a logical OR.
  • not(Runnable) negates the combination of predicates inside the lambda.
  • put(List) can be used to set SIComponentPorts into the selection. This is the most efficient way to create a selection from existing objects. If further predicates are specified the predicates will be applied only on the component ports that were given into this put(List) method. The iteration order is relevant for getting deterministic results on further usage of the selection API. This method should only be called once.

Examples

Selects all component ports
scriptTask("selectAllPorts", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def selectedPorts =
             selectComponentPorts {
                // no predicates: select ALL component ports
             } getComponentPorts()
        scriptLogger.info("Selected {0} component ports.", selectedPorts.size())
      }
    }
  }
}

Selects all unconnected component ports
scriptTask("selectAllUnconnectedPorts", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def selectedPorts =
             selectComponentPorts {
                unconnected() // select all unconnected component ports
             } getComponentPorts()
        scriptLogger.info("Selected {0} component ports.", selectedPorts.size())
      }
    }
  }
}

Select all unconnected sender/receiver or connected mode-switch component ports
scriptTask("selectAllUnconnectedSRAndConnectedModePorts", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def selectedPorts =
             selectComponentPorts {
                // start with logical OR
                or {
                 and { // unconnected sender/receiver ports
                    unconnected()
                    senderReceiver()
                 }
                 and { // connected modeSwitch ports
                    connected()
                    modeSwitch()
                 }
                }
             } getComponentPorts()
        scriptLogger.info("Selected {0} component ports.", selectedPorts.size())
      }
    }
  }
}

Selects not completed component ports
scriptTask("selectNotCompletedPorts", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def selectedPorts =
             selectComponentPorts {
                // this predicate filters for ports
                // which needs to be connected and/or a data mapping
                notCompleted()
             } getComponentPorts()
        scriptLogger.info("Selected {0} component ports.", selectedPorts.size())
      }
    }
  }
}

Use origin context predicates for selecting component ports
scriptTask ("selectComponentPortsUsingOriginContextPredicates", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {

                // we want to use information from the structured extract to select flat extract ports

                def selectedComponentPorts = selectComponentPorts {
                    // use component port related predicates
                    senderReceiver()
                    required()

                    // combine them with origin context related predicates
                    // but remember that we are still selecting flat extract ports here
                    // we only use the origin context ports as additional criteria

                    // we want only ports for which the connection ends at the highest composition level inside the top level composition
                    // of the structured extract
                    hasInnerTopLevelDelegationOriginComponentPort()

                    // and only ports whose origin context has a special name pattern for their composition owner instance
                    originComponentPortComponent(~"Origin.*")
                }.getComponentPorts()

                scriptLogger.info("Selected {0} component ports using their origin context as additional selection criteria.",
                    selectedComponentPorts.size())
            }
        }
    }
}

Signal Instance Selection

The system signals and system signal groups to be data-mapped are represented by a signal instance (SIAbstractSignalInstance). SISignalInstance represents a system signal, SISignalGroupInstance represents a system signal group. 'Signal instance' means that the system signal or system signal group is at least referenced by one ISignal or ISignalGroup. System signals or system signal groups which are not referenced by an ISignal or ISignalGroup are not represented as signal instance and so are not available for data mapping.

selectSignalInstances(Action) allows the selection of SIAbstractSignalInstances using predicates.

The signal instance selection can be used to select and filter signal instances and either do further operations on them, such as map them to communication elements or to just return a list of signal instances with which you can continue working.

getSignalInstances() allows access to the single signal instances in the ISignalInstanceSelection.

Signal Instance Predicates

To select signal instances predicates can be provided to narrow down the result.

Per default the predicates are combined via logical AND. To realize other combinations, use the 'or','not' and 'and' predicates.

  • unmapped() matches signal instances which are not data-mapped.
  • mapped() matches signal instances which are data-mapped.
  • signalGroup() matches signal instances which are a signal group instance.
  • groupSignal() matches signal instances which are a group signal.
  • transformed() matches signal instances which are transformation signals.
  • tx() matches signal instances whose direction is compatible to EDirection.Tx.
  • rx() matches signal instances whose direction is compatible to EDirection.Rx.
  • name(String) matches signal instances with the given name.
  • names(Collection) matches signal instances with the given names. The order of the names is not relevant in any kind.
  • name(Pattern) matches signal instances with the given name pattern.
  • asrPath(String) matches signal instances with the given autosar path.
  • asrPaths(Collection) matches signal instances with the given autosar paths. The order of the names is not relevant in any kind.
  • asrPath(Pattern) matches signal instances with the given autosar path pattern.
  • iSignal(String) matches signal instances which are referenced at least by one ISignal/ISignalGroup with the given name.
  • iSignal(Pattern) matches signal instances which are referenced at least by one ISignal/ISignalGroup with the given name pattern.
  • iSignalAsrPath(String) matches signal instances which are referenced at least by one ISignal/ISignalGroup with the given autosar path.
  • iSignalAsrPath(Pattern) matches signal instances which are referenced at least by one ISignal/ISignalGroup with the given autosar path pattern.
  • physicalChannel(String) matches signal instances which are referenced by at least an ISignal/ISignalGroup for which an ISignalTriggering exists for a PhysicalChannel with the given name.
  • physicalChannel(Pattern) matches signal instances which are referenced by at least an ISignal/ISignalGroup for which an ISignalTriggering exists for a PhysicalChannel with the given name pattern.
  • physicalChannelAsrPath(String) matches signal instances which are referenced by at least an ISignal/ISignalGroup for which an ISignalTriggering exists for a PhysicalChannel with the given autosar path.
  • physicalChannelAsrPath(Pattern) matches signal instances which are referenced by at least an ISignal/ISignalGroup for which an ISignalTriggering exists for a PhysicalChannel with the given autosar path pattern.
  • communicationCluster(String) matches signal instances which are referenced by at least an ISignal/ISignalGroup which is sent via a PhysicalChannel of a CommunicationCluster with the given name.
  • communicationCluster(Pattern) matches signal instances which are referenced by at least an ISignal/ISignalGroup which is sent via a PhysicalChannel of a CommunicationCluster with the given name pattern.
  • communicationClusterAsrPath(String) matches signal instances which are referenced by at least an ISignal/ISignalGroup which is sent via a PhysicalChannel of a CommunicationCluster with the given autosar path.
  • communicationClusterAsrPath(Pattern) matches signal instances which are referenced by at least an ISignal/ISignalGroup which is sent via a PhysicalChannel of a CommunicationCluster with the given autosar path pattern.
  • pdu(String) matches signal instances which are referenced by at least an ISignal/ISignalGroup for which an ISignalToIPduMapping exists for a Pdu with the given name.
  • pdu(Pattern) matches signal instances which are referenced by at least an ISignal/ISignalGroup for which an ISignalToIPduMapping exists for a Pdu with the given name pattern.
  • pduAsrPath(String) matches signal instances which are referenced by at least an ISignal/ISignalGroup for which an ISignalToIPduMapping exists for a Pdu with the given autosar path.
  • pduAsrPath(Pattern) matches signal instances which are referenced by at least an ISignal/ISignalGroup for which an ISignalToIPduMapping exists for a Pdu with the given autosar path pattern.
  • frame(String) matches signal instances which are referenced by at least an ISignal/ISignalGroup which is sent via a Pdu for that a PduToFrameMapping exists for a Frame with the given name.
  • frame(Pattern) matches signal instances which are referenced by at least an ISignal/ISignalGroup which is sent via a Pdu for that a PduToFrameMapping exists for a Frame with the given name pattern.
  • frameAsrPath(String) matches signal instances which are referenced by at least an ISignal/ISignalGroup which is sent via a Pdu for that a PduToFrameMapping exists for a Frame with the given autosar path.
  • frameAsrPath(Pattern) matches signal instances which are referenced by at least an ISignal/ISignalGroup which is sent via a Pdu for that a PduToFrameMapping exists for a Frame with the given autosar path pattern.
  • filterAdvanced(Predicate) matches signal instances for which the given lambda results to true.
  • and(Runnable) combines the predicates inside the lambda with a logical AND.
  • or(Runnable) combines the predicates inside the lambda with a logical OR.
  • not(Runnable) negates the combination of predicates inside the lambda.
  • put(List) can be used to set SIAbstractSignalInstances into the selection. This is the most efficient way to create a selection from existing objects. If further predicates are specified the predicates will be applied only on the signal instances that were given into this put(List) method. The iteration order is relevant for getting deterministic results on further usage of the selection API. This method should only be called once.

Examples

Select all unmapped signal instances
scriptTask("SelectAllUnmappedSignalInstances", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def signalInstances =
                 selectSignalInstances {
                   unmapped() // select all signal instances which are not yet data mapped
                 } getSignalInstances()
        scriptLogger.info("Selected {0} signal instances.",signalInstances.size())
      }
    }
  }
}

Select all unmapped rx or transformed signal instances
scriptTask("SelectAllUnmappedRxOrTransformedSignalInstances", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def signalInstances =
                 selectSignalInstances {
                   // the signal instances should not be data-mapped yet
                   unmapped()
                   or { // and should either be a rx signal or a transformation signal
                     rx()
                     transformed()
                   }
                 } getSignalInstances()
        scriptLogger.info("Selected {0} signal instances.",signalInstances.size())
      }
    }
  }
}

Select signal instances using an advanced filter
import com.vector.cfg.sysdesc.model.communication.instance.SIAbstractSignalInstance
scriptTask("SelectSignalInstancesUsingAdvancedFilter", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def signalInstances =
                 selectSignalInstances {
                   filterAdvanced { SIAbstractSignalInstance signalInstance ->
                          // implement own custom filter
                          def mdfObject = signalInstance.getMdfObject()
                          // work on directly on autosar model level ...
                          // select signal instance only which has admin data
                          def select = mdfObject.adminData != null
                          select
                   }
                 } getSignalInstances()
        scriptLogger.info("Selected {0} signal instances.",signalInstances.size())
      }
    }
  }
}

Communication Element Selection

A data element, an operation or a trigger to be data-mapped is represented by an SICommunicationElement. A data element is represented by the subtype SIDataCommunicationElement, an operation is represented by the subtype SIOperationCommunicationElement and a trigger is represented by the subtype SITriggerCommunicationElement. A communication element contains the full context information (component prototype, port prototype, data type hierarchy) necessary for data mapping.

selectCommunicationElements(Action) allows the selection of SICommunicationElements using predicates.

The communication element selection can be used to select and filter communication elements and either do further operations on them, such as map them to signal instances or to just return a list of communication elements with which you can continue working.

getCommunicationElements() allows access to the single communication elements in the ICommunicationElementSelection. Please make sure you are using the correct expansion mode, see ICommunicationElementSelector.selectFullyExpanded() and ICommunicationElementSelector.selectFullyExpandedButPrimitiveArraysAsLeafs().

Communication Element Predicates

To select communication elements predicates can be provided to narrow down the result.

Per default the predicates are combined via logical AND. To realize other combinations, use the 'or','not' and 'and' predicates.

  • unconnected() matches communication elements whose component port is unconnected.
  • connected() matches communication elements whose component port is connected.
  • senderReceiver() matches communication elements whose port has a sender/receiver port interface.
  • clientServer() matches communication elements whose port has a client/server port interface.
  • trigger() matches communication elements whose port has a trigger port interface.
  • provided() matches communication elements whose port is a provided port (p-port).
  • required() matches communication elements whose port is a required port (r-port).
  • delegation() matches communication elements whose port is delegation port.
  • unmapped() matches communication elements whose are not data-mapped.
  • mapped() matches communication elements whose are data-mapped.
  • ownerPortTerminated() matches communication elements whose component port is terminated.
  • ownerPortNotTerminated() matches communication elements whose component port is not terminated.
  • name(String) matches communication elements with the given data element or operation name.
  • names(Collection) matches communication elements with the given data element or operation names. The order of the names is not relevant in any kind.
  • name(Pattern) matches communication elements with the given data element or operation name pattern.
  • fullyQualifiedName(String) matches communication elements with the given full qualified communication element name. E.g. 'App1.Port1.DataElement1', 'ECU Composition.DelegationPort2.DataElement2'. See also SICommunicationElement.getFullyQualifiedName().
  • fullyQualifiedNames(Collection) matches communication elements with the given full qualified communication element names. E.g. 'App1.Port1.DataElement1', 'ECU Composition.DelegationPort2.DataElement2'. See also SICommunicationElement.getFullyQualifiedName(). The order of the names is not relevant in any kind.
  • asrPath(String) matches communication elements with the given data element or operation autosar path.
  • asrPath(Pattern) matches communication elements with the given data element or operation autosar path pattern.
  • component(String) matches communication elements with the given component name.
  • components(Collection) matches communication elements with the given component names. The order of the names is not relevant in any kind.
  • component(Pattern) matches communication elements with the given component name pattern.
  • componentAsrPath(String) matches communication elements with the given component name autosar path.
  • componentAsrPath(Pattern) matches communication elements with the given component name autosar path pattern.
  • port(String) matches communication elements with the given component port name.
  • ports(Collection) matches communication elements with the given component port names. The order of the names is not relevant in any kind.
  • port(Pattern) matches communication elements with the given component port name pattern.
  • portAsrPath(String) matches communication elements with the given component port autosar path.
  • portAsrPath(Pattern) matches communication elements with the given component port autosar path pattern.
  • filterAdvanced(Predicate) Add a custom predicated which matches communication elements for which the given lambda results to true.
  • and(Runnable) combines the predicates inside the lambda with a logical AND.
  • or(Runnable) combines the predicates inside the lambda with a logical OR.
  • not(Runnable) negates the combination of predicates inside the lambda.
  • put(List) can be used to set SICommunicationElements into the selection. This is the most efficient way to create a selection from existing objects. If further predicates are specified the predicates will be applied only on the communication elements that were given into this put(List) method. The iteration order is relevant for getting deterministic results on further usage of the selection API. This method should only be called once.
  • selectFullyExpanded() modifies the behavior of the selection. Using this option you are not only selecting the root communication elements (as you know from the data mapping assistant in GUI), but also the leafs. See SIDataCommunicationElement.getLeafsFullExpanded() for more details.
  • selectFullyExpandedButPrimitiveArraysAsLeafs() modifies the behavior of the selection. Using this option you are not only selecting the root communication elements (as you know from the data mapping assistant in GUI), but also the leafs. Arrays of primitives (e.g. uint8 arrays) will not be expanded. See SIDataCommunicationElement.getLeafsFullExpandedExceptPrimitiveArrays() for more details.

Examples

Select all unmapped delegation port communication elements
scriptTask("SelectAllUnmappedDelPortComElements", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def comElements =
                 selectCommunicationElements {
                   // select all unmapped delegation communication elements
                   delegation()
                   unmapped()
                 } getCommunicationElements()
        scriptLogger.info("Selected {0} communication elements.",comElements.size())
      }
    }
  }
}

Select all communication elements with their leafs
scriptTask("SelectComplexFullyExpanded", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def comElements =
                 selectCommunicationElements {
                   // expand all complex communication elements except primitive arrays
                   // and select all communication elements with their leafs
                   // e.g. for a record we select both here, the record and its record elements
                   selectFullyExpandedButPrimitiveArraysAsLeafs()
                 } getCommunicationElements()
        scriptLogger.info("Selected {0} communication elements.",comElements.size())
      }
    }
  }
}

Select communication elements using an advanced filter
import com.vector.cfg.sysdesc.model.communication.SICommunicationElement
import com.vector.cfg.sysdesc.model.communication.SIDataCommunicationElement
scriptTask("SelectComElementsUsingAdvancedFilter", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def comElements =
             selectCommunicationElements {
               // advanced filter:
               // only select communication elements
               // which represent data elements of a specific data type
               filterAdvanced { SICommunicationElement comElement ->
                   if (comElement instanceof SIDataCommunicationElement) {
                      def mdfDataElement = comElement.getTargetElement().getMdfObject()
                      // check directly on autosar model level
                      return mdfDataElement.type.refTarget.name.equals("myCustomDataType")
                   }
                   false
               }
             } getCommunicationElements()
        scriptLogger.info("Selected {0} communication elements.",comElements.size())
      }
    }
  }
}

Component Type Selection

An SIComponentType represents a software component type according to AUTOSAR. It might define functionality and behavior of a software component in case of an atomic component type, contain other software components and connections in case of a composition component type or define parameters and characteristic values in case of a parameter component type.

SIComponent is an instance of a software component type.

selectComponentTypes(Action) allows the selection of SIComponentTypes using predicates.

The component type selection can be used to select and filter component types and either do further operations on them, such as instantiating them by creating new component prototypes or to just return a list of component types with which you can continue working.

getComponentTypes() allows access to the single component types in the IComponentTypeSelection.

Component Type Predicates

To select the component types predicates can be provided to narrow down the result.

Per default the predicates are combined via logical AND. To realize other combinations, use the 'or','not' and 'and' predicates.

  • name(String) matches component types with the given component type name.
  • names(Collection) matches component types with the given component type names. The order of the names is not relevant in any kind.
  • name(Pattern) matches component types with the given component type name pattern.
  • asrPath(String) matches component types with the given componet type autosar path.
  • asrPath(Pattern) matches component types with the given component type autosar path pattern.
  • component(String) matches component types for which a component prototype with the given component name exists.
  • component(Pattern) matches component types for which a component prototype with the given component name pattern exists.
  • application() matches component types which are application component types. Application component types are all component types which are not service component types, as displayed in the ECU Software Components Editor, not ApplicationSwComponentTypes as defined by AUTOSAR.
  • service() matches component types which are service component types.
  • parameter() matches component types which are parameter (calibration) component types.
  • nvBlock() matches component types which are nv block component types.
  • sensorActuator() matches component types which are sensor actuator component types.
  • ioHwAbstraction() matches component types which are I/O hardware abstraction component types, also called EcuAbstractionSwComponentType.
  • complexDeviceDriver() matches component types which are complex device driver component types.
  • serviceProxy() matches component types which are service proxy component types.
  • instantiated() matches component types that are already instantiated. In other words matches if a component prototype of that component type already exists.
  • supportsMultipleInstantiation() matches component types which support multiple instantiation.
  • filterAdvanced(Predicate) matches component types for which the given lambda results to true.
  • and(Runnable) combines the predicates inside the lambda with a logical AND.
  • or(Runnable) combines the predicates inside the lambda with a logical OR.
  • not(Runnable) negates the combination of predicates inside the lambda.
  • put(List) can be used to set SIComponentTypes into the selection. This is the most efficient way to create a selection from existing objects. If further predicates are specified the predicates will be applied only on the component types that were given into this put(List) method. The iteration order is relevant for getting deterministic results on further usage of the selection API. This method should only be called once.

Examples

Select component type by name
scriptTask ("selectComponentTypeByName", DV_PROJECT ){
    code {
        domain.runtimeSystem {
            def selectedComponentTypes = selectComponentTypes {
                name "App1"
            }.getComponentTypes()

            scriptLogger.info("Selected '{0}' component types.", selectedComponentTypes.size())
        }
    }
}

Select not instantiated component types
scriptTask ("selectNotInstantiatedComponentTypes", DV_PROJECT ){
    code {
        domain.runtimeSystem {
            def selectedComponentTypes = selectComponentTypes {
                not {
                    instantiated()
                }
            }.getComponentTypes()

            scriptLogger.info("Selected '{0}' component types.", selectedComponentTypes.size())
        }
    }
}

Event Selection

An event SIEvent (called AbstractEvent in AUTOSAR) represents a RTEEvent or a BswEvent. Events are raised on different conditions and are used to implement application or basic software in AUTOSAR. (Sometimes they are also called triggers.)

A task mapping (SITaskMapping) represents an SIEvent (also called trigger) that is mapped to a task in the context of a component prototype or a module configuration. It corresponds to the task mapping container in the RTE configuration.

selectEvents(Action) allows the selection of SIEvents using predicates.

The event selection can be used to select and filter events and either do further operations on them, such as mapping the executable entities they trigger to tasks or to just return a list of events or the task mappings for them with which you can continue working.

++++++

+++getEvents() allows access to the single events in the IEventSelection.+++

+++

+++getTaskMappings() retrieves all SITaskMappings for the selected events (see getEvents()).

Note:
1. In case of multi instantiation of component prototypes, the different instances share the same events, since the event is part of the internal behavior of the component type. Therefore if the event is selected, getTaskMappings() will always return the task mappings for all component prototypes.
2. Since this method can be run outside of a transaction, there might be selected events for which no task mapping container does exist yet. The container cannot be created by calling getTaskMappings(), so no task mapping can be returned. This happens if the system description is not synchronized, after changes in the structured extract were done (see Automation Interface Documentation, chapter about Model Synchronization for examples how to synchronize).

Event Predicates

To select the events predicates can be provided to narrow down the result.

Per default the predicates are combined via logical AND. To realize other combinations, use the 'or','not' and 'and' predicates.

  • +++name(String) matches events (triggers) with the given event name.+++
  • +++names(Collection) matches events (triggers) with the given event names. The order of the names is not relevant in any kind.+++
  • +++name(Pattern) matches events (triggers) with the given event name pattern.+++
  • +++asrPath(String) matches events (triggers) with the given event autosar path.+++
  • +++asrPath(Pattern) matches events (triggers) with the given event autosar path pattern.+++ +++
    +++
  • +++applicationComponent() matches events (triggers) which belong to an application component.+++
  • +++serviceComponent() matches events (triggers) which belong to a service component.+++
  • +++component(String) matches events (triggers) which belong to components with the given component name.+++
  • components(Collection) matches events (triggers) which belong to components with the given component names. The order of the names is not relevant in any kind.
  • component(Pattern) matches events (triggers) which belong to components which matches the given component name pattern.
  • componentType(String) matches events (triggers) which are part of the internal behavior of component types with the given component type name.
  • componentType(Pattern) matches events (triggers) which are part of the internal behavior of component types which matches the given component type name pattern.
  • componentTypeAsrPath(String) matches events (triggers) which are part of the internal behavior of component types with the given component type autosar path.
  • componentTypeAsrPath(Pattern) matches events (triggers) which are part of the internal behavior of component types whose autosar path matches the given component type autosar path pattern.
  • moduleConfiguration(String) matches events (triggers) which belong to module configurations with the given module configuration name.
  • moduleConfigurations(Collection) matches events (triggers) which belong to module configurations with the given module configuration names. The order of the names is not relevant in any kind.
  • moduleConfiguration(Pattern) matches events (triggers) which belong to module configurations which matches the given module configuration name pattern.
  • moduleConfigurationAsrPath(String) matches events (triggers) which belong to module configurations with the given module configuration autosar path.
  • moduleConfigurationAsrPath(Pattern) matches events (triggers) which belong to module configurations whose autosar path matches the given module configuration autosar path pattern.
  • +++task(String) matches events (triggers) which are mapped to a task with the given task name.+++
  • +++task(Pattern) matches events (triggers) which are mapped to a task whose name matches the given task name pattern.+++
  • +++bswEvent() matches events (triggers) which are bsw events.+++
  • +++rteEvent() matches events (triggers) which are rte events.+++
  • unmapped() matches unmapped events (triggers). In case of multi instantiated components/modules matches if unmapped at least in one context. Use fullyUnmapped() to determine whether an event is unmapped in all contexts.
  • fullyUnmapped() matches events (triggers) which are not mapped in any context. If no multi instantiation is used, the result is the same as for unmapped().
  • mapped() matches mapped events (triggers). In case of multi instantiated components/modules matches if mapped at least in one context. Use fullyMapped() to determine whether an event is mapped in all contexts.
  • fullyMapped() matches events (triggers) which are mapped in every context. If no multi instantiation is used, the result is the same as for mapped().
  • +++timing() matches events which are timing events (triggers).+++
  • +++timing(Double) matches events (triggers) which are timing events with the given period (seconds).+++
  • +++init() matches events (triggers) which are init events.+++
  • +++dataReceived() matches events (triggers) which are data received events.+++
  • +++dataReceiveError() matches events (triggers) which are data receive error events.+++
  • +++dataSendCompleted() matches events (triggers) which are data send completed events.+++ +++
    +++
  • +++dataWriteCompleted() matches events (triggers) which are data write completed events.+++
  • +++operationInvoked() matches events (triggers) which are operation invoked events.+++
  • operationInvoked(String) matches operation invoked events (triggers) which are invoked by an operation with the given operationName.
  • +++serverCallReturns() matches events (triggers) which are asynchronous server call returns events.+++
  • +++modeSwitch() matches events (triggers) which are mode switch events.+++ +++
    +++
  • +++modeEntry() matches events (triggers) which are mode switch events with activation kind ON-ENTRY.+++
  • +++modeExit() matches events (triggers) which are mode switch events with activation kind ON-EXIT.+++
  • +++modeTransition() matches events (triggers) which are mode switch events with activation kind ON-TRANSITION.+++
  • +++modeSwitchedAck() matches events (triggers) which are mode switched acknowledgement events.+++
  • +++externalTrigger() matches events (triggers) which are external trigger occurred events.+++
  • +++internalTrigger() matches events (triggers) which are internal trigger occurred events.+++
  • +++background() matches events (triggers) which are background events.+++ +++
    +++
  • +++transformerHardError() matches events (triggers) which are transformer hard error events.+++ +++
    +++
  • mandatory() matches events (triggers) which must be mapped. (The mapping of operation invoked events and bsw events whose schedulable entity has no via symbol matching runnable is optional.)
  • +++filterAdvanced(Predicate) matches events (triggers) for which the given lambda results to true.+++
  • +++and(Runnable) combines the predicates inside the lambda with a logical AND.+++
  • +++or(Runnable) combines the predicates inside the lambda with a logical OR.+++
  • +++not(Runnable) negates the combination of predicates inside the lambda.+++
  • put(List) can be used to set SIEvents into the selection. This is the most efficient way to create a selection from existing objects. If further predicates are specified the predicates will be applied only on the events that were given into this put(List) method. The iteration order is relevant for getting deterministic results on further usage of the selection API. This method should only be called once.

Examples

Select events example
scriptTask ("selectEvents", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                def selectedEvents = selectEvents {
                    // select all unmapped events of component 'App1'
                    unmapped()
                    component("App1")
                }.getEvents()

                scriptLogger.info("Selected '{0}' events.", selectedEvents.size())
            }
        }
    }
}

Executable Entity Selection

+++

+++An executable entity (SIExecutableEntity) represents a RunnableEntity or a BswSchedulableEntity. Both are abstractions of executable code in AUTOSAR. (Sometimes they are also called functions.)

+++

+++A task mapping (SITaskMapping) represents an SIEvent (also called trigger) that is mapped to a task in the context of a component prototype or a module configuration. It corresponds to the task mapping container in the RTE configuration.

+++

+++

+++

+++selectExecutableEntities(Action) allows the selection of SIExecutableEntitys using predicates.

The executable entity selection can be used to select and filter executable entities and either do further operations on them, such as mapping them to tasks or to just return a list of executable entities or the task mappings for them with which you can continue working.

+++

+++getExecutableEntities() allows access to the single executable entities in the IExecutableEntitySelection.

+++

+++getTaskMappings() retrieves all SITaskMappings for the selected executable entities (see getExecutableEntities()).

Executable Entity Predicates

To select the executable entities predicates can be provided to narrow down the result.

Per default the predicates are combined via logical AND. To realize other combinations, use the 'or','not' and 'and' predicates.

  • symbol(String) matches runnable entities with the given symbol and bsw schedulable entities whose corresponding bsw module entry short name matches the given symbol.
  • symbol(Pattern) matches runnable entities whose symbol matches the given symbol pattern and bsw schedulable entities whose corresponding bsw module entry short name matches the given symbol pattern.
  • +++name(String) matches executable entities (functions) with the given name.+++
  • names(Collection) matches executable entities (functions) with the given names. The order of the names is not relevant in any kind.
  • +++name(Pattern) matches executable entities (functions) with the given name pattern.+++
  • +++asrPath(String) matches executable entities (functions) with the given autosar path.+++
  • +++asrPath(Pattern) matches executable entities (functions) with the given autosar path pattern.+++ +++
    +++
  • +++applicationComponent() matches executable entities (functions) whose owner is an application component.+++
  • +++serviceComponent() matches executable entities (functions) whose owner is a service component.+++
  • +++component(String) matches executable entities (functions) which belong to components with the given component name.+++
  • components(Collection) matches executable entities (functions) which belong to components with the given component names. The order of the names is not relevant in any kind.
  • component(Pattern) matches executable entities (functions) which belong to components which matches the given component name pattern.
  • componentType(String) matches executable entities (functions) which are part of the internal behavior of component types with the given component type name.
  • componentType(Pattern) matches exectuable entities (functions) which are part of the internal behavior of component types which matches the given component type name pattern.
  • componentTypeAsrPath(String) matches executable entities (functions) which are part of the internal behavior of component types with the given component type autosar path.
  • componentTypeAsrPath(Pattern) matches executable entities (functions) which are part of the internal behavior of component types whose autosar path matches the given component type autosar path pattern.
  • moduleConfiguration(String) matches executable entities (functions) which belong to module configurations with the given module configuration name.
  • moduleConfigurations(Collection) matches executable entities (functions) which belong to module configurations with the given module configuration names. The order of the names is not relevant in any kind.
  • moduleConfiguration(Pattern) matches executable entities (functions) which belong to module configurations which matches the given module configuration name pattern.
  • moduleConfigurationAsrPath(String) matches executable entities (functions) which belong to module configurations with the given module configuration autosar path.
  • moduleConfigurationAsrPath(Pattern) matches executable entities (functions) which belong to module configurations whose autosar path matches the given module configuration autosar path pattern.
  • task(String) matches executable entities (functions) which have at least one event (trigger) that is mapped to a task with the given task name.
  • task(Pattern) matches executable entities (functions) which have at least one event (trigger) that is mapped to a task whose name matches the given task name pattern.
  • +++bswSchedulableEntity() matches executable entities (functions) which are bsw schedulable entities.+++
  • +++runnableEntity() matches executable entities (functions) which are runnable entities.+++
  • +++unmapped() matches executable entities (functions) with at least one unmapped event (trigger).+++
  • fullyUnmapped() matches executable entities (functions) with all of its events (triggers) being not mapped in any context to a task.
  • +++mapped() matches executable entities (functions) with at least one mapped event (trigger).+++
  • fullyMapped() matches executable entities (functions) with all of its events (triggers) being mapped in each context to a task.
  • +++filterAdvanced(Predicate) matches executable entities (functions) for which the given predicate results to true.+++
  • +++and(Runnable) combines the predicates inside the lambda with a logical AND.+++
  • +++or(Runnable) combines the predicates inside the lambda with a logical OR.+++
  • +++not(Runnable) negates the combination of predicates inside the lambda.+++
  • put(List) can be used to set SIExecutableEntitys into the selection. This is the most efficient way to create a selection from existing objects. If further predicates are specified the predicates will be applied only on the executable entities that were given into this put(List) method. The iteration order is relevant for getting deterministic results on further usage of the selection API. This method should only be called once.

Examples

Select executable entities example
scriptTask ("selectExecutableEntities", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                def selectedExecutables = selectExecutableEntities {
                    // select all runnables with symbol 'MySymbol'
                    symbol("MySymbol")
                    runnableEntity()
                }.getExecutableEntities()

                scriptLogger.info("Selected '{0}' executable entities.", selectedExecutables.size())
            }
        }
    }
}

Port Interface Selection

+++

+++A SIPortInterface represents a port interface according to AUTOSAR. A port interface is an interface that is either provided or required by a port of a software component.

+++

+++

+++

+++selectPortInterfaces(Action) allows the selection of SIPortInterfaces using predicates.

The port interface selection can be used to select and filter port interfaces and either do further operations on them, such as instantiating them by creating new delegation port prototypes or to just return a list of port interfaces with which you can continue working.

+++

+++getPortInterfaces() allows access to the single port interfaces in the IPortInterfaceSelection.

Port Interfaces Predicates

To select the port interfaces predicates can be provided to narrow down the result.

Per default the predicates are combined via logical AND. To realize other combinations, use the 'or','not' and 'and' predicates.

  • +++name(String) matches port interfaces with the given port interface name.+++
  • names(Collection) matches port interfaces with the given port interface names. The order of the names is not relevant in any kind.
  • +++name(Pattern) matches port interfaces with the given port interface name pattern.+++
  • +++asrPath(String) matches port interfaces with the given port interface autosar path.+++
  • +++asrPath(Pattern) matches port interfaces with the given port interface autosar path pattern.+++
  • +++service() matches port interfaces which are service interfaces.+++
  • +++application() matches port interfaces which are application interfaces.+++
  • +++senderReceiver() matches port interfaces which are sender receiver interfaces.+++
  • +++clientServer() matches port interfaces which are client server interfaces.+++
  • +++modeSwitch() matches port interfaces which are mode switch interfaces.+++
  • +++nvData() matches port interfaces which are NvData interfaces.+++
  • +++trigger() matches port interfaces which are trigger interfaces.+++
  • +++parameter() matches port interfaces which are parameter interfaces.+++
  • componentType(String) first matches all component types with the given component type name, then retrieves all port interfaces of the component type's port prototypes.
  • componentType(Pattern) first matches all component types with the given component type name pattern, then retrieves all port interfaces of the component type's port prototypes.
  • componentTypeAsrPath(String) first matches all component types with the given component type asr path, then retrieves all port interfaces of the component type's port prototypes.
  • componentTypeAsrPath(Pattern) first matches all component types with the given component type asr path pattern, then retrieves all port interfaces of the component type's port prototypes.
  • component(String) first matches all components with the given component name, then retrieves all port interfaces of the component's ports.
  • components(Collection) first matches all components with the given component names, then retrieves all port interfaces of the component's ports. The order of the names is not relevant in any kind.
  • component(Pattern) first matches all components with the given component name pattern, then retrieves all port interfaces of the component's ports.
  • componentPort(String) first matches all SIComponentPorts with the given name, then retrieves all port interfaces of the component ports.
  • componentPorts(Collection) first matches all SIComponentPorts with the given names, then retrieves all port interfaces of the component ports. The order of the names is not relevant in any kind.
  • componentPort(Pattern) first matches all SIComponentPorts with the given name pattern, then retrieves all port interfaces of the component ports.
  • +++filterAdvanced(Predicate) matches port interfaces for which the given lambda results to true.+++
  • +++and(Runnable) combines the predicates inside the runnable with a logical AND.+++
  • +++or(Runnable) combines the predicates inside the lambda with a logical OR.+++
  • +++not(Runnable) negates the combination of predicates inside the lambda.+++
  • put(List) can be used to set SIPortInterfaces into the selection. This is the most efficient way to create a selection from existing objects. If further predicates are specified the predicates will be applied only on the port interfaces that were given into this put(List) method. The iteration order is relevant for getting deterministic results on further usage of the selection API. This method should only be called once.

Examples

Select PortInterface by name and type
scriptTask("selectPortInterfacesByName", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def selectedPortInterfaces =
             selectPortInterfaces {
                // selects all sender receiver application port interfaces with the name 'MyPortInterface'
                senderReceiver()
                application()
                name "MyPortInterface"

             // getPortInterfaces() will filter all port interfaces for the given predicates
             // so in our example we will receive
             // all sender receiver application port interfaces with the short name 'MyPortInterface'
             } getPortInterfaces()
        scriptLogger.info("Selected {0} port interfaces.", selectedPortInterfaces.size())
      }
    }
  }
}

Select PortInterfaces by component ports
scriptTask("selectPortInterfacesByComponentPorts", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def selectedPortInterfaces =
             selectPortInterfaces {
                // selects the port interface of the port 'pCSPort1' of component 'App1'
                componentPort "App1.pCSPort1"
             } getPortInterfaces()
        scriptLogger.info("Selected {0} port interfaces.", selectedPortInterfaces.size())
      }
    }
  }
}

Origin Component Port Selection

Origin Context

+++

+++ According to AUTOSAR the flat extract is created out of the structured extract. During the flattening process, the inner compositions and their ports are lost. However sometimes the information about this objects is helpful to perform actions on the flat extract, such as for example connecting ports or doing the data mapping. We call the objects of the structured extract, which are related to the flat extract objects, origin contexts.

The component port connection provides an option to use the origin context's names as additional mapping criteria. This will be introduced below (see +++IComponentPortAutoMapper_useOriginContextForMatch+++).

Remark: Since the RuntimeSystem-API now works on a flat-view of the StructuredExtract, the origin-context-APIs are doing the same, but behave as original designed for flat extract usage.

Origin Component Port

There is an own model element for the component ports of the structured extract.

+++

+++

+++

+++A component port (see also SIComponentPort) represents a port prototype and its corresponding component prototype. The SIOriginComponentPort represents a port in context of a component prototype for the upstream model (structured extract).

Remark:

The original design of the origin component ports was done for the flattened components of the structured extract. Since system description SIModel allows working directly on the structured extract and provides the ISysDescService.getFlatComponentView() as view of the flattened components (which is used in the RuntimeSystem-APIs), the SIOriginComponentPorts now represent the SIComponentPorts of the structured extract directly and are interface compatible to the original design, but do not work on the flat extract anymore.

Further we want to clarify some of the terminology which is used in context of the origin component port. The term delegation port is pretty clear for the flat extract, since there are no other compositions beside the top level composition. However it is possible to instantiate also compositions inside the top level composition and inside other compositions in the structured extract. We call all ports whose owner is a composition, delegation ports.

Another term used here is the inner top level. Since a project can have only one top level composition, the first hierarchy level defining the rough structure of the software components is directly inside the top level composition. So everything directly inside the top level composition is called the inner top level.

For example if a composition 'MyComposition' is instantiated directly in the top level composition and has a port named 'SendData', so we call the origin component port 'MyComposition.SendData' an inner top level delegation port. Let's assume the composition named 'OtherComposition' has a port named 'ReceiveData' and is instantiated in ' MyComposition'. The origin component port 'OtherComposition.ReceiveData' is not an inner top level delegation port, since we use this term only for the hierarchy level inside the top level composition.

+++

+++

+++

+++selectOriginComponentPorts(Action) allows the selection of SIOriginComponentPorts using predicates. The origin component ports which are selected here, are ends of incomplete delegation connections in the structured extract.

The origin component port selection can be used to select and filter origin component ports and either do further operations on them, such as creating new delegation ports in the flat extract for them or to just return a list of origin component ports with which you can continue working.

+++

+++getOriginComponentPorts() allows access to the single origin component ports in the IOriginComponentPortSelection.

Origin Component Port Predicates

To select the origin component ports predicates can be provided to narrow down the result.

Per default the predicates are combined via logical AND. To realize other combinations, use the 'or','not' and 'and' predicates.

  • +++name(String) matches origin component ports with the given port name.+++
  • +++names(Collection) matches origin component ports with the given port names. The order of the names is not relevant in any kind.+++
  • +++name(Pattern) matches origin component ports with the given port name pattern.+++
  • +++asrPath(String) matches origin component ports with the given port autosar path.+++
  • +++asrPath(Pattern) matches origin component ports with the given port autosar path pattern.+++
  • +++component(String) matches origin component ports with the given component name.+++
  • components(Collection) matches origin component ports with the given component names. The order of the names is not relevant in any kind.
  • +++component(Pattern) matches origin component ports with the given component name pattern.+++
  • +++componentAsrPath(String) matches the origin component ports with the given component autosar path.+++
  • +++componentAsrPath(Pattern) matches origin component ports with the given component autosar path pattern.+++
  • +++componentType(String) matches origin component ports whose component type's name equals the given component type name.+++
  • componentType(Pattern) matches origin component ports whose component type's name matches the given component type name pattern.
  • componentTypeAsrPath(String) matches origin component ports whose component type's autosar path equals the given component type autosar path.
  • componentTypeAsrPath(Pattern) matches origin component ports whose component type's autosar path matches the given component type autosar path pattern.
  • +++provided() matches provided origin component ports (p-port).+++
  • +++required() matches required origin component ports (r-port).+++
  • +++providedRequired() matches provided-required origin component ports (pr-port).+++
  • innerTopLevelDelegation() matches origin component ports on the highest hierarchy level. In other words the component of the matched ports is instantiated directly inside the top level composition (ECU Composition).
  • +++ofFlatExtractPort(SIComponentPort) retrieves the origin component ports of the given flatComponentPort.+++
  • +++senderReceiver() matches origin component ports whose port has a sender/receiver port interface.+++
  • +++clientServer() matches origin component ports whose port has a client/server port interface.+++
  • +++trigger() matches origin component ports whose port has a trigger port interface.+++
  • +++filterAdvanced(Predicate) matches origin component ports for which the given predicate results to true.+++
  • +++and(Runnable) combines the predicates inside the lambda with a logical AND.+++
  • +++or(Runnable) combines the predicates inside the lambda with a logical OR.+++
  • +++not(Runnable) negates the combination of predicates inside the lambda.+++ +++
    +++
  • completed() matches origin component ports which are completed.

    An SIOriginComponentPort is completed if an only if all of its flat extract ports and additionally all of the delegation ports which are connected to these flat extract ports are completed. (See SIComponentPort for definition of completed state for flat extract ports.)

  • notCompleted() matches origin component ports which are not completed.

    See completed() for the conditions an origin port has to meet to be a completed port.

  • put(List) can be used to set SIOriginComponentPorts into the selection. This is the most efficient way to create a selection from existing objects. If further predicates are specified the predicates will be applied only on the origin component ports that were given into this put(List) method. The iteration order is relevant for getting deterministic results on further usage of the selection API. This method should only be called once.

Examples

Select ends of incomplete connections
scriptTask("selectOriginComponentPorts", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def selectedOriginPorts = selectOriginComponentPorts {
            innerTopLevelDelegation()
            provided()
        } getOriginComponentPorts()

        scriptLogger.info("Selected '{0}' origin component ports.", selectedOriginPorts.size())
     }
    }
  }
}

Select the ends of incomplete connections for a specific flat view component port
scriptTask("originPortsForFlatExtractPort", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        // first we need to find our flat view port
        // we will use the component port selection for this example
        def componentPort = selectComponentPorts {
            name "pDataSend"
            component "App1"
        } getComponentPorts().iterator().next()

        def selectedOriginPorts = selectOriginComponentPorts {
            ofFlatExtractPort(componentPort)
        } getOriginComponentPorts()

        scriptLogger.info("Selected '{0}' origin component ports for {1}.",
            selectedOriginPorts.size(),
            componentPort.getName())
     }
    }
  }
}

Component Port Connection

This chapter is about connecting (a.k.a. mapping) component ports to other component ports. There are two ways to do that.
The first way is using a the component port selection API (see +++ComponentPortSelection+++) and calling a method to connect the selected ports to other ports. It is possible to filter the targets and to evaluate and change by the auto-mapper suggested connections. So this way is similar to the component connection assistant from the GUI.
The second way is to use a simple API that requires already prepared data structures e.g. two lists of component ports that are sorted applying certain custom rules and to map them via index matching. To initially find the appropriate component ports you can use the common selection APIs.

Auto-Mapping

The use case of auto-mapping component ports is based on the selection of component ports. The auto-mapper matches component ports using their names.

+++

+++autoMap() tries to auto-map the selection of component ports according the component connection assistant default rules.

Examples for autoMap ()

Tries to auto-map all ports
scriptTask("automapAll", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def mappedConnectors =
                 selectComponentPorts {
                    // no predicates: select ALL component ports
                 } autoMap()
        scriptLogger.info("Created {0} mappings.", mappedConnectors.size())
      }
    }
  }
}

Tries to auto-map all unconnected component ports
scriptTask("automapAllUnconnected", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def mappedConnectors =
             selectComponentPorts {
                 unconnected() // select all unconnected component ports
             } autoMap()
        scriptLogger.info("Created {0} mappings.", mappedConnectors.size())
      }
    }
 }
}

Tries to auto-map all unconnected sender/receiver and client/server ports
scriptTask("autoMapUnconnectedSRCS", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def mappedConnectors =
                selectComponentPorts {
                   // select all unconnected client/server and unconnected sender/receiver ports
                   unconnected()
                   or {
                     clientServer()
                     senderReceiver()
                   }
                } autoMap()
        scriptLogger.info("Created {0} mappings.",mappedConnectors.size())
      }
    }
  }
}

Tries to auto-map port determined by advanced filter
import com.vector.cfg.sysdesc.model.component.SIComponentPort

scriptTask("autoMapAdvancedfilter", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def mappedConnectors =
                selectComponentPorts {
                  // select component port by own custom filter predicate
                  filterAdvanced { SIComponentPort port ->
                       "MyUUID".equals(port.getPort().getMdfObject().getUuid2())
                  }
                } autoMap()
        scriptLogger.info("Created {0} mappings.",mappedConnectors.size())
      }
    }
  }
}

+++

+++autoMapTo(Action) tries to auto-map the selection of component ports according the component connection assistant rules but offers more control for the auto-mapping: Inside the lambda additional predicates for narrowing down the target component ports can be defined and code to evaluate and change the auto-mapper results can be provided.

Narrowing down the target component ports may be useful to gain better matches for the auto-mapper: In case several target component ports match equally, no auto-mapping is performed. So reducing the target component ports may improve the results of the auto-mapping.

The component port selection will produce trace, info and warning logs. To see them, activate the 'IComponentPortSelection' logger with the appropriate log level.

The provided list of connections will contain all created connections for each connected component port pair: since some connections need a connection chain through the composition hierarchy this includes SIDelegationConnectors as well (which are usually not visible in the flat component view of the structured extract). But it ensures completeness of the result.

Control the auto-mapping in autoMapTo (Closure)

+++

+++selectTargetPorts(Action) allows to define predicates to narrow down the target ports for the auto-mapping. The predicates are used to filter the possible target component ports which were computed from the source component port selection.

Tries to auto map all unconnected ports to the ports of one component prototype
scriptTask("autoMapUnconnectedToComponentPrototype", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
       def mappedConnectors =
                selectComponentPorts {
                   unconnected() // select all unconnected ports
                 } autoMapTo {
                   selectTargetPorts {
                       component "App1" // and auto-map them to all ports of component "App1"
                   }
                 }
        scriptLogger.info("Created {0} mappings.",mappedConnectors.size())
      }
    }
  }
}

+++

+++evaluateMatches(IMultiAutoMappingEvaluator) allows to evaluate and change the results of the auto-mapping. It corresponds to the confirm page of the component connection assistant.

For each source component port the provided lambda is called: Parameters are the source component port, the optional matched target component port (or null), and a list of all potential target component ports (respecting the selectTargetPorts(Action) predicates). The return value must be a list of target component ports.

Tries to auto-map all unconnected ports and evaluate matches
import com.vector.cfg.sysdesc.model.connector.SISourceComponentPort
import com.vector.cfg.sysdesc.model.connector.SITargetComponentPort

scriptTask("automapAllUnconnectedAndEvaluateMatches", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def mappedConnectors =
             selectComponentPorts {
               unconnected()
             } autoMapTo {
                evaluateMatches {
                    SISourceComponentPort sourcePort,
                    SITargetComponentPort optionalMatchedTargetPort,
                    List<SITargetComponentPort> potentialTargetPorts ->
                        if (sourcePort.getPortName().equals("MyExceptionalPort")) {
                            // example for excluding a port from auto-mapping by having a close look
                            // sourcePort.getMdfPort()....
                            return null
                        }
                        // default: do not change the auto-matched port
                        [optionalMatchedTargetPort]
                }
             }
        scriptLogger.info("Created {0} mappings.",mappedConnectors.size())
      }
    }
  }
}

Another example for using evaluate matches
import com.vector.cfg.sysdesc.model.connector.SISourceComponentPort
import com.vector.cfg.sysdesc.model.connector.SITargetComponentPort

scriptTask("anotherExampleForUsingEvaluateMatches", DV_PROJECT){
   code {
      transaction {
         domain.runtimeSystem {
            def mappedConnectors =
               selectComponentPorts {
               unconnected()
                    } autoMapTo {
                        evaluateMatches {
                            SISourceComponentPort sourcePort,
                            SITargetComponentPort optionalMatchedTargetPort,
                            List<SITargetComponentPort> potentialTargetPorts ->

                            // iterate over potential target ports to find the correct target

                            // like in java you can use a for loop
                            for (SITargetComponentPort targetCP : potentialTargetPorts) {
                                if (targetCP.getPortName().startsWith("MyPort_")) {
                                    return [targetCP]
                                }
                            }

                            // or you can use a stream
                            def myTargets = potentialTargetPorts.findAll {
                                it.getPortName().startsWith("OtherPort_")
                            }
                            return myTargets
                        }
                  }
             scriptLogger.info("Created {0} mappings.",mappedConnectors.size())
         }
       }
    }
 }

Auto-map a component port and realize 1:n connection by using evaluate matches
import com.vector.cfg.sysdesc.model.connector.SISourceComponentPort
import com.vector.cfg.sysdesc.model.connector.SITargetComponentPort

scriptTask("automap1ToN", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def mappedConnectors =
                 selectComponentPorts {
                   // select single delegation port
                   delegation()
                   name "rDelegationSRPort1"
                 } autoMapTo {
                    selectTargetPorts {
                       // select a collection of target ports (names start with "rSRPort")
                       name ~"rSRPort.*"
                    }
                    evaluateMatches {
                         SISourceComponentPort sourcePort,
                         SITargetComponentPort optionalMatchedTargetPort,
                         List<SITargetComponentPort> potentialTargetPorts ->
                            // return all potentialTargetPorts for 1:n connections, not only the one matched best
                            potentialTargetPorts
                    }
                 }
        scriptLogger.info("Created {0} mappings.",mappedConnectors.size())
      }
    }
  }
}

+++

+++forceConnectionWhen1To1() allows to force a mapping even the usual auto-mapping rules will not match. Precondition is that the collections of source component ports and target component ports only contain one component port each. Otherwise no mapping is done.

Create mapping between two ports which names do not match.
scriptTask("autoMapTwoNonMatchingPorts", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def mappedConnectors =
                 selectComponentPorts {
                   // select a single source component port
                   name "prNVPort1"
                   component "NvApp1"
                 } autoMapTo {
                   selectTargetPorts {
                       // select a single target component port
                       name "rSRPort2"
                       component "App2"
                   }
                   // force the connection even names do not match at all
                   forceConnectionWhen1To1()
                 }
        scriptLogger.info("Created {0} mappings.",mappedConnectors.size())
      }
    }
  }
}

+++

+++

+++

+++useOriginContextForMatch() uses another algorithm to match the component ports.
The standard algorithm matches only the names of the ports (delegation port of flat extract or port of a SWC of the flat extract).
This option uses also the origin context's name for the name matching.

Incomplete Connections:
Below we will talk about complete and incomplete connections. A connection is complete if the port of a SWC is connected to another SWC port or to a delegation port of the top level ECU composition. A connection is incomplete if a SWC port is connected to a delegation port of a composition which is not the top level ECU composition and the connection stops at this port (the delegation port is unconnected on the other side).

Origin Context:
Origin contexts of an inner port are delegation ports of the structured extract which are connected to this port and are the outermost ports of an incomplete connection. Delegation ports of the flat extract cannot have any origin contexts.

Example:
We want to map the port 'pData' of 'App1' of the flat extract. The corresponding component in the structured extract is instantiated inside the composition 'Comp1'. 'pData' is connected to the port 'pOriginContext' of 'Comp1'. 'pOriginContext' has no further ports connected to it.
When not using useOriginContextForMatch() option, only 'pData' would be used for the port name matching.
When using the useOriginContextForMatch() option, not only (but also) the name 'pData' is used for the port name matching, but also the origin context 'pOriginContext'.

Use the origin context for the port name matching
scriptTask("mapUsingOriginContext", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def createdConnections = selectComponentPorts {
            component("App1OriginContextMatch")
            name("A")
        } autoMapTo {
            // this option will not only match the name of the port 'A'
            // but also the delegation ports' names of incomplete connections of the structured extract
            useOriginContextForMatch()
        }

        scriptLogger.info("Created '{0}' connections.", createdConnections.size())
     }
    }
  }
}

Diagnostic Connections

+++

+++

For diagnostic connections (previously created by RTE59002 solving actions) a special mode can be used while selecting the source component port.

diagnosticConnection() narrows down selection to component ports which are derived from diagnostic mappings. See IComponentPortSelector.hasDiagnosticConnection() for more details.

diagnosticConnection() cannot be combined with and(Runnable),
or(Runnable) and not(Runnable).
If possible always prefer using diagnosticConnection() over hasDiagnosticConnection() which can be also combined with not(Runnable), and(Runnable) and or(Runnable) due to performance reasons.

This mode has the similar behavior as the diagnostic connections mode in the component connection assistant. It also creates potential missing port interface mappings.

The enum EDiagnosticPortRole allows to filter ports for the different uses cases:

+++

+++The EDiagnosticPortRole can be used to determine the role of a port when connecting diagnostic ports which depends on the used service needs.

Connects diagnostic ports of App1 based on diagnostic mappings
scriptTask("connectDiagPorts", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
       def mappedConnectors =
                selectComponentPorts {
                   // activate diagnostic connection mode
                   // this mode shall not be part of a or{...}, and{...} or not{...} closure
                   // hasDiagnosticConnection can be used instead if required, but is very expensive in terms of performance
                   diagnosticConnection()
                   // further predicates can also be specified here if required
                 } autoMapTo {
                   selectTargetPorts {
                       component "App1" // narrow down selection of target ports if necessary
                   }
                 }
        scriptLogger.info("Created {0} mappings.", mappedConnectors.size())
      }
    }
  }
}

Connects diagnostic ports based on diagnostic mappings, excludes Nv Ports
scriptTask("connectDiagPortsWithoutNvPorts", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
       def mappedConnectors =
                selectComponentPorts {
                   diagnosticConnection()
                   not {
                       nvData() // exclude nv ports
                   }
                 } autoMapTo {
                 }
        scriptLogger.info("Created {0} mappings. Excluded Nv Ports.", mappedConnectors.size())
      }
    }
  }
}

Connects IOControl ports
import com.vector.cfg.sysdesc.model.port.EDiagnosticPortRole

scriptTask("connectDiagPortsIOControl", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
       def mappedConnectors =
                selectComponentPorts {
                   diagnosticConnection()
                   diagnosticPortRole(EDiagnosticPortRole.IO_CONTROL)
                 } autoMap()
        scriptLogger.info("Created {0} mappings for IOControl ports.", mappedConnectors.size())
      }
    }
  }
}

Simple API for connection between ports

+++

+++ This API covers the use case when the names of the components and ports which should be connected are known, but the naming rules are too specific or if you just want to increase the level of control by giving exactly the pairs that should be mapped into the API. There is one method for connecting exactly one component port to another and one API for doing multiple connections at once requiring a list of source and a list of target ports.

+++

+++componentPort(String, String) allows to select an SIComponentPort and to do further operations on it, e.g. connecting the port to another port.

+++

+++ISelectedComponentPort represents a selection of exactly one SIComponentPort and provides further actions on it.

+++

+++

connectTo(String, String, Optional) creates an SIConnector between the SIComponentPort which is represented by this ISelectedComponentPort and the SIComponentPort which is retrieved by the given component and port name. It is possible to connect the component port to a delegation port by using 'COMPOSITIONTYPE' as componentName.

The connectTo(String, String, Optional) returns only one connector, even when the created connection involves a connection chain instead. Use connectToWithFullConnectorChain(String, String, Optional) instead for getting the complete connection chain.

The API provides only the very basic checks.

  • +++

    +++Direction of the ports is checked. E.g. it is not allowed to connect two PPorts within an AssemblySwConnector.

  • +++

    +++Connecting incompatible types of port interfaces is not allowed. E.g. it is not allowed to connect a mode switch with a sender receiver port.

  • +++

    +++Connecting two delegation ports is not allowed.

  • +++

    +++The port interface mapping has to reference the port interfaces of the selected component ports.

  • +++

    +++ Connecting a terminated port is not allowed. Please remove the port terminator first. Use ISelectedComponentPort.removePortTerminator().

  • +++

    +++ Creating redundant connections is not allowed. The ports cannot be connected by a second connector.

If you want to use some internal rules other than name matching to connect ports you can apply this rules to sort a list of source and another list of target ports and then use the simple API below that connects two lists of ports via index.

+++

+++

+++

+++connectTo(List) creates SIConnectors between the SIComponentPorts which are represented by this ISelectedComponentPorts with the given targetPorts. The ports are connected using the index. The first port of this ISelectedComponentPorts will be connected to the first target port, the second to the second target port and so on.
In case you want to ignore already connected port pairs please use assureConnectedTo(List).
If you want to connect ports using name matching please use IRuntimeSystemApi.selectComponentPorts(Action).

+++

+++assureConnectedTo(List) checks whether the SIComponentPorts represented by this ISelectedComponentPorts are already connected to the given targetPorts matching them via index. In contrast to connectTo(List) this method does nothing if the ports are already connected. If the ports are not connected a new connector will be created.

Examples

Example how to create a simple assembly connection
import java.util.Optional

scriptTask ("assemblyConnectionExample", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {

                // enter component and port name of a component port and the component port to connect it to
                // optionally you can add a port interface mapping
                def createdConnector = componentPort("App1", "pDataSend").connectTo("App2", "rSRPort2", Optional.empty())

                scriptLogger.info("Created a connection between '{0}' and '{1}'.",
                createdConnector.getProviderPort().getName(),
                createdConnector.getRequesterPort().getName())
            }
        }
    }
}

Example how to create a simple delegation connection
import java.util.Optional

scriptTask ("delegationConnectionExample", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                // to select a delegation port the name of the ECU Composition is used as component name
                def createdConnector = componentPort("COMPOSITIONTYPE", "rDelegationSRPort1").connectTo("App2", "rSRPort2", Optional.empty())

                // the provided and required port getter work also for delegation connections
                // you can find more info in the java doc of IConnector
                scriptLogger.info("Created a connection between '{0}' and '{1}'.",
                createdConnector.getProviderPort().getName(),
                createdConnector.getRequesterPort().getName())
            }
        }
    }
}

Create connector with port interface mapping
import java.util.Optional

scriptTask ("delegationConnectionExample", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                def portInterfaceMappingPath = "/ComponentTypes/DataTypeMappingSets/PortInterfaceMappingSet1/Mapping1"

                // to add a port interface mapping to the connection, use an optional with the AUTOSAR path to the port interface mapping
                def createdConnector = componentPort("COMPOSITIONTYPE", "pDelegationSRPort2").connectTo("App1", "pSRPort1", Optional.of(portInterfaceMappingPath))

                scriptLogger.info("Created a connection between '{0}' and '{1}'.",
                createdConnector.getProviderPort().getName(),
                createdConnector.getRequesterPort().getName())
            }
        }
    }
}

Connect ports using simple API
import com.vector.cfg.sysdesc.model.connector.SIConnector
import com.vector.cfg.sysdesc.model.component.SIComponentPort

scriptTask("UseSimpleAPIToCreateMultipleConnections", DV_PROJECT) {
    code {
        transaction {
            domain.runtimeSystem {
                // in this example we know for each port the target port (for example stored in some external file)
                // and we know that the names of source and target ports do not always match
                // so we use the simple API instead of the auto mapping
                List<String> sourcePortNames = ["App1.pDataSend",
                        "App1.pNvPort1",
                        "App1.pCSPort1"]
                List<String> targetPortNames = ["ECU Composition.pDelegationSRPort2",
                        "App2.rNVPort1",
                        "App3.rOtherPort1CS"]

                // retrieve the component ports for the names
                List<SIComponentPort> sourcePorts = new ArrayList<SIComponentPort>(selectComponentPorts {
                    componentPortNames(sourcePortNames)
                }.getComponentPorts())

                // since our used predicate does not guarantee any order, we have to sort our ports to assure they are in correct order
                // because the connections below will be created matching index of source and target ports
                sourcePorts.sort{a,b -> sourcePortNames.indexOf(a.getName()) <=> sourcePortNames.indexOf(b.getName())}

                // do the same for the target ports
                List<SIComponentPort> targetPorts = new ArrayList<SIComponentPort>(selectComponentPorts {
                    componentPortNames(targetPortNames)
                }.getComponentPorts())

                targetPorts.sort{a,b -> targetPortNames.indexOf(a.getName()) <=> targetPortNames.indexOf(b.getName())}

                // we just want to make sure that the ports are connected
                // so we use assureConnectedTo(...) instead of connectTo(...)
                // in other words we do not care, which ports are already connected
                List<SIConnector> newConnectors = componentPorts(sourcePorts).assureConnectedTo(targetPorts)

                // finally do some reporting for the port pairs that were unconnected
                for (SIConnector connector in newConnectors) {
                    scriptLogger.info("Connected {0} to {1}.",
                            connector.getProviderPort().getName(),
                            connector.getRequesterPort().getName())
                }
            }
        }
    }
}

Disconnect (unmap) Component Ports

+++

+++ The previous chapter was about connecting component ports. Now we want to have a look how to remove such connections again. We call it unmapping component ports.
This can be done using the component port selection API (see +++ComponentPortSelection+++) and calling a method to unmap the selected ports from other ports. It is possible to filter and evaluate the targets, so that you can have the control also for 1:n or n:m connected ports.

Unmapping Component Ports

The use case of unmapping component ports is based on the selection of component ports. The targets are the ports which are connected to the selected port.

+++

+++unmap() unmaps the selected component ports of this selection from ALL connected ports. In case that not all connections shall be removed the targets can be narrowed down using unmapFrom(Action).

Examples for unmap ()

Remove Connectors between Component Ports
import com.vector.cfg.dom.runtimesys.pai.api.IUnmappedPortsResult

scriptTask("unmapComponentPorts", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def unmappedPorts =
                selectComponentPorts {
                  // select the component ports to be unmapped
                  connected()
                  componentPortName("App1.pDataSend")
                } unmap()

        // the simple 'unmap()' removes all connectors connecting the selected component ports to any other ports

        // now print info of for the component ports that were unmapped from each other
        // the data structure is a pair representing the source and the target port which were unmapped
        for (final IUnmappedPortsResult unmappedPortPair : unmappedPorts) {
            scriptLogger.info("Removed connector between {0} -> {1}.",
                    unmappedPortPair.getSourcePort().getName(),
                    unmappedPortPair.getTargetPort().getName())
        }
      }
    }
  }
}

Control unmapping in unmapFrom (Closure)

+++

+++selectTargetPorts(Action) allows to define predicates to narrow down the target ports which shall be disconnected from the in previous step selected ports.

+++

+++evaluateMatches(IUnmappingEvaluator) allows to evaluate and change the results of the unmapped component ports.

For each selected component port the provided lambda is called: Parameters are the current handled component port and a list of all connected target component ports (respecting the selectTargetPorts(Action) predicates). The return value must be a list of component ports which are connected to the current handled source port.

Remove Connectors between Component Ports Filtering Targets
import com.vector.cfg.dom.runtimesys.pai.api.IUnmappedPortsResult
import com.vector.cfg.sysdesc.model.component.SIComponentPort

scriptTask("unmapComponentPorts", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def unmappedPorts =
                selectComponentPorts {
                  // select the component ports to be unmapped
                  connected()
                  componentPortName("App1OriginContextMatch.CompletedOriginPortTest")
                } unmapFrom {
                  // the connected (or target) ports can be filtered in this closure
                  selectTargetPorts {
                    componentPortNames(["App1.ConnectedToCompletedOriginTest",
                        "App1_1.ConnectedToCompletedOriginTest"])
                  }

                  // additionally the target matches to be unmapped can be evaluated
                  // the 'targetPorts' below are all ports connected to the 'sourcePort' considering the 'selectTargetPorts' call above
                  evaluateMatches { SIComponentPort sourcePort, List<SIComponentPort> targetPorts ->
                    // in our example we want to unmap the source ports only from ports of the component 'App1_1'
                    targetPorts.each {
                        if (it.getComponent().getName().equals("App1_1")) {
                            return [it]
                        }
                    }
                  }
                }

        // print info for newly unmapped ports
        for (final IUnmappedPortsResult unmappedPortPair : unmappedPorts) {
            scriptLogger.info("Removed connector between {0} -> {1}.",
                    unmappedPortPair.getSourcePort().getName(),
                    unmappedPortPair.getTargetPort().getName())
        }
      }
    }
  }
}

Terminating Component Ports

+++

+++ Port terminators can be used to acknowledge the fact, that the port is not connected yet. This will prevent validation rules to produce validation results reporting these ports as unconnected or missing data mappings for these ports. It also allows you to filter such ports very easily using the according predicates of the selection APIs.

Starting point is the component port selection (see +++ComponentPortSelection+++).

terminate() terminates all selected SIComponentPorts. If one of the selected ports is already terminated or connected to another component port, the port will be ignored.

The termination of component ports disables the validation of these ports. In other words, these ports are acknowledged as not connected yet. This should give a better overview of the open ports, which still have to be connected or need a data mapping.

removePortTerminators() removes the port terminators of all selected component ports. If one of the selected component ports is not terminated the method will ignore that port.

See terminate() for more information about the purpose of terminating ports.

It is also possible to create and remove port terminators via the simple API starting with the selection of one component port (componentPort (String, String)).

terminate() simple API to terminate the selected SIComponentPort if it is not already terminated or connected to another component port. You can use SIComponentPort.isTerminated() to check if a port is terminated and SIComponentPort.isConnected() if a port is connected to other ports.

The termination of component ports disables the validation of these ports. In other words, these ports are acknowledged as not connected yet. This should give a better overview of the open ports, which still have to be connected or need a data mapping.

removePortTerminator() simple API to remove the port terminator of the selected component port.

See terminate() for more information about the purpose of terminating ports.

Examples

Terminate port using the component port selection API
import com.vector.cfg.sysdesc.model.component.SIComponentPort

scriptTask("terminatePort", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        // the statements below will return us a collection with all component ports which will be terminated
        def terminatedPorts =
             selectComponentPorts {
                delegation()
                name("pDelegationCSPort1")

             // use terminate() to terminate all selected component ports
             // if a selected port is already terminated or connected, it will not be terminated (again)
             } terminate()

        // this result may contain less ports than the actual selected ports,
        // if some of the selected ports were connected or terminated
        for (final SIComponentPort terminatedPort : terminatedPorts) {
            scriptLogger.info("Terminated component port '{0}'.", terminatedPort.getName())
        }
      }
    }
  }
}

Remove port terminator using the component port selection API
import com.vector.cfg.sysdesc.model.component.SIComponentPort

scriptTask("removePortTerminator", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        // the statements below will return us a collection with all component ports for which a port terminator was removed
        def removedPortTerminators =
             selectComponentPorts {
                // filter for all terminated delegation ports
                delegation()
                // there are predicates to filter for terminated() and notTerminated() ports
                terminated()

             // if a port is not terminated it will be skipped
             } removePortTerminators()

        // the result may contain less component ports than the selection,
        // if some of the ports were not terminated
        for (final SIComponentPort componentPort : removedPortTerminators) {
            scriptLogger.info("Removed port terminator of component port '{0}'.", componentPort.getName())
        }
      }
    }
  }
}

Create a port terminator using the simple API
scriptTask("createPortTerminator", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        // select the component port via the simple API and call terminate()
        // this API is more strict and throws an exception if the selected port cannot be terminated
        def terminatedPort = componentPort("COMPOSITIONTYPE", "rDelegationSRPort1").terminate()

        scriptLogger.info("Terminated component port '{0}'.", terminatedPort.getName())
      }
    }
  }
}

Remove a port terminator using the simple API
scriptTask("removePortTerminator", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        // select the component port via the simple API and call terminate()
        // this API is more strict and throws an exception if the selected port has no port terminator to remove
        def removedTerminatorPort = componentPort("App1_1", "pSRPort1").removePortTerminator()

        scriptLogger.info("Terminated component port '{0}'.", removedTerminatorPort.getName())
      }
    }
  }
}

Terminating Component Ports of Communication Elements

+++

+++ As already mentioned above port terminators can be used to acknowledge the fact, that the port is not connected yet. It is possible to terminate owner ports of communication elements using the communication element selection.

terminateOwnerPorts() terminates the SIComponentPorts of all selected SICommunicationElements. If one of the selected ports is already terminated or connected to another component port, the port will be ignored.

The termination of component ports disables the validation of these ports. In other words, these ports are acknowledged as not connected yet. This should give a better overview of the open ports, which still have to be connected or need a data mapping.

removePortTerminatorsForOwnerPorts() removes the port terminators of the SIComponentPorts of all selected SICommunicationElements.

See terminateOwnerPorts() for more information about the purpose of terminating ports.

Examples

Terminate port using the communication element selection API
import com.vector.cfg.sysdesc.model.component.SIComponentPort

scriptTask("terminatePort", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        // the the statements below will return us a collection with all component ports which will be terminated
        def terminatedPorts =
             selectCommunicationElements {
                // also for the communication elements there are predicates to filter for terminated owner ports
                ownerPortNotTerminated()
                port("pSRPort1")

             // this call will terminate the component port owner of each selected communication element
             } terminateOwnerPorts()

        // if multiple communication elements has the same component port owner
        // the component port will be terminated and returned only once
        for (final SIComponentPort terminatedPort : terminatedPorts) {
            scriptLogger.info("Terminated component port '{0}'.", terminatedPort.getName())
        }
      }
    }
  }
}

Remove port terminator using the communication element selection API
import com.vector.cfg.sysdesc.model.component.SIComponentPort

scriptTask("removePortTerminator", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        // the statements below will return us a collection with all component ports for which a port terminator was removed
        def removedPortTerminators =
             selectCommunicationElements {
                component("App1_1")
                port("pSRPort1")

             // if a port is not terminated it will be skipped
             } removePortTerminatorsForOwnerPorts()

        for (final SIComponentPort componentPort : removedPortTerminators) {
            scriptLogger.info("Removed port terminator of component port '{0}'.", componentPort.getName())
        }
      }
    }
  }
}

Data Mapping

The data mapping use case allows to connect signal instances and data elements / operations / triggers. We will introduce two ways for that.
The first one will be using a selection API allowing to define predicates to filter communication elements/signals for the data mapping and calling a method to filter the target signals/communication elements. This is the way to map communication elements to system signals in a way like the data mapping assistant from the GUI. See +++CommunicationElementSelection+++ and +++SignalInstanceSelection+++ for the selection starting points.
The second way is to use a simple API that requires already prepared data structures e.g. a list of communication elements and a list of signal instances. To initially find the appropriate communication elements and signals you can use the common selection APIs.

Mapping signal instances

The use case of auto-mapping signal instances is based on the selection of signal instances.

+++

+++autoMap() tries to auto-map the selection of SIAbstractSignalInstances (SISignalInstance or SISignalGroupInstance) according the data mapping assistant default rules. Therefore the selection of possible target communication elements is computed and tried to match to the selected signal instances.

Examples for autoMap ()

Auto data map all unmapped signal instances
scriptTask("autoDatamapAllUnmappedSignalInstances", DV_PROJECT){
    code {
        transaction {
            domain.runtimeSystem {
                def dataMappings =
                             selectSignalInstances {
                               unmapped()
                             } autoMap()
                scriptLogger.info("Created {0} data mappings.",dataMappings.size())
            }
        }
    }
}

+++

+++autoMapTo(Action) tries to auto-map the selection of signal instances according the data mapping assistant rules but offers more control for the auto-mapping: Inside the lambda additional predicates for narrowing down the target communication elements can be defined and code to evaluate and change the auto-mapper results can be provided.

autoMapTo(Action) will produce trace, info and warning logs. To see them, activate the 'com.vector.cfg.dom.runtimesys.pai.api.ISignalInstanceSelection' logger with the appropriate log level.

Control the auto-mapping in autoMapTo (Closure)

+++

+++ selectTargetCommunicationElements(Action) allows to define predicates to narrow down the target communciation elements for the auto-mapping. The predicates are used to filter the possible target communication elements which were computed from the signal instance selection.

+++

+++evaluateMatches(IAutoMappingEvaluator) allows to evaluate and change the results of the auto-mapping. It corresponds to the confirm page of the data mapping assistant.

For each signal instance the provided lambda is called: Parameters are the signal instance, the optional matched target communication element (or null), and a list of all potential target communication elements (respecting the selectTargetCommunicationElements(Action) predicates). The return value must be a communication element or null.

Auto data map all unmapped signal instances to unmapped communication elements and evaluate
import com.vector.cfg.sysdesc.model.communication.instance.SIAbstractSignalInstance
import com.vector.cfg.sysdesc.model.communication.SICommunicationElement

scriptTask("autoDatamapAllUnmappedSignalInstancesAndEvaluate", DV_PROJECT){
    code {
        transaction {
            domain.runtimeSystem {
                def dataMappings =
                     selectSignalInstances {
                       unmapped()
                     } autoMapTo {
                          selectTargetCommunicationElements {
                               unmapped()
                          }
                          evaluateMatches {
                             SIAbstractSignalInstance signal,
                             SICommunicationElement optionalMatchedComElement,
                             List<SICommunicationElement>  potentialComElements ->
                                  // evaluate
                                  optionalMatchedComElement
                          }
                     }
                scriptLogger.info("Created {0} data mappings.",dataMappings.size())
            }
        }
    }
}

Nested Array of Primitives

+++
+++ expandNestedArraysOfPrimitive(boolean) allows to control the expansion of nested arrays of primitive globally. Per default, arrays are fully expanded (allowing to data map each array element). By setting the value to 'false', all nested arrays of primitive are not expanded and can be directly data-mapped to a signal.

Auto data map all signal instances and do not expand nested array elements
 import com.vector.cfg.sysdesc.model.communication.instance.SIAbstractSignalInstance
 import com.vector.cfg.sysdesc.model.communication.SICommunicationElement

scriptTask("autoDatamapAllSignalInstancesAndDoNotExpandNestedArrayElements", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def dataMappings =
           selectSignalInstances {
           } autoMapTo {
              // do not expand nested array elements
              expandNestedArraysOfPrimitive false
              evaluateMatches {
               SIAbstractSignalInstance signal,
               SICommunicationElement optionalMatchedComElement,
               List<SICommunicationElement>  potentialComElements ->
                 // perform manual mapping to a signal group
                 if (signal.getName().equals("elemB_c255f5e38fd8b21d")) {
                  for (final SICommunicationElement comElement : potentialComElements) {
                    if (comElement.getFullyQualifiedName().equals("App2.rSRPort1.Element_2")) {
                      return comElement
                    }
                  }
                }
                // now check: for the group signal the the record element representing an array is not expanded
                if (signal.getName().equals("fieldA_f1d3783e235e88d3")) {
                  // group signal
                  for (final SICommunicationElement comElement : potentialComElements) {
                    if (comElement.getFullyQualifiedName().equals("App2.rSRPort1.Element_2.RecordElement")) {
                      // do some direct mapping here
                    }
                  }
                }
                optionalMatchedComElement
              }
           }
        scriptLogger.info("Created {0} data mappings.",dataMappings.size())
      }
    }
  }
}

expandNestedArraysOfPrimitive(String,boolean) allows to control the expansion of nested arrays of primitive for single nested arrays. Per default, the expandNestedArraysOfPrimitive(boolean) applies. For the given fully qualified communication element name, the global setting can be overridden.

Auto data map all signal instances and expand specific nested array element
 import com.vector.cfg.sysdesc.model.communication.instance.SIAbstractSignalInstance
 import com.vector.cfg.sysdesc.model.communication.SICommunicationElement

scriptTask("autoDatamapAllSignalInstancesAndDoExpandSpecificNestedArrayElement", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def dataMappings =
           selectSignalInstances {
           } autoMapTo {
              // do not expand nested array elements
              expandNestedArraysOfPrimitive false
              expandNestedArraysOfPrimitive( "App2.rSRPort1.Element_2.RecordElement",true)
              evaluateMatches {
               SIAbstractSignalInstance signal,
               SICommunicationElement optionalMatchedComElement,
               List<SICommunicationElement>  potentialComElements ->
                 // perform manual mapping to a signal group
                 if (signal.getName().equals("elemB_c255f5e38fd8b21d")) {
                  for (final SICommunicationElement comElement : potentialComElements) {
                    if (comElement.getFullyQualifiedName().equals("App2.rSRPort1.Element_2")) {
                      return comElement
                    }
                  }
                }
                // now check: for the group signal the the record element representing an array is expanded:
                // the single array elements can be mapped
                if (signal.getName().equals("fieldA_f1d3783e235e88d3")) {
                  // group signal
                  for (final SICommunicationElement comElement : potentialComElements) {
                    if (comElement.getFullyQualifiedName().equals("App2.rSRPort1.Element_2.RecordElement[0]")) {
                      // do some direct mapping to array element here
                    }
                  }
                }
                optionalMatchedComElement
              }
           }
        scriptLogger.info("Created {0} data mappings.",dataMappings.size())
      }
    }
  }
}

+++

+++evaluateMatchesWithCompatibility(IAutoMappingEvaluatorWithCompatibility) allows to evaluate and change the results of the auto-mapping. It corresponds to the confirm page of the data mapping assistant. In contrast to evaluateMatches(IAutoMappingEvaluator) this method also provides the compatibility of the optional match.

For each signal instance the provided lambda is called: Parameters are the signal instance, the optional matched target communication element (or null), their compatibility and a list of all potential target communication elements (respecting the selectTargetCommunicationElements(Action) predicates). The return value must be a communication element or null.

+++

+++

Evaluate matched communication elements using compatibility
import com.vector.cfg.sysdesc.model.communication.ECompatibility
import com.vector.cfg.sysdesc.model.communication.instance.SIAbstractSignalInstance
import com.vector.cfg.sysdesc.model.communication.SICommunicationElement
import com.vector.cfg.sysdesc.model.datamapping.SIDataMapping

scriptTask("evaluateCommunicationElementsByCompatibility", DV_PROJECT) {
    code {
        transaction {
            domain.runtimeSystem {

                // in this example we want to accept full matches for data mapping
                // and apply some custom rules for non-full matches

                List<SIDataMapping> createdMappings = selectSignalInstances {
                    unmapped()
                } autoMapTo {
                    evaluateMatchesWithCompatibility {
                        SIAbstractSignalInstance signal,
                        SICommunicationElement optionalMatchedCommunicationElement,
                        ECompatibility compatibility,
                        List<SICommunicationElement> potentialComElements ->

                        if (compatibility == ECompatibility.FULL) {
                            return optionalMatchedCommunicationElement
                        }
                        // for non-full matches we return the first potential match if present
                        if (potentialComElements.size() > 0) {
                            return potentialComElements.get(0)
                        }
                        return null
                    }
                }

                scriptLogger.info("Created {0} data mappings.", createdMappings.size())
            }
        }
    }
}

+++

+++confirmByCompatibility(IAutoMappingConfirmation) allows to evaluate the mappings which should be created.

For each signal instance the provided lambda is called: Parameters are the signal instance, the optional matched target communication element (or null) and the compatibility of them (ECompatibility.NULL if no optional match present) respecting all previous evaluations. So this is the final verifying step to confirm or reject the mapping. The return value must be true if the mapping should be created or false if you want to reject the mapping.

+++

+++

Decide which mappings should be created by compatibility
import com.vector.cfg.sysdesc.model.communication.ECompatibility
import com.vector.cfg.sysdesc.model.communication.instance.SIAbstractSignalInstance
import com.vector.cfg.sysdesc.model.communication.SICommunicationElement
import com.vector.cfg.sysdesc.model.datamapping.SIDataMapping

scriptTask("confirmMappingToComElementByCompatibility", DV_PROJECT) {
    code {
        transaction {
            domain.runtimeSystem {

                // in this example we want only to accept data mappings with a full match
                // and report all other

                List<SIDataMapping> createdMappings = selectSignalInstances {
                    unmapped()
                } autoMapTo {
                    confirmByCompatibility {
                        SIAbstractSignalInstance signal,
                        SICommunicationElement optionalMatchedCommunicationElement,
                        ECompatibility compatibility ->

                        if (compatibility == ECompatibility.FULL) {
                             // accept full match
                            return true
                        }

                        if (optionalMatchedCommunicationElement != null) {
                            // report non-full matches
                            scriptLogger.info("Compatibility {0} between signal {1} and communication element {2}.",
                                compatibility,
                                signal.getName(),
                                optionalMatchedCommunicationElement.getFullyQualifiedName())
                        } else {
                            // report signals for which the auto mapper could not find a match
                            scriptLogger.info("No match for signal {0}.",
                                signal.getName())
                        }
                        return false
                    }
                }

                scriptLogger.info("Created {0} data mappings.", createdMappings.size())
            }
        }
    }
}

Mapping communication elements

+++

+++autoMap() tries to auto-map the selection of SICommunicationElements (SIDataCommunicationElement or SIOperationCommunicationElement) according the data mapping assistant default rules. Therefore the selection of possible target signal instances is computed and tried to match to the selected communication elements. You do not have to expand the communication elements in the previous selection step. They will be expanded after the root is mapped automatically as you know from the data mapping assistant.

Examples for autoMap ()

Auto data map all unmapped sender/receiver delegation port communication elements
scriptTask("autoDatamapAllUnmappedSRDelPortComElements", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def dataMappings =
                 selectCommunicationElements {
                   // select all unmapped sender/receiver delegation ports
                   delegation()
                   unmapped()
                   senderReceiver()
                 } autoMap()
        scriptLogger.info("Created {0} data mappings.",dataMappings.size())
      }
    }
  }
}

+++

+++autoMapTo(Action) tries to auto-map the selection of communication elements according the data mapping assistant rules but offers more control for the auto-mapping: Inside the lambda additional predicates for narrowing down the target signal instances can be defined and code to evaluate and change the auto-mapper results can be provided. You do not have to expand the communication elements in the previous selection step. They will be expanded after the root is mapped automatically as you know from the data mapping assistant.

autoMapTo(Action) will produce trace, info and warning logs. To see them, activate the

'com.vector.cfg.dom.runtimesys.pai.api.ICommunicationElementSelection'

logger with the appropriate log level.

Control the auto-mapping in autoMapTo (Closure)

+++

+++selectTargetSignalInstances(Action) allows to define predicates to narrow down the target signal instances for the auto-mapping. The predicates are used to filter the possible target signal instances which were computed from the communication element selection.

+++

+++evaluateMatches(IAutoMappingEvaluator) allows to evaluate and change the results of the auto-mapping. It corresponds to the confirm page of the data mapping assistant.

For each communication element the provided lambda is called: Parameters are the communication element, the optional matched target signal instance (or null), and a list of all potential target signal instances (respecting the selectTargetSignalInstances(Action) predicates). The return value must be a signal instance or null.

Auto data map all unmapped communication elements to unmapped rx signal instances and evaluate
import com.vector.cfg.sysdesc.model.communication.instance.SIAbstractSignalInstance
import com.vector.cfg.sysdesc.model.communication.SICommunicationElement

scriptTask("autoDatamapAllUnmappedComElementsAndEvaluate", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def dataMappings =
             selectCommunicationElements {
               unmapped() // only unmapped communication elements
             } autoMapTo {
                  selectTargetSignalInstances {
                       // only map to unmapped rx signal instances
                       unmapped()
                       rx()
                  }

                  // we selected only the root communication elements, but for performing the data mapping the complex data elements are expanded
                  // this is a behavior which you can also notice in the data mapping assistant in the GUI
                  // that means the evaluateMatches method will also offer child communication elements and the corresponding matched group signals
                  evaluateMatches {
                     SICommunicationElement  communicationElement,
                     SIAbstractSignalInstance optionalMatchedSignalInstance,
                     List<SIAbstractSignalInstance>  potentialSignalinstances ->
                          // evaluate the match here
                          if (optionalMatchedSignalInstance != null) {
                                def mdfSystemSignal = optionalMatchedSignalInstance.getMdfObject()
                                // check more specific ...
                          }
                          optionalMatchedSignalInstance
                  }
             }
        scriptLogger.info("Created {0} data mappings.", dataMappings.size())
      }
    }
  }
}

Nested Array of Primitives

+++
+++ expandNestedArraysOfPrimitive(boolean) allows to control the expansion of nested arrays of primitive globally. Per default, arrays are fully expanded (allowing to data map each array element). By setting the value to 'false', all nested arrays of primitive are not expanded and can be directly data-mapped to a signal.

Autodatamap and do not expand nested array elements
import com.vector.cfg.sysdesc.model.communication.instance.SIAbstractSignalInstance
import com.vector.cfg.sysdesc.model.communication.SICommunicationElement
import com.vector.cfg.sysdesc.model.communication.instance.SISignalGroupInstance

scriptTask("autoDatamapDoNotExpandNestedArrayElements", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def dataMappings =
         selectCommunicationElements {
         } autoMapTo {
             expandNestedArraysOfPrimitive false // do not expand nested arrays of primitive
             evaluateMatches {
                 SICommunicationElement  communicationElement,
                 SIAbstractSignalInstance optionalMatchedSignalInstance,
                 List<SIAbstractSignalInstance>  potentialSignalInstances ->
                    if ("App2.rSRPort1.Element_2".equals(communicationElement.getFullyQualifiedName())) {
                        // manual matching: map to first signal group
                        for (SIAbstractSignalInstance potentialSignal: potentialSignalInstances) {
                            if (potentialSignal instanceof SISignalGroupInstance) {
                                return potentialSignal
                            }
                        }
                    }
                    if ("App2.rSRPort1.Element_2.RecordElement".equals(communicationElement.getFullyQualifiedName())) {
                        // now the RecordElement which represents an array is directly offered to map
                        // ....
                    }
                    optionalMatchedSignalInstance
              }
         }
        scriptLogger.info("Created {0} data mappings.",dataMappings.size())
      }
    }
  }
}

expandNestedArraysOfPrimitive(String,boolean) allows to control the expansion of nested arrays of primitive for single nested arrays. Per default, the expandNestedArraysOfPrimitive(boolean) applies. For the given fully qualified communication element name, the global setting can be overridden.

The fully qualified communication element name is e.g. determinable when using the data mapping assistant, performing an arbitrary signal group mapping of the root data element, and using the right-mouse menu its 'Copy fully qualified name' action on the nested array element.

Autodatamap and do expand a specific nested array element
import com.vector.cfg.sysdesc.model.communication.instance.SIAbstractSignalInstance
import com.vector.cfg.sysdesc.model.communication.SICommunicationElement
import com.vector.cfg.sysdesc.model.communication.instance.SISignalGroupInstance

scriptTask("autoDatamapDoExpandSpecificNestedArrayElement", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def dataMappings =
             selectCommunicationElements {
             } autoMapTo {
                 // do not generally expand nested arrays of primitive
                 expandNestedArraysOfPrimitive false
                 // but expand the following specific record element
                 expandNestedArraysOfPrimitive("App2.rSRPort1.Element_2.RecordElement",true)
                 evaluateMatches {
                     SICommunicationElement  communicationElement,
                     SIAbstractSignalInstance optionalMatchedSignalInstance,
                     List<SIAbstractSignalInstance>  potentialSignalInstances ->
                        if ("App2.rSRPort1.Element_2".equals(communicationElement.getFullyQualifiedName())) {
                            // manual matching: map to first signal group
                            for (SIAbstractSignalInstance potentialSignal: potentialSignalInstances) {
                                if (potentialSignal instanceof SISignalGroupInstance) {
                                    return potentialSignal
                                }
                            }
                        }
                        if ("App2.rSRPort1.Element_2.RecordElement[0]".equals(communicationElement.getFullyQualifiedName())) {
                            // the RecordElement (representing an array of primitive)  is expanded to map the single array elements
                            // ....
                        }
                        optionalMatchedSignalInstance
                  }
             }
        scriptLogger.info("Created {0} data mappings.",dataMappings.size())
      }
    }
  }
}

+++

+++evaluateMatchesWithCompatibility(IAutoMappingEvaluatorWithCompatibility) allows to evaluate and change the results of the auto-mapping. In contrast to evaluateMatches(IAutoMappingEvaluator) this method also provides the compatibility of the optional match.

For each communication element the provided lambda is called: Parameters are the communication element, the optional matched target signal instance (or null), the compatibility of them and a list of all potential target signal instances (respecting the selectTargetSignalInstances(Action) predicates). The return value must be a signal instance or null.

Evaluate matched signal instances using compatibility
import com.vector.cfg.sysdesc.model.communication.ECompatibility
import com.vector.cfg.sysdesc.model.communication.instance.SIAbstractSignalInstance
import com.vector.cfg.sysdesc.model.communication.SICommunicationElement
import com.vector.cfg.sysdesc.model.datamapping.SIDataMapping

scriptTask("evaluateSignalsByCompatibility", DV_PROJECT) {
    code {
        transaction {
            domain.runtimeSystem {

                // in this example we want to accept full matches for data mapping
                // and apply some custom rules for non-full matches

                List<SIDataMapping> createdMappings = selectCommunicationElements {
                    unmapped()
                    senderReceiver()
                } autoMapTo {
                    evaluateMatchesWithCompatibility {
                        SICommunicationElement communicationElement,
                        SIAbstractSignalInstance optionalMatchedSignal,
                        ECompatibility compatibility,
                        List<SIAbstractSignalInstance> potentialSignals ->

                        if (compatibility == ECompatibility.FULL) {
                            return optionalMatchedSignal
                        }
                        // for non-full matches we return the first potential match if present
                        if (potentialSignals.size() > 0) {
                            return potentialSignals.get(0)
                        }
                        return null
                    }
                }

                scriptLogger.info("Created {0} data mappings.", createdMappings.size())
            }
        }
    }
}

+++

+++confirmByCompatibility(IAutoMappingConfirmation) allows to evaluate the mappings which should be created.

For each communication element the provided lambda is called: Parameters are the communication element, the optional matched target signal instance (or null) and the compatibility of them (ECompatibility.NULL if no optional match present) respecting all previous evaluations. So this is the final verifying step to confirm or reject the mapping. The return value must be true if the mapping should be created or false if you want to reject the mapping.

Decide which mappings should be created by compatibility
import com.vector.cfg.sysdesc.model.communication.ECompatibility
import com.vector.cfg.sysdesc.model.communication.instance.SIAbstractSignalInstance
import com.vector.cfg.sysdesc.model.communication.SICommunicationElement
import com.vector.cfg.sysdesc.model.datamapping.SIDataMapping

scriptTask("confirmMappingToSignalByCompatibility", DV_PROJECT) {
    code {
        transaction {
            domain.runtimeSystem {

                // in this example we want only to accept data mappings with a full match
                // and report all other


                List<SIDataMapping> createdMappings = selectCommunicationElements {
                    unmapped()
                    senderReceiver()
                } autoMapTo {
                    confirmByCompatibility {
                        SICommunicationElement communicationElement,
                        SIAbstractSignalInstance optionalMatchedSignal,
                        ECompatibility compatibility ->

                        if (compatibility == ECompatibility.FULL) {
                            return true
                        }
                        if (optionalMatchedSignal != null) {
                            // report non-full matches
                            scriptLogger.info("Compatibility {0} between signal {1} and communication element {2}.",
                                compatibility,
                                optionalMatchedSignal.getName(),
                                communicationElement.getFullyQualifiedName())
                        } else {
                            // report signals for which the auto mapper could not find a match
                            scriptLogger.info("No match for communication element {0}.",
                                communicationElement.getName())
                        }
                        return false
                    }
                }

                scriptLogger.info("Created {0} data mappings.", createdMappings.size())
            }
        }
    }
}

Compatibility Between Communication Elements and Signal Instances

+++

+++

+++

+++ECompatibility represents the compatibility between an SIAbstractSignalInstance and an SICommunicationElement for a potential or existing SIDataMapping. This enum helps to determine how good the elements are matching in terms of names and types and is available for example at the data mapping assistant or the data mapping automation API.

FULL

+++

+++For a FULL match the SIAbstractSignalInstance and the SICommunicationElement have to be compatible regarding their types (see TYPE_INCOMPATIBLE) and the name of the signal has to match either the owner port name of the communication element, the communication element name itself or a combination of the two. All names are normalized (e.g. removing some common signal group and group signal suffixes and convert capital to small letters) before performing the match.

FULL matches will be mapped automatically by the auto-mapper when not using further evaluation.

Examples:
Fully qualified SICommunicationElement names on the left mapped to fully qualified SIAbstractSignalInstance names on the right.

- 'MyPort.MyData' -> 'MyData': full match, signal and data element names are equal.
- 'MyData.DataElement' -> 'MyData': full match, signal and port names are equal.
- 'MyData_Record' -> 'MyData_SignalGroup': full match, the suffix is recognized as marker of signal group and marker of record without further meaning.
- 'ParkingBrake_Status' -> 'ParkingBrake_Position': no match, the suffixes are no obvious markers which can be ignored, compatibility NONE.
- 'MyPort.MyStructure.MyData1' -> 'MyStructure.MyData1': full match, group signal and record element have equal names.
- 'ParkingBrake.ParkingBrakeStatus' -> 'MyStatus1': no full match, compatibility NONE.
- 'ParkingBrake.ParkingBrakeStatus' -> 'BrakeStatus': no full match, but a PARTIAL_NAME match because signal name is contained in data element name.

PARTIAL_NAME

+++

+++For a PARTIAL_NAME match the SIAbstractSignalInstance and the SICommunicationElement have to be compatible regarding their types (see TYPE_INCOMPATIBLE). Additionally the name of the signal should be contained in the owner port name of the communication element or in the communication element name itself, but also vice versa, that means if the owner port name or the communication element name is contained in the signal name. All names are normalized (e.g. removing some common signal group and group signal suffixes and convert capital to small letters) before performing the match.

PARTIAL_NAME matches will be mapped automatically by the auto-mapper when not using further evaluation.

Examples:
Fully qualified SICommunicationElement names on the left mapped to fully qualified SIAbstractSignalInstance names on the right.
- 'ParkingBrake.BrakeStatus' -> 'ParkingBrakeStatus': partial name match, data element name is part of signal name.
- 'ParkingBrake.ParkingBrakeStatus' -> 'BrakeStatus': partial name match, signal name is part of data element name.
- 'SendBrakeStatus.ParkingBrake' -> 'Status': partial name match, signal name is part of port name.
- 'SendStatus.ParkingBrake' -> 'ParkingBrake_SendStatus': partial name match, port name is part of signal name.

TYPE_INCOMPATIBLE

+++

+++An SIAbstractSignalInstance is TYPE_INCOMPATIBLE to an SICommunicationElement if they match FULL or by PARTIAL_NAME and the values of dynamic length attribute of the signal and variable size of the communication element's data type do not match, but also if the signal is an SISignalGroupInstance and the communication element's data type uses variable size. Signals using data transformation are never TYPE_INCOMPATIBLE.

TYPE_INCOMPATIBLE matches will be mapped automatically by the auto-mapper when not using further evaluation.
Hint: At first it sounds strange that the auto-mapper accepts TYPE_INCOMPATIBLE matches. The reason is that the auto-mapper is strongly based on name matching and since the names match (as it is the case here), the auto-mapper will already do the mapping, but you have probably to correct some attributes at the signal or the data type which do not match some expectations of our validations.

STRUCTURE_INCOMPATIBLE

+++

+++Compatibility STRUCTURE_INCOMPATIBLE is only used for SISignalGroupInstances. It is used if the compatibility between the signal group and the root communication element is either FULL or PARTIAL_NAME and at the same time there is at least one communication element leaf for which neither a group signal that matches FULL nor by PARTIAL_NAME exist below the signal group.

Examples:
A signal group named 'MyComplexData' has the group signals 'SubData1' and 'OtherGroupSignal'. The communication element of port 'MyPort' to be matched is named 'MyComplexData' and is representing a record with the record elements 'SubData1' and 'OtherRecordElement'. So that the roots will match by names and types, but no match for the record element 'OtherRecordElement' does exist at the signal group, since group signal 'OtherGroupSignal' is not matching by name.
The auto-mapper will produce the following result for that:
MyPort.MyComplexData -> MyComplexData
MyPort.MyComplexData.SubData1 -> MyComplexData.SubData1
MyPort.MyComplexData.OtherRecordElement -> unmapped

STRUCTURE_INCOMPATIBLE matches will NOT be mapped automatically by the auto-mapper.

NONE

+++

+++Compatibility NONE is used in the following cases:

1. SIAbstractSignalInstance and SICommunicationElement names are neither matching FULL, nor by PARTIAL_NAME.
2. EDirections of SIAbstractSignalInstance and SICommunicationElement are incompatible.
3. If the SIAbstractSignalInstance does not use data transformation but the communication element is an SIOperationCommunicationElement.
4. The length of the signal is not 0 but the communication element is an SITriggerCommunicationElement.
5. The SIAbstractSignalInstance is not a signal group and does not use data transformation but the communication element represents a record, a union or an array of non-primitives.
6. If the SIAbstractSignalInstance is a group signal but the communication element is not a leaf of a complex SIDataCommunicationElement.
7. SIAbstractSignalInstance is a signal group but the communication element is neither representing a record nor an array.

NONE matches will NOT be mapped automatically by the auto-mapper.

NULL

+++

+++The compatibility NULL is only used in case the auto-mapper did not find any matching communication elements.

Simple API for data mapping

+++

+++ This API can be used when the names of the communication elements, which should be data mapped, are known, as well as the AUTOSAR paths to the system signal groups and system signals or if you want to use custom rules which you apply to sort the elements and want to map a list of communication elements and a list of signals via index which helps you to increase the level of control. Possible entry points are the selection of a communication element and potentially also its child communication elements by using the fully qualified names or using the communication and signal selections introduced above to select and later sort a list of communication elements and a list of signals. For complex data mappings there is a comfort function. If you define the root mapping only (e.g. mapping a record to a system signal group) the auto-mapper will try to match the children (e.g. record elements and group signals) by naming. This comfort function does not expand primitive arrays.

+++

+++communicationElement(String...) allows to select an SICommunicationElement and to do further operations on it, e.g. performing a data mapping. For complex communication elements also the children can be selected. In such case the first communicationElementName has to be the name of the root element.

+++

+++ISelectedCommunicationElement represents a selection of exactly one SICommunicationElement and provides further actions on it. For complex communication elements, also a subset of the child elements is represented.

+++

+++mapTo(String...) creates an SIDataMapping for the SICommunicationElement which is represented by this ISelectedCommunicationElement. The mapped signal is the given abstractSignalInstance.

In case of a complex mapping first the system signal group has to be referenced. The child mappings are created considering the given order or in other words, the first communication element is mapped to the first signal, the second element to the second signal and so on.
For a client server to signal mapping, select the operation communication element and enter the paths to two serialized signals. Which signal is the call and which one the return signal is determined by the direction of the signals.
Hint: Use 'ECU Composition' or 'COMPOSITIONTYPE' as component name to select communication elements of delegation ports.

There are a few checks also for the simple API.

  • +++

    +++Before creating the data mapping check if an equal mapping already exists. Do not create redundant mappings.

  • +++

    +++Check that the amount of the selected communication elements is equal to the amount of the selected signals. For the client server use case there will be one communication element for the call direction and one for the return direction.

  • +++

    +++Checks that the direction of the signal and communication element are compatible. Checks also the type compatibility of signal (group) and communication element.
    An operation communication element can only be mapped to a serialized signal.
    Records can only be mapped to serialized signals or signal groups.
    Unions can only be mapped to serialized signals.
    Arrays with complex array element can only be mapped to serialized signals or signal groups.
    Trigger communication elements cannot be mapped to signal groups.

  • +++

    +++For the client server data mappings, check that exactly two singals are selected and that both signals are serialized signals.

  • +++

    +++Checks for complex mappings, that the first abstract signal instance is a signal group and the other instances are group signals of this signal group.

  • +++

    +++Check that the selected communication elements are suitable for data mapping. That means they should belong to a sender receiver, client server or a trigger port, which is not a service port and not a PRPort.

  • +++

    +++Check the hierarchy of the selected communication elements for complex mappings. First selected element should be the root element and all further selected elements children of the root element.

  • +++

    +++Check for the client server use case, that both communication elements, one for the call and one for the return direction can be found. The communication elements have to be operation communication elements.

  • +++

    +++Check for a complex mapping that the first selected communication element is really a complex root element.

  • +++

    +++ Check if the owner port of the communication element is terminated. Terminated ports should not be data mapped. Please remove the port terminator first.

If you want to use some internal rules other than name matching to map communication elements to system signals you can apply this rules to sort a list of communication elements and a list of abstract signal instances and then use the simple API below that maps them via index.

+++

+++communicationElements(List) wraps SICommunicationElements to do further operations on them, e.g. map them to system signals.

+++

+++

+++

+++mapTo(List) maps the SICommunicationElements which are represented by this ISelectedCommunicationElements to the given SIAbstractSignalInstances via index matching. So the first communication element will be mapped to the first abstract signal instance, the second to the second abstract signal instance and so on.
In case you want to ignore communication element and system signal pairs for which a mapping does already exist please use assureMappedTo(List).
If you want to map your communication elements to system signals using name matching please use IRuntimeSystemApi.selectCommunicationElements(com.vector.cfg.util.function.Action).

If you want to create complex mappings (currently only SenderReceiverToSignalGroupMappings) the given abstractSignalInstances should contain the group signals right after the parent signal group instances.
For a client server to signal mapping, select call and return signal instance directly after each other.

+++

+++assureMappedTo(List) does the same as mapTo(List) but ignores communication element and abstract signal instance pairs for which a data mapping does already exist.

If you want to create complex mappings (currently only SenderReceiverToSignalGroupMappings) the given abstractSignalInstances should contain the group signals right after the parent signal group instances.
For a client server to signal mapping, select call and return signal instance directly after each other.

Examples

Create sender receiver to signal mapping
scriptTask ("createSimpleMapping", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                // specify path to the system signal
                def signalPath = "/VectorAutosarExplorerGeneratedObjects/SYSTEM_SIGNALS/Element_1_b16df82332bcf915"

                // enter the fully qualified communication element name
                // that means ComponentName.PortName.DataElementName
                def communicationElementName = "App1.pDataSend.Element"

                def createdMapping = communicationElement(communicationElementName).mapTo(signalPath)

                scriptLogger.info("Mapped '{0}' to '{1}'.",
                createdMapping.getCommunicationElement().getFullyQualifiedName(),
                createdMapping.getSystemSignal().getAutosarPath())
            }
        }
    }
}

Create data mapping for delegation port
scriptTask ("mapDelegationPort", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                def signalPath = "/VectorAutosarExplorerGeneratedObjects/SYSTEM_SIGNALS/Element_1_b16df82332bcf915"

                // for delegation ports use 'ECU Composition' instead of the component name
                def communicationElementName = "ECU Composition.pDelegationSRPort2.Element"

                def createdMapping = communicationElement(communicationElementName).mapTo(signalPath)

                scriptLogger.info("Mapped '{0}' to '{1}'.",
                createdMapping.getCommunicationElement().getFullyQualifiedName(),
                createdMapping.getSystemSignal().getAutosarPath())
            }
        }
    }
}

Create client server to signal mapping
scriptTask ("createClientServerMapping", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                def callSignalPath = "/VectorAutosarExplorerGeneratedObjects/SYSTEM_SIGNALS/rSRPort2_d4aecc362f1feef3"
                def returnSignalPath = "/VectorAutosarExplorerGeneratedObjects/SYSTEM_SIGNALS/pSRPort3_2264a06bc04fc81d"

                // if an operation communication element is selected, a client server to signal mapping will be created
                // the assignment of call and return signal role is depending on the direction of the signal
                def communicationElementName = "ECU Composition.pDelegationCSPort1.Operation"

                def createdMapping = communicationElement(communicationElementName).mapTo(callSignalPath, returnSignalPath)

                scriptLogger.info("Mapped '{0}' to '{1}' as call signal and '{2}' as return signal.",
                createdMapping.getCommunicationElement().getFullyQualifiedName(),
                createdMapping.getSystemSignal().getAutosarPath(),
                createdMapping.getReturnSystemSignal().getAutosarPath())
            }
        }
    }
}

Map record to signal group
import com.vector.cfg.sysdesc.model.datamapping.SISenderReceiverDataMapping

scriptTask ("mapRecordToSignalGroup", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                // specify the path to the signal group
                def signalGroup = "/VectorAutosarExplorerGeneratedObjects/SYSTEM_SIGNAL_GROUPS/Element_2_de8db6949370c6b4"

                // specify the paths to the group signals of the signal group
                def groupSignal1 = "/VectorAutosarExplorerGeneratedObjects/SYSTEM_SIGNALS/ay1_48523fe229ba8c99"
                def groupSignal2 = "/VectorAutosarExplorerGeneratedObjects/SYSTEM_SIGNALS/ay2_071a3305d39fcca4"
                def groupSignal3 = "/VectorAutosarExplorerGeneratedObjects/SYSTEM_SIGNALS/ay3_84eba37e401eacd1"

                // the name of the root element
                def record = "ECU Composition.pDelegationSRPort1.Element_2"

                // the names of the child elements
                def recordElement1 = "ECU Composition.pDelegationSRPort1.Element_2.RecordElement"
                def recordElement2 = "ECU Composition.pDelegationSRPort1.Element_2.RecordElement_1"
                def recordElement3 = "ECU Composition.pDelegationSRPort1.Element_2.RecordElement_2"

                // create the mapping, first argument should be the root element, followed by the leaf elements for the child mappings
                // for the signals, first argument should be the signal group, followed by the group signals

                // the mapping will be done using the given order
                // e.g. the first element (record) will be mapped to the signal group (signalGroup),
                // the last record element (recordElement3) will be mapped to the last group signal (groupSignal3)
                def createdMapping = communicationElement(record, recordElement1, recordElement2, recordElement3)
                    .mapTo(signalGroup, groupSignal1, groupSignal2, groupSignal3)

                scriptLogger.info("Mapped '{0}' to '{1}'.",
                createdMapping.getCommunicationElement().getFullyQualifiedName(),
                createdMapping.getSystemSignal().getAutosarPath())

                // print info for the child mappings
                for (final SISenderReceiverDataMapping childMapping : createdMapping.getChildDataMapping()) {
                    scriptLogger.info("Mapped '{0}' to '{1}'.",
                    childMapping.getCommunicationElement().getFullyQualifiedName(),
                    childMapping.getSystemSignal().getAutosarPath())
                }
            }
        }
    }
}

Map array to signal group
import com.vector.cfg.sysdesc.model.datamapping.SISenderReceiverDataMapping

scriptTask ("mapArrayToSignalGroup", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                // specify the path to the signal group
                def signalGroup = "/VectorAutosarExplorerGeneratedObjects/SYSTEM_SIGNAL_GROUPS/Element_2_de8db6949370c6b4"

                // specify the paths to the group signals of the signal group
                def groupSignal1 = "/VectorAutosarExplorerGeneratedObjects/SYSTEM_SIGNALS/ay1_48523fe229ba8c99"
                def groupSignal2 = "/VectorAutosarExplorerGeneratedObjects/SYSTEM_SIGNALS/ay2_071a3305d39fcca4"
                def groupSignal3 = "/VectorAutosarExplorerGeneratedObjects/SYSTEM_SIGNALS/ay3_84eba37e401eacd1"

                // the name of the root element
                def array = "ECU Composition.pDelegationSRPort2.Element_1"

                // select the element of the array using the position index of the element
                def arrayElement1 = "ECU Composition.pDelegationSRPort2.Element_1[0]"
                def arrayElement2 = "ECU Composition.pDelegationSRPort2.Element_1[1]"
                def arrayElement3 = "ECU Composition.pDelegationSRPort2.Element_1[2]"

                def createdMapping = communicationElement(array, arrayElement1, arrayElement2, arrayElement3)
                    .mapTo(signalGroup, groupSignal1, groupSignal2, groupSignal3)

                scriptLogger.info("Mapped '{0}' to '{1}'.",
                createdMapping.getCommunicationElement().getFullyQualifiedName(),
                createdMapping.getSystemSignal().getAutosarPath())

                // print info for the child mappings
                for (final SISenderReceiverDataMapping childMapping : createdMapping.getChildDataMapping()) {
                    scriptLogger.info("Mapped '{0}' to '{1}'.",
                    childMapping.getCommunicationElement().getFullyQualifiedName(),
                    childMapping.getSystemSignal().getAutosarPath())
                }
            }
        }
    }
}

+++

+++

Map complex data element to system signal group and let the auto-mapper complete the mapping if possible
import com.vector.cfg.sysdesc.model.datamapping.SISenderReceiverDataMapping

scriptTask("completeComplexDataMapping", DV_PROJECT) {
    code {
        transaction {
            domain.runtimeSystem {

                // in this example we want to map a record to a system signal group
                // we will map only the roots
                // a comfort function will try to find matches in record elements and group signals via naming

                String recordName = "ECU Composition.pDelegationSRPort1.Element_2"
                String signalGroupPath = "/VectorAutosarExplorerGeneratedObjects/SYSTEM_SIGNAL_GROUPS/Element_2_de8db6949370c6b4"

                SISenderReceiverDataMapping createdDataMapping = communicationElement(recordName).mapTo(signalGroupPath)

                scriptLogger.info("Mapped {0} -> {1}.",
                createdDataMapping.getCommunicationElement().getFullyQualifiedName(),
                createdDataMapping.getSystemSignal().getName())

                // we want also to print info for the child mappings
                for (SISenderReceiverDataMapping childMapping in createdDataMapping.getLeafDataMappings()) {
                    scriptLogger.info("Mapped {0} -> {1}.",
                    childMapping.getCommunicationElement().getFullyQualifiedName(),
                    childMapping.getSystemSignal().getName())
                }
            }
        }
    }
}

Map communication elements to system signals using simple API Part1
import com.vector.cfg.sysdesc.model.communication.SICommunicationElement
import com.vector.cfg.sysdesc.model.datamapping.SIDataMapping
import com.vector.cfg.sysdesc.model.datamapping.SIClientServerToSignalDataMapping
import com.vector.cfg.sysdesc.model.communication.instance.SIAbstractSignalInstance

scriptTask("UseSimpleAPIToCreateMultipleDataMappings", DV_PROJECT) {
    code {
        transaction {
            domain.runtimeSystem {

                // in this example we know for each communication element the name of the system signal to map it to
                // (for example stored in some external file)
                // so we use the simple API instead of the auto mapping

                List<String> comElementNames =
                    ["ECU Composition.TriggerDataMappingZeroLengthSignal.SomeTrigger",
                    // com element below for client server to signal mapping
                    "App1_1.pCSPort1.Operation",
                    "App2.rSRPort1.Element",
                    // com elements below are a record and its record elements
                    "App2.rSRPort1.Element_2",
                    "App2.rSRPort1.Element_2.RecordElement",
                    "App2.rSRPort1.Element_2.RecordElement_2"]
                List<String> signalNames =
                    ["TriggerDataMappingZeroLengthSignal_896bde67e5a0f5b4",
                    // the two signals below are used for a client server to signal mapping
                    // one call and one return signal
                    "rSRPort2_d4aecc362f1feef3", "pSRPort3_2264a06bc04fc81d",
                    "RElement_1_c07c9ba68bc545ba",
                    // com elements below is a signal group and its group signals
                    "elemB_c255f5e38fd8b21d",
                    "fieldA_f1d3783e235e88d3",
                    "fieldB_344fdc16e87cfdaa"]

                // we use the communication element selection to retrieve the communication elements
                // for the client server to signal mapping the selection will find two com elements for the one name
                // one for the call direction and one for the return direction
                List<SICommunicationElement> comElements = selectCommunicationElements {
                    fullyQualifiedNames(comElementNames)
                    // we need to select also unmapped record elements, so use fully expanded selection
                    // another way would be to select only the root
                    // and then access the leafs e.g. via IDataCommunicationElement.getLeafsFullExpandedExceptPrimitiveArrays()
                    selectFullyExpanded()
                }.getCommunicationElements()

                // since our used predicate does not guarantee any order, we have to sort our communication elements to assure they are in correct order
                comElements.sort{a,b -> comElementNames.indexOf(a.getFullyQualifiedName()) <=> comElementNames.indexOf(b.getFullyQualifiedName())}

Map communication elements to system signals using simple API Part2
              // now select and sort the signal instances
              List<SIAbstractSignalInstance> signals = new ArrayList<SIAbstractSignalInstance>(selectSignalInstances {
                  names(signalNames)
              }.getSignalInstances())

              signals.sort{a,b -> signalNames.indexOf(a.getName()) <=> signalNames.indexOf(b.getName())}

              // map communication elements via index to the system signals
              // for complex mappings the children need to be inserted directly after the parent

              // for client server mappings call and return elements right after each other
              // call first or return first does not matter

              // mapTo(...) would fail if one of the mappings does already exist
              // but in this example we just want to make sure that the mapping exist, if not assureMappedTo(...) will create it, if it does exist it will do nothing
              List<SIDataMapping> dataMappings = communicationElements(comElements).assureMappedTo(signals)

              // finally do some reporting for the pairs that were previously not mapped to each other
              for (SIDataMapping dataMapping in dataMappings) {
                  scriptLogger.info("Mapped {0} to {1}.",
                          dataMapping.getCommunicationElement().getFullyQualifiedName(),
                          dataMapping.getSystemSignal().getName())

                  if (dataMapping instanceof SIClientServerToSignalDataMapping) {
                      scriptLogger.info("Return signal is {0}.",
                              ((SIClientServerToSignalDataMapping) dataMapping).getReturnSystemSignal().getName())
                  }
              }
          }
      }
  }
            }

Remove Data Mappings

+++

+++ The previous chapter was about mapping communication elements and signal instances. Now we want to have a look how to remove such mappings again.
This can be done using the communication element selection API (see +++CommunicationElementSelection+++) or the signal instance selection API (see +++SignalInstanceSelection+++) and calling a method to unmap the selected communication elements / signal instances.

Unmapping by Selecting Communication Elements

The use case of unmapping communication elements is based on the selection of communication elements. The targets to be unmapped are signal instances, which can be also narrowed down by further closures.

+++

+++unmap() unmaps the selected communication elements from all mapped system signals. In case that not all data mappings of the selected communication elements shall be removed the mapped signal instances can be narrowed down using unmapFrom(Action).

For SenderReceiverToSignalGroupMappings (complex mappings) it is already enough to select one of the communication elements (for example the root element), all mappings belonging to the complex mapping will be removed. In other words removing the root mapping also removes the child mappings, removing a child mapping also removes the root mapping and the other child mappings of the same root.

Examples for unmap ()

Remove Data Mapping of Communication Element
import com.vector.cfg.dom.runtimesys.pai.api.IUnmappedComElementAndSignalResult

scriptTask("UnmapCommunicationElements", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {

        // we want to remove all data mappings of delegation ports in this example
        def result = selectCommunicationElements {
                  mapped()
                  delegation()
                } unmap()


        // now print a detailed info for all removed data mappings
        // we want also detailed info for client server to signal mappings and sender receiver to signal group mappings
        scriptLogger.info("Removed {0} (root) mappings.", result.size())

        for (IUnmappedComElementAndSignalResult unmappedResult : result) {
            scriptLogger.info("{0} -> {1}",
                    unmappedResult.getCommunicationElement().getFullyQualifiedName(),
                    unmappedResult.getSignalInstance().getName())

            // additional info for return signal mapping
            if (unmappedResult.getReturnSignalCommunicationElement() != null) {
                scriptLogger.info("{0} -> {1}",
                        unmappedResult.getReturnSignalCommunicationElement().getFullyQualifiedName(),
                        unmappedResult.getReturnSignalInstance().getName())
            }

            //  additional info for mapped record and array elements
            if (!unmappedResult.getChildCommunicationElements().isEmpty()) {

                for (int i = 0; i < unmappedResult.getChildCommunicationElements().size(); i++) {
                    scriptLogger.info("{0} -> {1}",
                            unmappedResult.getChildCommunicationElements().get(i).getFullyQualifiedName(),
                            unmappedResult.getGroupSignalInstances().get(i).getName())
                }
            }
        }
      }
    }
  }
}

Control unmapping in unmapFrom (Closure)

+++

+++selectTargetSignalInstances(Action) allows to define predicates to narrow down the target signal instances to be unmapped from the previously selected communication elements.

+++

+++evaluateMatches(IUnmappingEvaluator) allows to evaluate and change the results of the communication elements which are about to be unmapped from signal instances.

For each selected communication element the provided lambda is called: Parameters are the current handled communication element and a list of all mapped signal instances (respecting the selectTargetSignalInstances(Action) predicates). The return value must be a list of signal instances which are mapped to the current handled communication element.

Examples for unmapFrom (Closure)

Remove Data Mapping of Communication Element Considering Signals
scriptTask("UnmapCommunicationElementsAdvanced", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {

        // we want to remove only data mappings for delegation ports to signals of a special frame
        def result = selectCommunicationElements {
                  mapped()
                  delegation()
                } unmapFrom {
                    // we have already filtered the communication elements
                    // in this closure we can now additionally filter also for the signals of the data mapping to be removed
                    selectTargetSignalInstances {
                        frame("MyFrame")
                    }
                }


        // see the simple example above how to print more detailed info
        scriptLogger.info("Removed {0} (root) mappings.", result.size())
      }
    }
  }
}

Unmapping by Selecting Signal Instances

The use case of unmapping system signals is based on the selection of signal instances. The targets to be unmapped are communication elements, which can be also narrowed down by further closures.

+++

+++unmap() unmaps the selected signal instances from all mapped communication elements. In case that not all data mappings of the selected signal instances shall be removed the mapped communication elements can be narrowed down using unmapFrom(Action).

For SenderReceiverToSignalGroupMappings (complex mappings) it is already enough to select the signal group or one of the group signals, all mappings belonging to the complex mapping will be removed. In other words removing the root mapping also removes the child mappings, removing a child mapping also removes the root mapping and the other child mappings of the same root.

Examples for unmap ()

Remove Data Mapping of Signal
import com.vector.cfg.dom.runtimesys.pai.api.IUnmappedComElementAndSignalResult

scriptTask("UnmapSignalInstances", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {

        // we want to remove all data mappings of all mapped tx signals in this example
        def result = selectSignalInstances {
                  mapped()
                  tx()
                } unmap()


        // now print a detailed info for all removed data mappings
        // we want also detailed info for client server to signal mappings and sender receiver to signal group mappings
        scriptLogger.info("Removed {0} (root) mappings.", result.size())

        for (IUnmappedComElementAndSignalResult unmappedResult : result) {
            scriptLogger.info("{0} -> {1}",
                    unmappedResult.getCommunicationElement().getFullyQualifiedName(),
                    unmappedResult.getSignalInstance().getName())

            // additional info for return signal mapping
            if (unmappedResult.getReturnSignalCommunicationElement() != null) {
                scriptLogger.info("{0} -> {1}",
                        unmappedResult.getReturnSignalCommunicationElement().getFullyQualifiedName(),
                        unmappedResult.getReturnSignalInstance().getName())
            }

            //  additional info for mapped record and array elements
            if (!unmappedResult.getChildCommunicationElements().isEmpty()) {

                for (int i = 0; i < unmappedResult.getChildCommunicationElements().size(); i++) {
                    scriptLogger.info("{0} -> {1}",
                            unmappedResult.getChildCommunicationElements().get(i).getFullyQualifiedName(),
                            unmappedResult.getGroupSignalInstances().get(i).getName())
                }
            }
        }
      }
    }
  }
}

Control unmapping in unmapFrom (Closure)

+++

+++ selectTargetCommunicationElements(Action) allows to define predicates to narrow down the target communciation elements to be unmapped from the previously selected signal instances.

+++

+++evaluateMatches(IUnmappingEvaluator) allows to evaluate and change the results of the signal instances which are about to be unmapped from communication elements.

For each selected signal instance the provided lambda is called: Parameters are the current handled signal instance and a list of all mapped communication elements (respecting the selectTargetCommunicationElements(Action) predicates). The return value must be a list of communication elements which are mapped to the current handled signal instance.

Examples for unmapFrom (Closure)

Remove Data Mapping of Signals Considering Communication Elements
scriptTask("UnmapSignalInstancesAdvanced", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {

        // we want to remove only data mappings for transformed signals which are mapped to communication elements of component 'App1'
        def result = selectSignalInstances {
                  mapped()
                  transformed()
                } unmapFrom {
                    // we have already filtered the signal instances
                    // in this closure we can now additionally filter also for communication elements of the data mapping to be removed
                    selectTargetCommunicationElements {
                        component("App1")
                    }
                }


        // see the simple example above how to print more detailed info
        scriptLogger.info("Removed {0} (root) mappings.", result.size())
      }
    }
  }
}

Configure RTE Implementation Plug-ins

+++

+++ RTE implementation plug-ins (RIPs) can be configured directly at the communication element (recommended) or using the according methods at the communication element selection. They are stored in the flat map at the entry of the flat instances descriptor which belongs to the communication element. It is a reference to the according ECUC container representing the RIP. When setting a RIP the flat instance descriptor will be created automatically if missing. The getters and setters at the ICommunicationElement are not explicitly listed here. At which communication elements the references need to be configured is defined in [SWS_Rte_CONSTR_80002].

mapToRIPs(Action) offers the possibility to map the selected communication elements to RTE implementation plug-ins or to modify the name of their flat instance descriptors.

setLocalRIPsReference(String) sets the RTE implementation plug-in reference for local communication (associatedRtePlugin reference).

setCrossClusterRIPsReference(String) sets the RTE implementation plug-in reference for cross-cluster communication (associatedCrossSwClusterComRtePlugin reference).

+++name(String) sets the name of the flat instance descriptor referencing the communication element.+++

+++name(Function) allows to define a function which maps the communication element to the flat instance descriptor name.+++

useCommunicationGraph() extends the selection of each communication element by its whole communication graph. Communication graph means all required and provided ports taking part in the communication. For example in a 1:n connection it would be the provider port and all n required ports.

removeLocalRIPsReference() removes the associatedRtePlugin references of the selected communication elements, so that they do not use an RTE implementation plug-in for local communication anymore.

removeCrossClusterRIPsReference() removes the associatedCrossSwClusterComRtePlugin references of the selected communication elements, so that they do not use an RTE implementation plug-in for cross-cluster communication anymore.

deleteFlatInstanceDescriptors() deletes the flat instance descriptors of the selected communication elements.

Since the RIP references are stored at the flat instance descriptor they might not always be changeable. This can be checked via the according methods at the SICommunicationElement (SICommunicationElement.isAssociatedLocalClusterRtePluginReferenceChangeable (),
SICommunicationElement.isAssociatedCrossClusterRtePluginReferenceChangeable (),
SICommunicationElement.isFlatInstanceDescriptorNameChangeable ()
and SICommunicationElement.isFlatInstanceDescriptorDeletable ()).

There are also methods available at the runtime system API to get the according ECUC containers which can be referenced as RIP.

+++

+++getAvailableLocalRIPsContainers() collects and returns all containers which are associated with RTE implementation plug-ins (RIPs) for local communication.

+++

+++getAvailableCrossClusterRIPsContainers() collects and returns all containers which are associated with RTE implementation plug-ins (RIPs) for cross-cluster communication.

Examples

Configure RTE implementation plug-ins
scriptTask("ConfigureRIPs", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
          def ripContainers = getAvailableLocalRIPsContainers()
          String ripContainerPath = AsrPath.create(ripContainers.first).toString()

          def comElementsWithRIP = selectCommunicationElements {
              component("App1_1")
              port("pDataWrite")
              name("Element")
          }.mapToRIPs {
              // set the RTE implementation plug-in
              setLocalRIPsReference(ripContainerPath)
              // there are also according methods to set the cross-cluster plug-in
              // and to modify the name of the created flat instance descriptor
          }
          scriptLogger.info("Mapped {0} communication elements to RTE implementation plug-in {1}.",
            comElementsWithRIP.size(),
            ripContainerPath)
       }
    }
  }
}

Remove RTE implementation plug-ins
scriptTask("RemoveRIPs", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
          def comElementsRemovedRIPs = selectCommunicationElements {
              component("App1")
          }.removeLocalRIPsReference()
          // it is also possible to remove the flat instance descriptor or the cross-cluster reference

          scriptLogger.info("Removed RTE implementation plug-ins of {0} communication elements.", comElementsRemovedRIPs.size())
      }
    }
  }
}

Access RTE implementation plug-ins directly at the communication element
import com.vector.cfg.model.mdf.model.autosar.ecucdescription.MIContainer

scriptTask("RemoveRIPOfComElement", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
          def selectedComElements = selectCommunicationElements {
              component("App1")
          }.getCommunicationElements()

          // the communication element has getters and setter which can be also used
          // check if comElement has a RIP reference and remove it if it is changeable
          def comElement = selectedComElements.first
          MIContainer ripContainer = comElement.getAssociatedLocalClusterRtePlugin()
          if (ripContainer != null && comElement.isAssociatedLocalClusterRtePluginReferenceChangeable()) {
             comElement.setAssociatedLocalClusterRtePluginReference(null)
          }
       }
    }
  }
}

Create Component Prototypes

In the create component prototypes use case, components can be instantiated after a component type was selected. So the entry point is the component type selection (see +++ComponentTypeSelection+++).

Instantiate Components

+++

+++createPrototype() creates a SwComponentPrototype in the StructuredEXtract for each selected component type. The names of the created SwComponentPrototypes are derived from the selected component types.

Examples for createPrototype ()

Create component prototypes for not instantiated types
scriptTask ("createComponentPrototypesForNotInstantiatedTypes", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                def createdComponents = selectComponentTypes {
                    not {
                        instantiated()
                    }
                }.createPrototype()

                scriptLogger.info("Created '{0}' component prototypes.", createdComponents.size())
            }
        }
    }
}

Specify the component prototype instantiation in createPrototypeWith (Closure)

+++

+++IComponentPrototypeCreator provides an Api to control some aspects, e.g. the naming, of newly created components.

  • name(Function) computes a name for the component prototypes that should be created for, by the IComponentTypeSelection provided, component types.

  • +++count(int) defines how many component prototypes should be created for each selected component type. The default is 1.+++

Examples for customizing the instantiation

Specify name of created component
import com.vector.cfg.sysdesc.model.component.SIComponentType

scriptTask ("specifyNameOfCreatedComponent", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                def createdComponents = selectComponentTypes {
                    application()
                }.createPrototypeWith {
                    name {
                        // define the naming of new created prototypes
                        SIComponentType<?> type -> type.getName() + "_postfix"
                    }
                }

                scriptLogger.info("Created '{0}' component prototypes.", createdComponents.size())
            }
        }
    }
}

Create more than 1 component prototype
import com.vector.cfg.sysdesc.model.component.SIComponentType

scriptTask ("specifyNameOfCreatedComponent", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                def createdComponents = selectComponentTypes {
                    name ~"App.*"
                }.createPrototypeWith {
                    name {
                        // you can still define a naming pattern
                        SIComponentType<?> type -> type.getName() + "_CP"
                    }

                    // and at the same time define how many prototypes should be created for each component type
                    count(3)
                }

                scriptLogger.info("Created '{0}' component prototypes.", createdComponents.size())
            }
        }
    }
}

Create Delegation Ports

+++

+++ The automation interface offers a possibility to create delegation ports at the TopLevel-Composition of the StructuredExtract. Therefore a port interface needs to be selected and a direction specified. Alternatively the component port and the origin port selections offer also APIs for that use case. For the origin context based creation of delegation ports see +++CreatePortsFromOriginContext+++ below, the component port based creation of delegation ports can be found in the examples at the end of following chapter (+++DelegationPortBasedOnComponentPort+++).

The entry points are the port interface selection (see +++PortInterfaceSelection+++), the component port selection (see +++ComponentPortSelection+++) or the origin component port selection (see +++OriginComponentPortSelection+++).

Instantiate Delegation Ports

+++

+++createPrototype(Action) creates a PortPrototype on the ecu composition of the StructuredExtract for each selected port interface. If the naming is not specified, the names of the created delegation ports are derived from the selected port interfaces. The direction of the ports has to be specified.

Specify the delegation port prototype instantiation

+++

+++IDelegationPortCreator provides an Api to control some aspects, e.g. the naming or the direction, of newly created delegation ports.

  • name(Function) computes a name for the delegation port prototypes that should be created for port interfaces, which are provided by the used selection API.

  • direction(EDirection) defines the direction of the port prototype that should be created. EDirection.Tx will create provided ports, EDirection.Rx will create required ports. Delegation provided-required ports are not supported.

  • +++count(int) defines how many delegation port prototypes should be created for each selected port interface. The default is 1.+++

For the origin and component port selection APIs the naming can be also done based on the selected ports.

  • nameFromOriginPort(Function) computes a name for the delegation port prototypes that should be created for origin ports, which are provided by the used IOriginComponentPortSelection.

  • nameFromComponentPort(Function) computes a name for the delegation port prototypes that should be created for component ports, which are provided by the used IComponentPortSelection.

Examples

Create delegation port simple
import com.vector.cfg.sysdesc.model.communication.EDirection

scriptTask("createDelegationPortSimple", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def createdComponentPorts =
             selectPortInterfaces {
                // select all client server application port interfaces of component 'App3'
                componentType "App3"
                clientServer()
                application()
             } createPrototype {
                // EDirection.Tx to create a PPort and EDirection.Rx to create a RPort
                direction(EDirection.Tx)
                // if no name is specified, the name of the port interface will be taken for the port
               }
        scriptLogger.info("Created {0} delegation ports.", createdComponentPorts.size())
      }
    }
  }
}

Create delegation port customized
import com.vector.cfg.sysdesc.model.communication.EDirection
import com.vector.cfg.sysdesc.model.port.SIPortInterface

scriptTask("createDelegationPortCustomized", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
        def createdComponentPorts =
             selectPortInterfaces {
                // select the port interface of 'App1.ppFirst' and the port interface named 'Second'
                or {
                    componentPort "App1.ppFirst"
                    name "Second"
                }
             } createPrototype {
                name {
                    // specify the naming of the new ports
                    SIPortInterface<?> portInterface -> "pp" + portInterface.getName() + "_new"
                }
                // EDirection.Rx is leading to the creation of required ports
                direction(EDirection.Rx)
                // for each selected port interface two delegation ports will be created
                count(2)
               }
        scriptLogger.info("Created {0} delegation ports.", createdComponentPorts.size())
      }
    }
  }
}

+++

+++

Create delegation port based on existing component port
import com.vector.cfg.sysdesc.model.component.SIComponentPort

scriptTask("createDelegationPortFromComponentPort", DV_PROJECT){

  // in this example we want to create a delegation port for an existing SWC port

  code {
    transaction {
      domain.runtimeSystem {
        def createdComponentPorts =
             selectComponentPorts {
                 component "App3"
                 name "rOtherSR1Port"
             } createDelegationPorts {

                // we can use the selected component port to specify the name of the new port
                // also we could have used the name(Closure) method from examples above and use the port interface for naming
                nameFromComponentPort {
                    // specify the naming of the new ports
                    SIComponentPort componentPort -> componentPort.getPortName() + "_new"
                }
                // since we have selected a component port previously, we can now use the direction of it
                // of course it is also possible to use direction(EDirection) here as in the examples above
                useDefaultDirection()
               }
        scriptLogger.info("Created {0} delegation ports.", createdComponentPorts.size())
      }
    }
  }
}

Create Delegation Ports Using Origin Context

+++

+++ We have already learned how to create new delegation ports in the flat extract using the port interface selection (see +++CreateDelegationPorts+++). Sometimes a delegation connection was not completed in the structured extract because the delegation port was missing and is not flattened out. To complete this connection in the flat extract we need a new delegation port and want to use exactly the same port interfaces as in the structured extract. For this use case there is a shortcut directly at the origin component port selection, that simplifies the transition from origin port to its port interface. To specify the name of the new port, the API offers to do it using the port interface or the origin component port itself (see examples below).

For more details about origin context see +++OriginContext+++.

+++

+++createFlatExtractDelegationPorts(Action) creates a PortPrototype on the ecu composition of the FlatExtract for each selected origin component port using their port interfaces. If the naming is not specified, the names of the created delegation ports are derived from the port interfaces. The direction of the ports has to be specified.

Examples

Create a delegation port using the port interface of an origin context port
import com.vector.cfg.sysdesc.model.communication.EDirection

scriptTask("createPortFromOriginContext", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {

        // in this example we create a delegation port which is missing
        // the port interface for our new port is provided by an origin context port

        def selectedOriginPorts
        def createdDelegationPorts = selectOriginComponentPorts {
            provided()
            name "OriginContext"

            // remember the selected ports to print better info later
            selectedOriginPorts = getSelectedOriginComponentPorts()

        }.createFlatExtractDelegationPorts {
            // this call retrieves the port interfaces of the selected origin component ports
            // and creates for each origin component port a delegation port

            // specify the name and direction of the new port
            name {
                // optionally you could use the port interface as help for specifying the name here
                // IPortInterface portInterfaceOfOriginPort -> ...
                "PortWithInterfaceOfOriginContext"
            }
            direction(EDirection.Tx)
        }

        for (int i = 0; i < selectedOriginPorts.size(); i++) {
            scriptLogger.info("Created new delegation port {0} for origin port {1}.",
                createdDelegationPorts.get(i).getName(),
                selectedOriginPorts.get(i).getName())
        }
     }
    }
  }
}

Create a delegation port using the origin context port to specify name and direction
import com.vector.cfg.sysdesc.model.component.origin.SIOriginComponentPort

scriptTask("createPortFromOriginContextUsingPort", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {

        // in this example we create a delegation port which is missing
        // the port interface for our new port is provided by an origin context port
        // and we use the original port for naming and direction this time

        def selectedOriginPorts
        def createdDelegationPorts = selectOriginComponentPorts {
            provided()
            name "OriginContext"

            // remember the selected ports to print better info later
            selectedOriginPorts = getSelectedOriginComponentPorts()

        }.createFlatExtractDelegationPorts {

            // specify the name and direction of the new port
            nameFromOriginPort {  SIOriginComponentPort originPort ->
                originPort.getPortName() + "_new"
            }
            // for the origin component port selection we can use the direction of the previously selected origin ports
            useDefaultDirection()
        }

        for (int i = 0; i < selectedOriginPorts.size(); i++) {
            scriptLogger.info("Created new delegation port {0} for origin port {1}.",
                createdDelegationPorts.get(i).getName(),
                selectedOriginPorts.get(i).getName())
        }
     }
    }
  }
}

Task Mapping

The task mapping use case allows to map executable entities (also called functions) directly or using their events (also called triggers) to tasks.

The entry point for the task mapping is either to select events (see +++EventSelection+++) or executable entities (see +++ExecutableEntitySelection+++). After that a task can be selected and the task mappings customized.

Mapping to a Task

Event selection +++

+++mapToTask(Action) tries to perform a task mapping for the selection of events (triggers). Inside the lambda the task mapping can be controlled, e.g. selecting the task to which the events should be mapped to and order the event's positions. Does not consider events (triggers) which do not reference an executable entity (function).

+++

+++

+++

+++unmapTaskMappings(Action) performs the unmapping of task mappings from OSTasks for the selection of events (triggers).

ExecutableEntity selection +++

+++mapToTask(Action) tries to perform a task mapping for the selection of executable entities (functions). Inside the lambda the task mapping can be controlled, e.g. selecting the task to which the events (triggers) of the selected executable entities should be mapped to and order the event's positions.

+++

+++

unmapTaskMappings(Action) performs the unmapping of task mappings from OSTasks for the selection of executable entities (functions).

Select a task

Exactly one task has to be selected to perform a task mapping. Since the task selection is only available for the task mapping use case there is no own chapter for it.

++++++

selectTask(Action) allows to define predicates to select a task for the task mapping.

Per default the predicates are combined via logical AND. To realize other combinations, use the 'or','not' and 'and' predicates.

Task Predicates
  • name(String) matches tasks with the given task name.
  • name(Pattern) matches tasks with the given task name pattern.
  • core(String) matches tasks running on a core with the given name / number (whether a core name or a core number is used, depends on the OS, if core number is used the String to be matched is 'Core', e.g. 'Core1').
  • core(Pattern) matches tasks running on a core with the given name pattern / number pattern (whether a core name or a core number is used, depends on the OS, if core number is used the String to be matched is 'Core', e.g. 'Core1').
  • application(String) matches tasks which belong to an application with the given name.
  • application(Pattern) matches tasks which belong to an application whose name matches the given name pattern.
  • numberOfTaskMappings(int) matches tasks which already have the given number of task mappings. The predicate can also be used to search for empty tasks with '0' as argument.
  • priority(BigInteger) matches tasks with the given priority value.
  • filterAdvanced(Predicate) matches tasks for which the given predicate results to true.
  • and(Runnable) combines the predicates inside the lambda with a logical AND.
  • or(Runnable) combines the predicates inside the lambda with a logical OR.
  • not(Runnable) negates the combination of predicates inside the lambda.

Examples for mapToTask (Closure)

Perform task mapping example
import com.vector.cfg.sysdesc.model.taskmapping.SITaskMapping

scriptTask ("doTaskMappingOfApp1", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                def taskMappings = selectEvents {
                    // select all events of component App1
                    component("App1")
                } mapToTask {
                    selectTask {
                        // select a task
                        name("OsTask")
                    }
                }

                scriptLogger.info("Created '{0}' task mappings.", taskMappings.size())

                // let's print more information to check the created task mappings
                for (SITaskMapping taskMapping : taskMappings) {
                    scriptLogger.info("Mapped '{0}' triggered by '{1}' to position '{2} on task '{3}'.",
                        taskMapping.getExecutableEntity().getName(),
                        taskMapping.getEvent().getName(),
                        taskMapping.getPositionInTask(),
                        taskMapping.getMappedTask().getName())
                }
            }
        }
    }
}

Advanced Filter for Events
import com.vector.cfg.sysdesc.model.internalbehavior.SIEvent
import com.vector.cfg.model.mdf.ar4x.swcomponenttemplate.swcinternalbehavior.rteevents.MIDataReceivedEvent

scriptTask ("advancedFilterForEvents", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                     def taskMappings = selectEvents {
                         // use advanced filter if you cannot find a suitable predicate
                         filterAdvanced { SIEvent event ->
                            // use the mdf model if the SIEvent does not offer required methods
                            def mdfEvent = event.getMdfObject()

                            // for example, filter for data received events with special criteria
                            if (mdfEvent instanceof MIDataReceivedEvent) {
                                // filter here for the special criteria
                                return true
                            }

                            // do not select other events
                            return false
                         }
                } mapToTask {
                    selectTask {
                        name("OtherName")
                    }
                }

                scriptLogger.info("Created '{0}' task mappings.", taskMappings.size())
            }
        }
    }
}

Examples for unmapTaskMappings (Closure)

Unmaps task mappings
scriptTask ("unmapTaskMappings", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                def unmappedTaskMappings = selectEvents {
                    // define predicate for event selection
                    task("OsTask")
                    componentType("App1")
                } unmapTaskMappings {
                    filterTaskMappings {
                        // define further task mapping predicates
                        // in our example we have multi-instantiation of SWCs
                        // and want to unmap only one of them.
                        component "App1_1"
                    }
                }
                scriptLogger.info("Unmapped '{0}' task mappings.", unmappedTaskMappings.size())
            }
        }
    }
}

Additional Comfort Functions

The API provides some comfort functions listed below.

Combine via Symbol

combineViaSymbol(boolean) determines whether the BswModuleEntities and the RunnableEntities should be combined using their symbol. That means they will be mapped to the same position on the same task. It is enough to select only the RunnableEntity or only the BswModuleEntity, when using this option both will be mapped. The default is true.

The condition is that the symbol of a RunnableEntity and the BswModuleEntry short name of a BswModuleEntity are equal.

Example

Do not combine runnable and bsw module entity via symbol
scriptTask ("combineViaSymbol", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                def taskMappings = selectEvents {
                    component("Service1")
                    timing()
                } mapToTask {
                    selectTask {
                        name("OtherName")
                    }
                    // the default is true
                    // call this if you do not want to combine runnables and bsw module entities via their symbol
                    combineViaSymbol(false)
                }

                scriptLogger.info("Created '{0}' task mappings.", taskMappings.size())
            }
        }
    }
}

Map Events of a Runnable Entity Together

mapAllEventsOfRunnableEntity(boolean, boolean) is a possibility to map all events of a RunnableEntity to the same position on a task. In case of the selection of events, the task mapping will be extended, by all events (triggers) of runnable entities (functions) for which at least one event (trigger) is selected.

With help of the two boolean arguments, the behavior of ignoring already mapped events and ignoring events whose mapping is optional can be controlled.

Example

Map all events of a runnable together
scriptTask ("mapAllEventsOfRunnable", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                def taskMappings = selectEvents {
                    name("background_event")
                    component("App1_1")
                } mapToTask {
                    selectTask {
                        name("OsTask")
                    }
                    // decide whether to consider only unmapped events
                    // and whether to consider only events whose mapping is mandatory
                    mapAllEventsOfRunnableEntity(true, false)
                }

                scriptLogger.info("Created '{0}' task mappings.", taskMappings.size())
            }
        }
    }
}

Order Task Mappings by Defining Successor Mappings

If you do not care about the absolute position value of the task mappings, but want to define an order, there is an option to specify successor relationships between the selected task mappings. This is the preferred way to define an order to using order (Closure) which will be introduced below, since it is easier to use in most cases. One exception is for example if you already read in a sorted list of executable entity names from external files.

defineSuccessors(Action) allows to specify the order of the selected task mappings by defining successor relationships between the task mappings. The order defined by this method may still be overridden by order(Consumer) and queue() if used.

First you have to specify one task mapping as the starting point.

forTaskMapping(Action) allows to select a starting task mapping for which successors can be defined.

After that you can define a direct successor or a (logical) successor for the previously selected task mapping.

successor(Action) allows to select a successor for the previously selected task mapping of the sequence. The sequence can be continued by another successor(Action) or directSuccessor(Action) call. To start a new sequence call ITaskMappingSuccessorDefinition.forTaskMapping(Action).

directSuccessor(Action) allows to select a direct successor for the previously selected task mapping of the sequence. The sequence can be continued by another successor(Action) or directSuccessor(Action) call. To start a new sequence call ITaskMappingSuccessorDefinition.forTaskMapping(Action).

Within these calls you can select task mappings using task mapping predicates (see TaskMappingPredicates). If the task mappings cannot be ordered to match the defined rules (for example if cycles were defined), an exception is thrown.

Example

Order the task mappings by defining successor relationships
import com.vector.cfg.sysdesc.model.taskmapping.SITaskMapping

scriptTask ("defineSuccessorsSimple", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {

                // you can use both the event selection or the executable entity selection API here
                def taskMappings = selectEvents {
                    component("App1")
                } mapToTask {
                    selectTask {
                        name("OsTask")
                    }
                    defineSuccessors {
                        forTaskMapping {
                            // define task mapping predicates to select the start of your sequence
                            // here we really use the predicates for task mappings, not for events nor executable entities
                            // but the task mapping selection offers us a lot of predicates
                            // it allow us to filter e.g. for the events which the task mappings reference or the executable entity which is triggered by the referenced event
                            executableEntity "Runnable1"
                        } successor {
                            // now define predicates to select successors for Runnable1
                            executableEntity "Runnable2"
                        } successor {
                            // we can continue by defining the successors for Runnable2 now
                            externalTrigger()
                        }
                    }
                }

                // so the result on OsTask will be Runnable1 -> Runnable2 -> all runnables triggered by external trigger events

                scriptLogger.info("Created '{0}' task mappings.", taskMappings.size())

                for (final SITaskMapping taskMapping : taskMappings) {
                    scriptLogger.info("Mapped runnable {0} to position {1}.",
                    taskMapping.getExecutableEntity().getName(),
                    taskMapping.getPositionInTask())
                }
            }
        }
    }
}

Order groups by using successor calls
import com.vector.cfg.sysdesc.model.taskmapping.SITaskMapping

scriptTask ("successorForGroup", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {

                def taskMappings = selectExecutableEntities {
                    runnableEntity()
                } mapToTask {
                    selectTask {
                        name("OsTask")
                    }
                    defineSuccessors {
                        // you do NOT have to narrow the selection down to one task mapping
                        // we want to order the task mappings by their SWC owner in this example

                        // we want the runnables of App1 be executed before the runnables of App2 and App3
                        // but we do not care about any order for the runnables of App2 and App3 or want define them later

                        // execute runnables of App1 before runnables of App2
                        forTaskMapping {
                            component "App1"
                        } successor {
                            component "App2"
                        }

                        // you can define multiple sequences for the same task mappings
                        // execute runnables of App1 before runnables of App3
                        forTaskMapping {
                            component "App1"
                        } successor {
                            component "App3"
                        }
                    }

                }

                // the script will map the runnables to OsTask and guarantees that the runnables of App1 are mapped before the runnables of App2 and App3

                scriptLogger.info("Created '{0}' task mappings.", taskMappings.size())

                for (final SITaskMapping taskMapping : taskMappings) {
                    scriptLogger.info("Mapped runnable {0} to position {1}.",
                    taskMapping.getExecutableEntity().getName(),
                    taskMapping.getPositionInTask())
                }
            }
        }
    }
}

Insert new task mappings always below existing - Part 1
// in this example we have a task on which periodically 50ms trigger are mapped after periodically 10ms trigger
// additionally we want the new task mappings will be insert always at the bottom of each group
// so new 50ms triggered task mappings shall be inserted below the other 50ms triggered task mappings
// and the new 10ms below the other 10ms triggered task mappings

scriptTask("DefineSuccessorsAndInsertBelowAlreadyMapped", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {

        def result = selectEvents {
           or {
               timing(0.01)
               timing(0.05)
           }
        }.mapToTask {
           selectTask {
               name("OsTask")
           }
           mapAllEventsOfRunnableEntity(false, true)

           // example continues on next page

Insert new task mappings always below existing - Part 2
defineSuccessors {

    // you can define it in one forTaskMapping sequence if you want to
    // we use in this example multiple sequences to demonstrate that it is possible to split one complex rule into a few simple rules
    // Note: we use task("OsTask") and the negation instead of mapped() / unmapped(), to eventually correct 10ms and 50ms trigger mapped to other tasks by accident

    // at first define that 10ms trigger shall be mapped ahead of 50ms trigger
    forTaskMapping {
        timing(0.01)
    }.successor {
        timing(0.05)
    }

    // already to 'OsTask' mapped 10ms trigger shall be mapped ahead of the other 10ms trigger
    forTaskMapping {
        timing(0.01)
        task("OsTask")
    }.successor {
        timing(0.01)
        not {
           task("OsTask")
        }
    }

    // and already to 'OsTask' mapped 50ms trigger ahead of the other 50ms trigger
    forTaskMapping {
        timing(0.05)
        task("OsTask")
    }.successor {
        timing(0.05)
        not {
           task("OsTask")
        }
    }
}
                   }

                scriptLogger.info("Created {0} task mappings.", result.size())
               }
             }
           }
         }

Additionally Sort Successors

When you automate the task mapping using successor definition, there might be use cases where you still need the mappings in a 'well human readable' form. For example if you look them up in the task mapping editor from time to time. In that case you can sort the task mappings using the methods below so you can find them faster in the GUI. The sorting algorithm will respect the logical structure that is defined by the successor calls, so that these constraints are still guaranteed.

Quick example, if you define that all periodical 50ms trigger shall be mapped after the periodical 10ms trigger, all 50ms trigger will be sorted among the other 50ms trigger and all 10ms among the other 10ms trigger, without messing up the successor constraint.

sortSuccessorsInternally(Comparator) allows to define an additional comparator to increase the overview. Therefore the defined successors will be analyzed and divided in logical groups. The given comparator is applied on each logical group separately, so that the defined successor relationships will not be violated.
Hint: You can use only one comparator at the same time. So defining a custom comparator and using a default comparator at the same time will cause an exception.

The following default comparators can be used instead:
sortSuccessorsInternallyByExecutableEntity() - sorts the task mappings alphabetically by their executable entity names.

sortSuccessorsInternallyByExecutableEntity() sorts the task mappings of the defined successors alphabetically by their executable entity names. See sortSuccessorsInternally(Comparator) for more details.

To use a custom comparator use sortSuccessorsInternally(Comparator) instead.

Example

Define successors and sort elements for better overview
// in this example we have a task were all mode exit events shall be mapped ahead of  all mode entry events
// but additionally we want to sort them alphabetically without breaking this constraint

// the result will be a task on which all mode exit events are mapped first, sorted alphabetically
// followed by as well alphabetically sorted mode entry events

scriptTask("DefineSuccessorsAndSort", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {

        def result = selectEvents {
           or {
               modeExit()
               modeEntry()
           }
        }.mapToTask {
           selectTask {
               name("OsTask")
           }
           mapAllEventsOfRunnableEntity(false, true)

           defineSuccessors {
               forTaskMapping {
                   modeExit()
               }.successor {
                   modeEntry()
               }

               // you can use an own comparator calling sortSuccessorsInternally(Comparator<ITaskMapping>)
               // in our example we sort alphabetically by executable entity names with a default comparator
               sortSuccessorsInternallyByExecutableEntity()
           }
       }

       scriptLogger.info("Created {0} task mappings.", result.size())
      }
    }
  }
}

Specify an Order

The order of the task mappings can be specified also with the help of an internal structural element, the so called position in task entry.

An SIPositionInTaskEntry represents a position in task for the task mapping. The entry is able to combine several events that are mapped to one position (e.g. needed when mapping a main function of a service component and its corresponding schedulable entity).

order(Consumer) allows to evaluate and change the order of the task mappings. The received SIPositionInTaskEntrys are already sorted respecting the defined successors by defineSuccessors(Action) code. If used, the queue() option may override the order defined by this order(Consumer) call.

It provides a possibility to order the already existing task mappings of the selected task and the new task mappings that should be created.

Example

Simple example of ordering the task mappings
import com.vector.cfg.sysdesc.model.taskmapping.SIPositionInTaskEntry
import com.vector.cfg.sysdesc.model.taskmapping.SITaskMapping

scriptTask ("orderTaskMapppingsSimple", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                     def taskMappings = selectEvents {
                    component("App1")
                } mapToTask {
                    selectTask {
                        name("OsTask")
                    }
                    order {
                        List<SIPositionInTaskEntry> entries ->

                        for (SIPositionInTaskEntry entry : entries) {
                            // identify by executable entity name and set the position
                            if (entry.getTriggeredExecutableEntity().equals("DataSendComp")) {
                                // Runnable 'DataSendComp' will be mapped
                                // to position 0 on task 'OsTask'
                                entry.setPosition(0)
                                continue
                            } else if (entry.getTriggeredExecutableEntity().equals("Runnable1")) {
                                entry.setPosition(1)
                                continue
                            } else if (entry.getTriggeredExecutableEntity().equals("Runnable2")) {
                                entry.setPosition(2)
                                continue
                            }
                        }
                    }
                }

                // print info to the console which runnable was mapped to which position
                for (final SITaskMapping taskMapping : taskMappings) {
                    scriptLogger.info("Mapped runnable {0} to position {1}.",
                    taskMapping.getExecutableEntity().getName(),
                    taskMapping.getPositionInTask())
                }
            }
        }
    }
}

Manually order the task mappings
import com.vector.cfg.sysdesc.model.taskmapping.SIPositionInTaskEntry

scriptTask ("orderTaskMapppings", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                     def taskMappings = selectEvents {
                    component("App1")
                } mapToTask {
                    selectTask {
                        name("OtherName")
                    }
                    order {
                        List<SIPositionInTaskEntry> entries ->

                        int mappedIndex = 0
                        int index = 10

                        for (SIPositionInTaskEntry entry : entries) {
                            // identify by executable entity name
                            if (entry.getTriggeredExecutableEntity().equals("DataSendComp")) {
                                entry.setPosition(9)
                                continue
                            }

                            // already mapped on task
                            def alreadyMapped = entry.getAssociatedTaskMappings().find {
                                taskMapping -> taskMapping.getMappedTask() != null
                            }
                            if (alreadyMapped != null) {
                                entry.setPosition(mappedIndex)
                                mappedIndex++
                                continue
                            }

                            // newly mapped
                            entry.setPosition(index)
                            index++
                        }
                    }
                }

                scriptLogger.info("Created '{0}' task mappings.", taskMappings.size())
            }
        }
    }
}

Order task mappings on OsTask
import com.vector.cfg.sysdesc.model.taskmapping.SIPositionInTaskEntry

scriptTask ("orderTaskMapppingsOfOsTask", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                     def taskMappings = selectEvents {
                    task("OsTask")
                } mapToTask {
                    filterTaskMappings {
                        task("OsTask")
                    }
                    selectTask {
                        name("OsTask")
                    }
                    order {
                        List<SIPositionInTaskEntry> entries ->

                        // in this example runnables of App1, App2 and App3 (with only 1 task mapping) are mapped on OsTask
                        // sort the runnables by owner
                        int runnablesOfApp1 = 0
                        int runnablesOfApp2 = 0
                        for (SIPositionInTaskEntry entry : entries) {
                            if (entry.getOwner().equals("Component App1")) {
                                runnablesOfApp1++
                            }
                            if (entry.getOwner().equals("Component App2")) {
                                runnablesOfApp2++
                            }
                        }

                        // we sort in this example first runnables of 'App1'
                        // followed by the runnabels of 'App2'
                        // and last but not least the runnable of 'App3'
                        int maxIndex = entries.size() - 1
                        int indexForApp1 = 0
                        int indexForApp2 = runnablesOfApp1

                        for (SIPositionInTaskEntry entry : entries) {
                            // the runnable of App3 should be mapped to the last position on OsTask
                            if (entry.getOwner().equals("Component App3")) {
                                entry.setPosition(maxIndex)
                            }
                            if (entry.getOwner().equals("Component App1")) {
                                entry.setPosition(indexForApp1)
                                indexForApp1++
                            }
                            if (entry.getOwner().equals("Component App2")) {
                                entry.setPosition(indexForApp2)
                                indexForApp2++
                            }
                        }
                    }
                }
                scriptLogger.info("Created '{0}' task mappings.", taskMappings.size())
            }
        }
    }
}

Filter Task Mappings

There is a way to narrow down the selected task mappings after selecting events or executable entities. This might be helpful especially in case you use multi-instantiation of software components. Since the selection of task mappings is only available for the task mappings use case, there is no own chapter for it.

filterTaskMappings(Action) allows to filter the task mappings that should be created. This might be especially helpful to narrow down the task mappings after selecting events or executable entities when using multi instantiation (e.g. to filter the task mappings for only one instance of a multi instantiated component prototype).

Per default the predicates are combined via logical AND. To realize other combinations, use the 'or','not' and 'and' predicates.

Task Mapping Predicates

  • component(String) matches task mappings whose event is part of the internal behavior of a component with the given component name.
  • component(Pattern) matches task mappings whose event is part of the internal behavior of a component with the given component name pattern.
  • moduleConfiguration(String) matches task mappings whose event is part of the internal behavior of a module configuration with the given module configuration name.
  • moduleConfiguration(Pattern) matches task mappings whose event is part of the internal behavior of a module configuration with the given module configuration name pattern.
  • moduleConfigurationAsrPath(String) matches task mappings whose event is part of the internal behavior of a module configuration with the given module configuration autosar path.
  • moduleConfigurationAsrPath(Pattern) matches task mappings whose event is part of the internal behavior of a module configuration with the given module configuration autosar path pattern.
  • unmapped() matches task mappings which are not mapped to a task.
  • mapped() matches task mappings which are mapped to a task.
  • task(String) matches task mappings which are mapped to a task with the given task name.
  • task(Pattern) matches task mappings which are mapped to a task whose name matches the given task name pattern.
  • componentType(String) matches task mappings which belongs to component types with the given component type name.
  • componentType(Pattern) matches task mappings which belongs to component types matching the given component type name pattern.
  • componentTypeAsrPath(String) matches task mappings which belongs to component types with the given component type autosar path.
  • componentTypeAsrPath(Pattern) matches task mappings which belongs to component types matching the given component type autosar path pattern.
  • event(String) matches task mappings for events with the given event name.
  • event(Pattern) matches task mappings for events matching the given event name pattern.
  • eventAsrPath(String) matches task mappings for events with the given event autosar path.
  • eventAsrPath(Pattern) matches task mappings for events matching the given event autosar path pattern.
  • bswEvent() matches task mappings for bsw events.
  • rteEvent() matches task mappings for rte events.
  • timing() matches task mappings for timing events.
  • timing(Double) matches task mappings for timing events with the given period (seconds).
  • init() matches task mappings for init events.
  • dataReceived() matches task mappings for data received events.
  • dataReceiveError() matches task mappings for data receive error events.
  • dataSendCompleted() matches task mappings for data send completed events.
  • dataWriteCompleted() matches task mappings for data write completed events.
  • operationInvoked() matches task mappings for operation invoked events.
  • operationInvoked(String) matches task mappings for operation invoked events which are invoked by an operation with the given operationName.
  • serverCallReturns() matches task mappings for events which are asynchronous server call returns events.
  • modeSwitch() matches task mappings for mode switch events.
  • modeEntry() matches task mappings for mode switch events with activation kind ON-ENTRY.
  • modeExit() matches task mappings for mode switch events with activation kind ON-EXIT.
  • modeTransition() matches task mappings for mode switch events with activation kind ON-TRANSITION.
  • modeSwitchedAck() matches task mappings for mode switched acknowledgement events.
  • externalTrigger() matches task mappings for external trigger occurred events.
  • internalTrigger() matches task mappings for internal trigger occurred events.
  • background() matches task mappings for background events.
  • transformerHardError() matches task mappings for transformer hard error events.
  • mandatory() matches task mappings for events which must be mapped. (The mapping of operation invoked events and bsw events whose schedulable entity has no via symbol matching runnable is optional.)
  • symbol(String) matches task mappings for runnable entities with the given symbol and bsw schedulable entities whose corresponding bsw module entry short name matches the given symbol.
  • symbol(Pattern) matches task mappings runnable entities whose symbol matches the given symbol pattern and bsw schedulable entities whose corresponding bsw module entry short name matches the given symbol pattern.
  • executableEntity(String) matches task mappings for executable entities (functions) with the given name.
  • executableEntity(Pattern) matches task mappings for executable entities (functions) with the given name pattern.
  • executableEntityAsrPath(String) matches task mappings for executable entities (functions) with the given autosar path.
  • executableEntityAsrPath(Pattern) matches task mappings for executable entities (functions) with the given autosar path pattern.
  • filterAdvanced(Predicate) matches task mappings for which the given lambda results to true.

Example

Filter task mappings
scriptTask ("firstTaskMappings", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                def taskMappings = selectExecutableEntities {
                    componentType("App1")
                } mapToTask {
                    selectTask {
                        name("OsTask")
                    }

                    // in this example two components ('App1' and 'App1_1') are of component type 'App1'
                    // do the task mapping only for 'App1_1'
                    filterTaskMappings {
                        component("App1_1")
                    }
                }

                scriptLogger.info("Created '{0}' task mappings.", taskMappings.size())
            }
        }
    }
}

Check Current Task Mapping

The event and the executable entity selections offer getters to retrieve task mappings. Therefore first the given predicate is evaluated to identify which events are selected, then all task mappings which references the selected events are collected.

getTaskMappings() retrieves all SITaskMappings for the selected events (see getEvents()).

Note:
1. In case of multi instantiation of component prototypes, the different instances share the same events, since the event is part of the internal behavior of the component type. Therefore if the event is selected, getTaskMappings() will always return the task mappings for all component prototypes.
2. Since this method can be run outside of a transaction, there might be selected events for which no task mapping container does exist yet. The container cannot be created by calling getTaskMappings(), so no task mapping can be returned. This happens if the system description is not synchronized, after changes in the structured extract were done (see Automation Interface Documentation, chapter about Model Synchronization for examples how to synchronize).

getTaskMappings() retrieves all SITaskMappings for the selected executable entities (see getExecutableEntities()).

Example

Check which events are currently mapped to OsTask
import com.vector.cfg.sysdesc.model.taskmapping.SITaskMapping

scriptTask("checkTaskMapping", DV_PROJECT){
  code {

      // because we use only a getter method and no transaction below,
      // make sure that your system description is synchronized,
      // otherwise task mapping container may be missing or obsolete.
      // since Cfg 5.18 this call is enough to make sure your task mapping containers are up to date
      modelSynchronization.synchronize()

      domain.runtimeSystem {
          def taskName = "OsTask"

          def taskMappings = selectEvents {
              task(taskName)
          // getTaskMappings will apply the predicate and return all task mappings for the selected events
          } getTaskMappings()

          // be careful in case of multi-instantiated component prototypes,
          // since events and executable entities are part of the internal behavior of the component type,
          // you will receive always the task mappings for all instances here
          // (even if the task mappings of the other component prototype instances are not mapped to "OsTask")

          // print info to the console with owner of the task mapping and the mapped task
          for (final SITaskMapping taskMapping : taskMappings) {
              scriptLogger.info("TaskMapping of '{1}' for event '{0}' is mapped to '{2}'.",

              taskMapping.getEvent().getName(),
              taskMapping.getOwnerDescription(),
              taskMapping.getMappedTask() == null ? "no task" : taskMapping.getMappedTask().getName())
          }
      }
  }
}

Keep Existing Task Mappings on Current Position

queue() is an option that allows to keep the task mappings which are already mapped to the selected task on the current position. The new task mappings will be placed in the defined order into existing gaps. That means they are mapped to the lowest free position. This method may override the order defined in defineSuccessors(Action) and order(Consumer).

Example: The selected task 'Task1' has already a TaskMappingA at position 1 and a TaskMappingB at position 3. The task mappings TaskMappingC, TaskMappingD and TaskMappingE (in that order) should be mapped to the same task using the queue() option. The new task mappings will be assigned in the defined order to the next free position on 'Task1'.
So the result will be:
0 -> TaskMappingC (new1)
1 -> TaskMappingA (old)
2 -> TaskMappingD (new2)
3 -> TaskMappingB (old)
4 -> TaskMappingE (new3)

If the options mapAllEventsOfRunnableEntity(boolean, boolean) or combineViaSymbol(boolean) needs to combine an existing mapping with other mappings, the combined task mapping is seen as a new mapping. Its position will be assigned according to the rules of a new mapping explained above. The old mapping which was not combined will be removed. In other words combined task mappings are preferred over single task mappings.

Example

Use the queue option example
scriptTask ("queueExample", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {
                def taskMappings = selectExecutableEntities {
                    componentType("App1")
                } mapToTask {
                    selectTask {
                        name("OsTask")
                    }
                    // this option will consider the existing mappings on the task
                    // if an existing task mapping is not combined for another new incoming mapping, it will remain on its current position
                    queue()
                }

                // if the existing task mapping was combined for another new incoming mapping, it is considered as a new mapping and will appear in the taskMappings below
                scriptLogger.info("Created '{0}' task mappings.", taskMappings.size())
            }
        }
    }
}

Set Activation Offset

You can set the value of the activation offset for the events/executable entities which will be newly mapped.

setActivationOffset(Double) allows to set the activation offset at the created task mappings. The offset will be set for all created task mappings to the given offsetInSeconds value.

It is also possible to set the activation offset parameter value of a task mapping using the event or the executable entity selection without mapping the events/executable entities to a task. You can use this option for example if you just want to set the activation offset and do not care whether the event/executable is already mapped to a task or not.

setActivationOffset(double) sets the activation offset at the task mapping containers for the selected events. If the symbol of a schedulable entity matches a runnable name, the activation offset will be set for both, even if only one of them is selected. (Matching works as for ITaskMapper.combineViaSymbol(boolean).)

setActivationOffset(double)} sets the activation offset at the task mapping containers for the selected executable entities. If the symbol of a schedulable entity matches a runnable name, the activation offset will be set for both, even if only one of them is selected. (Matching works as for ITaskMapper.combineViaSymbol(boolean).)

Examples

Set the activation offset using the event selection
import com.vector.cfg.sysdesc.model.taskmapping.SITaskMapping

scriptTask("setActivationOffset", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
          def taskMappings = selectEvents {
              // define predicates to select your event
              component("App1")
              timing()

          // set the activation offset parameter value
          // for the task mapping to 10 ms
          }.setActivationOffset(0.01)

            // print info to the console with the runnable name which is triggered by the event
            // and the activation offset of the task mapping
            for (final SITaskMapping taskMapping : taskMappings) {
                scriptLogger.info("TaskMapping of runnable {0} has the activation offset {1}.",
                taskMapping.getExecutableEntity().getName(),
                taskMapping.getActivationOffset())
            }
      }
    }
  }
}

Set the activation offset using the executable entity selection
import com.vector.cfg.sysdesc.model.taskmapping.SITaskMapping

scriptTask("setActivationOffset", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
          def taskMappings = selectExecutableEntities {
              // define predicates to select your runnable
              component("App1")
              name("Runnable1")

          // set the activation offset parameter value
          // for the task mapping to 100 ms
          }.setActivationOffset(0.1)

            // print info to the console with runnable name and the activation offset
            for (final SITaskMapping taskMapping : taskMappings) {
                scriptLogger.info("TaskMapping of runnable {0} has the activation offset {1}.",
                taskMapping.getExecutableEntity().getName(),
                taskMapping.getActivationOffset())
            }
      }
    }
  }
}

Set the activation offset while mapping to a task
import com.vector.cfg.sysdesc.model.taskmapping.SITaskMapping

scriptTask("mapAndSetActivationOffset", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
          def taskMappings = selectEvents {
              // define predicates to select your event
              component("App1")
              init()
          } mapToTask {
                // map the event to task 'OsTask'
                selectTask {
                    name("OsTask")
                }
                // set the activation offset parameter value
                // for the task mapping to 10 ms
                setActivationOffset(0.01)
            }

            // print info to the console which runnable was mapped and the activation offset
            for (final SITaskMapping taskMapping : taskMappings) {
                scriptLogger.info("Mapped runnable {0} to position {1} with activation offset {2}.",
                taskMapping.getExecutableEntity().getName(),
                taskMapping.getPositionInTask(),
                taskMapping.getActivationOffset())
            }
      }
    }
  }
}

Set Os Schedule Point

You can also set the value of the OsSchedulePoint parameter for the events/executable entities which will be newly mapped.

setOsSchedulePoint(String) allows to set the OsSchedulePoint at the created task mappings. The schedule point will be set for all created task mappings to the given osSchedulePoint value.

Also, it is possible to set the OsSchedulePoint parameter value of a task mapping using the event or the executable entity selection without mapping the events/executable entities to a task. You can use this option for example if you just want to set the OsSchedulePoint and do not care whether the event/executable is already mapped to a task or not. Typical values are "CONDITIONAL" and "UNCONDITIONAL".

setOsSchedulePoint(String) sets the OsSchedulePoint at the task mapping containers for the selected events. If the symbol of a schedulable entity matches a runnable name, the schedule point value will be set for both, even if only one of them is selected. (Matching works as for ITaskMapper.combineViaSymbol(boolean).)

setOsSchedulePoint(String) sets the OsSchedulePoint at the task mapping containers for the selected executable entities. If the symbol of a schedulable entity matches a runnable name, the OsSchedulePoint will be set for both, even if only one of them is selected. (Matching works as for ITaskMapper.combineViaSymbol(boolean).)

Examples

Set the OsSchedulePoint using the event selection
import com.vector.cfg.sysdesc.model.taskmapping.SITaskMapping

scriptTask("setOsSchedulePoint", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
          def taskMappings = selectEvents {
              // define predicates to select your event
              component("App1")
              timing()

          // set the OsSchedulePoint value
          }.setOsSchedulePoint("CONDITIONAL")

            // print info to the console with the runnable name which is triggered by the event
            // and the schedule point of the task mapping
            for (final SITaskMapping taskMapping : taskMappings) {
                scriptLogger.info("TaskMapping of runnable {0} has the OsSchedulePoint value {1}.",
                taskMapping.getExecutableEntity().getName(),
                taskMapping.getOsSchedulePoint())
            }
      }
    }
  }
}

Set the OsSchedulePoint using the executable entity selection
import com.vector.cfg.sysdesc.model.taskmapping.SITaskMapping

scriptTask("setOsSchedulePoint", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
          def taskMappings = selectExecutableEntities {
              // define predicates to select your runnable
              component("App1")
              name("Runnable1")

          // set the OsSchedulePoint parameter value
          }.setOsSchedulePoint("UNCONDITIONAL")

            // print info to the console with runnable name and the OsSchedulePoint
            for (final SITaskMapping taskMapping : taskMappings) {
                scriptLogger.info("TaskMapping of runnable {0} has the OsSchedulePoint value {1}.",
                taskMapping.getExecutableEntity().getName(),
                taskMapping.getOsSchedulePoint())
            }
      }
    }
  }
}

Set the OsSchedulePoint value while mapping to a task
import com.vector.cfg.sysdesc.model.taskmapping.SITaskMapping

scriptTask("mapAndSetOsSchedulePoint", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
          def taskMappings = selectEvents {
              // define predicates to select your event
              component("App1")
              init()
          } mapToTask {
                // map the event to task 'OsTask'
                selectTask {
                    name("OsTask")
                }
                // set the OsSchedulePoint parameter value
                setOsSchedulePoint("CONDITIONAL")
            }

            // print info to the console which runnable was mapped and the OsSchedulePoint
            for (final SITaskMapping taskMapping : taskMappings) {
                scriptLogger.info("Mapped runnable {0} to position {1} with OsSchedulePoint value {2}.",
                taskMapping.getExecutableEntity().getName(),
                taskMapping.getPositionInTask(),
                taskMapping.getOsSchedulePoint())
            }
      }
    }
  }
}

Set Cyclic Trigger Implementation

You can set the value of the cyclic trigger implementation for the events/executable entities which will be newly mapped.

setCyclicTriggerImplementation(String) allows to set the cyclic trigger implementation at the created task mappings. The cyclic trigger implementation will be set for all created task mappings to the given cyclicTriggerImplementation value.

It is also possible to set the cyclic trigger implementation parameter value of a task mapping using the event or the executable entity selection without mapping the events/executable entities to a task. You can use this option for example if you just want to set the cyclic trigger implementation and do not care whether the event/executable is already mapped to a task or not.

setCyclicTriggerImplementation(String) sets the CyclicTriggerImplementation at the task mapping containers for the selected events. If the symbol of a schedulable entity matches a runnable name, the CyclicTriggerImplementation value will be set for both, even if only one of them is selected. (Matching works as for ITaskMapper.combineViaSymbol(boolean).)

setCyclicTriggerImplementation(String) sets the CyclicTriggerImplementation at the task mapping containers for the selected executable entities. If the symbol of a schedulable entity matches a runnable name, the CyclicTriggerImplementation will be set for both, even if only one of them is selected. (Matching works as for ITaskMapper.combineViaSymbol(boolean).)

Examples

Set the CyclicTriggerImplementation using the event selection
import com.vector.cfg.sysdesc.model.taskmapping.SITaskMapping

scriptTask("setCyclicTriggerImplementation", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
          def taskMappings = selectEvents {
              // define predicates to select your event
              component("App1")
              timing()

          // set the CyclicTriggerImplementation value
          }.setCyclicTriggerImplementation("Auto")

            // print info to the console with the runnable name which is triggered by the event and the cyclic trigger implementation of the task mapping
            for (final SITaskMapping taskMapping : taskMappings) {
                scriptLogger.info("TaskMapping of runnable {0} has the CyclicTriggerImplementation value {1}.",
                taskMapping.getExecutableEntity().getName(),
                taskMapping.getCyclicTriggerImplementation())
            }
      }
    }
  }
}

Set the CyclicTriggerImplementation using the executable entity selection
import com.vector.cfg.sysdesc.model.taskmapping.SITaskMapping

scriptTask("setCyclicTriggerImplementation", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
          def taskMappings = selectExecutableEntities {
              // define predicates to select your runnable
              component("App1")
              name("Runnable1")

          // set the CyclicTriggerImplementation parameter value
          }.setCyclicTriggerImplementation("Auto")

            // print info to the console with runnable name and the CyclicTriggerImplementation
            for (final SITaskMapping taskMapping : taskMappings) {
                scriptLogger.info("TaskMapping of runnable {0} has the CyclicTriggerImplementation value {1}.",
                taskMapping.getExecutableEntity().getName(),
                taskMapping.getCyclicTriggerImplementation())
            }
      }
    }
  }
}

Set the CyclicTriggerImplementation value while mapping to a task
import com.vector.cfg.sysdesc.model.taskmapping.SITaskMapping

scriptTask("mapAndSetCyclicTriggerImplementation", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {
          def taskMappings = selectEvents {
              // define predicates to select your event
              component("App1")
              init()
          } mapToTask {
                // map the event to task 'OsTask'
                selectTask {
                    name("OsTask")
                }
                // set the CyclicTriggerImplementation parameter value
                setCyclicTriggerImplementation("Auto")
            }

            // print info to the console which runnable was mapped and the CyclicTriggerImplementation
            for (final SITaskMapping taskMapping : taskMappings) {
                scriptLogger.info("Mapped runnable {0} to position {1} with CyclicTriggerImplementation value {2}.",
                taskMapping.getExecutableEntity().getName(),
                taskMapping.getPositionInTask(),
                taskMapping.getCyclicTriggerImplementation())
            }
      }
    }
  }
}

Bridge Between MDF and SI Model elements

The Runtime System Domain uses SI Model elements as model abstractions to simplify the structure of the AUTOSAR model. All objects which you select using the selection APIs are SI model elements.

SIModelObject is the common super interface for all SI model elements (as e.g. Object for all java classes). It defines common functionality which all SI model elements provide for generic handling of model abstractions.

On MDF level the base interface for AUTOSAR model objects is the MIObject.

It is possible to switch between model abstractions and MDF objects. This might be helpful for advanced script tasks that extend the current scope of the model abstractions.

getModelAbstractionsForMdfObjects(Collection) is a method for an arbitrary access to all SI-model abstractions which correspond to the given collection of MDF objects.

getMdfObject() is a bridge from the SIModelObject to the underlying MDF object. For compound model abstractions, the main object will be returned, e.g. returns the port for a component port.

Example for navigating between MDF model and model abstractions

Switch between MDF and model abstraction example
import com.vector.cfg.model.asr.access.IAsrReferrableAccess
import java.util.Collections
import com.vector.cfg.model.si.base.SIModelObject
import com.vector.cfg.sysdesc.model.communication.instance.SIAbstractSignalInstance

scriptTask ("switchBetweenMdfAndModelAbstraction", DV_PROJECT ){
    code {
        transaction {
            domain.runtimeSystem {

                // --------------------------------------------------
                // get a model abstraction object for your MDF object
                // --------------------------------------------------
                def referrableAccess = ScriptApi.activeProject.getInstance(IAsrReferrableAccess)

                // get some MDF objects by e.g. using the referrable access
                def mdfSystemSignal = referrableAccess.getReferrableByPath("/VectorAutosarExplorerGeneratedObjects/SYSTEM_SIGNALS/Element_1_b16df82332bcf915")

                def mdfObjects = Collections.singletonList(mdfSystemSignal)

                // get the model abstractions for the MDF objects
                def modelAbstractions = getModelAbstractionsForMdfObjects(mdfObjects)

                // for the system signal an IAbstractSignalInstance is returned, if it is referenced by at least one ISignal
                // so there will be exactly one model abstraction in the collection in this example
                def signalInstanceModelAbstraction
                for (SIModelObject modelAbstraction : modelAbstractions) {
                    if (modelAbstraction instanceof SIAbstractSignalInstance) {
                        signalInstanceModelAbstraction = modelAbstraction
                    }
                }

                if (signalInstanceModelAbstraction == null) {
                    scriptLogger.info("System Signal '{0}' is not referenced by any ISignals",
                    mdfSystemSignal.getName())
                }

                // --------------------------------------------------
                // get a MDF object for your model abstraction object
                // --------------------------------------------------
                def mdfObject = signalInstanceModelAbstraction.getMdfObject()
                // now the system signal can be used on MDF level
            }
        }
    }
}

Deleting Elements

Removing elements is not covered by the runtime system API yet. So we have to use the MDF model for that use case for now (see chapter for MDF model). You can of course use the selection APIs to find the correct elements first (e.g. for the data mappings by selecting the signals and call getDataMappings () method) and then get their MDF objects by calling getMdfObject () which is supported for all objects of the runtime system domain model.

You can find examples for some common use cases below.

Example

Delete connectors to delegation ports
import com.vector.cfg.sysdesc.model.connector.SIConnector
import com.vector.cfg.sysdesc.model.component.SIComponentPort

scriptTask("diconnectDelegationPorts", DV_PROJECT) {
    code {
        transaction {
            domain.runtimeSystem {

                // in this example we want to delete the connectors to all delegation ports

                // select the component ports which should be disconnected first
                List<SIComponentPort> connectedDelegationPorts = selectComponentPorts {
                    connected()
                    delegation()
                }.getComponentPorts()

                // get the connectors to those component ports
                List<SIConnector> connectorsToDelegationPorts = []
                connectedDelegationPorts.each {
                    connectorsToDelegationPorts.addAll(it.getConnectedConnectors())
                }

                // we want to do a report for the disconnected ports
                // therefore we will remember them
                List<SIComponentPort> disconnectedPPorts = []
                List<SIComponentPort> disconnectedRPorts = []

                // now delete the connectors
                connectorsToDelegationPorts.each { SIConnector connector ->
                    // we need to check whether we did not already have deleted the connector
                    // and we need to check if the connector is deletable
                    // connectors which were not created in CFG5 cannot be deleted
                    if (!connector.getMdfObject().isDeleted()
                            && connector.getMdfObject().getCeState().isDeletable()) {
                        // add the component ports for a final report
                        disconnectedPPorts.add(connector.getProviderPort())
                        disconnectedRPorts.add(connector.getRequesterPort())
                        // finally delete the connector
                        connector.getMdfObject().delete()
                    }
                }

                for (int i = 0; i < disconnectedPPorts.size(); i++) {
                    scriptLogger.info("Deleted connector between {0} and {1}.",
                            disconnectedPPorts.get(i).getName(),
                            disconnectedRPorts.get(i).getName())
                }
            }
        }
    }
}

Delete data mappings of sender receiver delegation ports - Part 1
import com.vector.cfg.sysdesc.model.communication.SICommunicationElement
import com.vector.cfg.sysdesc.model.datamapping.SIDataMapping
import com.vector.cfg.sysdesc.model.datamapping.SISenderReceiverDataMapping
import com.vector.cfg.sysdesc.model.communication.SIAbstractSystemSignal

scriptTask("deleteDataMappingsForDelPorts", DV_PROJECT) {
    code {
        transaction {
            domain.runtimeSystem {

                // in this example we want to delete the data mappings of sender receiver delegation ports

                // select the communication elements first
                List<SICommunicationElement> communicationElements = selectCommunicationElements {
                    delegation()
                    senderReceiver()
                    mapped()
                }.getCommunicationElements()

                // get the data mappings of these communication elements
                List<SIDataMapping> dataMappingsToDelete = []
                communicationElements.each {
                    dataMappingsToDelete.addAll(it.getDataMappings())
                }
                // example continues on next page

Delete data mappings of sender receiver delegation ports - Part 2
                // we want to do a report for the removed data mappings
                // therefore we will remember communication element and signal
                List<SICommunicationElement> comElementsOfDeletedMapping = []
                List<SIAbstractSystemSignal> signalsOfDeletedMappings = []

                // now delete the data mappings
                dataMappingsToDelete.each { SIDataMapping dataMapping ->
                    // we need to check if the data mapping is deletable
                    // data mappings which were not created in CFG5 cannot be deleted
                    if (!dataMapping.getMdfObject().isDeleted()
                            && dataMapping.getMdfObject().getCeState().isDeletable()) {
                        // add the component ports for a final report
                        comElementsOfDeletedMapping.add(dataMapping.getCommunicationElement())
                        signalsOfDeletedMappings.add(dataMapping.getSystemSignal())

                        // we want to extend the reporting for sender receiver to signal group mappings
                        // report not only the signal group but also the group signal mappings
                        if (dataMapping instanceof SISenderReceiverDataMapping) {
                            ((SISenderReceiverDataMapping) dataMapping).getLeafDataMappings().each {
                                SISenderReceiverDataMapping childMapping ->
                                    comElementsOfDeletedMapping.add(childMapping.getCommunicationElement())
                                    signalsOfDeletedMappings.add(childMapping.getSystemSignal())
                            }
                        }

                        // finally delete the data mappings
                        // for sender receiver to signal group mappings it is enough to delete the root mapping
                        dataMapping.getMdfObject().delete()
                    }
                }

                for (int i = 0; i < comElementsOfDeletedMapping.size(); i++) {
                    scriptLogger.info("Deleted data mapping for {0} to signal {1}",
                            comElementsOfDeletedMapping.get(i).getFullyQualifiedName(),
                            signalsOfDeletedMappings.get(i).getName())
                }
            }
        }
    }
}

Variant Handling

The only use case that supports PostBuild selectable variance in the runtime system domain is the mapping between communication elements and signals (data mapping). If you have a variant project the data mapping can only be done in an active model view (see chapter about model views).

There is no edit variance function for the data mapping in the automation API yet. But if a signal is visible in exactly one variant, the created data mapping will automatically be created only for the variant in which the signal is visible. For invariant signals the created data mappings will also be invariant.

So a good approach for PostBuild variant configurations is to loop over the model views and run your script logic for each view.

Create variant data mappings
import com.vector.cfg.model.asr.view.IModelViewExecutionContext

// this example runs also successfully for project with no PostBuild variance
// because there just be only one model view - the invariant model view

scriptTask("dataMapVariant", DV_PROJECT) {
    code {
        transaction {
            domain.runtimeSystem {

                for (def modelView in variance.allPostBuildVariantViews) {
                    final IModelViewExecutionContext context = modelView.executeWithThisView()

                    // make sure to close the view when finish (even if exceptions occur) to not run further actions still in this view by accident
                    context.withCloseable {

                        // do the data mapping inside this closure, we will keep the example simple here
                        // remember: IAbstractSignalInstaces may also be variant
                        // so they should be selected also with an active model view
                        selectCommunicationElements {
                            // the auto mapper will not create mappings which are real duplicates
                            // but it is better in terms of performance to filter for unmapped here
                            unmapped()
                        }.autoMap()
                    }
                }
            }
        }
    }
}

Retrieving Short Name Paths and Fully Qualified Names

The runtime system automation API requires/allows to use short name paths and fully qualified names to select elements. This chapter describes how these can be retrieved.
In general you can find a 'Copy' -> 'Copy Short Name Path' command in the context menu for most elements in the GUI.
For the automation interface you can use appropriate getters depending on your use case.

Path of Port Interface Mapping

If you have already connected two ports and use a port interface mapping for the connection, you can search for your connector in the ECU Software Components Editor. You can find it in the Application Ports grid or the Service Mappings grid under the ECU Composition node or under the Application or Service Ports node of your application or service component.

'Copy' -> 'Copy Short Name Path' in the context menu available in the Port Interface Mapping column for a given connection copies the short name path of the connection's port interface mapping to the clip board.

If you have no connection yet which uses the port interface mapping, search for the port interface mapping in another way. Expand the Port Interface Mapping Sets node of the ECU Software Components Editor and the node of the set which contains your mapping. Now you can do the 'Copy' -> 'Copy Short Name Path' command in the context menu of the tree node which belongs to the port interface mapping your were looking for.

Paths of System Signals and System Signal Groups

GUI: If you have already used your signal / signal group for a data mapping, you can find the data mapping in the Data Mapping or the Application Ports grid under the ECU Composition node. Once you found your mapping you can retrieve the short name path of the signal / signal group via the 'Copy' -> 'Copy Short Name Path' context menu on the cell of the Signal column in the Data Mapping grid or the Mapped Signal column of the Application Ports grid.

AI: The following getter methods might be useful (see Javadoc of the method for more details):

  • SIAbstractSignalInstance.getAutosarPath ()
  • SIAbstractSignalInstance.getFullyQualifiedName () - This getter might help you identifying group signals.

Fully Qualified Name of Communication Elements

GUI: Communication elements are used for data mappings. Their fully qualified name is build out of three parts (in general, children of complex communication elements might have more). The name of the component, the name of the port and the name of the data element/operation/trigger itself. In case of a delegation port you can use 'ECU Composition' or 'COMPOSITIONTYPE' as component name.

Examples

Communication element of non-delegation port:
'ComponentName.PortName.DataElementName'

Communication element of delegation port:
'ECU Composition.DelegationPortName.DataElementName'

Complex communication element (record element of a record):
'ComponentName.PortName.RecordName.RecordElement1Name'

Complex communication element (array element at certain index):
'ComponentName.PortName.ArrayName[0]'

Open the data mapping assistant. You can find it in the navigation view under Runtime System -> Add Data Mapping or as hyperlink above grids which shows data mappings. Select the direction 'Find matching signals for the communication elements' on the first page and after that your communication elements on the second page. Now on the third page (Confirm page) you can open a context menu on the cell in the Communication Element column of your communication element and select copy fully qualified name. The name will be copied into the clip board. If you need the name of a child communication element which is not shown yet, you might have map the parent to a signal group first.

You can also just use the examples above and replace the names with the names of your component, port and communication element.

AI: The following getter methods might be useful (see Javadoc of the method for more details):

  • SICommunicationElement.getFullyQualifiedName ()

Best Practice And Further Examples

Create Selection Based on Existing Elements

Most selection APIs offer a put method at the selector. This method allows us to put elements into a selection and continue working with elements we already have created or selected previously. The purpose of that is to optimize performance, avoid defining the same predicates over and over again and increase the level of control.

Create delegation ports for selected origin ports and connect them
import com.vector.cfg.sysdesc.model.component.origin.SIOriginComponentPort
import com.vector.cfg.sysdesc.model.connector.SIConnector
import com.vector.cfg.sysdesc.model.component.SIComponentPort

scriptTask("createAndConnectDelegationPort", DV_PROJECT){
  code {
    transaction {
      domain.runtimeSystem {

        List<SIComponentPort> createdDelegationPorts = selectOriginComponentPorts {
            // select some origin context ports
            provided()
            innerTopLevelDelegation()
        }.createFlatExtractDelegationPorts {

            // create a delegation port for each selected origin port
            nameFromOriginPort {  SIOriginComponentPort originPort ->
                originPort.getPortName()
            }
            useDefaultDirection()
        }

        // now use the new ports to put them into a selection
        // we want to use the auto mapper (using the origin context names) to connect them to inner SWC ports
        List<SIConnector> createdConnections = selectComponentPorts {
            put(createdDelegationPorts)
            // we can still use predicates here, they would be applied only to our new ports which we put into the selection
            // for example we could connect only the provided new delegation ports here using additionally the predicate provided()
        } autoMapTo {
            useOriginContextForMatch()
        }

        // and finally do some reporting
        for (final SIConnector connector : createdConnections) {
            final SIComponentPort pPort = connector.getProviderPort()
            final SIComponentPort rPort = connector.getRequesterPort()

            scriptLogger.info("Created new delegation port {0} and connected it to {1}.",
                pPort.isDelegationPort() ? pPort.getName() : rPort.getName(), // our new created delegation port
                pPort.isDelegationPort() ? rPort.getName() : pPort.getName()) // the connected inner application port
        }

     }
    }
  }
}

Optimizing Performance

This chapter will give some advice on what may help if the script execution times get too high. In general we recommend to optimize the readability of your code in first place, but in some cases when processing a large number of objects restructure the code according to the points below may reduce the execution time of the script code.

Check complexity of the script code:

Scripts may get slow if the code iterate over big collections of elements and while doing that performs performance critical operations or iterates over another big collection (n² complexity). This may be also hidden somewhere between the lines. For example if the script needs to do many data mappings or connectors make sure you use the auto map call directly at the selection APIs and as few times as possible or use the simple API inside which you can put lists of elements at once instead of doing the calls for one single object after another.

In general the script performs better, when suitable data structures are prepared first so that the total amount of modification calls (e.g. autoMapTo (Closure) at the component port selection) at the selection APIs can be reduced.

Do not open unnecessary transactions and not over extend usage of transactions:

Each transaction has an overhead, for example the validation results needs to be updated. So avoid opening multiple transactions if there is no benefit for you by doing that. A good example is if you want to create 500 data mappings. You can do every single mapping in an own transaction or all in one transaction. If you do not need the undo operation for every single mapping separately, you should always prefer to do all 500 mappings in one transaction.

Narrow down selections where possible without significant effort:

For example when you connect ports and you have many already connected ports which you do not care about, use the unmapped predicate to not selecting them at all. The auto mapper will have to match less elements.

Prefer reusing elements over selecting elements:

Let's assume you have created new delegation ports and want to connect them to other component ports. After creating the new ports use the returned list and put it into the component port selection to connect them. This will be more efficient then defining predicates that match to that newly created ports.

Use @CompileStatic for advanced filters:

If your scripts use advanced filters whose closures need to be evaluated a large number of times, the code should be refactored so that the closure is built by an own method which uses @CompileStatic. That makes the advanced filter faster, since the closure needs to be compiled only one single time.

Avoid switching very often between selecting and creating elements

We use internal caches for many attributes and dependencies between elements which needs to be invalidated every time when model changes are performed. So if your selection does not depend on the model changes which you want to do in next steps, prefer to select all elements you need first and then start modifying the model.

So for example instead of:

  • select communication elements for sender receiver data mappings
  • create sender receiver data mappings
  • select operation communication elements for client server data mappings
  • create client server data mappings

The following workflow will use the caches more efficient:

  • select communication elements for sender receiver data mappings
  • select operation communication elements for client server data mappings
  • create sender receiver data mappings
  • create client server data mappings

Access to CEState of SI Model elements

For the domain model objects of the runtime system domain, the CEState can be retrieved via the underlying MDF object. So, first call getMdfObject at the according model abstraction and then call the getCEState getter. The CEState helps to identify if the object can be changed or deleted.

For example when deleting data mappings, some of them might have been created in the DaVinci Developer workspace and therefore cannot be deleted in Cfg5.

Evaluate CEState of Data Mapping
import com.vector.cfg.sysdesc.model.communication.SICommunicationElement
import com.vector.cfg.sysdesc.model.datamapping.SIDataMapping
import com.vector.cfg.model.mdf.ar4x.systemtemplate.datamapping.MIDataMapping

scriptTask("DeleteDataMappingDependingOnCEState", DV_PROJECT){
    code {
        transaction {
            domain.runtimeSystem {
                def selectedComElements = selectCommunicationElements {
                }.getCommunicationElements()

                for (SICommunicationElement comElement : selectedComElements) {
                    for (SIDataMapping dataMapping : comElement.getDataMapping()) {
                        // to get the CEState we need the underlying MDF object
                        MIDataMapping mdfDataMapping = (MIDataMapping) dataMapping
                        // now get CEState of MDF object
                        // if the Data Mapping is from DaVinci DEV workspace
                        // the CEState would return 'false' here
                        if (mdfDataMapping.getCeState().isDeletable()) {
                            mdfDataMapping.delete()
                        }
                    }
                }
            }
        }
    }
}