Transactions

Model changes must always be executed within a transaction. The automation API provides some simple means to execute transactions.

For details about transactions read ModelChanges.

Execute a transaction
scriptTask("TaskName", DV_PROJECT){
    code {
        transaction{
            // Your transaction code here
        }
    }
}

Execute a transaction with a name
scriptTask("TaskName", DV_PROJECT){
    code {
        transaction("Transaction name") {
            // The transactionName property is available inside a transaction
            String name = transactionName
        }
    }
}

Handle a TransactionException
import com.vector.cfg.model.uow.TransactionException
scriptTask("TaskName", DV_PROJECT){
    code {
      try {
        transaction("Transaction") {
            // Any exception occurs
            throw new RuntimeException()
        }
      } catch (TransactionException ex) {
        assert ex.getMessage() == "Failed executing transaction 'Transaction'"
      }
    }
}

The transaction name has no additional semantic. It is only be used for logging and to improve error messages.

Nested Transactions

If you open a transaction inside a transaction the inner transaction is ignored and it is as no transaction call was done. So be aware that nested transactions are no real transaction, which leads to the fact the these nested transactions can not be undone.

If you want to know whether a transaction is already running, see the transactions API below.

Transactions API

The Transactions API with the keyword transactions provides access to running transactions or the transaction history. You can use method isTransactionRunning() to check if a transaction is currently running. The method returns true, if a transaction is running in the current Thread.

Check if a transaction is running
scriptTask("TaskName", DV_PROJECT){
    code {
        // Switch to the transactions API
        transactions{

            //Check if a transaction is running
            assert isTransactionRunning() == false

            // Open a transaction
            transaction{
                // Now a transaction is running
                assert isTransactionRunning() == true
            }
        }
        // Or the short form
        transactions.isTransactionRunning()
    }
}

TransactionHistory

The transaction history API provides some methods to handle transaction undo and redo. This way, complex model changes can be reverted quite easily.

  • The undo() method executes an undo of the last transaction. If the last transaction frame cannot be undone or if the undo stack is empty this method returns without any changes.
  • The undoAll() method executes undo until the transaction stack is empty or an undoable transaction frame appears on the stack.
  • The redo() method executes an redo of the last undone transaction. If the last undone transaction frame cannot be redone or if the redo stack is empty this method returns without any changes.
  • The canUndo() method returns true if the undo stack is not empty and the next undo frame can be undone. This method changes nothing but you can call it to find out if the next undo() call would actually undo something.
  • The canRedo() method returns true if the redo stack is not empty and the next redo frame can be redone. This method changes nothing but you can call it to find out if the next redo() call would actually redo something.
  • The clearUndoRedoHistory() method clears the undo/redo history. After this method was called, all previous undo and redo information are lost and can not be restored.
  • The setUndoHistoryLimit(int) method allows to limit the number of the undo history stack size to the given value.

Undo a transaction with the transactionHistory
scriptTask("TaskName", DV_PROJECT){
    code {
        transaction("TransactionName") {
            // Your transaction code here
        }

        transactions{
            assert transactionHistory.canUndo()

            transactionHistory.undo()

            assert !transactionHistory.canUndo()
        }
    }
}

Redo a transaction with the transactionHistory
scriptTask("TaskName", DV_PROJECT){
    code {
        transaction("TransactionName") {
            // Your transaction code here
        }

        transactions{
            transactionHistory.undo()

            assert transactionHistory.canRedo()

            transactionHistory.redo()

            assert !transactionHistory.canRedo()
        }
    }
}

Clear the undo/redo history with the transactionHistory
scriptTask("TaskName", DV_PROJECT){
    code {
        transaction("Transaction1") {
            // Your transaction code here
        }

        transaction("Transaction2") {
            // Your transaction code here
        }

        transactions{

            assert transactionHistory.canUndo()

            transactionHistory.undo()

            assert transactionHistory.canRedo()

            assert transactionHistory.canUndo()

            transactionHistory.clearUndoRedoHistory()

            assert !transactionHistory.canRedo()

            assert !transactionHistory.canUndo()
        }
    }
}

Set the undo history limit with the transactionHistory
scriptTask("TaskName", DV_PROJECT){
    code {
        transactions{
           transactionHistory.setUndoHistoryLimit(1)
        }

        transaction("Transaction1") {
            // Your transaction code here
        }

        transaction("Transaction2") {
            // Your transaction code here
        }

        transactions{

            assert transactionHistory.canUndo()

            transactionHistory.undo()

            assert !transactionHistory.canUndo()
        }
    }
}

Operations

The model operations implement convenient means to execute complex model changes like AUTOSAR module activation or cloning complete model sub-trees. The operations API is available inside of a transaction with the keyword operation. The class IOperations defines the available methods.

  • The method activateModuleConfiguration(DefRef) activates the specified module configuration. This covers:
    • Creation of the module including the reference in the ActiveEcuC (the ECUC-VALUE-COLLECTION)
    • Creation of mandatory containers and parameters (lower multiplicity > 0)
    • Applying the recommended configuration
    • Applying the pre-configuration values

    Note: If the DefRef has a wildcard, activateModuleConfiguration(DefRef) tries to activate the most specific module definition matching the wildcard, if unique. If it is not unique the method will throw an exception. For example the DefRef /[ANY]/Dio will activate the /MICROSAR/Dio instead of /AUTOSAR/EcucDefs/Dio.

    transaction{
        // Activates the Dio module
        operations.activateModuleConfiguration(sipDefRef.Dio)
    }
  • The method deactivateModuleConfiguration(MIModuleConfiguration) deletes the specified module configuration from the model. In case of a split configuration, the related persistency location is being removed from the project settings. In XML file base configurations, the related file is being deleted during the next project save if it doesn't contain configuration objects anymore. If the module configuration is referenced from the active-ECUC this link is being removed too.
  • The method changeBswImplementation(MIModuleConfiguration, MIBswImplementation) changes the BSW-implementation of a module configuration including the definition of all contained containers and parameters.
  • setConfigurationVariantOfAllModuleConfigurations(EEcucConfigurationVariant) sets the implementation configuration variant of all active MIModuleConfiguration. If a module configuration does not support the requested variant it is ignored.

    Supported enum values are:

    • EEcucConfigurationVariant
      • VARIANT_PRE_COMPILE
      • VARIANT_LINK_TIME
      • VARIANT_POST_BUILD_LOADABLE

    This is for post-build loadable only! See the method setConfigurationVariant() in class IEcucModuleConfiguration for details.

  • The deepClone(MIObject, MIObject) operation copies (clones) a complete MDF model sub-tree and adds it as child below the specified parent.
    • The source object must have a parent. The clone will be added to the same MDF feature below the destination parent then
    • AUTOSAR UUIDs will not be cloned. The clone will contain new UUIDs to guarantee unambiguousness
  • The method createModelObject(Class) creates a new element of the passed modelClass (meta class). The modelObject must be added to the whole AUTOSAR model, before finishing the transaction.
  • The method createUniqueMappedAutosarPackage(AsrPath, Path, IVersion) can be used to create new MIARPackages in new arxml files. It creates an new instance of the specified AUTOSAR package and adds it to the model tree. All non-existing parent packages will be created too. The new package (including new created parent packages) will be mapped uniquely to the specified location (Path and AUTOSAR version).