Download Tutorial Acceleo Introducción Prerrequisitos
Document related concepts
no text concepts found
Transcript
Tutorial Acceleo Introducción Acceleo1 es actualmente una herramienta de generación para desarrollo dirigido por modelos, logrando hacer transformaciones M2T (Model to Text). Al integrarse a eclipse permite desarrollos rápidos en JEE, PHP y JSP, entre otros. Esta herramienta funciona partiendo de un modelo y seleccionando un módulo que define las transformaciones a realizar para la generación de código. Ilustración 1 Funcionamiento de Acceleo Se dará un pequeño tutorial con los pasos necesarios para realizar un proyecto Acceleo y generar código. Prerrequisitos Para poder seguir este tutorial es necesario lo siguiente: Eclipse Modeling Framework (EMF)- http://www.eclipse.org/modeling/emf/ Una vez descargado EMF se procede a instalar los componentes necesarios. Para 1 Página oficial de Acceleo. http://www.acceleo.org/pages/home/en esto es necesario hacer click en el botón para instalar componentes de modelamiento. Una vez cargue la ventana de los diferentes componentes de modelamiento disponibles, seleccionar el componente de Acceleo y proceder con la instalación. Una vez terminada la instalación la herramienta le pedirá que la reinicie. Proceda a reiniciar el IDE de Eclipse. Una vez vuelva a abrir eclipse, el plugin para el IDE con Acceleo integrado estará disponible para su uso. Creación del proyecto Acceleo Para lograr un proyecto de Acceleo es necesario obtener tanto un modelo de entrada como un folder de salida, en este caso podría ser tanto un diagrama de clases UML como un modelo generado en un proyecto ATL, y un Java Project respectivamente. El primer paso es usar la perspectiva Acceleo, que permitirá trabajar de una manera más rápida. Cree un Acceleo Project que contendrá las definiciones de las transformaciones que se quieren realizar a partir de un modelo. Haciendo Click derecho sobre el explorador de paquetes, seleccione New > Acceleo Project. Este proyecto puede llamarse como desee, para este tutorial se ha llamado org.eclipse.acceleo.module.sample, presione Next. Presione Browse para seleccionar el URI del metamodelo a usar, este paso no es relevante el metamodelo que seleccione si se desea trabajar con un metamodelo especifico generado en un proyecto ATL. Presione Next y luego Finish. Se creara y abrirá un archivo generate.mtl sobre el que se definirá el código a generar. El archivo generate.mtl describe el módulo de Acceleo, este es quien define el código que se generara para una plataforma específica, que para este estudio es Java. Este módulo, contiene una seria de plantillas que contienen las características del código fuente que se desea generar a partir de un modelo. De hecho la extensión mtl, hace referencia a model transformation languaje. El archivo generate.mtl es el siguiente: [comment encoding = UTF-8 /] [module generate('http://www.eclipse.org/uml2/3.0.0/UML')/] [template public generate(aClass : Class)] [comment @main /] [file (aClass.name, false, 'UTF-8')] [aClass.name/] [/file] [/template] El contenido del archivo generate.mtl debe ser reemplazado por el código que generara la clase junto con sus atributos, ya que aunque en este momento ya se esta generando un archivo de texto, aun no se han definido transformaciones. Reemplace el el contenido del archivo con el siguiente código correspondiente a las transformaciones para generar el código del kernel. [comment encoding = UTF-8 /] [module generate('/musicStore/input/mms/kernelMM.ecore')/] [template public generate(c : Kernel )] [comment @main /] [file (c.system.element.name.toUpperFirst().concat('.java'), false)] package org_eclipse_icesi_kernel; public class [c.system.element.name.toUpperFirst()/] { /**Conjunto de atributos de la clase [c.name/] */ [for (p: Attribute | c.system.element.attributes)] private String [p.name/]; [/for] /**Constructor de la clase [c.name/] [for (p: Attribute | c.system.element.attributes)] @param p[p.name/] valor del constructor [/for] */ public [c.system.element.name.toUpperFirst()/]([for (p: Attribute | c.system.element.attributes) separator(',')] String p[p.name/][/for]){ [for (p: Attribute | c.system.element.attributes)] [p.name/] = p[p.name/]; [/for] } /**Constructor de la clase [c.name/] */ public [c.system.element.name.toUpperFirst()/](){ } [for (p: Attribute | c.system.element.attributes) separator('\n')] /**Metodo get[p.name.toUpperFirst()/] Permite obtener [p.name/] @return String El valor para del atributo [p.name/]*/ public String get[p.name.toUpperFirst()/]() { return this.[p.name/]; } [/for] [for (p: Attribute | c.system.element.attributes) separator('\n')] /**Metodo set[p.name.toUpperFirst()/] Permite cambiar [p.name/] @param String Nuevo valor para el atributo [p.name/]*/ public void set[p.name.toUpperFirst()/](String p[p.name/]) { this.[p.name/] = p[p.name/]; } [/for] } [/file] [file (c.system.name.toUpperFirst().concat('.java'), false)] package org_eclipse_icesi_kernel; import import import import java.util.Observable; java.util.ArrayList; java.util.Iterator; java.util.Arrays; public class [c.system.name.toUpperFirst()/] extends Observable { private ArrayList<[c.system.element.name.toUpperFirst()/]> elements; private [c.system.element.name.toUpperFirst()/] selectedElement; private static [c.system.name.toUpperFirst()/] instance; private [c.system.name.toUpperFirst()/]() { this.selectedElement = null; this.elements = new ArrayList<[c.system.element.name.toUpperFirst()/]>(); } public static [c.system.name.toUpperFirst()/] getInstance() { if (instance == null) { instance = new [c.system.name.toUpperFirst()/] (); } return instance; } public boolean add([c.system.element.name.toUpperFirst()/] value) { boolean result = false; if (findSongByID(value) == null) { this.elements.add(value); result = true; } setChanged(); notifyObservers(); return result; } public ArrayList<[c.system.element.name.toUpperFirst()/]> getElements() { ArrayList<[c.system.element.name.toUpperFirst()/]> elementsCopy = new ArrayList<[c.system.element.name.toUpperFirst()/]>(elements); return elementsCopy; } public void setSelectedElement([c.system.element.name.toUpperFirst()/] selectedElement) { this.selectedElement = selectedElement; setChanged(); notifyObservers(); } public [c.system.element.name.toUpperFirst()/] getSelectedElement() { return this.selectedElement; } public [c.system.element.name.toUpperFirst()/] findSongByID([c.system.element.name.toUpperFirst()/] searchedElement) { boolean found = false; [c.system.element.name.toUpperFirst()/] element = null; for (Iterator<[c.system.element.name.toUpperFirst()/]> iterator = elements.iterator(); iterator.hasNext() && !found;) { element = iterator.next(); if (element.getName().equals(searchedElement.getName())) { found = true; } } if (!found) { element = null; } return element; } [for (p: Attribute | c.system.element.attributes) separator('\n')] public void bubbleSortBy[p.name.toUpperFirst()/]() { [c.system.element.name.toUpperFirst()/]['[]'/] objects = getElements().toArray(new [c.system.element.name.toUpperFirst()/]['[elements.size()]'/]); for (int i = 0; i < objects.length; i++) { for (int j = i + 1; j < objects.length; j++) { String value_1=objects['[i]'/].get[p.name.toUpperFirst()/]()+""; String value_2=objects['[j]'/].get[p.name.toUpperFirst()/]()+""; if (value_1.compareTo(value_2) > 0) { swap(objects, i, j); } } } elements = new ArrayList<[c.system.element.name.toUpperFirst()/]>(Arrays.asList(objects) ); setChanged(); notifyObservers(); } [/for] private void swap(Object['[]'/] objects, int i, int j) { Object temp = objects['[i]'/]; objects['[i]'/] = objects['[j]'/]; objects['[j]'/] = temp; } } [/file] [/template] Si se tienen en cuenta las siguientes líneas, se esta usando en este modulo el metamodelo del kernel que se encuentra en otro proyecto (ATL Project), y se define la plantilla para realizar una transformacion M2T de el. [module generate('/musicStore/input/mms/kernelMM.ecore')/] [template public generate(c : Kernel )] Se deben tener en mente ciertas cosas, entendiendo mejor el código usado. Los Templates son un conjunto de sentencias usadas para generar texto. [template public generate(c : Class)] ... [/template]. La etiqueta File le dice al motor de Acceleo que debe generar el contenido del tag en un archivo de texto. [file(<uri_expression>, <append_mode>, <outencoding>)] (...) [/file] La etiqueta For para recorrer las colecciones. [for (Sequence{1, 2, 3}) before ('sequence: ') separator (', ') after (';')] [/for] Las condiciones son escritas con la etiqueta If-else [if (condition)] ... [elseif (condition)] ... [else] ... [/if] En el código que se debe copiar al archivo generate.mtl ya es evidente el código Acceleo usado para generar los constructores, los atributos y métodos de la clase, que pueden ser mucho más compresibles con la breve explicación anterior. Se debe comprobar que en el archivo MANIFEST.MF contenga los siguientes plugins: org.eclipse.emf.ecore org.eclipse.emf.ecore org.eclipse.emf.ecore.xmi org.eclipse.ocl org.eclipse.ocl.ecore org.eclipse.acceleo.model org.eclipse.acceleo.engine Este archivo podría cambiar, dependiendo del metamodelo con el que se quiera trabajar, en el caso de un metamodelo que definamos propiamente se deben tener los plugins anteriores, pero si se desea trabajar por ejemplo, con el metamodelo UML se debe tener el plugin adicional. org.eclipse.uml2.uml Se debe crear un proyecto Acceleo haciendo Click derecho sobre el explorador de paquetes, seleccione New > Project, luego Java Project. Se puede nombre el nuevo proyecto como se desee, en nuestro caso se ha llamado musicStore. Para este momento ya se puede generar el código a partir del modelo UML que se creó, que para efectos de esta explicación se hace de esta manera, aunque se puede recibir como el resultado de transformaciones productos de un proyecto ATL. Seleccionado el archivo generate.mtl, Click Derecho > Run as > Launch Acceleo Application. Se lanza una página de configuración en la que se determinara el modelo de entrada y el folder de salida necesarios para ejecutar el proyecto Acceleo. La información debe ser como se muestra a continuación de acuerdo a los datos del metamodelo de entrada y al folder de salida para las transformaciones M2T. Se pueden tener en cuenta ciertas elementos al momento de profundizar con el trabajo de Acceleo. Un módulo puede usar otros módulos al momento de su ejecución, por lo que se debe usar una sentencia import en el archivo .mtl. [ import qualified::name::of::imported::module/] XMI generado en ATL XML (Extensible Markup Language), es un conjunto de reglas que definen unas etiquetas semánticas, y que en el tema de la generación de código permiten que se tome a los modelos de un específico, posteriormente llegando a código. Ilustración 1 - Código XMI generado en ATL De acuerdo a la ilustración 1, la etiqueta <system></system> hace referencia a la clase contenedora, <element></element> al resto de clases, <attributes></attributes> a los atributos de las clases y la etiqueta <sorts> a los ordenamientos de cada uno de los atributos. Identificando estos elementos se puede hacer fácilmente la transformación de modelo a texto, M2T, en Acceleo. Ejercicio A manera de ejercicio, se le pide que el código M2T para el método insertionSort. Anexos Para mayor información sobre Acceleo se recomienda visitar los siguientes sitios web: http://www.obeonetwork.com/page/acceleo-user-guide http://sistemas.uniandes.edu.co/~isis4712/dokuwiki/doku.php?id=tl_acceleo http://wiki.eclipse.org/Acceleo/Quick_Start www.dsic.upv.es/asignaturas/facultad/lsi/trabajos/192000.doc