MDA na Prática com Acceleo, Construindo um Gerador de XHTML

Continuando a série de posts sobre Model Driven Architecture (MDA), irei mostrar como desenvolver um gerador de XHTML baseado em um processo MDA, a partir da ferramenta Acceleo.

A Acceleo é uma ferramenta de código aberto, sob a Eclipse Public License (EPL). Ou seja, ela pode ser baixada e utilizada de forma gratuita.



Instalando a Acceleo
O primeiro passo na instalação é optar pelo download da suíte completa com o Eclipse Modeling Framework ou realizar a instalação a partir do método de update do próprio Eclipse. Para esta última opção, a url do site a ser utilizado é http://www.acceleo.org/update/.

Preparação
Esta seção irá ajudar na inicialização do ambiente necessário para tornar possível os próximos passos desta publicação.

Após instalar o plugin Acceleo, execute o Eclipse. No menu "Window" selecione "Open Perspective > Other". Na tela que for exibida escolha "Acceleo" e clique em Ok. As imagens a seguir ilustram essa sequência.
1)
2)
3)
Gerador de XHTML
A partir de agora irei apresentar a criação de um gerador capaz de produzir documentação de um modelo UML2 (resumidamente, uma especificação baseada em UML com foco no desenvolvimento de software). Uma página de documentação será criada para cada classe do modelo; este modelo irá descrever os atributos e fornecer informação adicional para cada entidade. Um exemplo do resultado esperado é ilustrado na imagem abaixo.
Página documentando a classe ArtigoBlog.
 Nesta publicação irei utilizar um método bottom-up na MDA. Este método consiste, primeiro, na produção de um protótipo do alvo da geração, visando definir os padrões para todos os geradores. Após isso, o segundo passo é utilizar este protótipo operacional e validado para produzir os geradores que irão fornecer o resultado esperado. Os geradores serão, então, aplicados na versão final do modelo.

Na próxima seção irei demonstrar o primeiro passo, como criar e validar um protótipo. No nosso exemplo, a criação de um gerador de XHTML a partir de um modelo UML2, será criada uma página XHTML que irá determinar o conteúdo final dos arquivos gerados.

Criação do Protótipo
Estrutura de um Projeto Protótipo

O primeiro passo é a criação de uma página XHTML que descreva uma classe UML. Para isso, no próprio Eclipse, crie um novo projeto: "File > New > Project..." depois "General > Project", adicione o nome do projeto no assistente e clique em "Finish" (a primeira figura a seguir ilustra essa etapa). Irei definir o nome como "net.felipealencar.tutorial.mda.acceleo.weblog.xhtml", mas este nome não tem impacto no resultado final, o leitor fica livre para definir a própria nomenclatura.
Criação do Projeto.

Após isso, crie um diretório para armazenar as páginas XHTML: clique com o botão direito no projeto e selecione "New > Folder", defina o nome "WebContent" no assistente de criação e clique em "Finish".

Criação do Protótipo da Página
Para criar esta página protótipo, primeiro clique com o botão direito no diretório "WebContent", então selecione "New > File", preencha o campo "File name" com "exemplo.html" e clique em "Finish".
Criação do arquivo de exemplo.
Você pode agora definir o conteúdo da página de exemplo que poderá ser obtido do gerador. Como o objetivo é descrever classes UML, a página irá carregar dois blocos, como no esquema a seguir:
  • Um bloco contendo informação sobre a própria classe (nome, descrição...);
  • Um bloco contendo a lista de atributos da classe (nome e tipo).
Os dois blocos de informações.

Insira o código abaixo no arquivo exemplo.html, através do caminho "Open with > Text Editor".
 <html>  
  <head/>  
  <body>  
     <h1>Descrição da Classe</h1>  
     <p>Nome da Classe: ArtigoBlog</p>  
     <p>Comentário: </p>  
     <h1>Atributos</h1>  
     <ul>  
        <li>titulo : String</li>  
        <li>dataCriacao : Date</li>  
        <li>corpo : String</li>  
        <li>autor : User</li>  
     </ul>  
  </body>  
 </html>  

Esta página descreve a classe "ArtigoBlog", que não apresenta comentários e possui quatro atributos ("titulo", "dataCriacao", "corpo" e "autor") de diferentes tipos ("String", "Date" e "User"). Este arquivo é o protótipo (em um conceito semelhante à template ou layout, mais utilizados no contexto de desenvolvimento). Sendo assim, todas as páginas irão possuir este formato.

Agora que o protótipo foi criado, o próximo passo é criar um gerador que irá retornar o resultado desejado para um determinado modelo UML2.

Criação do Gerador
O Acceleo é baseado em um sistema de templates, e então funciona melhor com um "desenvolvimento por protótipo". Uma vez que o protótipo foi desenvolvido, ele é utilizado como base para criar geradores. Esta última operação é descrita passo-a-passo nesta seção.

Criação de Projeto do Gerador
O primeiro passo é criar um projeto gerador no Acceleo: execute "File > New > Project... Acceleo > Generator Project". Neste tutorial, o projeto será nomeado "net.felipealencar.tutorial.mda.acceleo.pim.uml2.gen.xhtml". A nomenclatura indica que o metamodelo de entrada é um UML2, definindo o PIM (Plataform Independent Model) e que permite a geração de arquivos XHTML. Uma boa prática é sempre especificar estas características no nome do projeto, visando prover uma estrutura apropriada para suas ferramentas MDA.
Criação do projeto gerador.
O novo projeto irá ser exibido no Package Explorer do Eclipse e um pequeno ícone do Acceleo irá indicar que se trata de um projeto de Gerador.
Projeto Generation do Acceleo.
Criação do Gerador
O próximo passo é criar o arquivo gerador. Isto pode ser feito pelo item de menu "File > New > Empty Generator". Selecione o diretório "src". Estas ações iniciam um assistente de duas páginas. A primeira destas páginas irá solicitar que seja preenchido o tipo do metamodelo, assim como o tipo da raíz do template, em nosso casso uma classe UML2. O metamodelo pode ser definido pela URI "http://www.eclipse.org/uml2/1.0.0/UML" no Eclipse. A raiz do template é o tipo do objeto que irá começar a geração de um arquivo quando for executado. O tipo raiz para este exemplo é então "uml2.class". 

Gerador - Seleção do metamodelo e do tipo da raíz.
A segunda página do assistente solicita a verificação do diretório e a atribuição de um nome para o gerador. Para este tutorial o gerador foi nomeado "xhtml.mt".
Gerador - diretório e nome do gerador.
Clique em "Finish" para o gerador ser criado. Para abrir a edição do template, dê dois cliques em "xhtml.mt" no diretório "src", como na imagem abaixo. Para um gerador vazio como este, somente o metamodelo e o primeiro script são definidos. Agora irei mostrar como criar o corpo do script.
Script do gerador.
Do Template para o Gerador: Utilizando o Editor de Reflexo
Para o conteúdo do gerador, começaremos do protótipo criado no início deste tutorial, simplesmente copiando o código do arquivo "exemplo.html". O nome padrão do atributo "file" deve ser mudado para <%name%>.html, conforme a figura abaixo. Este atributo define o formato dos nomes de arquivos que são gerados. Definir o valor <%name%>.html irá fazer com que os arquivos tenham o nome derivado do nome da classe (<%name%>) concatenado com a extensão ".html".
Gerador modificado utilizando o protótipo.
Templates definidos desta forma são capazes de gerar arquivos baseados em um modelo UML2. O Acceleo oferece um editor para visualizar os resultados da geração: o "reflective editor".

Para abrir este editor, selecione o modelo em que o gerador será aplicado. Neste tutorial, o "WebLog_en.uml" será utilizado. Este modelo deve ser baixado do site do próprio Acceleo, na seção "Documentation > First Generator Module", http://www.acceleo.org/pages/first-generator-module. O arquivo está disponível por um link na seção "Model Creation".

Antes de tudo, você precisa criar um novo diretório para armazenar seus modelos. Clique com o botão direito no Projeto do Gerador que criamos anteriormente, selecione "New > Folder", especifique "model" no campo "name" e então clique em "Finish".

Mova o modelo que você baixou do site do Acceleo para este novo diretório. Isto deve ser feito diretamente do sistema de arquivos. Após esse passo, atualize (pressione F5 com o projeto selecionado) a lista de recursos do projeto para que o modelo possa estar disponível para uso.
Modelo UML2 no workspace.

Ao visualizar o modelo no workspace do Eclipse, é possível utilizar o Acceleo reflective editor. Clique com o botão direito em "model/WebLog_en.uml" e selecione a opção "Open with > Acceleo Reflective Editor" no menu. Uma nova aba será aberta, exibindo o modelo "WebLog_en.uml" em forma de árvore, com os pacotes, classes e associações.
Acceleo Reflective Editor exibindo o arquivo WebLog_en.

Com o objetivo de visualizar o resultado da geração, você precisa selecionar o gerador que o editor deve utilizar. Clique com o botão direito na janela do reflective editor, na parte branca, e selecione o item "Acceleo > Select Template". A janela irá exibir todos os geradores Acceleo que podem ser encontrados. Agora selecione o gerador "xhtml.mt" no seu projeto de geração e clique em "Ok".
Seleção do gerador "xhtml.mt".
Após este passo, é possível visualizar o código que será gerado a partir do modelo "WebLog_en.uml". Basta selecionar uma classe, "BlogEntry" por exemplo, e clicar na aba "Source". O código exibido é o escrito no template que definimos, independente da classe selecionada, isto acontece porque todo o código gerado é baseado num modelo estático. O template do gerador precisa ser modificado para exibir informações dinâmicas.

Utilizando informações do Modelo no Gerador
A primeira informação que precisa ser inserida de forma dinâmica é o nome da classe utilizada para gerar o arquivo de documentação. O metamodelo da UML2 define um atributo "name" no elemento "Class". Este atributo contém o nome da classe. Isto pode ser utilizado pelo gerador para obter a informação necessária, sendo assim alteramos o "xhtml.mt", substituindo "ArtigoBlog" como nome da classe pela instrução <%name%>, como mostrado na figura abaixo.
Adicionando a instrução <%name%> no arquivo template.
A mudança realizada no template irá impactar no resultado da geração. Sendo assim, clique novamente com o botão direito na área branca do reflective editor, e então selecione "Acceleo > Reload Template" no menu. Isto irá atualizar a visualização da geração. Observe que na aba "Source" do arquivo "WebLog_en.uml" o nome da classe foi alterado, em concordância com o que está especificado no modelo. O nome da classe passa a ser exibido como "BlogEntry".
Atualização do código gerado ao alterar o template "xhtml.mt".
Agora é preciso definir a parte do gerador que irá listar os atributos de cada classe. Devido ao número de atributos em uma classe não ser fixo, nós iremos utilizar um laço de repetição para criar a lista dinamicamente. Com a sintaxe do Acceleo, a instrução "for" permite um laço nas entidades do modelo, da seguinte forma:
 <%for (ElementList) {%>  
    Este texto será gerado para cada elemento  
 <%}%>  

Com isso será possível criar um texto para cada atributo da classe. Meu objetivo neste tutorial é criar uma lista XHTML com uma entrada por atributo. O laço de repetição irá gerar uma linha por atributo.
<ul>  
 <%for (attribute) {%>  
  <li>nome: tipo</li>  
 <%}%>  
</ul>  

Para cada atributo, uma linha é criada com a tag <li>, o conteúdo e o fechamento da tag </li>. Ainda assim, os valores "nome" e "tipo" continuam estáticos. Vamos ver agora como obter estes valores de forma dinâmica.

Os atributos UML2 possuem as informações com nome e tipo, mas, da maneira definida no template "xhtml.mt", o script utilizado está codificado para obter informações do tipo "Class" (<%script type="Class" [...]), como desejamos obter informações sobre os atributos precisamos mudar o contexto. O Acceleo automaticamente realiza a mudança de contexto ao utilizar um "for": as instruções <%name%> e <%type%> serão aplicadas de forma relativa aos atributos da classe.
 <ul>  
 <%for (attribute) {%>  
  <li><%name%> : <%type.name%></li>  
 <%}%>  
 </ul>  

Para melhorar a qualidade dos resultados iremos utilizar uma estrutura de decisão e um serviço do Acceleo "nSize" que retorna o número de elementos contidos numa lista. O código para exibir os atributos então é:
 <%if (attribute.nSize == 0){%>  
 <p>Nenhum atributo.</p>  
 <%}else{%>  
 <ul>  
  <%for (attribute) {%>  
  <li><%name%> : <%type.name%></li>  
  <%}%>  
 </ul>  
 <%}%>  

Com as alterações acima, seu template agora deve ser semelhante ao seguinte:
Codificação final do gerador XHTML.
Antes de executar a geração completa no modelo, um último teste no reflective editor irá garantir que o resultado será o esperado. O reflective editor atualiza a lista de atributos da classe, como exibido na figura abaixo, ao selecionar "Acceleo > Reload Template" através do menu com a classe "BlogEntry" selecionada.
Resultado final no reflective editor.
Criação de uma Cadeia (Chain) de Execução (Execution)
Como visto, realizamos a geração de apenas uma classe do modelo. Agora irei mostrar como criar um arquivo "Chain", já que múltiplas operações precisam ser executadas. Em "File > New > Chain", um assistente permite uma criação rápida de "Chain" no projeto alvo, enquanto fornece informação aos recursos envolvidos.

O assistente pode ser divido em quatro passos:
  • O primeiro passo consiste na inserção da URI do metamodelo relativo ao gerador;
  • O segundo passo solicita um modelo de entrada, no nosso caso é o arquivo "WebLog_en.uml";
  • O terceiro passo requisita o script/template que será executado. É o "xhtml.mt" que satisfaz essa condição;
  • Finalmente, a última página do assistente demanda que você especifique o diretório de geração e o nome do arquivo "Chain". Selecione o diretório "WebContent" no campo "Container" e nomeie o arquivo como "xhtml.mt". Se tudo ocorrer bem, a tela a seguir deve ser exibida ao acessar o arquivo "xhtml.chain".
Esquema do arquivo "xhtml.chain".
Para deixar as coisas mais claras, eu irei mover o arquivo "xhtml.chan" para a raíz do projeto. Este arquivo é composto por duas partes principais:
  • Um "Repository" referenciando todos os artefatos usado para a geração: os geradores, os diretórios alvo, etc..
  • Um conjunto de operações ("Action Set") que descreve a operação da geração do XHTML.
Alterando o local do arquivo "xhtml.chain".
O primeiro exemplo é simples: a informação fornecida para o assistente é suficiente para produzir uma cadeia que é totalmente configurada para obter o resultado desejado.

A execução da geração pode ser feita clicando com o botão direito no arquivo "xhtml.chain", selecionando "launch". Uma barra de progresso é exibida, indicando o progresso da geração. Uma vez que a barra de progresso desaparecer, o diretório "WebContent" é precedido por um ">", exibindo que este diretório possui arquivos. Vários arquivos html foram criados, um para cada classe do modelo "WebLog_en.uml". Eles podem ser visualizados usando o próprio browser do sistema.

Apesar de ser uma funcionalidade básica, talvez seja possível visualizar o potencial desta ferramenta, além de ficar claro que o paradigma MDA pode ser aplicado em soluções práticas na engenharia de software.

Espero que tenham gostado, keep coding.

Felipe Alencar

Felipe Alencar é doutorando em Ciência da Computação na UFPE, professor, desenvolvedor e acredita que só não virou jogador de futebol, surfista ou músico profissional por falta de tempo e talento.

10 comentários:

  1. Ola Felipe

    Excelente material. Eu estou precisando gerar arquivos .c e .h a partir de modelos EMF / GEF com Acceleo, voce teria algum exemplo bom quanto este material e minha outra duvida é pensando como requisito, você acha que o arquivo .mtl (Template) poderia ser um documento de requisito onde o implementador possa usa-lo para geração de código.

    ResponderExcluir
  2. Olá Fabio! Obrigado. :)

    Então, creio que seja só uma questão de modificar a extensão e codificar o gerador com a sintaxe de C, mas infelizmente não sei te dizer sobre algum material que te dê maiores detalhes sobre isto.
    Quanto aos requisitos, este é justamente um dos benefícios que este paradigma traz. Observe que seus modelos irão estar totalmente de acordo com o Template que pode sim ser visualizado como um documento de requisito.
    Eu acredito que, principalmente em fábricas de software, esta abordagem seja adotada em larga escala daqui a algum tempo.

    ResponderExcluir
  3. Ola Felipe

    Quando estou executando o arquivo .mtl para gerar o código na linguagem desejada, esta ocorrendo o erro que segue abaixo, sabe o que pode ser?


    The generation failed to generate any file because there are no model elements that matches at least the type of the first parameter of one of your main templates.
    The problem may be caused by a problem with the registration of your metamodel, please see the method named "registerPackages" in the Java launcher of your generator. It could also come from a missing [comment @main/]
    in the template used as the entry point of the generation.


    O meu arquivo .mtl esta bem simples conforme segue abaixo:

    [comment encoding = UTF-8 /]
    [module generate('http:///jfb/examples/gmf/filesystem.ecore')]

    [template public generateElement(aFile : File)]
    [comment @main/]
    [file (aFile.name, false, 'UTF-8')]
    public class [aFile.name.toUpperFirst()/] {}
    [/file]
    [/template]

    ResponderExcluir
  4. Verifique, primeiro, se você definiu o tipo do metamodelo durante a criação do gerador (Empty Generator). Você consegue ver alterações no source? Esse erro ocorre quando você vai fazer as transformações em cadeia? Se for, verifique também se você está inserindo o modelo correto na parte que solicita o modelo de entrada.

    ResponderExcluir
  5. Ola Felipe

    Não consegui encontrar o erro, não sei se esta com tempo, mas se puder efetuar o exemplo que segue abaixo, é bem rápido. Já tentei fazer tudo mas o erro sempre ocorre.

    Peguei da internet o exemplo que segue abaixo, quando vou gerar o arquivo texto a partir do.mtl apontando para o arquivo ecore da aplicação gmf o erro ocorre.

    Exemplo gmf
    http://gmfsamples.tuxfamily.org/wiki/doku.php?id=gmf_tutorial1

    Desde ja, muito obrigado.

    ResponderExcluir
    Respostas
    1. Fabio, tem um tutorial que acabei de adicionar aqui no blog que tem esse mesmo exemplo do tutorial que você está tentando fazer. Dá uma olhada, creio que fique mais fácil de te ajudar.

      Excluir
    2. O link do tutorial é o seguinte: http://www.felipealencar.net/2014/01/tutorial-desenvolvimento-de-software.html

      Excluir
  6. Oi Felipe,

    Estou usando o Acceleo 3.3.1. E estou tendo um problema com os tipos dos atributos das classes na geração do meu código.
    Quando executo o gerador como uma aplicação Acceleo ele consegue encontrar os tipos. Porém quando executo a geração a partir de um aplicação java, os tipos primitivos ficam como invalid.
    Você teria alguma dica?

    ResponderExcluir
    Respostas
    1. Tem como você colocar o erro aqui? Pode ser algo na sua sintaxe.

      Excluir
  7. Boa tarde Felipe tudo bem?
    Vi que você entende de Acceleo, cara preciso muito de seu ajuda, e se puder me dar uma força, curso S.I na UENP, e meu TCC é neste ramo de UML Executable... Meu objetivo é gerar codigo java a partir de diagramas UML mas até agora so consegui com o de classes e pouca coisa... teria um material para me auxiliar? Você ja conseguiu algo alem disso? Conto com você ok por gentileza, desde já agradeço; meu email: allan.bonifacio@uenp.edu.br

    ResponderExcluir