1. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Métodos Avanzados de Desarrollo de Software
Asignatura Optativa de 4º Año
Grado en Informática
Departamento de Sistemas Informáticos
Universidad de Castilla-La Mancha
Métodos avanzados de
desarrollo de software
Tema IX: Arquitecturas dirigidas por Modelos.
Atlas Transformation Language (ATL) - Parte II
2. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Índice
• Repaso
• Tipos de Datos
• ATL Modules
• Primitivos
• Colecciones
• Tipos
• Operaciones
• Iteradores
• Enumeraciones
• Tuplas
• Mapas
• Modelos
• Comentarios
• Expresiones
declarativas
• ATL Helpers
• Atributos
• Reglas
3. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Repaso
• ATL define 3 tipos de unidades
• ATL modules (transformaciones modelo a modelo)
• ATL queries (transformaciones a tipos primitivos)
• ATL libraries (librerías)
• Estas unidades están compuestas de una combinación de:
• Atributos
• ATL helpers
• Reglas
• Matched rules
• Called rules
• Lazy rules
• Todos estos elementos se definen con OCL
4. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Tipos de datos
No está definida en OCL
Module o Query
5. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Tipos de datos: OclType y OclAny
• OclType
• Instancias de tipos de OCL
• Operaciones:
• allInstances(): Todas las instancias de self
• allInstancesFrom(metamodel:String): Todas las instancias de un tipo en un meta-modelo
• OclAny
• Operaciones de comparación: = , <>
• oclIsUndefined(): true si self está indefinido
• oclIsKindOf(t:oclType): true si self es instancia de t o uno de sus subtipos
• oclIsTypeOf(t:oclType): true si self es instancia de t
• toString(): devuelve un String de self
• oclType(): devuelve el oclType de self
• asSequence(), asSet(), as Bag(): devuelve una secuencia, un conjunto o una bolsa conteniendo
a self.
• output(s:String): escribe el string s en la consola Eclipse (sólo en bloques imperativos)
• debug(s:String): devuelve self y escribe s en la consola
• refSetValue(name:String, val:oclAny): operación reflexiva que permite establecer la
característica identificada por name con el valor value.
• refGetValue(name:String): operación reflexiva que devuelve el valor de la propiedad name de
self
• refImmediateComposite(): es una operación reflexiva que devuelve el contenedor inmediato
de self
• refInvokeOperation(opName:String; String args:Sequence): operación reflexiva que permite
invocar la operación self llamada opName con la secuencia de parámetros definida por args.
6. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
ATL Module
• ATL Module
• Representa una ATL unit (module y query)
• thisModule: Permite acceder a los helpers y los atributos
• resolveTemp(var, target_pattern_name): Permite referenciar, desde
una regla ATL, cualquier elemento del modelo destino generados a
partir de un elemento dado del modelo fuente generado por una
matched rule
• var: variable que contiene el elemento del modelo fuente a partir del
cual se produce el elemento destino
• target_pattern_name: string del nombre del patrón destino (ya lo
veremos más adelante)
• Nota: Esta operación debe llamarse desde thisModule.
• Puede llamarse desde:
• Target patterns y secciones do de cualquier matched rule
• Target patterns y secciones do de una called rule ejecutada luego de la fase de
matching
7. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Análisis de casos 1 y 2
• Caso 1:
rule Case1 {
from i : MM_A!ClassA
to
o_1 : MM_B!Class1 (linkToClass2 <- o_2),
o_2 : MM_B!Class2 (...)
}
• Caso 2:
rule Case2_R1 {
from i : MM_A!ClassA
to
o_1 : MM_B!Class1 (linkToClass2 <- i.linkToClassB)
}
rule Case2_R2 {
from i : MM_A!ClassB
to
o_1 : MM_B!Class2 (...), …
}
ClassA Class1
Class2
linkToClass2
ClassA Class1
Class2
linkToClass2
ClassB
linkToClassB
8. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Análisis Caso 3
rule Case3_R1 {
from i : MM_A!ClassA
to
o_1 : MM_B!Class1 (linkToClass2 <- thisModule.resolveTemp(i.linkToClassB, 'o_n'))
}
rule Case3_R2 {
from in : MM_A!ClassB
to
o_1 : MM_B!Class3 (...),
...
o_n : MM_B!Class2 (...),
...
}
ClassA Class1
Class2
linkToClass2
ClassB
linkToClassB
Class3
9. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
TIPOS PRIMITIVOS
ATL
10. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Tipos de datos primitivos
• Se definen 4 tipos
• Integer
• Real
• Boolean
• String
• Boolean define:
• and, or, xor, not
• implies (b:Boolean): devuelve la implicación lógica
• String define
• size(): devuelve el tamaño de self
• concat(s: String): devuelve la concatenación de s con self
• substring (lower:Integer, upper:Integer) devuelve el String definido entre lower y upper de self
• toInteger() y toReal()
• <, >, =>,=<: devuelve la comparación
• + : concatena Strings
• toUpper(), toLower(): devuelve una copia de String en mayúsculas o minúsculas
• toSequence(): devuelve una secuencia de caracteres
• trim(): devuelve una copia de self con la omisión de (‘ ’,’t’, ‘n’, ‘f’, ‘r’)
• startsWith(s:String), endWith(s:String): devuelve true si self empieza o termina con s.
• indexOf(s:String), lastIndex(s:String): devuelve un entero dentro del self con la primera o última
ocurrencia de s en self
11. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Tipos de datos primitivos II
• String (cont.)
• split(regex:String) devuelve una secuencia de strings de self de acuerdo a las expresiones
regulares definidas por regex (Java).
• replaceAll(c1:String, c2:String) devuelve una copia de self en la que cada ocurrencia del
carácter c1 se reemplaza por el carácter c2 (Notar que aunque se usan strings para c1 y c2
sólo se toma el primer carácter de dichos strings.
• regexReplaceAll(regEx:String, replacement:String): devuelve una copia de self en la que cada
substring que se corresponde con regEx se reemplaza con replacement
• writeToFile(filename:String): escribe el string en un archivo
• println(): Imprime el string en el output
• Numéricos
• Operadores de comparación: <,>,=>, =<
• Operadores binarios: *,+,-,/,div, max(), min()
• Operadores unarios: abs()
• mod() enteros
• floor(), round() reales
• cos(), sin (), tan(), acos(), asin()
• toDegrees(), to Radians()
• exp(), log(), sqrt()
12. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
COLECCIONES
ATL
13. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Tipos de datos de colecciones
• Provee
• Set (sin duplicados, sin orden)
• OrderedSet (sin duplicados, ordenada)
• Bag (con duplicados, sin orden)
• Sequence (con duplicados, ordenada)
• Se usan como las templates de C++ o los generics de Java
• Declaración
• collection_type(element_datatype)
• Instanciación
• collection_type{elements}
14. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operaciones en Collection
• Uso
• self->operation_name(parameters)
• Operaciones
• size(): número de elementos de self
• includes(o: oclAny): devuelve true si o está en self
• excludes(o: oclAny): devuelve true si o no está en self
• count (o: oclAny): devuelve la cantidad de veces que o ocurren en self
• includesAll(c:Collection): devuelve true si todos los objetos de c están en self
• excludesAll(c:Collection): devuelve true si ninguno de los objetos de c están
en self
• isEmpty(): devuelve true si la colección está vacía
• notEmpty(): devuelve true si la colección no está vacía
• sum(): devuelve el valor que representa la suma de todos los elementos en
self. Los elementos deben soportar (+)
• asBag(): devuelve un Bag con los elementos de self
• asSequence(): devuelve una Sequence con los elementos de self
• asSet(): devuelve un Set con los elementos de self
15. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operaciones de Sequence
• union(c:Collection): devuelve una secuencia con los elementos de self seguida
de los de c
• flatten(): devuelve una secuencia con que contiene los hijos de las colecciones
contenidas en self
• append(o:oclAny): devuelve una copia de self con el elemento o al final
• prepend(o:oclAny): devuelve una copia de self con el elemento o al principio
• insertAt(n:Integer, o:oclAny): devuelve una copia de self con el elemento o en la
posición n
• subSequence(lower:Integer, upper:Integer): devuelve la secuencia de elementos
de self comprendida entre lower y upper
• at(n:Integer): devuelve el elemento en n de self
• indexOf(o:oclAny): devuelve el primer índice de o en self
• first(): devuelve el primer elemento de self
• last(): devuelve el último elemento de self
• including(o:oclAny): devuelve una copia de self con el elemento o al final
• excluding(o:oclAny): devuelve una copia de self con todas las ocurrencias de o en
self removidas
16. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operaciones de Set
• union(c:Collection): devuelve un Set compuesto con los y los de c sin
duplicados
• intersection(c:Collection): devuelve un Set con los elementos que
aparecen en self y c
• - (s:Set): devuelve un Set compuesto de los elementos de self que no
están en s
• including(o:oclAny): devuelve una copia de self con el elemento o
• excluding(o:oclAny): devuelve una copia de self sin el elemento o
• symetricDifference(s:Set): devuelve un Set compuesto por los
elementos que están en self o s pero no en ambos
• flatten() no está definido
17. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operaciones en OrderedSet
• append(o:oclAny): devuelve una copia de self con el elemento o al final, si no está
• prepend(o:oclAny): devuelve una copia de self con el elemento o al principio, si no está
• insertAt(n:Integer, o:oclAny): devuelve una copia de self con el elemento o en la posición n,
si no está
• subOrderedSet(lower:Integer, upper:Integer): devuelve una subSecuencia de self desde
lowes hasta upper
• at(n:Integer): devuelve el elemento en n de self
• indexOf(o:oclAny): devuelve el primer índice de o en self
• first(): devuelve el primer elemento de self
• last(): devuelve el último elemento de self
• union(c:Collection): devuelve un OrderedSet compuesto de los elementos de self seguidos
de los de c con los duplicados removidos
• flatten(): devuelve on OrderedSet que contiene los hijos de las colecciones contenidas en
self
• including (o:oclAny): devuelve una copia de self con el elemento o añadido al final de la
colección
• excluding (o:oclAny): devuelve una copia de self con el elemento o removido
18. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Iteradores
• La definición de una expresión iterativa define:
• La colección a iterar (colección fuente)
• Las variables de iteraciín (iteradores)
• La expresión pasada como parámetro (cuerpo)
• La sintaxis es la siguiente
source->operation_name(iterators|body)
• Expresiones iterativas
• exists(body): devuelve true si body evalúa a true para al menos un elemento de la colección fuente
• forAll(body): devuelve true si body evalúa a true para todos los elementos de la colección fuente
• isUnique(body): devuelve true si body devuelve un elemento para cada elemento de la colección
fuente
• any(body): devuelve un elemento de la colección fuente para el que body se evalua true, si ninguno
lo hace => oclUndefined
• one(body): devuelve true si body evalúa a true para un único elementos de la colección fuente
• collect(body): devuelve una colección de elementos cuyos resultados es la aplicaicón de body a cada
uno de los elementos de la colección fuente
• select(body): devuelve el subconjunto de elementos de la colección fuente que evalúan body a true
• reject(body): devuelve el subconjunto de elementos de la colección fuente que evalúan body a false
• sortedBy(body): devuelve una colección ordenada de acurdo al body del menor al mayor, los
elementos de la colección fuente deben definir deben definir el operador <
• El iterate
• source->iterate(iterator, varaible_declaration=init_exp| body)
19. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Enumeración y tuplas
• Enumeraciones
• Definición de literales
• Gender:Female
• #Female
• Tuplas
• Declaración:
TupleType(var_name1 : var_type1, ..., var_namen : var_typen)
• Ejemplo:
TupleType(a : MMAuthor!Author, title : String, editor : String)
• Instanciación
Tuple{var_name1 [: var_type1]? = init_exp1, ..., var_namen [:
var_typen]? = init_expn}
• Ejemplo:
Tuple{editor : String = 'ATL Eds.', title : String = 'ATL Manual', a :
MMAuthor!Author = anAuthor}
• Ejemplo (recuperar datos):
Tuple{editor : String = 'ATL Eds.', title : String = 'ATL Manual', a :
MMAuthor!Author = anAuthor}.title
20. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Map, modelos y comentarios
• Adicional a OCL
• Declaración:
Map(key_type, value_type)
• Ejemplo:
Map(Integer, MMAuthor!Author)
• Instanciación
Map{(key1, value1), ..., (keyn, valuen) }
• Ejemplo
Map{(0, anAuthor1), (1, anAuthor2)}
• Operaciones
• get(key:oclAny): devuelve el valor asociado a key en el Map self.
• including(key:oclAny, val: oclAny): devuelve una copia de self en el par (key, val) ha sido
insertado
• union(m:Map): devuelve un Map conteniendo todos los elementos de self en los que se
agregan los elementos de m que no aparencen en self.
• getKeys(): devuelve un Set que contienen todas las claves de self
• getValues(): devuelve un Bag que contiene todos los valores de self
• Modelos
• Acceso a características (.)
• Comentarios
• -- Comentario
21. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Expresiones declarativas
• El if
• Sintaxis
if condition then exp1 else exp2 endif
• Ejemplo:
if 3 > 2 then 'three is greater than two‘ else
'this case should never occur' endif
• El let
• Sintaxis:
let var_name : var_type = var_init_exp in exp
• Ejemplo:
let x :Real =
if aNumber > 0 then aNumber.sqrt()
else aNumber.square() endif
in let y : Real = 2 in x/y
22. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Tips…
• not person.oclIsUndefined() and person.name = 'Isabel‘
• if person.oclIsUndefined() then false
else person.name= 'Isabel' endif
• collection->select(person | not person.oclIsUndefined() and
person.name = 'Isabel')
• collection->select(person |
if person.oclIsUndefined() then false
else person.name = 'Isabel'endif)
• collection
->select(person | not person.oclIsUndefined())
->select(person | person.name = 'Isabel')
23. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
HELPERS Y ATRIBUTOS
ATL
24. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
ATL Helpers y attributes
• ATL Helper
• Sintaxis
• helper [context context_type]? def : helper_name(parameters) :
return_type = exp;
• parameter_name : parameter_type
• Ejemplo
• helper def : averageLowerThan(s : Sequence(Integer), value : Real) :
Boolean = let avg : Real = s->sum()/s->size() in avg < value;
• ATL Attribute
• Sintaxis
• helper [context context]? def : attribute_name : return_type = exp;
• Ejemplo
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);
26. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
REGLAS
ATL
27. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
ATL Rules
Código imperativo
• Puede ser incluido en:
• Matched Rules
• Called Rules
• Lazy Rules
• La asignación
target <- exp;
• Ejemplo
helper def: counter : Integer = 0;
thisModule.counter <- thisModule.counter + 1;
28. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
ATL Rules
Código imperativo
• IF
if(condition) {
statements1
}
[else {
statements2
}]?
• Ejemplo
if(aPerson.gender = #male) {
thisModule.menNb <- thisModule.menNb + 1;
thisModule.men->including(aPerson);
}
• FOR
for(iterator in collection) {
statements
}
• Ejemplo
for(p in MMPerson!Person.allInstances()) {
if(p.gender = #male)
thisModule.men->including(aPerson);
else
thisModule.women->including(aPerson);
}
29. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Limitaciones
• No se pueden declarar variables en bloques imperativos
• Las variables que pueden ser utilizadas en estos bloques son:
• Elementos de modelo fuente y destino declarados en la matched
rule local
• Elementos del modelo destino declarados en la called rule local
• Variables declaradas localmente (ej. en la rule)
• Atributos declarados en el contexto del módulo ATL
30. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Matched rules
rule rule_name {
from
in_var : in_type [(condition)]?
[using {
var1 : var_type1 = init_exp1;
...
varn : var_typen = init_expn;
}]?
to
out_var1 : out_type1 (bindings1),
out_var2 : distinct out_type2 foreach(e in
collection)(bindings2),
...
out_varn : out_typen (bindingsn)
[do {
statements
}]?
}
Unique
Obligatorio
Opcional
31. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Patrón fuente
Variables locales
• Un único patrón fuente
from p : MMPerson!Person (p.name = 'Smith')
• Variables locales
from c : GeometricElement!Circle
using {
pi : Real = 3.14;
area : Real = pi * c.radius.square();
}
variable tipo condición
32. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Patrón destino simple
• Como mínimo 1 patrón destino
• Para más de 1 => ,
• El primero se considera default
• Existen 2 tipos de patrones destino:
1. Simples
2. Iterativos
33. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Ejemplo patrón destino simple
rule Journal2Book {
from j : Biblio!Journal
to b : Biblio!Book (
title <- j.title + '_(' + j.vol + '):' + j.num,
authors <- j.articles->collect(e | e.authors)->flatten()->asSet()
chapters <- j.articles,
pagesNb <- j.articles->collect(e | e.pagesNb)->sum()
)}
variable tipo
rule Article2Chapter {
from j : Biblio!Article
to b : Biblio!Chapter (...)
}
34. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Patrón de destino iterativo
(Colecciones)
• Permiten generar colecciones de elementos destino del
mismo tipo para el mismo elemento fuente
• Se utiliza la palabra distinct
• Produce un elemento destino por cada elemento dado en una
colección ordenada
• La colección junto con e se introduce por medio de la palabra
foreach
35. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Ejemplo patrón iterativo destino
iterativo
using {
coll : Sequence(String) = Sequence{'a', 'b', 'c'};
}
to cells : distinct Table!Cell foreach(e in coll)(
content <- e,
id <- coll->indexOf(e)
)
a b c
0 1 2
36. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Ejemplo patrón iterativo destino
iterativo anidado
• La colección origen y destino deben ser iguales en tamaño
using {
coll : Sequence(String) =
Sequence{'Score1', 'Score2', 'Total'};
}
to
tab : Table!Table (lines <- t_lines),
t_lines : distinct Table!Line foreach(e in coll)
(id <- coll->indexOf(e),caption <- line_captions),
line_captions : distinct Table!Caption foreach(e in coll)
(content <- e)
content: String
37. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Asignación de referencias
• Existen 3 casos de inicialización de características:
1. Asignar una referencia a un elemento del modelo destino
generado por la regla
2. Asignar una referencia a un elemento de modelo destino de
otra regla
3. Asignar una referencia a elemento de destino no default en
otra regla
38. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Análisis de casos 1 y 2
• Caso 1:
rule Case1 {
from i : MM_A!ClassA
to
o_1 : MM_B!Class1 (linkToClass2 <- o_2),
o_2 : MM_B!Class2 (...)
}
• Caso 2:
rule Case2_R1 {
from i : MM_A!ClassA
to
o_1 : MM_B!Class1 (linkToClass2 <- i.linkToClassB)
}
rule Case2_R2 {
from i : MM_A!ClassB
to
o_1 : MM_B!Class2 (...), …
}
ClassA Class1
Class2
linkToClass2
ClassA Class1
Class2
linkToClass2
ClassB
linkToClassB
39. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Análisis Caso 3
rule Case3_R1 {
from i : MM_A!ClassA
to
o_1 : MM_B!Class1 (linkToClass2 <- thisModule.resolveTemp(i.linkToClassB, 'o_n'))
}
rule Case3_R2 {
from in : MM_A!ClassB
to
o_1 : MM_B!Class3 (...),
...
o_n : MM_B!Class2 (...),
...
}
ClassA Class1
Class2
linkToClass2
ClassB
linkToClassB
Class3
40. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Bloques imperativos en rules
helper def : id : Integer = 0;
...
rule Journal2Book {
from
j : Biblio!Journal
to
b : Biblio!Book (...)
do {
thisModule.id <- thisModule.id + 1;
b.id <- thisModule.id;
}}
41. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Called Rules
[entrypoint]? rule rule_name(parameters){]?
[using {
var1 : var_type1 = init_exp1;
...
varn : var_typen = init_expn;
}]?
[to
out_var1 : out_type1 (bindings1),
out_var2 : distinct out_type2 foreach(e in collection)
(bindings2),
...
out_varn : out_typen (bindingsn)]?
[do {
statements
}]?
}
opcional
obligatorio
• Permiten generar elementos de modelo destino desde bloques imperativos (salvo los marcados
con entrypoint)
• No pueden ser llamadas main
• El nombre no debe coincidir con el de ningún helper
• Sólo puede haber un solo entrypoint
• Las marcadas con entrypoint se invocan al comienzo de la transformación
42. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Ejemplo Lazy Rule
lazy rule getCross {
from
i: ecore!EObject
to
rel: metamodel!Relationship (
)
}
rule Example {
from
s : ecore!EObject
to
t : metamodel!Node (
name <- s.toString(),
edge <- thisModule.getCross(s)
)
}
MÁS DE UNA VEZ…
rule Example {
from
o2 : ecore!EObject
to
t : metamodel!Node (
name <- o.toString(),
edges <- ecore!EClass.allInstancesFrom('yourmodel')
->collect(e | thisModule.getCross(e))
}
EObject Relationship
Node
name:String
edge
ecore metamodel
edge
EClass
43. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Herencia de reglas
Definición
abstract rule A {
from [fromA]
using [usingA]
to [toA]
do [doA]
}
rule B extends A {
from [fromB]
using [usingB]
to [toB]
do [doB]
}
rule C extends B {
from [fromC]
using [usingC]
to [toC]
do [doC]
}
Resultado
rule B {
from [fromB]
using [usingB]
to [toA.bindings union toB.bindings]
do [doB]
}
rule C {
from [fromC]
using [usingC]
to [toA.bindings union toB.bindings
union toC.bindings]
do [doC]
}
44. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Referencias
1. ATL User Guide: Overview of Atlas Transformation Language.
http://wiki.eclipse.org/ATL/User_Guide_-
_Overview_of_the_Atlas_Transformation_Language.
2. ATL User Guide: The ATL Language.
http://wiki.eclipse.org/ATL/User_Guide_-
_The_ATL_Language