Model Migration

When changing on the metamodel, it has to made sure that old models still load in AutoFOCUS3. Models cannot be loaded any more after renaming or deletion of model elements such as classes or attributes. Plugins that are part of the release have to load all models from release n also in release n+1 (backward compatibility). Therefore the AutoFOCUS3 kernel offers a MigrationService.

Workflow for model changes after release n

  • Do not delete deprecated model elements (e.g. entire classes, but also single fields) in release n+1.
    • Rather, mark all concrete classes with a @deprecated comment (interfaces and abstract classes cannot be instantiated and may be omitted).
    • This causes the @Deprecated annotation to be added to the respective classes and field accessor methods in the generated source code.
    • Instructions
      • Open ecore file with Sample Ecore Model Editor (default editor)
      • Context menu -> fortiss EMF tools -> Generate comment templates.
      • Ensure that Eclipse Properties view is visible (can be opened e.g. by typing "Properties" in Quick Access control)
      • Select GenModel -> documentation node that as been created for the respective
      • Edit value properties field and change it to @deprecated
      • Hint: To speed up the process, you may also copy and paste the initial GenModel deprecation node.
  • Write an IMigrationProvider for your plugin that adjusts old models to the new model (e.g. remove, rename, ...). See below.
    • Test model changes with all example models that are available in the file menu.
    • Update the models shipped in the test-data directory of the RCP plugin (can be done when all migrators required for the current release are ready).
  • Actual removal of deprecated metamodel elements:
    • After publishing the release n+1, the deprecated model elements and migration code written between release n and n+1 can be deleted.
    • It is advised to create an issue for release n+2 to ensure that this cleanup task is actually performed.

Writing an IMigrationProvider

  • Option 1: Directly implement org.fortiss.tooling.kernel.extension.base.IMigrationProvider.
    • needMigration() is a predicate that determines if the migrator has to be applied to a given model
    • migrate() performs the actual migration
    • org.fortiss.tooling.base.utils.MigrationUtils contains useful methods to migrate Kernel / Tooling-Base based models
  • Option 2: Use org.fortiss.tooling.kernel.extension.base.RemoveDeprecatedArtifactsMigrationProviderBase
    • Implement getDeprecatedArtifacts(), a method that returns the Collection of deprecated artifact types to be removed from the model.
    • Optionally also implement getDeprecatedRootArtifacts(), a method that returns the Collection of deprecated root artifact types (possibly empty subset of
      getDeprecatedArtifacts()) for which a comment is added to the migrated model that deprecated artifacts have been removed.
  • Register migration provider
       <extension point="org.fortiss.tooling.kernel.migrationProvider">
          <migrationProvider migrationProvider="org.fortiss.af3.xy.model.migration.AbcMigrationProvider">
             <objectClass objectClass="org.fortiss.some.package.model.ProjectRootElement"/>
  • Hints
    • Migration service initializes and starts very early, e.g. before the persistency service and the logging service.
    • During startup, the actual migration is triggered from the (also very early in the AF3 initialization / startup phase).
    • For this reason, operations that are based on these services may not be used when implementing a model migrator, e.g.