urbanisation-si.com

urbanisation-si.com

Ingénierie Dirigée par les Modèles (IDM)


Cours complet sur ATL (ATLAS Transformation Language) : le code impératif ATL, l’instruction de test : if

cours-complet-atl-atlas-transformation-language-code-imperatif-test-if.jpg

 

Dans l'article précédent :

https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-le-code-imperatif-atl-linstruction-daffectation

nous avion abordé le code impératif ATL et  l’instruction d’affectation. Voyons à présent l’instruction de test : if

 

L’instruction if

Syntaxe :

if(condition) {
      statements1
}
[else {
      statements2
}]?

La condition doit être une condition OCL renvoyant une booléen.

ATTENTION : le "then" est obligatoire et le “else” est facultatif. Je ne vais pas vous faire l’affront de vous expliquez à quoi sert in “if” et comment il fonctionne. Google est votre ami, vous trouverez des milliards de sites traitant de la programmation pour débutant.

 

Voici tout de même des exemples :

if(aPerson.gender = #male) {
      thisModule.menNb <- thisModule.menNb + 1;
      thisModule.men->including(aPerson);
}

 

if(aPerson.gender = #male) {
      thisModule.fullName <- 'Mr. ' + aPerson.name + ' ' + aPerson.surname;
}
else {
      if(aPerson.isSingle) {
            thisModule.fullName <- 'Miss ' + aPerson.name;
            thisModule.surname <- aPerson.surname;
      }
      else {
            thisModule.fullName <- 'Mrs. ' + aPerson.name;
            thisModule.surname <- aPerson.marriedTo.surname;
      }
      hisModule.fullName <- thisModule.fullName + ' ' + thisModule.surname;
}

 

if(aPerson.gender = #male)
      thisModule.men->including(aPerson);
else
      thisModule.women->including(aPerson);

 

"L'enthousiasme est une maladie qui se gagne."
Voltaire

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


08/10/2015
0 Poster un commentaire

Cours complet sur ATL (ATLAS Transformation Language) : le code impératif ATL, l’instruction d’affectation

cours-complet-atl-atlas-transformation-language-code-imperatif-affectation.jpg

 

Dans l'article précédent :

https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-introduction-aux-regles-atl

nous avion abordé une introduction aux règles ATL. Voyons à présent le code impératif ATL et  l’instruction d’affectation.

 

Le code impératif ATL

ATL permet aux développeurs de spécifier du code impératif à l’intérieur de blocs dédiés ou dans une règle appelée (“called rule”). Un bloc impératif est composé de sequenceé d’instructioné impérativeé et comme en Java, C ou C++ ou bien d’autres encore, elles sont terminées par un point virgule (";").

L’instruction d’affectation

Permet d’assigner une valeur à des attributs définis dans le contexte du module ATL ou à des éléments du modèle cible.

Syntaxe :

 

target <- exp;

 

Exemple, soit un compteur entier déclaré et initialisé à 0 :

 

helper def: counter : Integer = 0;

 

La valeur du compteur peut être incrémentée dans la portée du bloc impératif :

 

thisModule.counter <- thisModule.counter + 1;

 

Exemple avec un attribut :  

 

aPerson.father.age <- aPerson.age + 25;

 

Exemple d’affectation de référence d’instance à l’intérieur d’une même règle :

 

aPerson.father <- anotherPerson;

De même il est possible d’affecter une référence d’un élément de modèle généré par une autre règle de correspondence (matched rule). Si l’élément assigné n’est pas l’élément source correspondant ou s’il ne s’agit pas de la règle par défaut d’un élément alors on doit utiliser l’opération resolveTemp().

ATTENTION : l’opération resolveTemp() doit être appelée lorsque la phase de correspondance de la transformation est terminée. Cela signifie, que resolveTemp ne peut pas être invoquée du point d’entrée d’une règle appelée ni d’une autre règle appelée invoquée à partir de ce point d’entrée.

 

"Nous tissons notre destin, nous le tirons de nous comme l'araignée sa toile."
François Mauriac

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


07/10/2015
0 Poster un commentaire

Cours complet sur ATL (ATLAS Transformation Language) : introduction aux règles ATL

cours-complet-atl-atlas-transformation-language-introduction-aux-regles-atl.jpg

 

Dans l'article précédent :

https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-quelques-trucs-et-astuces-sur-les-expressions

nous avion abordé les helpers ATL. Voyons à présent une introduction aux règles ATL.

 

Introduction aux règles ATL

Dans le langage ATL language, la génération du modèle cible est réalisée grâce aux spécifications des règles de transformation.

ATL défini 2 types de règles de transformation : les règles de correspondance (« matched ») et les règles appelées  (« called »).  

Une règle de correspondance permet de faire correspondre certain éléments du modèle source et de générer à partir de ces éléments certains éléments du modèle cible.

A l’opposé des règles de correspondance , les règles appelées doivent être invoquées à partir d’un bloc impératif ATL pour être exécutés. Le code impératif ATL peut être défine soit dans un bloc “action”  d’une règle de correspondance soit dans le corps d’une règle appelée

 

"On n'est vieux que le jour où on le décide."
Jean Anouilh

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


06/10/2015
0 Poster un commentaire

Cours complet sur ATL (ATLAS Transformation Language) : les helpers

cours-complet-atl-atlas-transformation-language-helper-atl.jpg

 

Dans l'article précédent :

https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-quelques-trucs-et-astuces-sur-les-expressions

nous avion abordé les trucs et astuces sur les expressions. Voyons à présent les helpers ATL.

Les “Helpers” ATL

Les “helpers” ATL permettent aux développeurs de définir leurs propres methods dans les différentes unités d’ATL.

Dans le contexte d’ATL, ces méthodes sont appelées “helpers”. Comme toutes méthodes, ils permettent de factoriser du code ATL que l’on peut appeler à différents endroits du programme.

Il existe 2 type de “helpers” : fonctionnel et attribut. Tous les 2 sont définis dans le contexte d’une entité donnée. Un “attribut helper” est utilize comme un attribute alors qu’un “fonctionnel helper” accepte des paramètres.

Syntaxe

helper [context context_type]? def : helper_name(parameters) : return_type = exp;

Si le context est omis alors le “helper” est associé au context global du module ATL, c’est à dire que “self” fait reference         au module/query.

Le mot clé de fest utilize pour nommer le “helper”. La signature du “helper” comprend le context, le nom, les paramètres et le type de retour.

Les paramètres sont typés (n’importe quell type ATL) et dséparés par des virgules et le corps n’importe quelle expression valide OCL.

Exemple :

helper def : averageLowerThan(s : Sequence(Integer), value : Real) : Boolean =
        let avg : Real = s->sum()/s->size() in avg < value;

Ce “helper” nommé averageLowerThan, est défini dans le context du module ATL (pas de contexte  explicite) fait la moyenne d’une sequence d’entiers et renvoie vrai si elle inférieure à une certaine valeur.

Appel au helper de la super classe

 
class A {}
class B extends A {}
 
helper context A def: test() : Integer = 1;
helper context B def: test() : Integer = super.test() + 1;

Attribut

C’est une constante spécifiée dans un contexte spécifique. Il n’y a bien sur aucun paramètres.

Syntaxe :

 

helper [context context_type]? def : attribute_name : return_type = exp;

Exemple :  

helper def : getYoungest : MMPerson!Person =
        let allPersons : Sequence(MMPerson!Person) =
               MMPerson!Person.allInstances()->asSequence() in
        allPersons->iterate(p; y : MMPerson!Person = allPersons->first() |
               if p.age < y.age
               then
                       p
               else
                       y
               endif
        );

Cet attribute getYoungest, est défini dans le contexte du module ATL. Il s’applique à un métamodèle source MMPerson contenant Person comme élément de modèle. Le but est de renvoyer la pesonne la plus jeune (le type de reour est MMPerson!Person). Le corps de l’attribut est une "let" expression définissant la variable allPersons qui est une séquence de MMPerson!Person contenant toutes les personnes ( le « set » doit être casté en séquence ). La séquence est itérée, la variable p représente la personne itérée courante. Le résultat de l’itération est de type MMPerson!Person et correspond à la personne la plus jeune. Ce résultat est placé dans la variable y, initialisée avec la 1ère personne de la sequence  allPersons (pour avoir cette 1ère personne dans l’ordre, il faut une sequence qui est ordonné  plutôt qu’un set qui ne l’est pas). Le corps de l’expression iterate consiste en un "if" comparant l’age  de la plus jeune personne courante à la personne itérée courante. Suivant le résultat du if, on renvoie la personne courante (p) ou la plus jeune courante (y).

Un helper sans paramètrs est équivalent à un attribut.

ATTENTION : le code d’un helper est exécuté à chaque fois qu’il est invoqué contrairement à un attribut qui pour un élémént de modèle donné en enrée, retourne toujours la même valeur. Le moteur ATL interprête une seule fois la valeut retournée d’un attribute, soit à la 1ère invocation soit à l’initialisation de la transformation/query pour ceux qui sont déclarés dans le contexte du module ATL.

Limitations

L’implémentation courante a 3 limitations :

La 1ère limitation concerne les paramètres qui ne font pas encore partie de la signature. Ce qui entraîne que tous les helpers définis dans un contexte ATL donné, doivent avoir des noms distincts. Cela concerne aussi les helpers contenus des librairies importées.

La 2ème limitation concerne la définition de helpers dans un contexte de collection qui n’est pas supportée. La solution de contournement est de passer la collection en paramètre et de déclarer le helper dans le contexte du module ATL.

Exemple :

helper context Set(MMPerson!Person) def : getYoungPersons(age : Integer) :
        Set(MMPerson!Person) =
        self->select(p | p.age < age);

Compte de la limitation, il faudra definer le helper de la manière suivante :

helper def : getYoungPersons(s : Set(MMPerson!Person), age : Integer) :
        Set(MMPerson!Person) =
        s->select(p | p.age < age);

La dernière limitation  est le fait que l’implémentation courante  ne supporte pas la définition d’attributs dans une librairie ATL. La solution de contournement et de déclarer un helper sans paramètre pour chaque attribut de la librairie.

Exemple, dans une librairie,  l’attribut suivant :

helper context String def : getFirstChar : String = self.substring(1, 1);

doit être remplacé par le helper :

helper context String def : getFirstChar() : String = self.substring(1, 1);

 

"Si l'automobile avait suivi le même développement que les ordinateurs, une Rolls Royce coûterait aujourd'hui 500 francs, ferait du 700 kilomètres heure et exploserait une fois par an en faisant 10 morts."
Robert Cringely

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


05/10/2015
3 Poster un commentaire

Cours complet sur ATL (ATLAS Transformation Language) : quelques trucs et astuces sur les expressions

cours-complet-atl-atlas-transformation-model-trucs-et-astuces-expression.jpg

 

Dans l'article précédent :

https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-les-expressions-declaratives-dans-ocl-atl

nous avion abordé les énumérations ATL. Voyons à présent quelques trucs et astuces sur les expressions.

 

Quelques trucs et astuces sur les expressions

Les langages issus de la grande famille du “C” (C++, Java, C#, JavaScript, …), possèdent un optimiseur d’expression booléenne. Par exemple l’évaluation s’arrête quand le 1er membre est vrai et l’opérateur suivant est un or ou bien encore quand le 1er membre est false et que l’opérateur est un and.

Ce n’est pas la cas dans OCL. Toutes les expressions seront entièrement évaluées.

Parconséquent certaines expressions à priori correctes généreront une erreur dans ATL !

Exemples :

not person.oclIsUndefined() and person.name = 'Isabel'

Cette expression génère bien une erreur dans ATL dans le cas ou person n’est pas défini, une erreur est générée à l’évaluation de person.name.

Pour être certain de n’avoir aucune erreur :

if person.oclIsUndefined()
then
        false
else
        person.name = 'Isabel'
endif

Idem avec un or :

person.oclIsUndefined() or person.name = 'Isabel'

Pour être à l’abri d’erreurs comme précédemment :

if person.oclIsUndefined()
then
        true
else
        person.name = 'Isabel'
endif

Autre exemple :

collection->select(person | not person.oclIsUndefined() and person.name = 'Isabel')

La bonne solution pour être tranquille :

collection->select(person |
        if person.oclIsUndefined()
        then
               false
        else
               person.name = 'Isabel'
        endif
)

Plusieurs solutions existent, en voici une 2ème :

collection
        ->select(person | not person.oclIsUndefined())
        ->select(person | person.name = 'Isabel')

En terme de performance la 1ère solution est préférable à la 2ème car l’itération sur la collection est effectuée qu’une seule fois.

 
"Faites ce que vous aimez, pensez ce que vous ressentez et vivez de la façon dont vous voulez."
Santosh Kalwar

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


03/10/2015
0 Poster un commentaire

Cours complet sur ATL (ATLAS Transformation Language) : Les expressions déclaratives dans OCL / ATL

cours-complet-atl-atlas-transformation-language-les-expressions-declaratives-ocl-atl.jpg

 

Dans l'article précédent :

https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-les-elements-de-modeles-des-metamodeles

nous avion abordé les énumérations ATL. Voyons à présent les les expressions déclaratives dans OCL / ATL.

 

Les expressions déclaratives dans OCL

Il existe dans OCL 2 instructions de contrôle : if et let

Le « if »

Il s’agit du if que l’on trouve dans tous les langages de programmation.

ATTENTION le else est obligatoire :

if condition
then
exp1
else
exp2
endif

Je ne vous ferais l’affront de vous expliquez comment ça marche, même les apprentis geek de 10 ans savent ce que c’est qu’un if.

Un petit exemple juste pour la forme :

if 3 > 2
then
        'three is greater than two'
else
        'this case should never occur'
endif

 

if mySequence->notEmpty()
then
        if mySequence->includes(myElement)
        then
               'the element is at position '
               + mySequence->indexOf(myElement).toString()
        else
               'the sequence does not contain the element'
        endif
else
        'the sequence is empty'
endif

L’expression « let »

Elle permet de définir une variable :

let var_name : var_type = var_init_exp in exp

Exemples :

let a : Integer = 1 in a + 1

 

let x : Real =
        if aNumber > 0
        then
               aNumber.sqrt()
        else
               aNumber.square()
        endif
in let y : Real = 2 in x/y

Une variable OCL est visible à partir de sa déclaration jusqu’à la fin de l’expression OCL à laquelle elle appartient.

ATTENTION : il n’est pas conseillé qu’un développeur déclare plusieurs varaibles avec le même nom à l’intérieur d’une expression. Si tel était le cas, la dernière masquerait toutes les autres.

Très utile pour déboguer, par exemple dans l’espression suivante, si la la collection est vide, l’opération first() renvoie la valeur OclUndefined. L’opération square()  invoquée sur OclUndefined,va renvoyer une erreur au runtime. Donc dans ce cas il est intéressant pour pouvoir le verifier de stocker le 1er  element de la séquence dans une variable.

aSequence->first().square()

 

let firstElt : Real = aSequence->first() in firstElt.square()

 

"Pour différentes raisons, la plupart des gens sont tellement pris par leur quotidien qu'ils n'ont pas le temps de s'étonner de la vie."
Jostein Gaarder

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


02/10/2015
0 Poster un commentaire

Cours complet sur ATL (ATLAS Transformation Language) : les éléments de modèles des métamodèles

cours-complet-ATL-atlas-transformation-language-les-types-element-de-modele-1.png

 

 

cours-complet-ATL-atlas-transformation-language-les-types-element-de-modele-2.png

 

 

cours-complet-ATL-atlas-transformation-language-les-types-element-de-modele-3.png

 

 

Dans l'article précédent :

https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-les-tuples

nous avion abordé les énumérations ATL. Voyons à présent les types des éléments du modèle.

 

Les types des éléments du modèle

Il s’agit des types ou classes des métamodèles source et cible.

Dans ATL, une variable d’un élément de modèle est référencée par metamodel!classmetamodel identifie un des métamodèles gérés par la transformation, et où class pointe sur un élément de modèle (classe) de ce métamodèle.

La notation OCL ne précise pas le métamodèle contrairement à ATL qui gère plusieurs métamodèles en même temps.

Un élément de modèle possède des propriétés qui sont des attributs et des références. Les 2 sont accessibles avec la notation « point » self.propriete.

Exemple : dans le contexte du métamodèle MMAuthor, anAuthor.name permet d’accéder à l’attribut name de l’instance anAuthor de la classe Author class.

Dans ATL, un élément de modèle ne peut être généré que dans une règle ATL (matched ou called rules). L’initialisation d’un nouvel élément de modèle se fait avec les règles de correspondance avec le modèle cible.

L’opération oclIsUndefined(), definie dans le type OclAny, teste si la valeur d’une expression est indefinite. Cette opération est utile lorqu’un attribut à une multiplicité 0..1 (void ou non). Les attributs avec la multiplicité * sont représentés par une collection vide ou non.

Nom complet pour référencer une classe du métamodèle

<Package1Name>::<Package2Name>::<ClassifierName>

Comme le parseur ATL ne supporte pas le "::", on doit ajouter des ".

MM!"P1::C1"
MM!"P1::P2::C2"
MM!"P3::C3"

Cas ou cette notation est obligatoire :

package P1 {
  class C1 {}
  package P2 {
    class C1 {}
  }
}
package P3 {
  class C1 {}
}

MM!C1 n’est pas correct car il y a ambiguité. Un avertissement est généré dans la console. L’expression correcte est la suivante :

MM!"P1::C1"
MM!"P1::P2::C1"
MM!"P3::C1"

Exemples

Voici des exemples d’expression d’OCL utilisant des propriétés d’éléments de modèle. Ils sont définis dans le context du MOF métamodèlele :

  • Récupérer toutes les classes du MOF :
MOF!Class.allInstances()->collect(e | e.name)
  • Récupérer tous les types primitifs du MOF :
MOF!DataType.allInstances()
       ->select(e | e.oclIsTypeOf(MOF!PrimitiveType))
       ->collect(e| e.name)
  • La même chose mais en plus simple (mais pourquoi faire simple quand on peut faire compliquer ? ) :
MOF!PrimitiveType.allInstances()->collect(e| e.name)
  • Une énumaration du MOF :
MOF!VisibilityKind.labels
  • Récupérer le nom de toutes les classes qui héritent de plus d’une classe :
MOF!Class.allInstances()
       ->select(e | e.supertypes->size() > 1)
       ->collect(e | e.name)

 

Les commentaires ATL

Exemples :

-- this is an example of a comment

Pour specifier la documentation des ATL helpers et règles qui apparaissent dans l’aide automatique :

--- Evaluates whether the context has the given stereotype or not.
helper context UML!Element def: hasStereotype(stereotype : String) : Boolean =
        self.getAppliedStereotypes() -> collect(st | st.name) -> includes(stereotype);

 

 

"C'est quand on serre une femme de trop près qu'elle trouve qu'on va trop loin."
Alphonse Allais

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


02/10/2015
0 Poster un commentaire

Cours complet sur ATL (ATLAS Transformation Language) : les tuples

cours-complet-atl-atlas-transformation-language-les-tuples.jpg

 

Dans l'article précédent :

https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-les-enumerations

nous avion abordé les énumérations ATL. Voyons à présent les tuples.

 

Le type tuple

Le type tuple permet de mettre plusieurs valeurs dans une seule variable.

Un tuple est constitué de champs nommés pouvant avoir des types différents.

ATTENTION : un tuple type n’est pas nommé, donc à chaque fois que l’on doit l’identifier, il faut mentionner sa déclaration au complet !

La declaration d’un tuple :

TupleType(var_name1 : var_type1, ..., var_nameN : var_typeN)

L’ordre de declaration n’est pas significatif.

 

Exemple de déclaration :

TupleType(a : MMAuthor!Author, title : String, editor : String)

L’instanciation d’une variable tuple :

Tuple{var_name1 [: var_type1]? = init_exp1, ..., var_namen [: var_typen]? = init_expn}

Les 2 instanciations de tuple suivantes sont équivalentes :

Tuple{editeur : String = 'www.urbanisation-si.com', titre : String = 'Cours complet ATL', a : MMAuthor!Author = unAuteur}
Tuple{titre = 'Cours complet ATL', a = unAuteur, editeur = 'www.urbanisation-si.com'}

Pour accéder à un memebre du tuple :

Tuple{titre = 'Cours complet ATL', a = unAuteur, editeur = 'www.urbanisation-si.com'}.titre

Le type tuple possède une operation asMap() renvoyant une map dans laquelle les noms des champs du tuple sont associés avec leurs valeurs respectives.

 

Le type Map

Ce type a été ajouté dans ATL et n’existe pas dans OCL. Il est identique à la classe Map de Java. Chaque valeur est associée à une unique clé d’accès.

 

La declaration suit la syntaxe suivante :

Map(key_type, value_type)

Comme pour le tuple, un type map n’est pas nommé, ce qui oblige à répêter la declaration complete à chaque que l’on veut y faire référence.

Map(Integer, MMAuthor!Author)

L’instantiating suit la syntaxe :

Map{(key1, value1), ..., (keyn, valuen)}

Exemple :

Map{(0, anAuthor1), (1, anAuthor2)}

Le type map possède les operations suivantes :

  • get(key : oclAny) renvoie la valeur associée à key (ou OclUndefined si key n’est pas une clé de self);
  • including(key : oclAny, val : oclAny) renvoie une copie de self dans laquelle le couple ( key, val) a été inséré à la condition que key ne soit pas déjà une clé de self
  • union(m : Map) renvoie une map contenant tous les éléments de self auxquels sont ajoutés les éléments de m à condition que leurs clés n’existent pas dans self
  • getKeys() renvoie un set contenant toutes les clés de self
  • getValues()renvoie un bag contenant toutes les valeurs de self 

 

Une robe de femme, doit être comme une plaidoirie : assez longue pour couvrir le sujet, assez courte pour être suivie.

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


30/09/2015
0 Poster un commentaire

Cours complet sur ATL (ATLAS Transformation Language) : les énumérations

cours-complet-ATL-atlas-transformation-language-les-types-atl.png

 

Dans l'article précédent :

https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-les-collections 

nous avion abordé de manière extrêmement détaillée les collections ATL.

 

Après les collections, viennent bien sur les énumérations.

 

Le type Enumeration

Comme dans tous les langages (C, C++, Java, C#, …) on trouve dans ATL le type énumeration (OclType).

Il doit être défini dans les métamodèles source et cible.

En OCL, pour accéder aux valeurs d’une énumeration "Gender" définissant 2 valeurs male et female, la syntaxe est la suivante : Gender::female

 

ATTENTION en ATL, il suffit de faire : #female. (le nom de l’énumération n’est pas requis).

Une énumération ne contient aucune opération.

 

"Les politiques grecs ne reconnaissent d'autre force que celle de la vertu. Ceux d'aujourd'hui ne vous parlent que de manufactures, de commerce, de finances, de richesses et de luxe même."
Montesquieu

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


30/09/2015
0 Poster un commentaire

Cours complet sur ATL (ATLAS Transformation Language) : les collections

cours-complet-atl-atlas-transformation-language-les-collections.jpg

 

Dans l'article précédent :

https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-les-types-primitifs

nous avion abordé de manière quick and dirty les types primitifs ATL.

 

La suite logique est de voir les collections, qui sont en fait les 4 collections définies dans OCL :

  • Set : sans doublon et non ordonnée
  • OrderedSetsans doublon et ordonnée
  • Bag avec doublon possible et non ordonnée
  • Sequence avec doublon possible et ordonnée

Opérations sur les collection

  • size() renvoie le nombre d'éléments de la collection self
  • includes(o : oclAny) renvoie un booléen si l'objet o fait partie de la collection self
  • excludes(o : oclAny) renvoie un booléen si l'objet o ne fait pas partie de la collection self
  • count(o : oclAny) renvoie le nombre de fois ou l'objet o apparaît dans la collection self
  • includesAll(c : Collection) renvoie un booléen si tous les objets de la collection c sont contenus dans la collection self
  • excludesAll(c : Collection) renvoie un booléen si aucun des objets de la collection c sont contenus dans la collection self
  • isEmpty() renvoie un booléen si la collection self est vide
  • notEmpty() renvoie un booléen si la collection self n'est pas vide
  • sum() renvoie une valeur correspondant à l'addition de tous les éléments de la collection self. Les types des éléments doivent être supportés par l'opérateur + 

ATL défini des opérations supplémentaires par rapport à OCL :

  1. asBag() renvoie un bag contenant tous les éléments de la collection self. 
  2. asSequence() renvoie une sequence contenant tous les éléments de la collection self en introduisant un ordre pour un bag ou un set.
  3. asSet() renvoie un set contenant tous les éléments de la collection self en perdant l’ordre pour un sequence ou un orderedset.Les doublons d’un bag ou d’une sequence sont éliminés.

Les opérations sur les séquences

  1. union(c : Collection) renvoie une séquence composée de tous les éléments de self suivi de ceux de c
  2. flatten() renvoie une séquence contenant le fils de la collection interne contenu dans self
  3. append(o : oclAny) renvoie une copie de self avec les éléments de o ajoutés à la fin de la séquence
  4. prepend(o : oclAny) renvoie une copie de self avec les éléments de o ajoutés au début de la séquence
  5. insertAt(n : Integer, o : oclAny), renvoie une copie de self avec les éléments de o ajoutésau rang nde la séquence
  6. subSequence(lower : Integer, upper : Integer)  une sous séquence de self commençant à lower jusqu’à upper (tous les 2 inclus)
  7. at(n : Integer) renvoie l’élément du rang n de self
  8. indexOf(o : oclAny) renvoie le rang de la 1ère occurrence de o dans self
  9. first() renvoie le rang de la 1er élément de self (oclUndefined si self est vide);
  10. last()renvoie le rang de la dernier élément de self (oclUndefined si self est vide);
  11. including(o : oclAny) renvoie une copie de self avec les éléments de o ajoutés à la fin de la séquence
  12. excluding(o : oclAny) renvoie une copie de self avec toutes les occurrences de l’élément o supprimées.

Les opérations sur le type Set

  1. union(c : Collection) renvoie un set composé des éléments de self et de c avec les doublons
  2. intersection(c : Collection) renvoie un set composé des éléments qui apparaissent à la fois dans self et dans c
  3. operator - (s : Set) renvoie un set composé des éléments de self qui ne sont pas dans s
  4. including(o : oclAny), renvoie une copie de self avec les éléments de o s’ils ne sont pas présent dans self
  5. excluding(o : oclAny), renvoie une copie de self avec les éléments de o supprimés du set
  6. symetricDifference(s : Set) renvoie un set composé des éléments de self ou de s mais des 2

Les opérations sur le type OrderedSet

  1. append(o : oclAny) renvoie une copie de self avec l’élément o ajouté à la fin s’il n’existait pas déjà dans self
  2. prepend(o : oclAny) renvoie une copie de self avec l’élément o ajouté au début de l’orderedset s’il n’existait pas déjà dans self
  3. insertAt(n : Integer, o : oclAny), renvoie une copie de self avec l’élément o ajouté au rang n de l’orderedset s’il n’existait pas déjà dans self
  4. subOrderedSet (lower : Integer, upper : Integer) renvoie une sous séquence de self commençant au rang lower et finissant au rang upper (les 2 inclus)
  5. at(n : Integer) renvoie l’élément du rang n de self
  6. indexOf(o : oclAny) renvoie le rang de la 1ère occurrence de o dans self
  7. first()renvoie le 1er élément de self (oclUndefined si self est vide)
  8. last()renvoie le dernier élément de self (oclUndefined si self est vide)
  9. union(c : Collection) renvoie un orderedset composé des elements de self suivis des elements de c avec les doublons supprimés, ils apparaissent entre c et self
  10. flatten()renvoie un orderedset contenant directement le fils de la collection interne à la collection contenant self
  11. including(o : oclAny) renvoie une copie de self avec l’élément o ajouté à la fin de l’orderedset s’il n’apparaît pas déjà dans self
  12. excluding(o : oclAny) renvoie une copie de self avec l’élément o supprimé

Les opérations sur le type Bag

  1. including(o : oclAny) renvoie une copie de self avec l’élément o ajouté à la fin de l’orderedset s’il n’apparaît pas déjà dans self
  2. excluding(o : oclAny) renvoie une copie de self avec l’élément o supprimé
  3. flatten()renvoie un orderedset contenant directement le fils de la collection interne à la collection contenant self  

Itérer sur les collections

La principale difference entre une operation classique et une expression iterative sur les collections est que l’itérateur accepte une expression comme parameter.

  1. La collection itérée est celle dont on fait reference comme source
  2. Les variables d’itération déclarées dont on fait référence comme itérateurs
  3. L’expression passée comme parameter de l’opération dont on fait reference dans le corps de l’itérateur

source->operation_name(iterators | body)

ATL supporte les expression itératives suivantes

  1. exists(body) renvoie une valeur booléenne suivant qu’il existe au moins un élément de source dans le body
  2. forAll(body) renvoie une valeur booléenne suivant que body est évalué à vrai pour tous les éléments de source
  3. isUnique(body) renvoie une valeur booléenne suivant que body est évalué à une valeur différente pour chaque élément de source
  4. any(body) renvoie un élément de source pour laquelle body est évalué à vrai. Si body n’est jamais évalué à vrai, l’opération renvoie OclUndefined;
  5. one(body) renvoie une valeur booléenne s’il existe exactement un élément de source pour laquelle body est évalué à vrai
  6. collect(body) renvoie une collection d’éléments resultant de l’application de body à chaque élément de la collection source
  7. select(body) renvoie un sous ensemble de la collection source pour laquelle body est évalué à vrai
  8. reject(body) renvoie un sous ensemble de la collection source pour laquelle body est évalué à faux (équivalent à select(not body));
  9. sortedBy(body) renvoie une collection ordonnée suivant body à partir de la plus petite valeur jusqu’à la plus grande. Les éléments de la collection source doivent avoir l’opérateur < défini  

OCL spécifie un itérateur encore plus générique appelé iterate() dont l’expression posséde un iterator, un accumulator et un body. L’accumulator correspond à une variable initialiée. Le body est une expression qui utilise iterator et accumulator. La valeur renvoyée par iterate() correspond à la valeur de la variable accumulator une fois que la dernière iteration s’est exécutée.

source->iterate(iterator; variable_declaration = init_exp |

        body

)

Exemples

  1. declaration d’une sequence d’entiers : Sequence(Integer)
  2. une sequence d’entiers : Sequence{1, 2, 3}
  3. declaration d’un ensemble de sequence de String : Set(Sequence(String))
  4. un ensemble de sequence de String : Set{Sequence{'monday'}, Sequence{'march', 'april', 'may'}}
  5. test si un bag est vide : Bag{1, 2, 3}->isEmpty()
    1. false
    2. Set{1, 2, 3}->includes(1)
      1. true
    3. Set{1, 2, 3}->includesAll(Set{3, 2})
      1. true
    4. Sequence{1, 2, 3}->size()
      1. 3
      2. ATTENTION : Set{3, 3, 3}->size() est évalué à 1 car un set élimine les doublons
    5. OrderedSet{1, 2, 3}->first()
      1. 1
    6. Sequence{1, 2, 3}->union(Sequence{7, 3, 5})
      1. Sequence{1, 2, 3, 7, 3, 5}
    7. Set{1, 2, 3}->union(Set{7, 3, 5})
      1. Set{1, 2, 3, 7}
    8. Sequence{Sequence{1, 2}, Sequence{3, 5, 2}, Sequence{1}}->flatten()
      1. Sequence{1, 2, 3, 5, 2, 1}
    9. Sequence{Sequence{1, 2}, Sequence{3, 5, 2}, Sequence{1}}->subSequence(2, 3)
      1. Sequence{ Sequence{3, 5, 2}, Sequence{1}}
    10. Sequence{5, 15, 20}->insertAt(2, 10)
      1. Sequence{5, 10, 15, 20}
    11. Set{1, 2, 3}->intersection(Set{7, 3, 5})
      1. Set{3}
    12. Set{1, 2, 3}->symetricDifference(Set{7, 3, 5})
      1. Set{1, 2, 7, 5}
    13. Sequence{1, 2, 3, 4, 5, 6}->select(i | i <= 3)
      1. Set{1, 2, 3}
    14. Récupérer tous les noms des classes du MOF : MOF!Class.allInstances()->collect(e | e.name)
    15. Vérifier que tous les éléments d’une séquence sont plus grand que 2 : Sequence{12, 13, 12}->forAll(i | i > 2)
      1. true
    16. Vérifier s’il y a un unique élément d’une séquence plus grand que 2 :  Sequence{12, 13, 12}->one(i | i > 2)
      1. false
    17. Vérifier s’il existe un nombre dans la séquence plus grand que 2 :   Sequence{12, 13, 12}->exists(i | i > 2)
      1. evaluates to true
    18. Sequence{8, -1, 2, 2, -3}->iterate(e; res : Integer = 0 |
      if e > 0
      then res + e
      else res
      endif
      )
      1. 12;
      2. équivalent à Sequence{8, -1, 2, 2, -3}->select(e | e > 0)->sum()

 
"Si mon esprit peut le concevoir, et mon cœur peut le croire, alors je peux le réaliser."
Muhammad Ali

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


29/09/2015
0 Poster un commentaire