Détails d'une transformation de modèle à modèle avec des règles garantissant que les profils UML sont appliqués correctement aux modèles cible

Si la transformation met à jour un modèle existant au lieu de le réécrire complètement ou d'en créer un nouveau, les profils UML doivent être appliqués correctement aux versions en mémoire du modèle nouvellement généré et du modèle cible existant, qui est chargé dans la mémoire pendant l'opération de fusion. Ces modèles en mémoire doivent faire référence à la même instance en mémoire de chaque profil UML, sous peine d'empêcher leur fusion.

L'exécution d'une transformation de mappage de modèle à modèle génère un modèle temporaire en mémoire. Si le contenu de ce modèle est différent de celui d'un modèle cible existant dans le système de fichiers, les deux modèles sont fusionnés durant la phase de post-traitement de la transformation. La procédure de fusion par défaut, qui est une règle de transformation fournie dans l'infrastructure de transformation de modèle à modèle, charge le modèle cible existant en mémoire et utilise la fonctionnalité de fusion structurelle pour le combiner avec le modèle généré en mémoire. Le modèle résultant de la fusion structurelle remplace le modèle cible existant.

Les modèles contiennent souvent des références à des objets dans d'autres modèles. Par exemple, un modèle UML peut contenir des références à des stéréotypes définis dans des profils UML, ou bien il peut contenir des références à des types primitifs définis dans des bibliothèques UML. La fonctionnalité de fusion structurelle détecte que ces références intermodèles désignent le même objet uniquement si elles pointent sur la même instance en mémoire de cet objet.

Par exemple, supposons que le stéréotype «Perspective», qui est défini dans le profil UML nommé Default, est appliqué au package ExamplePackage dans un modèle généré en mémoire, ainsi qu'au même package dans le modèle cible existant. Lorsque le modèle cible existant est chargé en mémoire en vue de sa fusion structurelle, la référence au stéréotype «Perspective» est résolue. Si la fusion structurelle identifie une instance de l'objet stéréotype en mémoire qui n'est pas exactement la même que celle qui est référencée par le modèle généré en mémoire, elle ne peut pas détecter que le même stéréotype est appliqué aux deux versions du package ExamplePackage. Par défaut, la fusion structurelle s'arrête lorsqu'elle détecte des instances en double du même modèle chargées et référencées par les modèles à fusionner ; dans notre exemple, c'est le cas du profil UML Default.

Pour éviter que plusieurs instances d'un même modèle ne soient chargées dans la mémoire, assurez-vous que le jeu de ressources qui contient les modèles en mémoire ne comporte qu'une seule instance de chaque modèle.

Ce projet exemple de transformation fournit deux règles de transformation pour garantir que les profils UML sont appliqués correctement :
  • UMLDefaultLibrariesAddRule : utilisez cette règle pour ajouter d'une manière cohérente les bibliothèques et profils UML par défaut à un modèle généré en mémoire.
  • CrossModelReferenceCheckRule : utilisez cette règle pour vérifier qu'un modèle généré ne présente pas de références intermodèles qui soient externes à son jeu de ressources. De telles références externes pourraient faire échouer la fusion du modèle généré en mémoire et de la version chargée en mémoire du modèle cible existant.

Ces règles sont situées dans le package com.ibm.xtools.transform.authoring. Pour plus d'informations à leur propos, reportez-vous au manuel Rational Transformation Authoring Developer Guide API Reference. La transformation dans cet exemple utilise les deux règles. Explorez le code source généré de la transformation pour voir où elles sont instanciées dans les sections du code source que vous pouvez personnaliser.

Les fragments de code suivants montrent comment utiliser la règle nommée UMLDefaultLibrariesAddRule.

Le fragment de code suivant montre l'implémentation par défaut de la méthode addTransformElements dans la classe générée Model2ModelTransform ; la classe par défaut ne contient pas la règle. Dans la classe générée Model2ModelTransform, la méthode addTransformElements instancie la règle :
    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated
     */
    private void addTransformElements(Registry registry) {
      // You may add more transform element before the generated ones here
    	// Remember to remove the @generated tag or add NOT to it
    	addGeneratedTransformElements(registry);
    	// You may add more transform element after the generated ones here
    	// Remember to remove the @generated tag or add NOT to it
    }
Le fragment de code suivant montre comment la méthode addTransformElements instancie la règle :
Remarque : Pour empêcher le processus de génération de code source d'écraser les changements apportés au code, vous devez retirer la balise @generated ou la modifier comme dans le fragment de code suivant.
    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated NOT
     */
    private void addTransformElements(Registry registry) {
      add(new UMLDefaultLibrariesAddRule());
      // You may add more transform element before the generated ones here
    	// Remember to remove the @generated tag or add NOT to it
    	addGeneratedTransformElements(registry);
    	// You may add more transform element after the generated ones here
    	// Remember to remove the @generated tag or add NOT to it
    }
Le fragment de code suivant montre la version originale de la méthode createRootTransformation dans la classe générée TransformationProvider, sans la règle CrossModelReferenceCheckRule :
Remarque : Dans l'exemple, l'implémentation de la classe TransformationProvider s'appelle copyprofileTransformationProvider.
    /**
     * Creates a root transformation. You may add more rules to the transformation here
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @param transform The root transformation
     * @generated
     */
    protected RootTransformation createRootTransformation(ITransformationDescriptor descriptor) {
        // Create and return an instance of a class that extends RootTransformation 
        // and handles source objects of type = (resource) and target objects of type = (resource)
        // and remove the @generated tag.  The default implementation provided here is
        // for source and target objects of type = (resource).
        return new RootTransformation(descriptor, new MainTransform()) {
            protected void addPostProcessingRules() {
                add(new UMLProfilesConsistencyCheckRule());
                super.addPostProcessingRules();
            }};
    }
Le fragment de code suivant montre l'instanciation de la règle CrossModelReferenceCheckRule dans la méthode createRootTransformation :
Remarque : Dans l'exemple, l'implémentation de la classe TransformationProvider s'appelle copyprofileTransformationProvider.
    /**
     * Creates a root transformation. You may add more rules to the transformation here
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @param transform The root transformation
		 * @generated NOT
     */
    protected RootTransformation createRootTransformation(ITransformationDescriptor descriptor) {
        // Create and return an instance of a class that extends RootTransformation 
        // and handles source objects of type = (resource) and target objects of type = (resource)
        // and remove the @generated tag.  The default implementation provided here is
        // for source and target objects of type = (resource).
        return new RootTransformation(descriptor, new MainTransform()) {
            protected void addPostProcessingRules() {
                add(new CrossModelReferenceCheckRule());
                add(new UMLProfilesConsistencyCheckRule());
                super.addPostProcessingRules();
            }};
    }
Par défaut, la règle CrossModelReferenceCheckRule émet une exception si elle découvre, dans le modèle généré en mémoire, une référence qui n'est pas résolue dans le même jeu de ressources que celui du modèle cible existant. Pour voir cette exception, effectuez les étapes suivantes :
  1. Dans la classe Model2ModelTransform, mettez en commentaire la règle UMLDefaultLibrariesAddRule.
  2. Exécutez la transformation.
La transformation émet une exception et s'arrête, car le modèle généré en mémoire fait référence à la bibliothèque UML Primitives, mais le jeu de ressources de ce modèle ne contient pas la bibliothèque Primitives.

Vos commentaires