Pular para o conteúdo principal

Tutorial: Desenvolvimento de Software Baseado em Modelos na Prática com Epsilon, Parte 2

Na primeira parte deste tutorial, foi implementada de forma básica uma ferramenta CASE para o desenvolvimento de um sistema de arquivos, utilizando a Epsilon para realizar esta implementação. Nesta ferramenta é possível criar modelos e gerar código que reflita o sistema modelado. Até aqui, foi definido o metamodelo que descreve o domínio, seus conceitos e como estes conceitos estão relacionados.

Nesta segunda etapa irei mostrar como definir a sintaxe concreta da sua DSML, de forma que a ferramenta gerada contenha esta sintaxe. Além disso, será definida a geração de código, finalizando o processo MDD proposto neste tutorial.

Novos ícones
Caso você tenha conseguido gerar a ferramenta da maneira descrita na parte 1 deste tutorial, foi possível perceber que o Epsilon gera um editor com ícones padrões na paleta de ferramentas de modelagem. Essa solução vai de encontro ao que se propõe ao definirmos uma DSML, já que a sintaxe concreta deve representar conceitos e relacionamentos do domínio.

Para adicionar ícones que representem estes conceitos e relacionamentos com maior semântica, efetue o download de um pacote de ícones (neste tutorial vou utilizar este pacote) e adicione estes ícones ao projeto "filesystem.edit", na pasta "icons/full/obj16". Após isso é preciso realizar modificações no arquivo "filesystem.emf". Serão adicionadas anotações referentes aos ícones para cara entidade do modelo. O código ficará da seguinte forma:

@namespace(uri="filesystem", prefix="filesystem")
@gmf
package filesystem;

@gmf.diagram
class Filesystem {
    val Drive[*] drives;
    val Sync[*] syncs;
}

@gmf.node(label.icon="true",tool.small.bundle="filesystem.edit", tool.small.path="/icons/full/obj16/CD.gif")
class Drive extends Folder {

}

@gmf.node(label.icon="true",tool.small.bundle="filesystem.edit", tool.small.path="/icons/full/obj16/Folder.gif")
class Folder extends File {
    @gmf.compartment
    val File[*] contents;
}

@gmf.node(label.icon="true",tool.small.bundle="filesystem.edit", tool.small.path="/icons/full/obj16/Trackback.gif")
class Shortcut extends File {
    @gmf.link(target.decoration="arrow", style="dash")
    ref File target;
}

@gmf.link(source="source", target="target", style="dot", width="2")
class Sync {
    ref File source;
    ref File target;
}

@gmf.node(label = "name", label.icon="true",tool.small.bundle="filesystem.edit", tool.small.path="/icons/full/obj16/List.gif")
class File {
    attr String name;
}

Observe a inserção da anotação "@gmf.node". Os atributos adicionados ("label.icon", "tool.small.bundle" e "tool.small.path") nesta anotação definem a imagem que representará a classe logo abaixo dela. Para maiores informações sobre estas anotações, acesse a documentação do GMF.

Desta forma, é possível adicionar uma representação gráfica básica, que descreva os elementos do domínio graficamente. Outra representação gráfica que pode ser adicionada é aos próprios elementos desenhados no modelo. Ao invés de utilizarmos formas geométricas padrões do GMF, como elipse e quadrado para representar os nós, "nodes", é possível definir uma imagem no formato .png que irá ser desenhada no diagrama modelado.

Um exemplo desta segunda forma de definir a sintaxe concreta para representar conceitos do domínio é realizada da seguinte maneira: crie um novo projeto, "New > Project > General... Project", chamado "filesystem.figures", neste novo projeto crie dois pacotes: 1) "figures" e 2) "filesystem.figures.activator". No pacote "figures" iremos implementar a classe que cria a imagem, com o código a seguir:

package figures;

import org.eclipse.draw2d.ImageFigure;

import filesystem.figures.activator.PluginActivator;

public class FileFigure extends ImageFigure {

 public FileFigure() { 
  super(PluginActivator.imageDescriptorFromPlugin(PluginActivator.ID,"images/File.png").createImage(), 0);
 }

}

Observe que esta classe depende de um plugin ativador, "PluginActivator". Este plugin é implementado da seguinte forma:


package filesystem.figures.activator;

import org.eclipse.core.runtime.Plugin;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;

/**
 * @generated
 */
public class PluginActivator extends AbstractUIPlugin {

 /**
  * @generated
  */
 public static final String ID = "filesystem.figures"; //$NON-NLS-1$

 /**
  * @generated
  */
 private static PluginActivator ourInstance;

 /**
  * @generated
  */
 public PluginActivator() {
 }

 /**
  * @generated
  */
 public void start(BundleContext context) throws Exception {
  super.start(context);
  ourInstance = this;
 }

 /**
  * @generated
  */
 public void stop(BundleContext context) throws Exception {
  ourInstance = null;
  super.stop(context);
 }

 /**
  * @generated
  */
 public static PluginActivator getDefault() {
  return ourInstance;
 }
}

Para finalizar a construção do projeto "filesystem.figures", basta criar o diretório "images" neste mesmo projeto e adicionar as figuras que deseja atribuir para cada nó. Neste tutorial, adicionei somente a figura "File.png".

Além das implementação do projeto "filesystem.figures", é preciso modificar o arquivo "filesystem.emf", presente no projeto principal, "filesystem". O arquivo modificado deve ficar da seguinte forma:

@namespace(uri="filesystem", prefix="")
package filesystem;

@gmf.diagram
class Filesystem {
    val Drive[*] drives;
    val Sync[*] syncs;
}

@gmf.node(label.icon="true",tool.small.bundle="filesystem.edit", tool.small.path="/icons/full/obj16/CD.gif")
class Drive extends Folder {

}

@gmf.node(label.icon="true",tool.small.bundle="filesystem.edit", tool.small.path="/icons/full/obj16/Folder.gif")
class Folder {
    @gmf.compartment
    val File[*] contents;
    
    attr String name;
}

@gmf.node(label.icon="true",tool.small.bundle="filesystem.edit", tool.small.path="/icons/full/obj16/Trackback.gif")
class Shortcut {
    @gmf.link(target.decoration="arrow", style="dash")
    ref File target;
    
    attr String name;
}

@gmf.link(source="source", target="target", style="dot", width="2")
class Sync {
    ref File source;
    ref File target;
}

/*Alteração da anotação abaixo para modificar a representação gráfica do nó "File".*/
@gmf.node(figure="figures.FileFigure", 
 label.icon="false", label="name", label.placement="external",
 label = "name", label.icon="true",tool.small.bundle="filesystem.edit", tool.small.path="/icons/full/obj16/List.gif"")
class File {
    attr String name;
}

E para finalizar esta parte do tutorial, um pequeno fix deve ser realizado, já que o EuGENia ainda não oferece uma maneira de adicionar dependências de projetos de forma padrão na geração do editor. Este fix deve ser criado no diretório "models" do projeto principal, "filesystem". Para isso, no diretório "models", selecione "New > Other... > Epsilon > EOL Program". Nomeie o arquivo como "FixGMFGen.eol" e adicione o seguinte código:

var plugin := GmfGen!GenPlugin.all.first;
plugin.requiredPlugins.add('filesystem.figures');

Estrutura do projeto.
Após esta modificação, basta gerar o editor normalmente através do EuGENia, como já visto na parte 1 deste tutorial (clique com o botão direito no arquivo "filesystem.emf", "Eugenia > Generate GMF Editor"). A imagem ao lado mostra como deve ficar a estrutura do seu projeto.

Basta executar o projeto "Run > filesystem" e o resultado final deve ser igual ao da imagem abaixo:
Ferramenta com a sintaxe concreta definida.

No próximo e último tutorial sobre o Epsilon, irei mostrar como gerar código a partir dos modelos criados na ferramenta que estamos implementando. Lembrando que o projeto está disponível no github (https://github.com/felipealencar/filesystem). Espero que tenham gostado. Até a próxima!


Comentários

Postagens mais visitadas deste blog

Utilizando o padrão de referências da ABNT no Word

Uma importante funcionalidade do Microsoft Word é o seu Gerenciador de Fontes Bibliográficas. Para aqueles que estão escrevendo algum trabalho acadêmico ou científico, é possível cadastrar todas as referências do trabalho e no final gerar a listagem já enumerada dos documentos que foram consultados na pesquisa. Essa postagem traz os arquivos necessários e as instruções para facilitar essa etapa da elaboração.

Como elaborar um TCC em Sistemas de Informação

Alguns meses atrás estive na tão conhecida saga de elaboração do Trabalho de Conclusão de Curso, o TCC, e somente comprovei aquilo que eu via em forma de desabafo nas redes sociais e que tantos outros colegas de faculdade me falavam. Uma das definições mais aceitas por mim sobre o que é um TCC é a citada pela minha orientadora: "é uma gestação". E realmente, apesar de ter feito o meu em cerca de 1 mês (não recomendo isso para ninguém, mas era minha única saída para não ficar desempregado e sem a possibilidade de cursar meu mestrado, mas essa é outra história), um TCC bem feito deve ter seu cronograma definido para 6 meses, no mínimo, e isso deveria ser uma recomendação do Ministério da Saúde para que os graduandos não percam sua saúde mental.

Mininet: Uma Rede Virtual Instantânea no Seu PC

Baseado no texto de introdução presente no site oficial do Mininet (www.mininet.org) apresento esta ferramenta que possibilita a desenvolvedores e pesquisadores a criação de uma rede virtual realista, executando um kernel real, switch e código de aplicação, em uma única máquina (VM, cloud ou nativa), em segundos, com comandos simples.

A rede virtual criada pelo Mininet é escalável, uma rede definida por software em um único PC utilizando processos do Linux. Isso possibilita um meio inteligente de realizar testes e simulações de uma rede antes de implementá-la em meio físico, caso esse seja o objetivo.