Em um artigo publicado anteriormente no website da DevMedia, foram apresentados os primeiros passos para o desenvolvimento de plug-ins para Astah* [1].

Naquela publicação, comentou-se sobre algumas limitações do plug-in desenvolvido como estudo de caso, são elas:

Como pode ser notado, o plug-in desenvolvido (Validator) neste artigo apresenta diversas limitações, tais como: i) só realiza um tipo de verificação de violação de convenções de nomenclatura; ii) a estratégia utilizada para exibição dos erros de verificação é bastante limitada, principalmente para projetos que apresentam muitas classes; iii) para efetuar a verificação de um diagrama, o usuário precisa sempre acionar o menu Class Validator; e iv) há strings utilizadas na classe TemplateAction que não advém do arquivo plugin.properties, violando assim, a internacionalização do plug-in [1].

Saiba tudo sobre Engenharia de Software aqui na DevMedia

Este artigo visa a minimizar tais limitações, aprimorando o projeto do plug-in Validator. Para isso, aprenderemos a realizar outros tipos de verificações de nomenclatura para classes, como por exemplo, se os identificadores das classes possuem espaços em branco. Além disso: i) veremos como utilizar mecanismos mais adequados para apresentar os problemas de nomenclatura identificados pelo plug-in, utilizando views, tabelas de dados, entre outros recursos; ii) aprenderemos a realizar a verificação de um diagrama de classes automaticamente, sempre que o projeto UML sofrer alguma modificação, isto é, o usuário não precisará acionar qualquer item de menu do plug-in Validator; e iii) faremos a internacionalização completa das mensagens utilizadas na interface do plug-in.

Para que você consiga acompanhar este artigo adequadamente, recomendo fortemente a leitura do artigo comentado anteriormente [1]. Desta forma, estarei assumindo que você já possui o conhecimento necessário sobre: i) os principais conceitos para desenvolvimento de plug-ins para o Astah*, como por exemplo, sobre a instalação e configuração do ambiente de desenvolvimento; ii) os principais scripts do Astah Plug-in SDK; iii) os principais arquivos de um projeto de plug-in, como plug-in.xml; iv) os conceitos sobre extensões; entre outros.

Importando o projeto do plug-in Validator

A partir do artigo disponível em [1] você poderá baixar o código-fonte do projeto do plug-in Validator e importá-lo no Eclipse. Para isso, siga o procedimento abaixo:

Passo 1: descompacte o arquivo validador.zip em seu workspace Eclipse.

Passo 2: abra o Eclipse. No menu principal, escolha a opção File à Import, depois selecione Existing Maven Projects e clique em Next. Na próxima tela, clique em Browse e busque pelo projeto validator. Uma vez encontrado o projeto, clique em Finish e o mesmo será automaticamente importado. Pronto! Agora já podemos realizar alguns tipos de manutenção no plug-in Validator, a saber, manutenções evolutivas e corretivas.

Planejando as manutenções a serem realizadas

Segundo Sommerville [10], manutenções evolutivas visam a incorporar novas funcionalidades ao software, com o intuito de atender às necessidades emergentes do cliente/usuário. Já as manutenções corretivas visam a eliminar falhas no produto de software. Outro tipo de manutenção bastante comum é a adaptativa, que visa a efetuar modificações no software para adequá-lo a um novo ambiente operacional, por exemplo, mudança de sistema operacional, entre outros.

Manutenções corretivas

No caso do plug-in Validator, temos dois defeitos que podem ser tornar falhas a qualquer momento. O primeiro está no modo como os problemas de nomenclatura são apresentados ao usuário. Isso é feito por meio de uma caixa de diálogo, conforme pode ser visto na Figura 1.

Exibição dos problemas de nomenclatura de um
diagrama de classes

Figura 1. Exibição dos problemas de nomenclatura de um diagrama de classes.

Esse tipo de visualização é inadequado, principalmente para projeto com muitas classes. Quando há muitas classes com problemas de nomenclatura, a caixa de diálogo pode não comportar o nome de todas elas, omitindo alguns nomes de classes com problemas do usuário.

Para resolver esse problema, trabalharemos com o conceito de views, que são painéis extras adicionados à interface do Astah*. Tais painéis oferecem recursos mais poderosos para manipulação e visualização de dados, uma vez que permitem a utilização dos componentes de interface gráfica comuns do Java, como JLabel, JButton, entre outros.

O segundo problema está no código fonte da versão original do plug-in Validator (Listagem 1).

Listagem 1. Trecho de código da versão original do plug-in Validator.


  01. public Object run(IWindow window) throws UnExpectedException {
  02.     try {
  03.       ...
  04.       if (error != null)
  05.         JOptionPane.showMessageDialog(window.getParent(), error,
  06.           "Error", JOptionPane.ERROR_MESSAGE);
  07.       else
  08.         JOptionPane.showMessageDialog(window.getParent(),
  09.           "There are not errors!", "Success", JOptionPane.INFORMATION_MESSAGE);
  10.     } 
  11.     ...
  12. }
  13. 
  14. private String validate(IModel iCurrentProject) {
  15.     ...
  16.     for (IClass cl : classList) {
  17.       String name = cl.getName();
  18.       String upperCase = name.toUpperCase();
  19.       if (name.charAt(0) != upperCase.charAt(0)) {
  20.         error.append("[ERROR] Class: " + name + "\n"); hasError = true;
  21.       }
  22.     }
  23.     ...
  24. }

Observando-se o trecho de código da Listagem 1, nota-se que as linhas 6, 9 e 20 utilizam strings que representam mensagens a serem exibidas ao usuário na interface do Astah*. O problema é que esse tipo de implementação dificulta a internacionalização do plug-in, isto é, a tradução do texto da interface do mesmo para outros idiomas. O Astah Plug-in SDK oferece recursos para internacionalização de plug-ins [1], contudo esse recurso é utilizado apenas no arquivo plugin.xml para internacionalização dos itens de menu do plug-in.

Da forma como o código encontra-se na Listagem 1, caso o desenvolvedor traduza o arquivo de internacionalização do plug-in Validator para o português, as mensagens que aparecem nas linhas 6, 9 e 20 continuarão aparecendo em inglês. A única forma de mudar isso seria alterar o código fonte do plug-in, reconstrui-lo e redistribuir aos usuários, o que não é nada trivial. Para sanar este problema, faremos a leitura do arquivo de propriedades do plug-in, no qual estão localizadas as strings utilizadas na interface do Astah*, utilizando um recurso da plataforma Java conhecido como ResourceBundle.

Manutenções evolutivas

Uma manutenção evolutiva desejável para o plug-in Validator é permitir que ele faça novos tipos de verificação, antes não contempladas pelo mesmo. Neste artigo, iremos realizar duas verificações: i) se o identificador de uma classe não é um acrônimo; e ii) se há espaços em branco no identificador de uma classe.

A primeira convenção de nomenclatura é citada no guia de conveções de codificação da Oracle [8] e a justificativa é que nomes de classes devem ser simples, mas descritivos, isto é, devem passar a ideia ao desenvolvedor do que trata aquela classe. Sendo assim, este guia sugere que o desenvolvedor evite a utilização de siglas e acrônimos para nomear classes. Para verificar essa regras, observaremos se todas os caracteres do identificador da classe estão em maiúscula, o que pode indicar que um acrônimo está sendo utilizado.

A segunda convenção também é citada no guia da Oracle [8], porém está mais ligada às características de nomenclatura suportadas pela linguagem Java. Como você deve saber, em Java, identificadores de classes/interfaces, métodos e atributos não podem conter espaços em branco. Para verificar essa regra, basta procurar por espaços em branco no identificador das classes. Caso haja, um erro deve ser reportado ao usuário.

Realizando as modificações - Internacionalização

Para resolvermos o problema de internacionalização do plug-in, utilizaremos o recurso da própria linguagem Java conhecido como ResourceBundle. Foge ao escopo deste aritgo fazer uma explanação mais profunda sobre esse recurso; mais detalhes sobre ele podem ser encontrados em [2].

O importante é saber que a classe java.util.ResourceBundle é utilizada para armazenar textos (strings) que são sensíveis ao locale, isto é, textos que são internacionalizáveis, podendo variar de acordo com o idioma configurado na máquina do usuário. Este é o recurso necessário para internacionalizar os textos utilizados nas classes do plug-in Validator.

A forma de uso deste recurso é bastante simples. Inicialmente, precisamos obter ou criar um objeto do tipo Locale, que representa o idioma utilizado no sistema do usuário. Com este objeto em mãos, é possível obter uma instância de ResourceBundle, que representa um arquivo de propriedades do sistema com as strings internacionalizadas. A partir deste momento, o usuário pode obter uma string internacionalizada invocando o método getString da classe ResourceBundle. Este método recebe como parâmetro a chave da string que deve ser recuperada. Por exemplo, supondo que no arquivo de propriedades haja a entrada rotuloBotaoEnviar=Enviar, ao invocar o método getString(“rotuloBotaoEnviar”), o usuário irá receber string Enviar.

Para implementar esta funcionalidade, foram alterados os códigos de duas classes do plug-in, a saber, Activator e TemplateAction. O trecho de código alterado da classe Activator encontra-se na Listagem 2.

Listagem 2. Trecho de código modificado da classe Activator.


  01. public class Activator implements BundleActivator {
  02.     
  03.  private static ResourceBundle resourceBundle;
  04. 
  05.   public void start(BundleContext context) {
  06.     initializeResourceBundle();
  07.   }
  08. 
  09.   private void initializeResourceBundle() {
  10.     Locale locale = Locale.getDefault();
  11.     resourceBundle = ResourceBundle.getBundle("plugin", locale);
  12.   }
  13. 
  14.   public static String getLabel(String key) {
  15.     return resourceBundle.getString(key);
  16.   } 
  17. }

A classe Activator possui dois métodos pricipais, denominados start e stop. O primeiro método é invocado automaticamente quando o plug-in é ativado no Astah* e o segundo, quando o mesmo é desativado.

Como os recursos de internacionalização podem ser utilizado em diversos pontos do código do plug-in, optei por colocá-lo na classe Activator. O método initializeResourceBundle é responsável por identificar o locale padrão do sistema do usuário (linha 10) e obter o arquivo plugin.properties apropriado (este é o arquivo com as string internacionalizáveis de um plug-in Astah*). Por exemplo, se o locale for pt_BR, então o método getBundle da classe ResourceBundle (linha 11) tentará obter o arquivo de propriedades plugin_pt_BR.properties. Caso não seja encontrado um arquivo específico para o locale, o arquivo default é recuperado, isto é, plugin.properties.

Outro ponto a ser destacado na Listagem 2 é o método getLabel (linhas 14 à 16). Ele recupera uma string do arquivo de propriedades do plug-in Validator a partir de uma chave passada por parâmetro (linha 15). Para isso, ele utiliza o método getString da classe ResourceBundle. O objeto do tipo ResourceBundle é recuperado a partir do atributo resourceBundle, da própria classe Activator (linha 3). É importante ressaltar ainda que getLabel é um método público estático (método de classe). Isto significa que o acesso a ele é realizado de forma direta, sem a necessidade de se ter um objeto da classe Activator instanciado para isso. Para invocar esse método, basta utilizar Activator.getLabel(“chave”). Isso facilita o acesso ao mecanismo de internacionalização de qualquer ponto do projeto do plug-in.

O segundo trecho de código a ser apresentado é o da classe TemplateAction, que encontra-se na Listagem 3. As linhas 6 e 9 deste código fazem uso do método getLabel da classe Activator para obter strings a serem apresentadas na interface do Astah* de forma internacionalizada.

Listagem 3. Trecho de código modificado da classe TampleAction.


  01. public class TemplateAction implements IPluginActionDelegate {
  02.   public Object run(IWindow window) throws UnExpectedException {
  03.       ...
  04.   if (error != null) {                               
  05.         JOptionPane.showMessageDialog(window.getParent(), error,
  06.         Activator.getLabel("validationErrorsTitle"), JOptionPane.ERROR_MESSAGE);
  07.       } else {                               
 08.         JOptionPane.showMessageDialog(window.getParent(),
  09.           Activator.getLabel("successMessage"), Activator.getLabel("successTitle"),
  10.           JOptionPane.INFORMATION_MESSAGE);
  11.       }     
  12.       ...
  13.   }
  14.   ...       
  15. }

Para testar as alterações que fizemos, criamos um arquivo plugin_pt_BR.properties (Listagem 4) e o adicionamos ao projeto do plug-in (na pasta main/resources). Posteriormente, traduzimos as strings existentes neste arquivo para português do Brasil e inicializamos nosso plug-in com as alterações realizadas. Conforme explicado em [1], você pode inicializar o Astah* com seu plug-in carregado da seguinte forma:

..., basta mover-se ao diretório onde se encontra o projeto com o plug-in e digitar o comando astah-launch no console.

Listagem 4. Arquivo plugin_pt_BR.properties.


  pluginName = Validador de Diagramas de Classes
  providerName = by Paulo Afonso
   
  lb_group_validator=&Validador
  lb_item_classValidator=&Classes
  tooltip_item_classValidator=Valida a nomenclatura das classes existentes em seu projeto.
   
  validationErrorsTitle=Erros de Validação
  successTitle=Sucesso
  successMessage=Não há erros neste projeto!
  projectNoOpened=Não há projetos abertos. Por favor, abra um projeto existente ou crie um novo.
  projectNoOpenedTitle=Atenção
  unexpectedError=Ocorreu um erro inesperado!
  unexpectedErrorTitle=Atenção
   
  validationErrorMessage=[ERRO] Classe:  

Com isso, as modificações são visíveis na interface do Astah* (Figura 2), isto é, as strings utilizadas na interface do plug-in estão todas em português, uma vez que meu locale está configurado como português do Brasil. É importante notar que as strings dos outros itens de menus do Astah* continuam em inglês. Isso ocorre, pois eu não possuo o pacote de internacionalização da interface do Astah* para português. Mais detalhes de como obter e instalar este pacote podem ser encontrados em [9].

Interface do plug-in
Validator internacionaliada

Interface do plug-in
Validator internacionaliada

Interface do plug-in
Validator internacionaliada

Figura 2. Interface do plug-in Validator internacionaliada.

Adicionando novos tipos de verificação de nomenclatura

Adicionar novos tipos de verificação é relativamente simples. Neste caso, vamos alterar o método validate da classe TemplateAction, com o intuito de permitir que ele realize as verificações desejadas. Conforme já discutido anteriormente, os novos tipos de verificação de nomenclatura são: i) verificar se o identificador de uma classe não é um acrônimo; e ii) verificar se há espaços em branco no identificador de uma classe.

Antes de apresentar o código da classe TemplateAction, cabe ressaltar que o arquivo plugin.properties precisou ser modificado. Isso ocorreu, pois agora mais de um tipo de problema pode ser detecado pelo plug-in Validator e mensagens diferentes para cada tipo de problema devem ser apresentadas. Sendo assim, foram criadas strings específicas para cada tipo de problema de nomenclatura, conforme pode ser visto ena Listagem 5.

Listagem 5. Arquivo plugin_pt_BR.properties modificado.


  ...
  validationErrorMessageFirstLetter=[ERRO] A primeira letra do nome de uma classe deve ser maiúscula:  
  validationErrorMessageAcronym=[ERRO] O nome de uma classe não deve ser um acrônimo/sigla: 
  validationErrorMessageBlankSpace=[ERRO] O nome de uma classe não pode conter espaços em branco: 

Após alterar o código do método validate, o resultado é equivalente ao apresentado na Listagem 6. As linhas 4 à 8 já existiam e serviam para verificar se o nome da classe inicia com letra maiúscula. A única mudança ocorreu na linha 7, na chamada do método getLabel, para a qual foi passado como parâmetro uma outra chave.

Listagem 6. Trecho de código da classe TemplateAction modificado.


  01. private String validate(IModel iCurrentProject) {
  02.   ...
  03.   for (IClass cl : classList) {
  04.     String name = cl.getName();
  05.     String upperCase = name.toUpperCase();
  06.     if (name.charAt(0) != upperCase.charAt(0)) {
  07.       error.append(Activator.getLabel("validationErrorMessageFirstLetter") + name + "\n");
  08.       hasError = true;
  09.     } else if (upperCase.equals(name)) {
  10.       error.append(Activator.getLabel("validationErrorMessageAcronym") + name + "\n");
  11.       hasError = true;                             
  12.     } else if (name.contains(" ")) {
  13.       error.append(Activator.getLabel("validationErrorMessageBlankSpace") + name + "\n");
  14.       hasError = true;
  15.     }
  16.   }
  17.   ...
  18. }

As linhas 9 à 14 são responsáveis por verificar se o nome da classe é um acrônimo (linhas 9 à 11) e se há espaços em branco no nome da classe (linha 12 à 14).

Para testar a nova versão do plug-in Validator, foi criado o diagrama de classes fictício da Figura 3. Como pode ser observado, apenas a classe Class2 está correta; as classes Class 1, class3 e CLASS4 apresentam problemas, conforme segue:

  • Class 1: apenas a primeira letra do nome da classe é maisúcula, porém ele possui um espaço em branco entre “Class” e “1”;
  • class3: o nome da classe não possui espaços em branco, porém não começa com letra maiúscula; e
  • CLASS4: o nome da classe não possui espaços em branco, porém todas as letras do nome da classe são maiúscula, o que pode indicar que se trata de uma sigla ou acrônimo.

Diagrama de classes fictício

Figura 3. Diagrama de classes fictício.

Ao executar o plug-in Validator sobre o diagrama de classes da Figura 3, porém, ocorreu uma surpresa! Conforme pode ser visto na Figura 4, além dos erros já comentados, apareceu um erro a mais, referindo-se a uma classe denominada UUID, acusando que o nome desta classe não pode ser um acrônimo. Porém, não criamos uma classe denominada UUID, o que ocorreu então?

O que aconteceu é que quando criamos um projeto no Astah*, ele carrega automaticamente um conjunto de classes e interfaces comuns da plataforma Java, tais como String, Math, List, entre outras. Uma dessas classes é justamente a UUID que, segundo a documentação da plataforma Java [3], representa um identificador único imutável de 128 bits. Este tipo de classe é muito utilizada para serialização de objetos que precisam ser transportados via rede. Em suma, o plug-in Validator descobriu uma classe da API Java que vai de encontro a (contra) uma convenção da própria Oracle, interessante não!?

Resultado da execução da nova versão do plug-in Validator

Figura 4. Resultado da execução da nova versão do plug-in Validator.

É importante notar que a maneira como implementamos esta nova funcionalidade não é a mais adequada em termos de flexibilidade. Veja que precisamos adicionar novos comandos if-else no código da classe TamplateAction e, se seguirmos sempre esta estratégia, todas as vezes que um novo tipo de verificação for incorporado, mais comandos if-else precisarão ser adicionados ao código, o que diminiu bastante sua flexibilidade. Uma maneira mais interessante de realizar verificações de forma dinâmica e flexível é por meio da implementação do padrão de projeto Chain of Responsability [4]. Tente fazer isso como exercío, utilize os comentários no final deste artigo para esclarecer dúvidas e trocar experiências.

Trabalhando com views

No artigo “Desenvolvendo Plug-ins para o software Astah*” [1], foi apresentado um recurso de extensão do Astah*, a saber, o actionSet, que permitia a confecção de novos itens de menu para a ferramenta.

Neste artigo, será visto outro mecanismo de extensão conhecido como views. Eles são bem mais poderosos, uma vez que permitem ao desenvolvedor criar painéis extras para a ferramenta Astah* e incluir nesses painéis elementos de interface gráfica bem conhecidos por quem trabalha com Java, tais como JLabel, JButton, JTable, entre outros.

Nossa ideia é criar um painel que permita uma apresentação mais adequada dos problemas de nomenclatura identificados pelo plug-in Validator. A Figura 5 apresenta um protótipo da interface do que pretende-se implementar neste painel.

Protótipo do painel para visualização de problemas
de nomenclatura

Figura 5. Protótipo do painel para visualização de problemas de nomenclatura.

Será criada uma tabela de dados, na qual: i) a primeira coluna apresenta o nome da classe com problemas de nomenclarura; e ii) a segunda e última coluna apresenta o tipo de erro identificado pelo plug-in.

Para criar uma extensão desse tipo, precisamos criar um ponto de extensão por meio da tag extension, no arquivo plugin.xml. Esse ponto de extensão deve conter o valor com.change_vision.astah.ui.view atribuído ao atributo point da tag extension. Esse id é definido pelo próprio Astah Plug-in SDK; mais detalhes sobre os ids utilizados pelo SDK podem ser encontrados em [5].

A código que deve ser incorporado ao arquivo plugin.xml encontra-se na Listagem 7. O atributo id refere-se a um identificador único para a sua view. O atributo type identifica o tipo de view a ser criado. Atualmente, o Astah Plug-in SDK permite apenas a criação de views extras, que são apresentadas quando o usuário acessa o menu View à Show/Hide Extra View do Astah*. Para criar uma view extra, utilize o valor extraTab para o atributo type. O atributo class especifica a classe responsável pela criação da view (dos componentes visuais) e do tratamento dos eventos que poderão atualizar a interface desta view.

Listagem 7. Trecho de código a ser incorporado no arquivo plugin.xml


  01. <extension point="com.change_vision.astah.ui.view">
  02.         <view
  03.             id="validatorView"
  04.             type="extraTab"
  05.             class="com.validator.ValidatorView" />
  06. </extension>
  

A Listagem 8 apresenta os trechos de código mais importantes da classe ValidatorView, melhor detalhados a seguir. Os dois primeiros fatos que precisam ser observados é que esta classe deve herda da classe JPanel e implementa as interfaces IPluginExtraTabView, ProjectEventListener. Ela extende a classe JPanel, por se tratar de um painel que será apresentado pelo Astah* em uma aba extra de sua interface. O fato de implementar a interface IPluginExtraTabView obrigada o desenvolvedor a prover implementação para alguns métodos necessários para o Astah* poder tratar a view corretamente. Alguns desses métodos são:

  • getTitle: permite ao Astah* conhecer o título que deve ser atribuído à aba da view.
  • getComponent: permite ao Astah* capturar o painel que deve ser apresentado na tela da ferramenta.

O método getTitle do nosso exemplo busca o título da view no arquivo de propriedades plugin.properties, de forma internacionalizada (linha 31). Já o método getComponent retorna a própria instância da classe ValidatorView, criada automaticamente pelo Astah* no momento da execução do plug-in. O painel a ser exibido é construído por meio do método initComponents.

Quanto à interface ProjectEventListener, ela serve para informar ao Astah* que sua view estará observando as mudanças ocorridas no projeto UML, como a abertura e fechamento do projeto, as modificações feitas em alguns elementos, entre outros. Assim como a interface IPluginExtraTabView, ProjectEventListener também obriga o desenvolvedor a implementar alguns métodos, tais como:

  • projectChanged: notifica a visão de que o projeto UML do usuário foi modificação;
  • deactivated: notifica a visão de que o projeto atual foi fechado pelo usuário; e
  • activated: notifica a visão de que um projeto foi aberto pelo usuário.

Listagem 8. Trecho de código da classe ValidatorView.


  01. public class ValidatorView extends JPanel implements IPluginExtraTabView,
  02.   ProjectEventListener {
  03. 
  04.   public ValidatorView() {
  05.     initComponents();
  06.   }
  07. 
  08.   private void initComponents() {
  09.     setLayout(new BorderLayout());
  10.     add(createLabelPane(), BorderLayout.CENTER);
  11.     addProjectEventListener();
  12.   }
  13. 
  14.   private Container createLabelPane() {
  15.     JLabel label = new JLabel("hello world");
  16.     JScrollPane pane = new JScrollPane(label);
  17.     return pane;
  18.   }
  19. 
  20.   private void addProjectEventListener() {
  21.     try {
  22.       AstahAPI api = AstahAPI.getAstahAPI();
  23.       ProjectAccessor projectAccessor = api.getProjectAccessor();
  24.       projectAccessor.addProjectEventListener(this);
  25.     } catch (ClassNotFoundException e) {
  26.       System.err.println(Activator.getLabel("unexpectedError"));
  27.     }
  28.   }
  29.   @Override
  30.   public String getTitle() {
  31.     return Activator.getLabel("viewTitle");
  32.   }
  33.   @Override
  34.   public Component getComponent() {
  35.     return this;
  36.   }
  37.   @Override
  38.   public void projectChanged(ProjectEvent arg0) {
  39.     // TODO Auto-generated method stub
  40.   }
  41.  
  42.   @Override
  43.   public void activated() {  }
  44. 
  45.   @Override
  46.   public void deactivated() {  }  
  47.   ...
  48. }

Neste caso, estamos preocupados com a implementação dos métodos activated e projectChanged, uma vez que precisaremos verificar o projeto todas as vezes em que o mesmo for aberto ou que alguma modificação for realizada sobre ele. Contudo, para que a visão seja notificada é necessário cadastrá-la como um observador do projeto (esta estratégia de implementação utilizada pelo Astah* trata-se do conhecido padrão de projeto Observer [6]). Isso é feito no método addProjectEventListener, linha 24, por meio método addProjectEventListener da classe ProjectAccessor, que representa o projeto atual aberto pelo usuário. Da forma como está o código da Listagem 8, a view criada apenas apresentará um texto “hello world”, conforme pode ser visto na Figura 6. Para criar nossa tabela de dados, conforme o protótipo da Figura 5, precisamos alterar o código da classe ValidatorView, conforme exibido na Listagem 9.

Apresentação da view até o momento

Figura 6. Apresentação da view até o momento.

Listagem 9. Trecho de código da classe ValidatorView modificado.


  01. public class ValidatorView extends JPanel implements IPluginExtraTabView, ProjectEventListener {
  02.   private DefaultTableModel model = new DefaultTableModel(); 
  03.   private  JTable table = new JTable(model);
  04.   private IModel currentProject;
  05. 
  06.   private void initComponents() {
  07.     setLayout(new BorderLayout());
  08.     add(createDataTable(), BorderLayout.CENTER);
  09.     addProjectEventListener();
  10.   }
  11.   private Container createDataTable() {
  12.     model.addColumn(Activator.getLabel("colClass")); 
  13.     model.addColumn(Activator.getLabel("colError")); 
  14.     JScrollPane pane = new JScrollPane(table);
  15.     return pane;
  16.   }
  17.   private void updateTable() {
  18.     model.getDataVector().clear();
  19.     List<IClass> classList = new ArrayList<IClass>();
  20.     getAllClasses(currentProject, classList);
  21.     for (IClass cl : classList) {
  22.       String name = cl.getName();
  23.       String upperCase = name.toUpperCase();
  24.       if (name.charAt(0) != upperCase.charAt(0)) {
  25.         model.addRow(new Object[]{name, 
  26.           Activator.getLabel("validationErrorMessageFirstLetter")});
  27.       } else if (upperCase.equals(name)) {
  28.         model.addRow(new Object[]{name, 
  29.           Activator.getLabel("validationErrorMessageAcronym")});
  30.       } else if (name.contains(" ")) {
  31.         model.addRow(new Object[]{name, 
  32.           Activator.getLabel("validationErrorMessageBlankSpace")});
  33.       }
  34.     }
  35.   }  
  36.   private void getAllClasses(INamedElement element, List<IClass> classList) {
  37.     if (element instanceof IPackage) {
  38.       for (INamedElement ownedNamedElement : ((IPackage) element).getOwnedElements()) {
  39.        getAllClasses(ownedNamedElement, classList);
  40.       }
  41.     } else if (element instanceof IClass) {
  42.       classList.add((IClass) element);
  43.     }
  44.   }
  45.   private void addProjectEventListener() {
  46.     try {      
  47.       ...
  48.      currentProject = projectAccessor.getProject();
  49.       ...
  50.     } catch (ProjectNotFoundException e) {
  51.       System.out.println(Activator.getLabel("projectNoOpenedTitle"));
  52.     } catch (ClassNotFoundException e) {
  53.       System.out.println(Activator.getLabel("unexpectedError"));
  54.     }
  55.   }
  56.   public void activated() {
  57.     updateTable();
  58.   }
  59.   public void projectChanged(ProjectEvent arg0) {
  60.     updateTable();
  61.   }
  62. }

O método getAllClasses é o mesmo apresentado em [1] e é responsável por vasculhar um projeto a procura de classes, colocando-as em uma lista denominada classList. O método createDataTable constrói a estrutura de uma tabela de dados em Java e a coloca sobre um componente do tipo ScrollPane, responsável por atribuir barras de rolagem à tabela sempre que for necessário. Conforme planejado em nosso protótipo, esta tabela deve conter duas colunas, uma para o nome da classe e outro para o problema de nomenclatura encontrado na classe em questão.

O método updateTable é responsável por limpar os dados da tabela e preenchê-la novamente com as informações corretas, isto é, o nome das classes e seus respectivos problemas de nomenclatura. Este método é invocado em dois momentos distintos: i) quando o projeto é aberto pelo usuário (linha 57); e ii) quando alguma modificação é feita no projeto, como a criação de um novo elemento, a mudança do nome de uma classe, entre outros (linha 60). Assim, o usuário não precisará mais clicar em qualquer menu para realizar a verificação de seu diagrama de classes UML, pois isso é feito automaticamente. Mais detalhes sobre a construção e atualização de tabelas de dados em Java podem ser encontrados em [6].

Outra mudança que fizemos em nosso projeto foi apagar o trecho de código responsável pela criação do menu do plug-in Validator, uma vez que precisamos mais dele, além de excluir a classe TamplateAction, que era responsável por tratar o evento de clique sobre o item de menu do plug-in. Novas atualizações também foram realizadas no arquivo com as strings utilizadas na interface do plug-in, conforme pode ser visto na Listagem 10.

Listagem 10. Última versão do arquivo plugin.properties.


  ...
  validationErrorMessageFirstLetter=A primeira letra do nome de uma classe deve ser maiúscula.  
  validationErrorMessageAcronym=O nome de uma classe não deve ser um acrônimo/sigla. 
  validationErrorMessageBlankSpace=O nome de uma classe não pode conter espaços em branco.  
   
  viewTitle=Erros de Nomenclatura
   
  colClass=Classe
  colError=Erro

Pronto! Agora, basta executar a versão final do plug-in. O resultado é similar ao apresentado na Figura 7.

Interface gráfica da versão final plug-in Validator

Figura 7. Interface gráfica da versão final plug-in Validator.

Neste artigo foram apresentadas estratégias para minimizar as limitações existentes no plug-in desenvolvido no artigo [1]. Neste sentido, viu-se: i) como utilizar o mecanismo de extensão view, do Astah Plug-in SDK; ii) como identificar novos tipos de problemas de nomenclatura em diagramas de classes UML; e iii) como internacionalizar por completo um plug-in Astah*.

Ainda assim, esta nova versão do plug-in Validator apresenta algumas limitações, tais como: i) só realiza verificações sobre os nomes das classes, não levando em consideração, métodos, atributos, pacotes, associações, entre outros elementos importantes de um diagrama de classes; ii) a tabela de dados só apresenta o nome das classes. Neste sentido, se houver duas classes com o mesmo nome, porém em pacotes diferentes, o que é possível de ocorrer, o usuário ficará confuso ao tentar localizar a classe com problema; iii) todos os tipos de verificação são sempre inspecionados. O desenvolvedor pode desejar desabilitar algum tipo de verificação por algum tempo para se concentrar em um problema específico de cada vez; e iv) a tabela de dados não permite que usuário filtre os resultados por nome de classes ou por tipo de erro.

Acredita-se que com as informações apresentadas neste artigo e no artigo anterior [1], juntamente com seu conhecimento sobre a linguagem Java, você conseguirá aprimorar este plug-in a ponto de mitigar as limitações comentadas anteriormente.

Referências

[1] Desenvolvendo Plug-ins para o software Astah*. Disponível em: //www.devmedia.com.br/astah-desenvolvendo-plug-ins-para-o-software/31127

[2] Tutorial sobre utilização do ResourceBundle. Disponível em: http://tutorials.jenkov.com/java-internationalization/resourcebundle.html

[3] Documentação Java sobre a classe UUID. Disponível em: http://docs.oracle.com/javase/7/docs/api/java/util/UUID.html

[4] Padrão de projeto Chain of Responsability. Disponível em: http://pt.wikipedia.org/wiki/Chain_of_Responsibility

[5] Tutorial para desenvolvimento de plug-ins no Astah*. Disponível em: http://astah.net/tutorials/plug-ins/plugin_tutorial_en/html/index.html.

[6] Padrão de projeto Observer. Disponível em: http://en.wikipedia.org/wiki/Observer_pattern

[7] Documentação JTable. Disponível em: http://docs.oracle.com/javase/7/docs/api/javax/swing/JTable.html

[8] Oracle Code Convention. Disponível em: http://www.oracle.com/technetwork/java/codeconvtoc-136057.html

[9] Recurso de internacionalização do Astah*. Disponível em: http://astah.net/features/gui-localization

[10] Sommerville, Ian. Engenharia de Software. 9ª. edição. Pearson Prentice Hall, 529 p., 2011.