88
UNIVERSIDADE FEDERAL DE SANTA CATARINA XSwingMenu: Uma Linguagem Baseada em XML para Construção de Menus Java Swing Francisco de Assis Besen Hillesheim Florianópolis - SC 2004 / 2

UNIVERSIDADE FEDERAL DE SANTA CATARINA · 6.3 Iniciando o XSwingMenu ... No desenvolvimento de software em geral, ... objetos Swing (interface gráfica em Java)

  • Upload
    lyhanh

  • View
    212

  • Download
    0

Embed Size (px)

Citation preview

UNIVERSIDADE FEDERAL DE SANTA CATARINA

XSwingMenu: Uma Linguagem Baseada em XML para Construção de Menus Java Swing

Francisco de Assis Besen Hillesheim

Florianópolis - SC 2004 / 2

UNIVERSIDADE FEDERAL DE SANTA CATARINA DEPARTAMENTO DE INFORMÁTICA E ESTATÍSTICA

CURSO DE CIÊNCIAS DA COMPUTAÇÃO

XSwingMenu: Uma Linguagem Baseada em XML para Construção de Menus Java Swing

Francisco de Assis Besen Hillesheim

Trabalho de conclusão de curso apresentado como parte dos requisitos para obtenção do grau de Bacharel em Ciências da Computação.

Florianópolis - SC 2004 / 2

Francisco de Assis Besen Hillesheim

XSwingMenu: Uma Linguagem Baseada em XML para Construção de Menus Java Swing

Trabalho de conclusão de curso apresentado como parte dos requisitos para obtenção do grau de Bacharel em Ciências da Computação.

Orientador: _______________________________________ Prof. Dr. Leandro José Komosinski

Banca examinadora _______________________________________ Prof. Dr.José Leomar Todesco _______________________________________ Prof Dr. Roberto Carlos dos Santos Pacheco

Aos meus pais, Valdenir e Nilva, a homenagem da mais profunda gratidão pelas lições de

amor, honestidade, sabedoria e fé. Aos meus irmãos Ricardo e Ana Sophia, pelo

apoio, incentivo e companherismo durante toda a minha caminhada acadêmica.

AGRADECIMENTOS

Agradeço ao Professor e Orientador Leandro José Komosinski, pela contribuição para realização

deste trabalho. Aos Professores José Leomar Todesco e Roberto

Carlos dos Santos Pacheco pela participação como membros da banca.

À minha familía, em especial a vó Sophia, pelo convívio, compreensão e incentivo.

À todos os meus colegas da turma CCO011 pelo apoio e amizade durante o decorrer deste curso.

Por fim, agradeço a Deus por tudo.

SUMÁRIO

Índice de figuras .................................................................................................................... 8 Índice de tabelas .................................................................................................................... 9 Resumo................................................................................................................................ 10 Abstract ............................................................................................................................... 11 1 INTRODUÇÃO................................................................................................................ 12

1.1 Contexto..................................................................................................................... 12 1.2 Objetivos.................................................................................................................... 12

1.2.1 Objetivo Geral ..................................................................................................... 12 1.2.2 Objetivos Específicos .......................................................................................... 12

1.3 Metodologia ............................................................................................................... 13 2 ESTADO DA ARTE......................................................................................................... 14

2.1 Soluções existentes..................................................................................................... 14 2.2 XUL........................................................................................................................... 14 2.3 XAML ....................................................................................................................... 15 2.4 Um Exemplo utilizando XML e Java Swing............................................................... 17

2.4.1 SwiXml ............................................................................................................... 17 3 SOLUÇÃO PROPOSTA................................................................................................... 19

3.1 Primeira parte............................................................................................................. 19 3.2 Segunda parte............................................................................................................. 20 3.3 Tecnologias envolvidas .............................................................................................. 20

3.3.1 Java, Java Swing e Menus ................................................................................... 20 3.3.2 XML ................................................................................................................... 23 3.3.3 W3C XML Schema ............................................................................................. 24 3.3.4 XSLT .................................................................................................................. 24

4 XSWINGMENU............................................................................................................... 27 4.1 Descrição ................................................................................................................... 27 4.2 Especificação da linguagem ....................................................................................... 27

4.2.1 Descrição dos elementos...................................................................................... 27 4.2.2 Elementos............................................................................................................ 28 4.2.3 Descrição dos atributos........................................................................................ 29 4.2.4 Atributos ............................................................................................................. 30

4.3 Especificação XML Schema da linguagem................................................................. 30 5 DESENVOLVIMENTO ................................................................................................... 33

5.1 Primeiro ciclo de desenvolvimento............................................................................. 33 5.1.1 Especificação da linguagem................................................................................. 33 5.1.2 Validador da linguagem....................................................................................... 34

5.2 Segundo ciclo de desenvolvimento............................................................................. 34 5.2.1 Scripts XSLT....................................................................................................... 35 5.2.2 Tratamento de eventos......................................................................................... 36 5.2.3 Criação da GUI.................................................................................................... 37 5.2.4 Gerador de documentos XML.............................................................................. 37 5.2.5 Automatizador de testes....................................................................................... 38

5.3 Estrutura de classes simplificada ................................................................................ 38 5.4 Comparação entre XSwingMenu-0.2 e SwiXml-1.2 ................................................... 39

6 UM EXEMPLO UTILIZANDO XSWINGMENU............................................................ 41 6.1 Requerimentos ........................................................................................................... 41

6.2 Criação da especificação do Menu.............................................................................. 41 6.3 Iniciando o XSwingMenu........................................................................................... 42 6.4 Validando o arquivo XML.......................................................................................... 42 6.5 Transformando o arquivo XML em classe Java .......................................................... 44 6.6 Resultado ................................................................................................................... 45

7 CONCLUSÃO.................................................................................................................. 49 7.1 Trabalhos futuros ....................................................................................................... 49

8 REFERÊNCIAS BIBLIOGRÁFICAS............................................................................... 51 9 ANEXOS.......................................................................................................................... 53

9.1 Código fonte .............................................................................................................. 53 9.2 Artigo......................................................................................................................... 85

Índice de figuras

Figura 1 Exemplo de documento em XAML........................................................................ 16 Figura 2 Processo de renderização do XAML ...................................................................... 16 Figura 3 Helloworld em SwiXml ......................................................................................... 18 Figura 4 Renderização Helloworld em SwiXml.................................................................... 18 Figura 5 Execução programa Java........................................................................................ 20 Figura 6 Exemplo de barra de menu em Java Swing............................................................. 22 Figura 7 Classes relacionadas a menu em Java Swing .......................................................... 22 Figura 8 Processo de transformação de documentos XML ................................................... 26 Figura 9 Especificação XML Schema da linguagem XSwingMenu ...................................... 32 Figura 10 Figura simplificada de script XSLT...................................................................... 36 Figura 11 Estrutura de classes simplificada .......................................................................... 39 Figura 12 Exemplo de documento de XML de entrada......................................................... 42 Figura 13 Exemplo de erro de validação de um documento XML ........................................ 43 Figura 14 Exemplo de transformação bem sucedida ............................................................. 45 Figura 15 Classe gerada a partir do arquivo Exemplo1.xml .................................................. 47 Figura 16 Exemplo de classe de teste gerada automaticamente............................................. 48 Figura 17 Renderização da classe gerada.............................................................................. 48

Índice de tabelas

Tabela 1 Descrição dos elementos da linguagem.................................................................. 28 Tabela 2 Elementos da linguagem........................................................................................ 29 Tabela 3 Descrição dos atributos da linguagem .................................................................... 29 Tabela 4 Atributos da linguagem.......................................................................................... 30 Tabela 5 Comparação entre XSwingMenu e SwiXml........................................................... 40

Resumo

A criação e manutenção de interfaces gráficas de usuário representa um ponto crítico

no desenvolvimento de software em geral. Para resolver este problema, várias ferramentas e

arquiteturas foram concebidas no decorrer dos anos.

Este trabalho apresenta a linguagem baseada em XML XSwingMenu cujo propósito é

a criação de objetos gráficos Java Swing referentes a barras de menu. A partir da linguagem

XSwingMenu foi desenvolvida uma ferramenta homônima que provê suporte a geração de

código Java a partir de um documento XML por meio de transformações via XSLT. Além

disso, a ferramenta também possui suporte ao processo inverso, ou seja, extração de um

documento XML a partir de uma barra de menu codificada em Java Swing já existente.

Palavras-chave: Java – XML – interface gráfica

Abstract

The creation and maintenance of graphical user interfaces in general represent a

critical point in the software development. To solve this problem, some tools and

architectures had been conceived in the elapsing years.

This work presents a XML-based language called XSwingMenu which focuson

creating Java Swing graphical objects describing menu bars. Based on XswingMenu, a tool

was devoloped to provide Java code generation from a XML document by means of

transformations of the XML document through XSLT. Moreover, the tool also provides

support to the inverse process, in another words, extration of a document XML from a pre-

existent menu bar coded in Java Swing.

Key-words: Java – XML – graphic interface

12

1 INTRODUÇÃO

1.1 Contexto

No desenvolvimento de software em geral, a construção de interfaces gráficas de

usuário (GUI) consiste em uma tarefa que requer um alto grau de esforço na maioria das

linguagens de programação usuais. Em decorrência desse fato, várias tentativas de simplificar

este processo foram realizadas, com e sem sucesso, ao longo dos anos. Em Java Swing,

biblioteca incorporada à linguagem Java que permite o desenvolvimento de interfaces gráficas

de usuário, este fato também ocorre (SUN MICROSYSTEMS, INC [1]).

Com a ascensão da especificação XML (W3C [2]) nos últimos anos e o surgimento

de diversas ferramentas para sua utilização, principalmente em Java, é razoável que seu uso

para especificação de interfaces gráficas de usuário seja uma alternativa para minimizar o

esforço necessário no seu desenvolvimento.

1.2 Objetivos

1.2.1 Objetivo Geral

Definir uma linguagem baseada em XML para especificação de objetos visuais da

biblioteca Swing de Java, juntamente com uma ferramenta para manipulação de documentos

XML baseados nessa linguagem visando aumentar a produtividade com relação a codificação

destes objetos visuais.

1.2.2 Objetivos Específicos

Permitir a especificação de barras de menu através da linguagem a ser criada. Além

disso, desenvolver uma biblioteca Java que, quando incorporada a uma aplicação, gere

objetos Swing (interface gráfica em Java) relativos ao menu desta aplicação a partir de um

13

documento XML. Assim, para o programador, a implementação do menu de seu programa se

resumiria a especificar os seus itens no formato XML.

1.3 Metodologia

Na fase inicial, uma pesquisa bibliográfica será realizada sobre as soluções já

existentes, juntamente com os conceitos e tecnologias abordados. Em seguida, será definido

uma proposta de solução para alcançar os objetivos traçados através do desenvolvimento de

uma ferramenta. Esta ferramenta, então, será responsável pela interpretação de documentos

XML que deverão estar de acordo com uma especificação referente aos objetos gráficos em

pauta (barra de menu e seus componentes) que também será desenvolvida.

Por fim, uma comparação da ferramenta desenvolvida com as demais pesquisadas

será realizada para demonstrar as suas principais diferenças, além de um exemplo prático de

como a ferramenta pode ser utilizada.

14

2 ESTADO DA ARTE

2.1 Soluções existentes

Durante muitos anos, várias tentativas de se melhorar o desenvolvimento de GUI

foram realizadas. Atualmente, pode-se encontrar diversas tecnologias multi-plataforma que

melhoraram, sim, o desenvolvimento de GUI´s, porém não são muitos eficientes (Ex:

XWindows e Xt, Smalltalk, e diversas bibliotecas de classes como Xaw, GTK, Qt, Java AWT

e Swing). Essas soluções são poderosas, mas ainda precisam do aprendizado de uma

biblioteca (MCFARLANE, 2002).

Em contrapartida, a utilização de XML ao invés de bibliotecas representa uma

solução interessante. Uma prova disso é a linguagem XUL1 (BOJANIC, 2003) que faz parte

do projeto Mozilla (THE MOZILLA ORGANIZATION) e que já é utilizada, como por

exemplo, no browser Mozilla. Outra linguagem é XAML2 (MICROSOFT) que é um dialeto

XML que desenvolvedores utilizarão para construir aplicativos para o Longhorn, a nova

versão do sistema operacional Microsoft Windows.

XUL e XAML representam os maiores projetos nesta área, porém, vários outros

projetos com propostas semelhantes também podem ser encontrados. A seguir, alguns

exemplos dos principais projetos de código aberto nesta área: SwiXml, ThinLet, MyXAML,

Xulux, JellySwing/JellySWT e SwingML (OPEN XUL ALLIANCE).

2.2 XUL

XUL é uma linguagem de interface de usuário baseada em XML do projeto Mozilla

que permite construir aplicativos multi-plataforma que podem rodar conectados ou

desconectados da Internet. A seguir segue suas principais características (BOJANIC, 2003):

1 XUL - XML-based User-Interface Language. 2 XAML - Extensible Application Markup Language.

15

• Linguagem de marcação poderosa com suporte aos elementos clássicos de GUI

(widgets);

• Baseada em padrões existentes (Ex: Javascript e Cascading Style Sheets);

• Multi-plataforma;

• Separação da apresentação da lógica da aplicação;

• Fácil manutenção.

Além disso, existem outras tecnologias que são utilizadas pelo XUL como:

• XBL (Extensible Binding Language): uma linguagem de marcação que define

novos elementos para os widgets do XUL.

• Overlays: representam arquivos XUL utilizados para descrever conteúdos extra

para a UI.

• XPCOM/XPConnect: tecnologias complementares que permitem a integração de

bibliotecas externas à aplicações XUL.

• XPInstall: Mecanismo de instalação multi-plataforma do Mozilla.

XUL representa uma nova idéia de desenvolvimento de aplicações visto que

desenvolvedores habituados com os padrões tecnológicos do W3C3 podem utilizar seus

conhecimentos de programação em browsers diretamente nas aplicações desktop.

2.3 XAML

XAML define uma UI de aplicação com marcações representando controles padrões

do Windows. A seguir segue um exemplo para um formulário de Login:

<Canvas xmlns="http://schemas.microsoft.com/2003/XAML" ID="LoginPage"> <Label ID="lblUserId" FontFamily="verdana" FontSize="8" Canvas.Top="10" Canvas.Left="10"> User ID:</Label> <TextBox ID="txtUserId" FontSize="8" Canvas.Top="8" Canvas.Left="75"></TextBox> <Label ID="lblPassword" FontFamily="verdana" FontSize="8" Canvas.Top="35"

3 World Wide Web Consortium – Consórcio internacional de empresas envolvidas com a Internet e a Web.

16

Canvas.Left="10">Password:</Label> <TextBox ID="txtPassword" FontSize="8" Canvas.Top="33" Canvas.Left="75"></TextBox> <Button ID="cmdOK" Width="50" Canvas.Top="60" Canvas.Left="155">OK</Button> </Canvas>

Figura 1 Exemplo de documento em XAML

Neste exemplo, pode-se observar a idéia de XAML onde cada página é definida por

um arquivo XAML. Cada página possui um painel raiz (Canvas, DockPanel ou FlowPanel)

onde os elementos gráficos são definidos. Para criar uma aplicação, basta desenvolver um

arquivo .proj para agrupar os arquivos XAML e definir as opções de compilação, como

informação sobre a versão e se a aplicação irá rodar em um browser ou em uma janela. O

processo de renderização está demonstrado a seguir:

Figura 2 Processo de renderização do XAML

Com relação à adição de código, ela pode ser feita dentro do próprio documento

XAML ou em arquivos diferentes. As linguagens de programção aceitas são Microsoft Visual

Basic® .NET ou C#. Sobre o tratamento de eventos, ele deve ser escrito através destas

linguagens.

A renderização do XAML não é multi-plataforma porque ele constrói, a partir dos

documentos XML, objetos Avalon (que são nativos da nova versão do Microsoft Windows)

que são responsáveis pela renderização. Tal fato torna essa tecnologia dependente da

17

plataforma Windows. Atualmente, como o novo sistema operacional ainda não foi lançado, a

utilização de XAML é incipiente.

2.4 Um Exemplo utilizando XML e Java Swing

A seguir, será visto um exemplo de como se pode utilizar esses novos conceitos com

a biblioteca Java Swing.

2.4.1 SwiXml

SwiXml (PAULUS) é um pequeno motor de geração de interfaces gráficas de

usuário para aplicações Java e applets. A interface gráfica é definida através de documentos

XML que são analisados e renderizados em tempo de execução em objetos Swing.

Suas principais características são listadas a seguir:

• Focada exclusivamente na biblioteca javax.swing;

• Programadores acostumados com a biblioteca Swing podem utilizar SwiXml sem

maiores preocupações;

• SwiXml é rápido pois não adiciona novas camadas sob os objetos Swing;

• SwiXml é pequeno visto que seus componentes, presentes no arquivo swixml.jar,

ocupam 40 Kbytes.

• Só se preocupa com a interface gráfica. O comportamento dinâmico da interface e

a lógica de negócio devem ser implementados em Java.

Para se utilizar o motor do SwiXml basta acoplar, a um aplicativo Java, sua

biblioteca de classes contida no arquivo swixml.jar. Em seguida, basta invocar a classe

org.swixml.SwingEngine que é responsável pela renderização do documento XML. Eis um

exemplo de documento XML que pode ser usado:

<?xml version="1.0" encoding="UTF-8"?> <frame size="640,480" title="Hello SWIXML World" DefaultCloseOperation="JFrame.EXIT_ON_CLOSE"> <panel constraints="BorderLayout.CENTER"> <label LabelFor="tf" Font="Comic Sans MS-BOLD-12" Foreground="blue" text="Hello World!"/>

18

<textfield id="tf" Columns="20" Text="Swixml"/> <button Text="Click Here" Action="submit"/> </panel> </frame>

Figura 3 Helloworld em SwiXml

A seguir, a sua renderização:

Figura 4 Renderização Helloworld em SwiXml

Pode-se notar, através do exemplo, que usuários já habituados com a biblioteca

Swing não teriam problemas em utilizar este motor visto que a linguagem utilizada no seu

documento XML é parecida com a nomenclatura utilizada na biblioteca Java Swing. Apesar,

de apresentar um número de linhas de código menor e código mais claro (devido a hierarquia

dos elementos).

A questão agora é como os eventos e o comportamento dinâmico dos objetos Swing

seriam tratados. Pois bem, nas marcações utilizadas no documento XML pode-se definir o

atributo id, que deve ser único no documento, que representará o nome do objeto Swing

correspondente à marcação. Se desejado enviar mensagens ao objeto Swing, basta declarar

uma variável com o mesmo nome do atributo id. Caso um evento seja registrado no

documento XML, um objeto da classe javax.swing.Action deve ser declarado, onde o evento

será tratado. Estes atributos devem estar presentes em uma classe qualquer que deve ser

passada como parâmetro para a classe responsável pela renderização do documento.

Portanto, SwiXml é um exemplo prático de como a utilização de XML e Java Swing

pode ser realizada.

19

3 SOLUÇÃO PROPOSTA

A seguir, será descrita uma maneira de se alcançar os objetivos propostos utilizando-se

de padrões de manipulação de documentos XML estabelecidos pelo W3C para elaboração da

ferramenta XSwingMenu. Esta proposta de solução está divida em duas partes distintas:

3.1 Primeira parte

A primeira parte da solução do problema consistiria na geração de código Java a partir

de um documento XML, o que representa um diferencial em relação às outras soluções

existentes. Para que isto possa ser realizado, uma especificação de linguagem baseada em

XML deve ser criada. Para isso será utilizada uma especificação definida em W3C XML

Schema (W3C [3]).

Com a especificação em mãos, uma ferramenta de verificação e validação dos

documentos XML, de acordo com o esquema XML definido, será desenvolvida para

encontrar possíveis erros nos documentos XML e assegurar que o processo de geração de

código seja consistente.

Para a geração de código Java, considerada a tarefa mais complexa, a idéia inicial é

utilizar a linguagem XSLT (W3C [4])para especificar como a transformação dos documentos

XML, já checados e validados, será realizada. Caso a utilização da linguagem XSLT não

abranger toda o processo de geração de código, parte da biblioteca, será responsável por esta

tarefa.

Para o desenvolvimento de todas essas tarefas será criado um programa escrito na

linguagem Java juntamente com as bibliotecas Xerces e Xalan (THE APACHE XML

PROJECT), para a manipulação dos documentos XML. A escolha destas bibliotecas é em

virtude do fato de pertencerem ao respeitável projeto Apache, por serem de código aberto, por

proverem juntas suporte a W3C XML Schema e XSLT, e, finalmente, por serem largamente

utilizadas por várias outras aplicações. Com relação a W3C XML Schema e a XSLT, sua

utilização foi escolhida por serem padrões W3C.

20

3.2 Segunda parte

A segunda parte da solução seria permitir o processo inverso da primeira parte, ou

seja, gerar um documento XML a partir de uma classe Java existente. Para isso, uma idéia é

utilizar reflexão computacional, além das bibliotecas já citadas na primeira parte.

Essa tarefa teria como objetivo automatizar, em partes, a migração de aplicações já

existentes que possuem barra de menu definida para que a solução tenha uma maior

abrangência. Além disso, esta parte pode ser considerada um bom desafio por envolver outras

áreas.

3.3 Tecnologias envolvidas

A seguir, as tecnologias abordadas pela solução proposta serão descritas.

3.3.1 Java, Java Swing e Menus

Java é uma linguagem de programação orientada a objetos criada pela Sun

Microsystems. Java é multiplataforma, ou seja, um programa Java pode rodar em qualquer

plataforma que disponha de uma Máquina Virtual Java como mostra a figura a seguir (SUN

MICROSYSTEMS, INC. [1]):

Figura 5 Execução programa Java

21

O processo de compilação de um programa Java produz bytecodes (instruções de

máquina simplificados específicos da plataforma Java). Após isso, bytecodes Java podem ser

interpretados por uma Máquina Virtual Java qualquer, escrita em código nativo, que traduz os

bytecodes em código executável.

A linguagem Java pode ser utilizada em 3 plataformas distintas, definidas pela Sun:

• Java 2 Plataform, Micro Edition – para ambientes com recursos limitados;

• Java 2 Plataform, Standard Edition – para ambientes desktop;

• Java 2 Plataform, Enterprise Edition – para ambientes distribuídos e internet.

Neste trabalho, o foco é a plataforma J2SE, especialmente a biblioteca para construção

de interfaces gráficas de usuário Java Swing que é parte integrante da JFC4.

Java Swing, que foi anunciada em 1997, é uma biblioteca gráfica multi-plataforma

para Java. Ela substitui a a biblioteca anteriormente utilizada: Abstract Windowindo Toolkit

(AWT) que tinha como base para renderização de widgets5 bibliotecas nativas. A principal

característica de Java Swing é dispor de um mecanismo de troca de look and feel para todos

os componentes gráficos através de pequenas alterações subtanciais.

Como grande parte das bibliotecas gráficas existentes, Java Swing possui

componentes que suportam a idéia de menus. Menus são componentes gráficos que permitem

a seleção de uma opção entre várias possíveis. Menus são geralmente usados para

disponibilizar acesso a opções como salvar ou abrir um arquivo, sair de um programa, entre

outros. Por convenção, os menus possuem um posicionamento diferente dos demais

componentes gráficos pois são agrupados em uma barra de menu ou em um popup menu. A

seguir, um exemplo de barra de menu com todos os componentes possíveis (SUN

MICROSYSTEMS, INC. [2]):

4 Java Foundation Classes – Framework gráfico para construção de interfaces gráfica de usuário baseado em Java. É composto pelas bibliotecas AWT, Swing e Java2D. 5 Widget – Componente gráfico, ou controlador, que o usuário pode interagir. Menus, janelas e botões são exemplos de widgets.

22

Figura 6 Exemplo de barra de menu em Java Swing

Neste trabalho, apenas a construção de barras de menus e seus subcomponentes serão

abordados. Abaixo será descrita a hierarquia de classes de Java Swing que representa os

componentes de um menu:

Figura 7 Classes relacionadas a menu em Java Swing

Basicamente, uma barra de menu é composta por um objeto JMenuBar, que possui

objetos da classe JMenuItem (que, através de herença, podem ser também objetos das classes

JMenu, JCheckboxMenuItem e JRadioButtonMenuItem) e/ou JSeparator. Além disso, a

classe JMenu também é composta por objetos JMenuItem e/ou JSeparator.

23

3.3.2 XML

XML (Linguagem de marcação estensível) é uma linguagem de marcação simples,

derivada de SGML. Seu objetivo principal é facilitar o compartilhamento de textos

estruturados e informação através da Internet. XML, que foi desenvolvida em 1996 pelo XML

Working Group (coordenado por Jon Bosak da Sun Microsystems), virou uma recomendação

da W3C em 1998 (W3C [2]).

A seguir serão listadas algumas características de XML:

• Compatibilidade com a Web e os protocolos da Internet;

• Legível para humanos e para máquinas;

• Suporte a codificação Unicode;

• Permite representar as principais estruturas de dados (registros, listas e

árvores);

• Sintáxe rígida torna os algoritmos de análise rápidos e eficientes;

• Constitui um padrão internacional;

• Utiliza arquivo de texto comum, ou seja, não está atrelado a tecnologia alguma;

• Independente de plataforma.

A linguagem XML pode ser utilizada em diversos tipos de aplicações como uma

maneira de representar dados. Estes dados podem ser provenientes de um banco de dados, de

um arquivo de configuração, entre outros meios.

Em XML é possível fazer validação de um documento, ou seja, garantir que sua

estrutura está de acordo com um determinado esquema. Para especificação de um esquema,

existem duas tecnologias mais utilizadas: DTD (Document Type Definition) e XML Schema.

DTD não é feito em XML e possui uma abrangência menor que o XML Schema (que será

descrito no próximo tópico). Além de validação de documentos, os dados de um documento

XML podem ser transformados em outro tipo de representação (por exemplo: XML, HTML,

PDF ou texto simples) via XSL.

Para processamento de um documento XML existem várias API´s baseadas em alguns

modelos que podem ser utilizados para analisar e manipular estruturas XML (IBM). Um

24

desses modelos seria DOM6 que é baseado em objetos, onde cada parte do documento é

descrita como um tipo de nó. Esses nós, então, são agrupados em uma estrutura de árvore.

Existem implementações de DOM para diversas linguagens como Java, C++, Perl e Python.

Outro modelo popular seria SAX7 que é um modelo baseado em eventos, onde um documento

XML é traduzido em diversas chamadas a métodos (como startElement()). DOM e SAX

possuem suas vantagens e desvantagens que devem ser levadas em consideração de acordo

com o contexto onde forem utilizados.

3.3.3 W3C XML Schema

W3C XML Schema (W3C [3]) é uma linguagem XML utilizada para descrever e

restringir o conteúdo de documentos XML. W3C XML Schema é uma recomendação W3C.

Um documento que está conforme um determinado esquema é dito válido e o processo

de checagem é chamado validação (VLIST, 2001). A validação pode ser dividida basicamente

em dois momentos: validação da marcação (análise estrutural do documento) e validação do

conteúdo individual de cada nó (chamado de datatyping).

Além do W3C XML Schema existem outras linguagens de definição de esquema para

XML. Dentre elas estão: DTD, RELAX NG, Schematron e Examplotron. A mais comumente

utilizada é DTD (que apresenta um fraco suporte a datatyping), o que faz do W3C XML

Schema uma linguagem promissora.

3.3.4 XSLT

XSLT (Extensible Stylesheet Language Transformations) é uma linguagem que

permite transformar documentos XML em outros documentos XML, em documentos HTML

ou em qualquer outra coisa (DUCHARME, 2002). Uma transformação da linguagem XSLT é

feita através de um documento XML bem-formado, chamado “folha de estilo”, que utiliza

elementos e atributos XML especializados definidos pelo Namespace8 específico da

6 DOM - Document Object Model. 7 SAX - Simple API for XML. 8 Namespace – representa um padrão W3C para identificar unicamente os elementos e atributos de um documento XML. Serve para resolver possíveis amibuidades.

25

linguagem (chamado XSLT Namespace). XSLT é uma recomendação W3C (assim como

XML e XML Schema).

O XSLT é tecnicamente parte da XSL (Extensible Stylesheet Language). A

especificação descreve XSL como uma família de recomendações constituida de três partes:

uma linguagem para transformar documentos XML (XSLT), uma linguagem de expressão

utilizada em XSLT para acessar ou referenciar partes de um documento XML (XPATH) e um

vocabulário XML para descrever como formatar conteúdo de documentos (XSL-FO).

Além de XSLT, existem outras alternativas para transformar documentos XML. Duas

categorias possíveis seriam (DUCHARME, 2002, p.6):

• XML relacionadas a bibliotecas adicionadas a linguagens de programação de

finalidade geral como Java, Perl, Visual Basic, Python e C++;

• Linguagens como OMNImark e Balise, projetadas especificamente para

manipular documentos XML (e tipicamente SGML).

O que diferencia XSLT das outras alternativas é que XSLT é um padrão. Isto significa

que muitos fabricantes contribuiram para este projeto e que estão comprometidos em usá-lo

em seus produtos.

A geração de código utilizando transformação de documentos (SAKAR,

CLEAVELAND, 2001) via XSLT é possível através apenas de scripts XSLT juntamente com

expressões XPATH. Ainda, a geração de código é bastante flexível visto que a adição de

novos elementos e atributos no documento XML de entrada não afeta os scripts de geração de

código.

A seguir, uma figura explicando o processo de geração de um documento XML via

um processador XSLT:

26

Figura 8 Processo de transformação de documentos XML

27

4 XSWINGMENU

4.1 Descrição

XSwingMenu é uma linguagem baseada em XML para criação de menus Java Swing.

O objetivo desta linguagem é permitir de maneira simplificada a criação de barras de menu

para aplicações que utilizam Java Swing. Por esse motivo, XSwingMenu comtempla apenas

os aspectos mais comuns referentes a barra de menus.

Nos próximos itens serão comentados a especificação e documentação da linguagem

desenvolvida.

4.2 Especificação da linguagem

A seguir será mostrada uma especificação informal detalhada do esquema da

linguagem XSwingMenu.

4.2.1 Descrição dos elementos

Elemento Descrição

<menubar> Elemento raiz do documento. Representa uma barra de menu e

todos os seus itens. Por ser elemento raiz, possui o nome da classe

a ser gerada e seu respectivo package. Classe Swing

correspondente: javax.swing.JMenuBar

<menu> Representa um menu da barra de menu. É nele que estão presentes

os demais componentes. Classe Swing correspondente:

javax.swing.JMenu

<menuitem> Representa um item de menu. Seus eventos de ação são

automaticamente tratados. Classe Swing correspondente:

javax.swing.JMenuItem

28

<checkboxmenuitem> Representa um item de menu com checkbox. Seus eventos de ação

e alteração de estado são automaticamente tratados. Classe Swing

correspondente: javax.swing.JCheckboxMenuItem

<radiobuttonmenuitem> Representa um item de menu com radiobutton. Geralmente está

contido em um <grupo> para que no máximo um item do grupo

esteja selecionado. Seus eventos de ação e alteração de estado são

automaticamente tratados. Classe Swing correspondente:

javax.swing.JRadioButtonMenuItem

<grupo> Corresponde a um grupo de radiobutton´s. Permite apenas que um

de seus agrupados esteja selecionado. Classe Swing

correspondente: javax.swing.ButtonGroup.

<separador> Representa um separador entre itens de um <grupo> ou <menu>.

Corresponde a chamada do método addSeparator() do container

em questão.

Tabela 1 Descrição dos elementos da linguagem

4.2.2 Elementos

Elemento Elementos filhos Atributos

<menubar> <menu> id, package

<menu> <separador>, <menuitem>,

<checkboxmenuitem>, <menu>,

<radiobuttonmenuitem>, <grupo>

id (opcional), texto,

descricao, icone, mnemonico,

ativado

<menuitem> nenhum id, texto, descricao, icone,

mnemonico, ativado,

acelerador, selecionado

<checkboxmenuitem> nenhum id, texto, descricao, icone,

mnemonico, ativado,

acelerador, selecionado,

selecionado

<radiobuttonmenuitem> nenhum id, texto, descricao, icone,

mnemonico, ativado,

29

acelerador, selecionado,

selecionado

<grupo> <radiobuttonmenuitem>,

<separador>

id (opcional)

<separador> nenhum nenhum

Tabela 2 Elementos da linguagem

4.2.3 Descrição dos atributos

Atributo Descrição

id Utilizado como identificador único dentro do documento XML. Na geração de

código, este atributo se torna o identificador do componente em questão.

package Refere-se ao package da classe a ser gerada.

texto Corresponde ao método setText(...) do componente em questão, ou seja, o texto

exibido pelo componente.

descricao Representa um “tooltip” que é uma mensagem exibida quando o ponteiro do

mouse aponta para o componente. Corresponde ao método setToolTip(...) do

componente em questão.

icone Utilizado para indicar o caminho onde um ícone (imagem JPEG ou GIF) pode

ser encontrado. Método correspondente: setIcon(new ImageIcon(...))

docomponente em questão.

mnemonico Usado para indicar o mnemonico do componente em questão. Método

correspondente: setMnemonic(java.awt.event.KeyEvent.VK_...).

acelerador Representa um conjunto de teclas para acelerar o acionamento do componente.

Método correspondente: setAccelerator(javax.swing.KeyStroke.getKeyStroke("

... ")).

selecionado Indica se o item deve estar selecionado ou não no momento da inicialização.

Método correspondente: setSelected(...).

ativado Indica se o item deve estar ativado ou não no momento da inicialização. Método

correspondente: setEnabled(...).

Tabela 3 Descrição dos atributos da linguagem

30

4.2.4 Atributos

Atributo Tipo Uso Exemplo

id xs:ID obrigatório "btn_abrir"

package xs:string opcional “meuprojeto.menu”

texto xs:string opcional “Abrir”

descricao xs:string opcional “Clique aqui para abrir um arquivo.”

icone xs:string opcional “icones/Open16.gif”

mnemonico mnemonicos* opcional “A”

acelerador xs:string opcional "control A"

selecionado xs:boolean opcional “true”, “1”

ativado xs:boolean opcional “false”, “0”

Tabela 4 Atributos da linguagem

A coluna “Tipo” da tabela acima representa os tipos primitivos ou não utilizados para

restringir o universo de valores aceito pelo atributo.

* O tipo mnemonicos é uma restrição criada a partir do tipo xs:string que permite

apenas os caracteres utilizados na tabela de mnemonicos contida na classe

java.awt.event.KeyEvent (Documentação disponível em : http://java.sun.com/j2se/1.4.2/docs/

api/java/awt/event/KeyEvent). Obs: Os caracteres iniciais (“VK_”) presentes em todos os

mnemonicos devem ser omitido pois já são incluidos automaticamente na geração da classe.

4.3 Especificação XML Schema da linguagem

Com o intuito de formalizar a especificação da linguagem descrita nos tópicos

anteriores, segue o XML Schema desenvolvido:

<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:simpleType name="mnemonicos"> <xs:restriction base="xs:string"> <xs:pattern value="VK_([A-Z]|[0-9]|_)+"/> </xs:restriction> </xs:simpleType>

31

<xs:element name="menubar"> <xs:complexType> <xs:sequence> <xs:element ref="menu" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="id" type="xs:ID" use="required"/> <xs:attribute name="package" type="xs:string" use="optional"/> </xs:complexType> </xs:element> <xs:element name="menu"> <xs:complexType> <xs:sequence minOccurs="0" maxOccurs="unbounded"> <xs:element ref="separador" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="menuitem" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="checkboxmenuitem" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="radiobuttonmenuitem" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="grupo" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="menu" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="id" type="xs:ID" use="optional"/> <xs:attribute name="texto" type="xs:string" use="optional"/> <xs:attribute name="descricao" type="xs:string" use="optional"/> <xs:attribute name="icone" type="xs:string" use="optional"/> <xs:attribute name="mnemonico" type="mnemonicos" use="optional"/> <xs:attribute name="ativado" type="xs:boolean" use="optional"/> </xs:complexType> </xs:element> <xs:element name="separador" /> <xs:element name="menuitem"> <xs:complexType> <xs:attribute name="id" type="xs:ID" use="optional"/> <xs:attribute name="texto" type="xs:string" use="optional"/> <xs:attribute name="descricao" type="xs:string" use="optional"/> <xs:attribute name="icone" type="xs:string" use="optional"/> <xs:attribute name="mnemonico" type="mnemonicos" use="optional"/> <xs:attribute name="acelerador" type="xs:string" use="optional"/> <xs:attribute name="ativado" type="xs:boolean" use="optional"/> </xs:complexType> </xs:element> <xs:element name="checkboxmenuitem"> <xs:complexType> <xs:attribute name="id" type="xs:ID" use="optional"/> <xs:attribute name="texto" type="xs:string" use="optional"/> <xs:attribute name="descricao" type="xs:string" use="optional"/> <xs:attribute name="icone" type="xs:string" use="optional"/> <xs:attribute name="mnemonico" type="mnemonicos" use="optional"/> <xs:attribute name="acelerador" type="xs:string" use="optional"/> <xs:attribute name="selecionado" type="xs:boolean" use="optional"/> <xs:attribute name="ativado" type="xs:boolean" use="optional"/> </xs:complexType> </xs:element> <xs:element name="radiobuttonmenuitem">

32

<xs:complexType> <xs:attribute name="id" type="xs:ID" use="optional"/> <xs:attribute name="texto" type="xs:string" use="optional"/> <xs:attribute name="descricao" type="xs:string" use="optional"/> <xs:attribute name="icone" type="xs:string" use="optional"/> <xs:attribute name="mnemonico" type="mnemonicos" use="optional"/> <xs:attribute name="acelerador" type="xs:string" use="optional"/> <xs:attribute name="selecionado" type="xs:boolean" use="optional"/> <xs:attribute name="ativado" type="xs:boolean" use="optional"/> </xs:complexType> </xs:element> <xs:element name="grupo"> <xs:complexType> <xs:sequence> <xs:element ref="radiobuttonmenuitem" minOccurs="1" maxOccurs="unbounded" /> <xs:element ref="separador" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="id" type="xs:ID" use="optional"/> </xs:complexType> </xs:element> </xs:schema>

Figura 9 Especificação XML Schema da linguagem XSwingMenu

33

5 DESENVOLVIMENTO

O objetivo deste capítulo é mostrar a maneira como foi desenvolvida a ferramenta que

utiliza a linguagem XSwingMenu ressaltando as dificuldades e alguns detalhes de

implementação importantes com relação as tecnologias utilizadas. Este capítulo descreve os

dois ciclos de desenvolvimento (como descrito na prosposta de solução), uma visão geral das

classes criadas e um comparativo entre XSwingMenu e SwiXML.

5.1 Primeiro ciclo de desenvolvimento

Na primeira etapa de desenvolvimento, foram alcançados dois objetivos: a

especificação da linguagem XSwingMenu a ser utilizada nos documentos XML e o

desenvolvimento de um validador referente a esta especificação criada.

5.1.1 Especificação da linguagem

A criação da linguagem XSwingMenu foi baseada na linguagem dos documentos

XML utilizados pelo SwiXml, porém com diversas modificações. Primeiramente, foi levado

em consideração apenas as marcações referentes à barra de menu e seus subcomponentes que

serão apresentados a seguir:

• <menubar>

- filhos: <menu>

• <menu>

- filhos: <grupo>, <menuitem>, <checkboxmenuitem>, <radiobuttonmenuitem>,

<separador> e <menu>

• <grupo>

- filhos: <radiobuttonmenuitem>

• <menuitem>

• <checkboxmenuitem>

• <radiobuttonmenuitem>

• <separador>

34

A partir daí, foi desenvolvida a linguagem XSwingMenu, juntamente com o seu XML

Schema (que estão detalhados no capítulo 4).

5.1.2 Validador da linguagem

O validador tem como função analisar um documento XML de acordo com a

especificação Schema desenvolvida e, após essa análise, determinar se o documento XML é

válido de acordo com a linguagem XSwingMenu ou não indicando, em caso negativo, onde

estão as inconsistências. Vale lembrar que um documento XML só pode ser validado se ele

estiver bem-formado, ou seja, obece as regras básicas que todo documento XML deve

obedecer.

Para a construção do validador foi utilizada a biblioteca Xerces Java Parser 2.5.0

(Projeto XML Apache) que apresenta suporte para a recomendação XML Schema versão 1.0.

Sendo assim, a tarefa se resumiu em utilizar classes já prontas da biblioteca e em construir um

tratador de erros referentes aos possíveis problemas provenientes do processo de validação de

um documento XML.

5.2 Segundo ciclo de desenvolvimento Nesta etapa foi desenvolvido os scripts XSLT responsáveis pela geração de uma classe

Java que estende de javax.swing.JMenuBar a partir de um documento XML já validado frente

a linguagem XSwingMenu. Além disso, o refactoring das classes existentes referentes ao

validador foi realizado, juntamente com uma GUI (Interface Gráfica de Usuário) englobando

o validador e o transformador desenvolvidos.

Por fim, foram criadas duas ferramentas adicionais: o gerador de XML a partir de

objetos javax.swing.JMenuBar e automatizador do processo de teste de renderização.

35

5.2.1 Scripts XSLT Como descrito na solução proposta, para criação do transformador de documentos

XML para classes Java utilizou-se de scripts XSLT. O processo de transformação pode ser

dividido em dois momentos: Adição de identificadores omitidos (XML – XML) e Geração de

código Java (XML – Java).

Na primeira parte, o documento XML validado é sujeito a uma transformação XML –

XML com intuito de garantir que todos os elementos contidos no documento possuam um

identificador único (representado no atributo id da especificação). Tal processo é realizado

pois na etapa seguinte, o atributo id será utilizado como identificador do objeto gerado por

cada elemento.

Na segunda parte, após a adição dos identificadores, a criação da classe Java resultante

é realizada. Para isso, cada elemento do documento é mapeado para um componente Java

Swing específico relacionado a construção de menus. Como no validador, esse processo de

transformação é automatizado pela biblioteca Xalan-Java versão 2.6.0 (que implementa XSLT

versão 1.0 e XPath versão 1.0), o que significa dizer que toda especificação da transformação

está contida em arquivos do tipo XSL.

A seguir, um exemplo simplificado de como o XSLT foi utilizado para construção do

cabeçalho da classe gerada juntamente com a definição de atributos:

<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="text" indent="no"/> <xsl:strip-space elements="*"/> <xsl:template match="menubar"> /* * <xsl:value-of select="@id"/>.java * * Codigo gerado automaticamente pelo XSwingMenu 0.2 * Francisco Hillesheim - [email protected] */ public class <xsl:value-of select="@id"/> extends javax.swing.JMenuBar { <xsl:for-each select="descendant::menu"> protected javax.swing.JMenu <xsl:value-of select="@id"/>; </xsl:for-each>

36

<xsl:for-each select="descendant::menuitem"> protected javax.swing.JMenuItem <xsl:value-of select="@id"/>; </xsl:for-each> public <xsl:value-of select="@id"/>() { inicializaComponentes(); } private void inicializaComponentes() { <xsl:apply-templates/> } } </xsl:template>

Figura 10 Figura simplificada de script XSLT

Pode-se notar no exemplo de como as expressões XPATH são utilizadas em XSLT e

como são poderosas visto a maneira simplificada de se realizar a declaração dos atributos.

Outro ponto, é que XSLT é uma linguagem funcional o que pode não agradar a todos os

desenvolvedores.

5.2.2 Tratamento de eventos

A ferramenta desenvolvida ao gerar uma classe Java a partir de um documento XML

provê automaticamente suporte ao tratamento de eventos dos componentes: JMenuItem,

JRadioButtonMenuItem e JCheckboxMenuItem.

Esse tratamento é feito da seguinte forma: A classe gerada já possui 4 tipos de

construtores (construtor padrão, construtor com ActionListener, construtor com ItemListener

e construtor com ActionListener e ItemListener).

Quando o usuário, em sua aplicação, utiliza um dos construtores para inicializar sua

barra de menu, ele estará atrelando o ActionListener e/ou ItemListener passado como

parâmetro a todos os componentes JMenuItem (somente ActionListener),

JRadioButtonMenuItem (ActionListener e ItemListener) e JCheckboxMenuItem (somente

ItemListener).

37

Para facilitar na identificação da origem do evento, todos os componentes com eventos

automaticamente tratados terão na propriedade ActionCommand (presente em todos os objetos

que estendem javax.swing.JMenuItem) o valor do atributo id do componente presente no

documento XML mais a string “AC”. Além disso, a classe gerada possuirá todos esses valores

em constantes estáticas com o intuito de simplificar a obtenção desses valores.

Desta maneira, boa parte da necessidade de tratamento de eventos estará coberta no

caso de barras de menu. Entretanto, caso em alguma situação esta abordagem de tratamento

de evento não seja adequada, uma maneira de resolver isto seria estender a classe gerada e a

partir desta nova classe (que terá acesso a todos os atributos da classe gerada, visto que eles

são todos protected) codificar o que for necessário.

5.2.3 Criação da GUI Após o validador e o transformador prontos, uma interface de usuário foi elaborada

para disponibilizar as duas funcionalidades. Primeiramente, o usuário tem a opção de escolher

o arquivo XML a ser analisado. O conteúdo desse arquivo aparece na tela para verificação

pelo usuário. Com isso, o usuário pode, então, chamar o processo de validação. Se a validação

for efetuada com sucesso, o usuário escolhe o local onde deseja gerar a classe Java e pode

chamar o processo de transformação. Caso contrário, se a validação não for bem sucedida, a

interface gráfica deve mostrar os erros de validação que ocorreram.

A interface gráfica, como não poderia deixar de ser, foi feita em Java Swing. A

ferramenta utilizada para sua elaboração foi (como todo o código da ferramenta) o Netbeans9

3.6.

5.2.4 Gerador de documentos XML

Para que barras de menu já existentes em Java Swing possam ser reutilizadas pela

ferramenta, foi desenvolvido um mecanismo de geração de documentos XML (seguindo a

especificação da linguagem XSwingMenu) a partir de um objeto javax.swing.JMenuBar.

9 Netbeans – Ferramenta para desenvolvimento de programas Java. Disponível em: <http://www.netbeans.org/>.

38

Esta funcionalidade pode ser acionada a partir do arquivo build.xml via Ant. Para isso,

primeiramente deve-se configurar o arquivo build.xml para referenciar o classpath da classe

alvo e também alterar a classe xswingmenu.gui.GeradorXML para instanciar um objeto da

classe em questão. O resultado desta geração poderá ser encontrado na pasta “gerados” da

ferramenta.

Em suma, o gerador percorre todos os componentes do objeto JMenuBar em questão,

identifica os seus tipos e propriedades abordados pela linguagem XSwingMenu e gera uma

árvore DOM que em seguida é materializada em um documento XML. Portanto, as

propriedades que não são abordadas pela ferramenta serão descartadas.

5.2.5 Automatizador de testes

Para complementar as funcionalidades da ferramenta, foi desenvolvido um

automatizador de testes de renderização.

Para o seu desenvolvimento foi elaborado um mecanismo para iniciar os processos

“java” e “javac” para execução e compilação das classes criadas. No mais, uma classe

utilitária foi adicionada na ferramenta para possuir o código da classe de teste (visto que ele é

praticamente imutável). Com essa funcionalidade, o processo de teste da barra de menu feita a

partir do documento XML fica mais produtivo.

5.3 Estrutura de classes simplificada

Para a criação da ferramenta foram desenvolvidos os seguintes pacotes com suas

respectivas classes:

39

Figura 11 Estrutura de classes simplificada

O pacote engine é o responsável pela validação, transformação e geração de

documentos XML. Já o pacote gui é responsável pela interface com o usuário. O pacote util

possui apenas classes utilitárias.

A interface gráfica se relaciona com o motor (engine) da ferramenta através das

classes XSMEngine e XSMGerador. A classe XSMEngine possui referência as classes

XSMValidador e XSMTransformador, portanto é responsável pela parte de validação e

geração de código. Já a classe XSMGerador, que faz uso das classes XSMAtributo e

XSMElemento, é utilizada para a geração de documentos XML a partir de um objeto

javax.swing.JMenuBar.

5.4 Comparação entre XSwingMenu-0.2 e SwiXml-1.2

Para mostrar as principais diferenças entre XSwingMenu e SwiXml, será feito um

quadro comparativo das principais características de cada ferramenta. É importante ressaltar

que o objetivo desta comparação é apenas demonstrar que a utilização de XML para

desenvolvimento de interfaces gráficas pode ser feita de diversas maneiras, cada uma mais ou

menos apropriada de acordo com a situação e escopo abordados.

40

XSwingMenu-0.2 SwiXml-1.2

Escopo Barras de menu Quase todos os componentes do pacote

javax.swing

Geração de código Sim Não. Componentes são renderizados em

tempo de execução

Engenharia reversa Sim Não

Necessário adição

de biblioteca a

aplicação

Não Sim (apenas 40 Kb de tamanho)

Tratamento de

eventos

Via construtor ou

herança da classe

gerada

O acesso aos componentes (atributos) é feito

por atributos públicos de uma classe auxiliar.

A partir daí que os eventos podem ser

tratados.

Tabela 5 Comparação entre XSwingMenu e SwiXml

Mais uma vez, vale salientar que esta comparação entre as duas ferramentas só seria

válida se o escopo do problema fosse somente barras de menu.

41

6 UM EXEMPLO UTILIZANDO XSWINGMENU

O objetivo deste capítulo é mostrar um exemplo passo-a-passo de como a ferramenta

XSwingMenu pode ser usada para gerar uma barra de menu através de um documento XML

simples.

6.1 Requerimentos

Para execução deste exemplo, se faz necessário que a máquina local tenha instalada

uma JDK 1.4 ou superior. Além disso, seria opcional a utilização da ferramenta Ant

proveniente do projeto Apache, visto que o XSwingMenu possui um arquivo build.xml,

produzido para ser usado juntamente com o Ant, que visa automatizar o processo de

compilação e execução do programa. Caso o usuário pretenda utilizar a opção de criação de

teste automatizado, deve-se assegurar que os programas “javac” e “java” estejam disponíveis.

O JDK pode ser baixado gratuitamente pelo site da Sun Microsystems. Já o Ant pode

ser encontrado no site do projeto Apache. Ferramentas para desenvolvimento Java, como

Netbeans e Eclipse, possuem em sua maioria suporte ao Ant.

6.2 Criação da especificação do Menu

Neste exemplo será criado uma barra de menu simples contendo um menu “Arquivo”

com alguns elementos clássicos como “Abrir”, “Salvar” e “Sair”. Além disso, um grupo de

radiobutton´s foi adicionado para tornar o exemplo mais interessante. A seguir, a

especificação de acordo com o esquema definido:

<?xml version="1.0" encoding="UTF-8" ?> <menubar id ="Exemplo1" > <menu texto="Arquivo" mnemonico="O"> <menuitem id="abrir" texto="Abrir" mnemonico="A"/> <separador/> <menuitem id="salvar" texto="Salvar" mnemonico="S"/> <separador/> <menu texto="Arquivos em uso..."> <grupo> <radiobuttonmenuitem texto="Arquivo1.xml"/>

42

<radiobuttonmenuitem texto="Arquivo2.xml" selecionado="true"/> </grupo> </menu> <separador/> <menuitem id="abrir" texto="Sair" mnemonico="R"/> <separador/> </menu> </menubar>

Figura 12 Exemplo de documento de XML de entrada

Esta especificação foi armazenada no arquivo Exemplo1.xml. Para fins de

demonstração, foi incluído propositalmente um erro na especificação do documento. O erro é

a utilização do id = “abrir” em dois elementos do documento (o que não é permitido).

6.3 Iniciando o XSwingMenu

Após criado o arquivo XML, pode-se iniciar a ferramenta. Uma maneira fácil é iniciar

a ferramenta através do arquivo build.xml utilizando Ant do projeto Apache. Outra maneira

seria executar a classe xswingmenu.gui.JFramePrincipal, não esquecendo de adicionar as

bibliotecas presentes na pasta lib da ferramenta.

6.4 Validando o arquivo XML

Com a ferramento rodando, basta que o usuário indique o arquivo a ser validado. Após

selecionado o arquivo Exemplo1.xml, o seu conteúdo será exibido pela ferramenta. Para

iniciar o processo de validação o usuário deve pressionar o botão “Validar” presente na parte

inferior da tela. A seguir uma demonstração:

43

Figura 13 Exemplo de erro de validação de um documento XML

Conforme exposto anteriormente, a especificação do documento está incorreta visto

que há dois identificadores (id) com o mesmo nome em elementos diferentes. Com a presença

de erros, a ferramenta indica em que parte do documento o erro foi encontrado (parte

selecionada em vermelho) e exibe as mensagens de erro geradas pelo Validador. Vale lembrar

que estas mensagens são geradas pela biblioteca Xerces no processo de validação de um

documento XML por um determinado W3C XML Schema.

Corrigindo-se os erros encontrados pelo validador (através da troca do valor do

atributo id do último menuitem para “sair”) e iniciando novamente o processo de validação,

44

uma mensagem é apresentada ao usuário informando que o documento XML é válido e que o

processo de transformação (ou seja, geração de código) pode ser realizado.

6.5 Transformando o arquivo XML em classe Java

Para transformar um arquivo XML qualquer é necessário que este seja válido. Por esse

motivo, a ferramenta só dispõe a GUI referente a transformação após a validação do arquivo

XML. Sendo esta condição satisfeita, o usuário pode escolher o diretório onde será gerada a

classe Java correspondente à especificação presente no arquivo XML e iniciar o processo de

transformão através do botão “Transformar”, como mostra a figura abaixo:

45

Figura 14 Exemplo de transformação bem sucedida

6.6 Resultado

A transformação da etapa anterior resultou na seguinte classe Java:

/* * Exemplo1.java * * Codigo gerado automaticamente pelo XSwingMenu 0.2 * Francisco Hillesheim - [email protected] */ public class Exemplo1 extends javax.swing.JMenuBar { protected javax.swing.JMenu menuN400005;

46

protected javax.swing.JMenu menuN400017; protected javax.swing.JMenuItem abrir; protected javax.swing.JMenuItem salvar; protected javax.swing.JMenuItem sair; protected javax.swing.JRadioButtonMenuItem r1; protected javax.swing.JRadioButtonMenuItem r2; protected java.awt.event.ActionListener actionListener; protected java.awt.event.ItemListener itemListener; public static final String abrirAC = "abrir"; public static final String salvarAC = "salvar"; public static final String sairAC = "sair"; public static final String r1AC = "r1"; public static final String r2AC = "r2"; public Exemplo1() { this.actionListener = null; this.itemListener = null; inicializaComponentes(); } public Exemplo1(java.awt.event.ActionListener al) { this.actionListener = al; this.itemListener = null; inicializaComponentes(); } public Exemplo1(java.awt.event.ItemListener il) { this.actionListener = null; this.itemListener = il; inicializaComponentes(); } public Exemplo1(java.awt.event.ActionListener al, java.awt.event.ItemListener il) { this.actionListener = al; this.itemListener = il; inicializaComponentes(); } private void inicializaComponentes() { menuN400005 = new javax.swing.JMenu(); menuN400005.setText("Arquivo"); menuN400005.setMnemonic(java.awt.event.KeyEvent.VK_O); this.add(menuN400005); abrir = new javax.swing.JMenuItem(); abrir.setText("Abrir"); abrir.setMnemonic(java.awt.event.KeyEvent.VK_A); abrir.setActionCommand(abrirAC); if (actionListener != null) { abrir.addActionListener(actionListener); } menuN400005.add(abrir); menuN400005.addSeparator();salvar = new javax.swing.JMenuItem(); salvar.setText("Salvar"); salvar.setMnemonic(java.awt.event.KeyEvent.VK_S); salvar.setActionCommand(salvarAC); if (actionListener != null) {

47

salvar.addActionListener(actionListener); } menuN400005.add(salvar); menuN400005.addSeparator(); menuN400017 = new javax.swing.JMenu(); menuN400017.setText("Arquivos em uso..."); menuN400005.add(menuN400017); javax.swing.ButtonGroup grupoN40001A = new javax.swing.ButtonGroup(); r1 = new javax.swing.JRadioButtonMenuItem(); r1.setText("Arquivo1.xml"); r1.setActionCommand(r1AC); if (actionListener != null) { r1.addActionListener(actionListener); } if (itemListener != null) { r1.addItemListener(itemListener); } grupoN40001A.add(r1); menuN400017.add(r1); r2 = new javax.swing.JRadioButtonMenuItem(); r2.setText("Arquivo2.xml"); r2.setSelected(true); r2.setActionCommand(r2AC); if (actionListener != null) { r2.addActionListener(actionListener); } if (itemListener != null) { r2.addItemListener(itemListener); } grupoN40001A.add(r2); menuN400017.add(r2); menuN400005.addSeparator();sair = new javax.swing.JMenuItem(); sair.setText("Sair"); sair.setMnemonic(java.awt.event.KeyEvent.VK_R); sair.setActionCommand(sairAC); if (actionListener != null) { sair.addActionListener(actionListener); } menuN400005.add(sair); menuN400005.addSeparator(); } }

Figura 15 Classe gerada a partir do arquivo Exemplo1.xml

Com a seguinte classe de teste (caso desejado teste automático):

import java.awt.event.*; import javax.swing.*; public class Exemplo1Teste extends JFrame implements ActionListener, ItemListener { public static void main(String[] args) throws Exception { javax.swing.JFrame frame = new Exemplo1Teste();

48

frame.setTitle("XSwingMenu Teste"); frame.setSize(frame.getToolkit().getScreenSize()); frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE); javax.swing.JMenuBar barra = new Exemplo1((ActionListener)frame, (ItemListener)frame); frame.setJMenuBar(barra); frame.show(); } public void actionPerformed(java.awt.event.ActionEvent e) { JOptionPane.showMessageDialog(this, "'" + e.getActionCommand() + "' foi ACIONADO."); } public void itemStateChanged(java.awt.event.ItemEvent e) { String item = "'" + ((javax.swing.JMenuItem) e.getItem()).getActionCommand() + "'"; item += " foi "; item += (e.getStateChange() == e.SELECTED) ? "SELECIONADO" : "DESELECIONADO"; javax.swing.JOptionPane.showMessageDialog(this, item); } }

Figura 16 Exemplo de classe de teste gerada automaticamente

A seguir, a renderização do JFrame de teste:

Figura 17 Renderização da classe gerada

49

7 CONCLUSÃO

O produto final deste trabalho, XSwingMenu, representa mais uma maneira de se

abordar um ponto crítico, com relação a produtividade, no desenvolvimento de software: a

criação e manutenção de interfaces gráficas de usuário. Deve-se considerar, claro, que

XSwingMenu não é uma ferramenta completa para solução de problema, e sim, para um

determinado escopo: barras de menu da biblioteca Java Swing.

Neste sentido, a linguagem e a ferramenta desenvolvidas atenderam o objetivo

principal proposto por esse trabalho, o de simplificar a vida do desenvolvedor de software na

criação de barras de menu. Como exemplo disso, visto no capítulo 6, pode-se verificar por

meio do número de linhas utilizadas e organização dos elementos entre o documento XML de

entrada e a classe Java gerada que o documento XML é mais claro e conciso na representação

de uma barra de menu.

Por outro lado, este trabalho foi enriquecedor por permitir o contato, na prática, com

diversas tecnologias relaciandas a XML como XML Schema, XSLT, XPATH, XML

Namespace, DOM, SAX, entre outras. Estas siglas, que anteriormente representavam uma

“sopa de letras”, agora possuem seus propósitos mais claros que certamente serão levados em

conta para a resolução de futuros desafios profissionais.

7.1 Trabalhos futuros

Para continuidade e aperfeiçoamento deste trabalho, existem algumas sugestões que

podem ser desenvolvidas. Entre estas sugestões, pode-se destacar:

Ampliação do escopo abordado: Neste trabalho, o escopo foi somente barras de

menu. Pode-se, por meio de alterações basicamente do XML Schema e scripts XSLT

produzidos, aumentar este escopo para, por exemplo, abranger popup menus ou qualquer

outro componente de GUI.

50

Geração de código para outras bibliotecas: Um trabalho interessante seria alterar o

processo de geração de código via XSLT para produzir não só objetos Java Swing, e sim

objetos de qualquer biblioteca de qualquer linguagem desejado. Um exemplo seria a geração

de objetos SWT (que estão sendo amplamente utilizados) a partir do XSwingMenu.

Adição de um editor XML ao XSwingMenu: Para aumentar a produtividade e

simplificar o processo de criação de documentos XML para o XSwingMenu, a adição de um

editor XML a ferramenta traria maior comodidade ao desenvolvedor visto que todo o

processo poderia ser abordado dentro da própria ferramenta.

Realizar pesquisa bibliográfica mais aprofundada sobre XUL: A questão da

utilização de XML no desenvolvimento de interfaces gráficas está em alta nestes últimos.

Com o lançamento iminente da nova versão do Microsoft Windows (LongHorn) e a crescente

utilização do XUL proveniente do projeto Mozilla, este tema provavelmente será alvo de mais

discussões sobre suas vantagens e desvantagens. Além disso, várias ferramentas (gratuitas ou

não) foram e estão sendo desenvolvidas baseadas nesta tendência, o que justificaria uma

pesquisa bibliográfica mais completa sobre esta área.

51

8 REFERÊNCIAS BIBLIOGRÁFICAS

SAKAR, Soumen; CLEAVELAND, Craig. Code. Generation Using XML Based

Document Transformation, Novembro, 2001. Disponível em: <http://www.theserverside.

com/articles/content/XMLCodeGen/xmltransform.pdf>. Acesso em: 27 outubro 2004.

DUCHARME, Bob. XSLT guia prático. Tradução:Kirten Woltmann. Rio de Janeiro:

Ciência Moderna Ltda, 2002.

BOJANIC, Peter. The Joy of XUL, Dezembro, 2003. Disponível em:

<http://www.mozilla.org/projects/xul/joy-of-xul.html>. Acessado em: 10 de setembro de

2004.

MICROSOFT. "Longhorn" Markup Language (code-named "XAML") Overview.

Disponível em: <http://longhorn.msdn.microsoft.com/lhsdk/core/overviews/

about%20xaml.aspx>. Acessado em: 20 de outubro de 2004.

SUN MICROSYSTEMS, INC. [1] Java Technology. Disponível em: <http://java.sun.com>.

Acessado em: 23 de setembro de 2004.

SUN MICROSYSTEMS, INC. [2] How to Use Menus. Disponível em: <http://java.sun.com

/docs/books/tutorial/uiswing/components/menu.html>. Acessado em: 15 de setembro de 2004.

MCFARLANE, Nigel. New GUIs: XML Is the Heir Apparent, Outubro, 2002. Disponível

em: < http://www.devx.com/DevX/Article/9605>. Acessado em: 15 de setembro de 2004.

IBM.. developerWorks : XML: New to XML. Disponível em <http://www-106.ibm.com/

developerworks/xml/newto/>. Acessado em: 22 de setembro de 2004.

VLIST, Eric van der. Comparing XML Schema Languages. Disponível em:

<http://www.xml.com/pub/a/2001/12/12/schemacompare.html>. Acessado em: 23 de

setembro de 2004.

52

VLIST, Eric van der. Using W3C XML Schema. Disponível em:

<http://www.xml.com/pub/a/2000/11/29/schemas/part1.html>. Acessado em: 23 de setembro

de 2004.

OPEN XUL ALLIANCE. Open XUL Alliance – Creating A Rich Internet for Everyone.

Disponível em <http://xul.sourceforge.net/>. Acessado em: 15 de outubro de 2004.

W3C [1]. World Wide Web Consortium. Disponível em: <http://www.w3c.org/>. Acessado

em: 8 de outubro de 2004.

W3C [2]. Extensible Markup Language (XML) 1.0 (Third Edition). Disponível em:

<http://www.w3c.org/TR/2004/REC-xml-20040204/>. Acessado em: 20 de setembro de

2004.

W3C [3]. W3C XML Schema. Disponível em: < http://www.w3.org/XML/Schema>.

Acessado em: 20 de setembro de 2004.

W3C [4]. XSL Transformations (XSLT). Disponível em: <http://www.w3.org/TR/xslt>.

Acessado em: 20 de setembro de 2004.

THE APACHE XML PROJECT. xml.apache.org. Disponível em: <http://xml.apache.org/>.

Acessado em: 1 de outrubro de 2004.

WIKIPEDIA. Wikipedia, the free encyclopeia. Disponível em:

<http://en.wikipedia.org/wiki/Main_Page>. Acessado em: 28 de setembro de 2004.

PAULUS, Wolf. SwiXml. Disponível em: <http://www.swixml.org/>. Acessado em: 1 de

setembro de 2004.

THE MOZILLA ORGANIZATION. Mozilla - Home of the Firefox web browser,

Thunderbird and the Mozilla Suite. Disponível em: <http://www.mozilla.org>. Acessado

em: 3 de outrubro de 2004.

53

9 ANEXOS

9.1 Código fonte

schema.xsd <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:simpleType name="mnemonicos"> <xs:restriction base="xs:string"> <xs:pattern value="([A-Z]|[0-9]|_)+"/> </xs:restriction> </xs:simpleType> <xs:element name="menubar"> <xs:complexType> <xs:sequence> <xs:element ref="menu" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="id" type="xs:ID" use="required"/> <xs:attribute name="package" type="xs:string" use="optional"/> </xs:complexType> </xs:element> <xs:element name="menu"> <xs:complexType> <xs:sequence minOccurs="0" maxOccurs="unbounded"> <xs:element ref="separador" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="menuitem" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="checkboxmenuitem" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="radiobuttonmenuitem" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="grupo" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="menu" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="id" type="xs:ID" use="optional"/> <xs:attribute name="texto" type="xs:string" use="optional"/> <xs:attribute name="descricao" type="xs:string" use="optional"/> <xs:attribute name="icone" type="xs:string" use="optional"/> <xs:attribute name="mnemonico" type="mnemonicos" use="optional"/> <xs:attribute name="ativado" type="xs:boolean" use="optional"/> </xs:complexType> </xs:element> <xs:element name="separador" /> <xs:element name="menuitem"> <xs:complexType> <xs:attribute name="id" type="xs:ID" use="required"/> <xs:attribute name="texto" type="xs:string" use="optional"/> <xs:attribute name="descricao" type="xs:string" use="optional"/> <xs:attribute name="icone" type="xs:string" use="optional"/> <xs:attribute name="mnemonico" type="mnemonicos" use="optional"/> <xs:attribute name="acelerador" type="xs:string" use="optional"/> <xs:attribute name="ativado" type="xs:boolean" use="optional"/> </xs:complexType> </xs:element>

54

<xs:element name="checkboxmenuitem"> <xs:complexType> <xs:attribute name="id" type="xs:ID" use="required"/> <xs:attribute name="texto" type="xs:string" use="optional"/> <xs:attribute name="descricao" type="xs:string" use="optional"/> <xs:attribute name="icone" type="xs:string" use="optional"/> <xs:attribute name="mnemonico" type="mnemonicos" use="optional"/> <xs:attribute name="acelerador" type="xs:string" use="optional"/> <xs:attribute name="selecionado" type="xs:boolean" use="optional"/> <xs:attribute name="ativado" type="xs:boolean" use="optional"/> </xs:complexType> </xs:element> <xs:element name="radiobuttonmenuitem"> <xs:complexType> <xs:attribute name="id" type="xs:ID" use="required"/> <xs:attribute name="texto" type="xs:string" use="optional"/> <xs:attribute name="descricao" type="xs:string" use="optional"/> <xs:attribute name="icone" type="xs:string" use="optional"/> <xs:attribute name="mnemonico" type="mnemonicos" use="optional"/> <xs:attribute name="acelerador" type="xs:string" use="optional"/> <xs:attribute name="selecionado" type="xs:boolean" use="optional"/> <xs:attribute name="ativado" type="xs:boolean" use="optional"/> </xs:complexType> </xs:element> <xs:element name="grupo"> <xs:complexType> <xs:sequence> <xs:element ref="radiobuttonmenuitem" minOccurs="1" maxOccurs="unbounded" /> <xs:element ref="separador" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="id" type="xs:ID" use="optional"/> </xs:complexType> </xs:element> </xs:schema>

adicionaIdentificador.xsl <?xml version="1.0" encoding="UTF-8" ?> <!-- Document : adicionaIdentificador.xsl Created on : 20 de Agosto de 2004, 17:40 Author : Francisco Description: Purpose of transformation follows. --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="menu"> <xsl:element name="menu"> <xsl:if test="not(@id)"> <xsl:attribute name="id"> <xsl:text>menu</xsl:text><xsl:value-of select="generate-id()"/> </xsl:attribute> </xsl:if> <xsl:for-each select="@*"> <xsl:attribute name="{name()}"> <xsl:value-of select="."/> </xsl:attribute>

55

</xsl:for-each> <xsl:apply-templates/> </xsl:element> </xsl:template> <xsl:template match="menuitem"> <xsl:element name="menuitem"> <xsl:if test="not(@id)"> <xsl:attribute name="id"> <xsl:text>menuitem</xsl:text><xsl:value-of select="generate-id()"/> </xsl:attribute> </xsl:if> <xsl:for-each select="@*"> <xsl:attribute name="{name()}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:for-each> </xsl:element> <xsl:apply-templates/> </xsl:template> <xsl:template match="checkboxmenuitem"> <xsl:element name="checkboxmenuitem"> <xsl:if test="not(@id)"> <xsl:attribute name="id"> <xsl:text>checkboxmenuitem</xsl:text><xsl:value-of select="generate-id()"/> </xsl:attribute> </xsl:if> <xsl:for-each select="@*"> <xsl:attribute name="{name()}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:for-each> </xsl:element> <xsl:apply-templates/> </xsl:template> <xsl:template match="radiobuttonmenuitem"> <xsl:element name="radiobuttonmenuitem"> <xsl:if test="not(@id)"> <xsl:attribute name="id"> <xsl:text>radiobuttonmenuitem</xsl:text><xsl:value-of select="generate-id()"/> </xsl:attribute> </xsl:if> <xsl:for-each select="@*"> <xsl:attribute name="{name()}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:for-each> </xsl:element> <xsl:apply-templates/> </xsl:template> <xsl:template match="separador"> <xsl:element name="separador"> <xsl:if test="not(@id)"> <xsl:attribute name="id"> <xsl:text>separador</xsl:text><xsl:value-of select="generate-id()"/> </xsl:attribute> </xsl:if> <xsl:for-each select="@*"> <xsl:attribute name="{name()}"> <xsl:value-of select="."/>

56

</xsl:attribute> </xsl:for-each> <xsl:apply-templates/> </xsl:element> </xsl:template> <xsl:template match="grupo"> <xsl:element name="grupo"> <xsl:if test="not(@id)"> <xsl:attribute name="id"> <xsl:text>grupo</xsl:text><xsl:value-of select="generate-id()"/> </xsl:attribute> </xsl:if> <xsl:for-each select="@*"> <xsl:attribute name="{name()}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:for-each> <xsl:apply-templates/> </xsl:element> </xsl:template> <xsl:template match="*|@*|text()"> <xsl:copy> <xsl:apply-templates select="*|@*|text()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>

transformacao.xsl <?xml version="1.0" encoding="UTF-8"?> <!-- Cabeçalho padrão do XSLT --> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <!-- Aqui é definido o tipo de sáida como texto e com identação --> <xsl:output method="text" indent="no"/> <xsl:strip-space elements="*"/> <!-- Sub-rotina para tratamento de boolean --> <xsl:template name="formataBoolean"> <xsl:param name="boolean">1</xsl:param> <xsl:choose> <xsl:when test="($boolean = 1) or ($boolean = 'true')">true</xsl:when> <xsl:otherwise>false</xsl:otherwise> </xsl:choose> </xsl:template> <!-- Transformação do menubar (elemento raiz do documento) --> <xsl:template match="menubar"> <!-- Se menubar possuir package... --> <xsl:if test="@package"> <xsl:choose> <xsl:when test="string-length(@package) > 0">package <xsl:value-of select="@package"/>;</xsl:when> </xsl:choose> </xsl:if> /* * <xsl:value-of select="@id"/>.java * * Codigo gerado automaticamente pelo XSwingMenu 0.2 * Francisco Hillesheim - [email protected] */

57

public class <xsl:value-of select="@id"/> extends javax.swing.JMenuBar { <xsl:for-each select="descendant::menu"> protected javax.swing.JMenu <xsl:value-of select="@id"/>;<xsl:text/> </xsl:for-each> <xsl:for-each select="descendant::menuitem"> protected javax.swing.JMenuItem <xsl:value-of select="@id"/>;<xsl:text/> </xsl:for-each> <xsl:for-each select="descendant::checkboxmenuitem"> protected javax.swing.JCheckBoxMenuItem <xsl:value-of select="@id"/>;<xsl:text/> </xsl:for-each> <xsl:for-each select="descendant::radiobuttonmenuitem"> protected javax.swing.JRadioButtonMenuItem <xsl:value-of select="@id"/>;<xsl:text/> </xsl:for-each> protected java.awt.event.ActionListener actionListener; protected java.awt.event.ItemListener itemListener; <xsl:for-each select="descendant::menuitem"> public static final String <xsl:value-of select="@id"/>AC = "<xsl:value-of select="@id"/>";<xsl:text/> </xsl:for-each> <xsl:for-each select="descendant::checkboxmenuitem"> public static final String <xsl:value-of select="@id"/>AC = "<xsl:value-of select="@id"/>";<xsl:text/> </xsl:for-each> <xsl:for-each select="descendant::radiobuttonmenuitem"> public static final String <xsl:value-of select="@id"/>AC = "<xsl:value-of select="@id"/>";<xsl:text/> </xsl:for-each> public <xsl:value-of select="@id"/>() { this.actionListener = null; this.itemListener = null; inicializaComponentes(); } public <xsl:value-of select="@id"/>(java.awt.event.ActionListener al) { this.actionListener = al; this.itemListener = null; inicializaComponentes(); } public <xsl:value-of select="@id"/>(java.awt.event.ItemListener il) { this.actionListener = null; this.itemListener = il; inicializaComponentes(); } public <xsl:value-of select="@id"/>(java.awt.event.ActionListener al, java.awt.event.ItemListener il) { this.actionListener = al; this.itemListener = il; inicializaComponentes(); } private void inicializaComponentes() { <xsl:apply-templates/> } <xsl:for-each select="descendant::checkboxmenuitem">

58

/** Setter de estado do <xsl:value-of select="@id"/> */ public void setEstado<xsl:value-of select="concat(translate(substring(@id, 1, 1),'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), substring(@id, 2))" />(boolean estado) { <xsl:value-of select="@id"/>.setState(estado); } /** Setter de estado do <xsl:value-of select="@id"/> */ public boolean getEstado<xsl:value-of select="concat(translate(substring(@id, 1, 1),'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), substring(@id, 2))" />() { return <xsl:value-of select="@id"/>.getState(); } </xsl:for-each> } </xsl:template> <!-- Transformação do menu (filho de menubar) --> <xsl:template match="menubar/menu"> <xsl:value-of select="@id"/> = new javax.swing.JMenu();<xsl:text> </xsl:text> <!-- Se menu possuir texto... --> <xsl:if test="@texto"> <xsl:value-of select="@id"/>.setText("<xsl:value-of select="@texto"/>"); </xsl:if> <!-- Se menu possuir descricao (tooltip)... --> <xsl:if test="@descricao"> <xsl:value-of select="@id"/>.setToolTipText("<xsl:value-of select="@descricao"/>"); </xsl:if> <!-- Se menu possuir icone... --> <xsl:if test="@icone"> <xsl:value-of select="@id"/>.setIcon(new javax.swing.ImageIcon("<xsl:value-of select="@icone"/>")); </xsl:if> <!-- Se menu possuir mnemonico... --> <xsl:if test="@mnemonico"> <xsl:value-of select="@id"/>.setMnemonic(java.awt.event.KeyEvent.VK_<xsl:value-of select="@mnemonico"/>); </xsl:if> <!-- Se menu possuir ativado... --> <xsl:if test="@ativado"> <xsl:value-of select="@id"/>.setEnabled(<xsl:call-template name="formataBoolean"><xsl:with-param name="boolean"><xsl:value-of select="@ativado"/></xsl:with-param></xsl:call-template>); </xsl:if> <xsl:text/>this.add(<xsl:value-of select="@id"/>); <xsl:apply-templates/> </xsl:template> <!-- Transformação do menu (NÃO filho de menubar) --> <xsl:template match="menu"> <xsl:text> </xsl:text><xsl:value-of select="@id"/> = new javax.swing.JMenu();<xsl:text> </xsl:text> <!-- Se menu possuir texto... --> <xsl:if test="@texto"> <xsl:value-of select="@id"/>.setText("<xsl:value-of select="@texto"/>"); </xsl:if> <!-- Se menu possuir descricao (tooltip)... --> <xsl:if test="@descricao"> <xsl:value-of select="@id"/>.setToolTipText("<xsl:value-of select="@descricao"/>"); </xsl:if>

59

<!-- Se menu possuir icone... --> <xsl:if test="@icone"> <xsl:value-of select="@id"/>.setIcon(new javax.swing.ImageIcon("<xsl:value-of select="@icone"/>")); </xsl:if> <!-- Se menu possuir mnemonico... --> <xsl:if test="@mnemonico"> <xsl:value-of select="@id"/>.setMnemonic(java.awt.event.KeyEvent.VK_<xsl:value-of select="@mnemonico"/>); </xsl:if> <!-- Se menu possuir ativado... --> <xsl:if test="@ativado"> <xsl:value-of select="@id"/>.setEnabled(<xsl:call-template name="formataBoolean"><xsl:with-param name="boolean"><xsl:value-of select="@ativado"/></xsl:with-param></xsl:call-template>); </xsl:if> <xsl:value-of select="../@id"/>.add(<xsl:value-of select="@id"/>); <xsl:apply-templates/> </xsl:template> <!-- Transformação do menuitem --> <xsl:template match="menuitem"> <xsl:value-of select="@id"/> = new javax.swing.JMenuItem();<xsl:text> </xsl:text> <!-- Se menuitem possuir texto... --> <xsl:if test="@texto"> <xsl:value-of select="@id"/>.setText("<xsl:value-of select="@texto"/>"); </xsl:if> <!-- Se menuitem possuir descricao (tooltip)... --> <xsl:if test="@descricao"> <xsl:value-of select="@id"/>.setToolTipText("<xsl:value-of select="@descricao"/>"); </xsl:if> <!-- Se menuitem possuir icone... --> <xsl:if test="@icone"> <xsl:value-of select="@id"/>.setIcon(new javax.swing.ImageIcon("<xsl:value-of select="@icone"/>")); </xsl:if> <!-- Se menuitem possuir mnemonico... --> <xsl:if test="@mnemonico"> <xsl:value-of select="@id"/>.setMnemonic(java.awt.event.KeyEvent.VK_<xsl:value-of select="@mnemonico"/>); </xsl:if> <!-- Se menuitem possuir acelerador... --> <xsl:if test="@acelerador"> <xsl:value-of select="@id"/>.setAccelerator(javax.swing.KeyStroke.getKeyStroke("<xsl:value-of select="@acelerador"/>")); </xsl:if> <!-- Se menu possuir ativado... --> <xsl:if test="@ativado"> <xsl:value-of select="@id"/>.setEnabled(<xsl:call-template name="formataBoolean"><xsl:with-param name="boolean"><xsl:value-of select="@ativado"/></xsl:with-param></xsl:call-template>); </xsl:if> <xsl:value-of select="@id"/>.setActionCommand(<xsl:value-of select="@id"/>AC); if (actionListener != null) { <xsl:value-of select="@id"/>.addActionListener(actionListener); } <xsl:value-of select="../@id"/>.add(<xsl:value-of select="@id"/>); <xsl:apply-templates/> </xsl:template> <!-- Transformação do checkboxmenuitem --> <xsl:template match="checkboxmenuitem">

60

<xsl:value-of select="@id"/> = new javax.swing.JCheckBoxMenuItem();<xsl:text> </xsl:text> <!-- Se checkboxmenuitem possuir texto... --> <xsl:if test="@texto"> <xsl:value-of select="@id"/>.setText("<xsl:value-of select="@texto"/>"); </xsl:if> <!-- Se checkboxmenuitem possuir descricao (tooltip)... --> <xsl:if test="@descricao"> <xsl:value-of select="@id"/>.setToolTipText("<xsl:value-of select="@descricao"/>"); </xsl:if> <!-- Se checkboxmenuitem possuir icone... --> <xsl:if test="@icone"> <xsl:value-of select="@id"/>.setIcon(new javax.swing.ImageIcon("<xsl:value-of select="@icone"/>")); </xsl:if> <!-- Se checkboxmenuitem possuir mnemonico... --> <xsl:if test="@mnemonico"> <xsl:value-of select="@id"/>.setMnemonic(java.awt.event.KeyEvent.VK_<xsl:value-of select="@mnemonico"/>); </xsl:if> <!-- Se checkboxmenuitem possuir acelerador... --> <xsl:if test="@acelerador"> <xsl:value-of select="@id"/>.setAccelerator(javax.swing.KeyStroke.getKeyStroke("<xsl:value-of select="@acelerador"/>")); </xsl:if> <!-- Se checkboxmenuitem possuir acelerador... --> <xsl:if test="@selecionado"> <xsl:value-of select="@id"/>.setSelected(<xsl:value-of select="@selecionado"/>); </xsl:if> <!-- Se menu possuir ativado... --> <xsl:if test="@ativado"> <xsl:value-of select="@id"/>.setEnabled(<xsl:call-template name="formataBoolean"><xsl:with-param name="boolean"><xsl:value-of select="@ativado"/></xsl:with-param></xsl:call-template>); </xsl:if> <xsl:value-of select="@id"/>.setActionCommand(<xsl:value-of select="@id"/>AC); if (itemListener != null) { <xsl:value-of select="@id"/>.addItemListener(itemListener); } <xsl:value-of select="../@id"/>.add(<xsl:value-of select="@id"/>); <xsl:apply-templates/> </xsl:template> <!-- Transformação do radiobuttonmenuitem --> <xsl:template match="grupo/radiobuttonmenuitem"> <xsl:value-of select="@id"/> = new javax.swing.JRadioButtonMenuItem();<xsl:text> </xsl:text> <!-- Se radiobuttonmenuitem possuir texto... --> <xsl:if test="@texto"> <xsl:value-of select="@id"/>.setText("<xsl:value-of select="@texto"/>"); </xsl:if> <!-- Se radiobuttonmenuitem possuir descricao (tooltip)... --> <xsl:if test="@descricao"> <xsl:value-of select="@id"/>.setToolTipText("<xsl:value-of select="@descricao"/>"); </xsl:if> <!-- Se radiobuttonmenuitem possuir icone... --> <xsl:if test="@icone"> <xsl:value-of select="@id"/>.setIcon(new javax.swing.ImageIcon("<xsl:value-of select="@icone"/>")); </xsl:if>

61

<!-- Se radiobuttonmenuitem possuir mnemonico... --> <xsl:if test="@mnemonico"> <xsl:value-of select="@id"/>.setMnemonic(java.awt.event.KeyEvent.VK_<xsl:value-of select="@mnemonico"/>); </xsl:if> <!-- Se radiobuttonmenuitem possuir acelerador... --> <xsl:if test="@acelerador"> <xsl:value-of select="@id"/>.setAccelerator(javax.swing.KeyStroke.getKeyStroke("<xsl:value-of select="@acelerador"/>")); </xsl:if> <!-- Se radiobuttonmenuitem possuir acelerador... --> <xsl:if test="@selecionado"> <xsl:value-of select="@id"/>.setSelected(<xsl:value-of select="@selecionado"/>); </xsl:if> <!-- Se menu possuir ativado... --> <xsl:if test="@ativado"> <xsl:value-of select="@id"/>.setEnabled(<xsl:call-template name="formataBoolean"><xsl:with-param name="boolean"><xsl:value-of select="@ativado"/></xsl:with-param></xsl:call-template>); </xsl:if> <xsl:value-of select="@id"/>.setActionCommand(<xsl:value-of select="@id"/>AC); if (actionListener != null) { <xsl:value-of select="@id"/>.addActionListener(actionListener); } if (itemListener != null) { <xsl:value-of select="@id"/>.addItemListener(itemListener); } <xsl:value-of select="../@id"/>.add(<xsl:value-of select="@id"/>); <xsl:value-of select="../../@id"/>.add(<xsl:value-of select="@id"/>); <xsl:apply-templates/> </xsl:template> <!-- Transformação do radiobuttonmenuitem --> <xsl:template match="radiobuttonmenuitem"> <xsl:value-of select="@id"/> = new javax.swing.JRadioButtonMenuItem();<xsl:text> </xsl:text> <!-- Se radiobuttonmenuitem possuir texto... --> <xsl:if test="@texto"> <xsl:value-of select="@id"/>.setText("<xsl:value-of select="@texto"/>"); </xsl:if> <!-- Se radiobuttonmenuitem possuir descricao (tooltip)... --> <xsl:if test="@descricao"> <xsl:value-of select="@id"/>.setToolTipText("<xsl:value-of select="@descricao"/>"); </xsl:if> <!-- Se radiobuttonmenuitem possuir icone... --> <xsl:if test="@icone"> <xsl:value-of select="@id"/>.setIcon(new javax.swing.ImageIcon("<xsl:value-of select="@icone"/>")); </xsl:if> <!-- Se radiobuttonmenuitem possuir mnemonico... --> <xsl:if test="@mnemonico"> <xsl:value-of select="@id"/>.setMnemonic(java.awt.event.KeyEvent.VK_<xsl:value-of select="@mnemonico"/>); </xsl:if> <!-- Se radiobuttonmenuitem possuir acelerador... --> <xsl:if test="@acelerador"> <xsl:value-of select="@id"/>.setAccelerator(javax.swing.KeyStroke.getKeyStroke("<xsl:value-of select="@acelerador"/>")); </xsl:if> <!-- Se radiobuttonmenuitem possuir acelerador... -->

62

<xsl:if test="@selecionado"> <xsl:value-of select="@id"/>.setSelected(<xsl:value-of select="@selecionado"/>); </xsl:if> <!-- Se menu possuir ativado... --> <xsl:if test="@ativado"> <xsl:value-of select="@id"/>.setEnabled(<xsl:call-template name="formataBoolean"><xsl:with-param name="boolean"><xsl:value-of select="@ativado"/></xsl:with-param></xsl:call-template>); </xsl:if> <xsl:value-of select="@id"/>.setActionCommand(<xsl:value-of select="@id"/>AC); if (actionListener != null) { <xsl:value-of select="@id"/>.addActionListener(actionListener); } if (itemListener != null) { <xsl:value-of select="@id"/>.addItemListener(itemListener); } <xsl:value-of select="../@id"/>.add(<xsl:value-of select="@id"/>); <xsl:apply-templates/> </xsl:template> <!-- Transformação do separador --> <xsl:template match="separador"> <xsl:value-of select="../@id"/>.addSeparator();<xsl:text/> </xsl:template> <!-- Transformação do grupo --> <xsl:template match="grupo"> javax.swing.ButtonGroup <xsl:value-of select="@id"/> = new javax.swing.ButtonGroup(); <xsl:apply-templates/> </xsl:template> </xsl:stylesheet>

XSMAtributo.java /* * XSMElemento.java * * Created on 15 de Setembro de 2004, 19:53 */ package xswingmenu.engine; /** Classe que contém todos os atributos da especificação do XSM. * * @author Francisco */ public class XSMAtributo { /** valor do atributo ID*/ public static final String ID = "id"; /** valor do atributo PACKAGE*/ public static final String PACKAGE = "package"; /** valor do atributo TEXTO*/ public static final String TEXTO = "texto"; /** valor do atributo DESCRICAO*/ public static final String DESCRICAO = "descricao"; /** valor do atributo ICONE*/ public static final String ICONE = "icone"; /** valor do atributo MNEMONICO*/ public static final String MNEMONICO = "mnemonico"; /** valor do atributo ACELERADOR*/ public static final String ACELERADOR = "acelerador";

63

/** valor do atributo SELECIONADO*/ public static final String SELECIONADO = "selecionado"; /** valor do atributo ATIVADO*/ public static final String ATIVADO = "ativado"; }

XSMElemento.java /* * XSMElemento.java * * Created on 15 de Setembro de 2004, 19:53 */ package xswingmenu.engine; /** Classe que contém todos os elementos da especificação do XSM. * * @author Francisco */ public class XSMElemento { /** valor do elemento MENU_BAR*/ public static final String MENU_BAR = "menubar"; /** valor do elemento MENU*/ public static final String MENU = "menu"; /** valor do elemento MENU_ITEM*/ public static final String MENU_ITEM = "menuitem"; /** valor do elemento CHECK_BOX_MENU_ITEM*/ public static final String CHECK_BOX_MENU_ITEM = "checkboxmenuitem"; /** valor do elemento RADIO_BUTTON_MENU_ITEM*/ public static final String RADIO_BUTTON_MENU_ITEM = "radiobuttonmenuitem"; /** valor do elemento SEPARADOR*/ public static final String SEPARADOR = "separador"; /** valor do elemento GRUPO*/ public static final String GRUPO = "grupo"; }

XSMEngine.java /* * XSMEngine.java * * Created on 31 de Agosto de 2004, 21:40 */ package xswingmenu.engine; import java.io.File; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import java.io.IOException; import java.io.OutputStream; import java.util.List; import org.w3c.dom.Document; /** Classe que engloba todas as funcionalidades de validação e transformação * de um arquivo XML. * * @author Francisco */

64

public class XSMEngine { private XSMValidador validador; private XSMTransformador transformador; private Document doc; /** Creates a new instance of Engine */ public XSMEngine() { this.validador = new XSMValidador(); this.transformador = new XSMTransformador(); } /** Retorna o valor do atributo ID do elemento MENU_BAR * * @return String contendo o valor de id */ public String getDocMenuBarId() { return getAtributo(XSMElemento.MENU_BAR, XSMAtributo.ID); } /** Retorna o valor do atributo PACKAGE do elemento MENU_BAR * * @return String contendo o valor de package */ public String getDocMenuBarPackage() { String pack = getAtributo(XSMElemento.MENU_BAR, XSMAtributo.PACKAGE); return (pack != null && pack.length() > 0) ? pack : null; } private String getAtributo(String elemento, String atributo) { if (doc == null) return null; NodeList nl = doc.getElementsByTagName(elemento); Node no = null; if (nl.getLength() > 0) { no = nl.item(0); } if (no != null) { no = no.getAttributes().getNamedItem(atributo); } return no != null ? no.getNodeValue() : null; } /** Valida um arquivo XML. * * @param arquivoFonte * @throws IOException * @return true - o arquivo foi validado * false - o arquivo não foi validado */ public boolean valida(File arquivoFonte) throws IOException { try { validador.valida(arquivoFonte); doc = validador.getDocument(); } catch(SAXException e) { e.printStackTrace(); } return doc != null; } /** Transforma o documento gerado a partir da validação, onde o resultado * da transformação será colocada no OuputStream passado como paramentro. * * @param out outputstream * @return true - transformação realizada com sucesso * false - ocorreu erros na transformação */ public boolean transforma(OutputStream out) { boolean retorno = false;

65

try { if (doc != null) { transformador.transforma(doc, out); retorno = true; } } catch(Exception e) { e.printStackTrace(); } return retorno; } /** Retorna uma lista de erros de validação * * @return lista */ public List getListaErrosValidacao() { return validador.getListaErrosValidacao(); } /** * Getter for property doc. * @return Value of property doc. */ public Document getDoc() { return doc; } /** * Setter for property doc. * @param doc New value of property doc. */ public void setDoc(Document doc) { this.doc = doc; } }

XSMGerador.java /* * XSMGerador.java * * Created on 15 de Setembro de 2004, 18:39 */ package xswingmenu.engine; import java.awt.Component; import java.awt.event.KeyEvent; import javax.swing.*; import org.apache.xerces.dom.DocumentImpl; import org.w3c.dom.Document; import org.w3c.dom.Element; /** Classe responsável pela geração de um documento XML através de um objeto * javax.swing.JMenuBar. * * @author Francisco */ public class XSMGerador { private int contadorMenu; private int contadorMenuItem; private int contadorCheckBoxMenuItem; private int contadorRadioButtonMenuItem;

66

/** Creates a new instance of XSMGerador */ public XSMGerador() { } /** Gera um documento XML, seguindo a especificação do XSM a partir de um * objeto JMenuBar. * * @param menuBar menubar a ser utilizado * @param nomeClasse nome da classe resultante (atributo ID da tag <menubar> * @return Um doc contendo a especificação da barra de menu */ public Document geraDocumento(JMenuBar menuBar, String nomeClasse) { Document doc = new DocumentImpl(); if (menuBar != null) { Element novoElemento = doc.createElement(XSMElemento.MENU_BAR); novoElemento.setAttribute(XSMAtributo.ID, nomeClasse); doc.appendChild(novoElemento); for (int i = 0; i < menuBar.getComponentCount(); i++) { Component componente = menuBar.getComponent(i); if (componente instanceof JMenu) { montaJMenu((JMenu) componente, doc, novoElemento); } } } return doc; } private void montaJMenu(JMenu menu, Document doc, Element elemento) { if (menu != null && elemento != null) { Element novoElemento = doc.createElement(XSMElemento.MENU); adicionaAtributo(novoElemento, XSMAtributo.ID, geraIdentificadorMenu()); adicionaAtributo(novoElemento, XSMAtributo.TEXTO, menu.getText()); adicionaAtributo(novoElemento, XSMAtributo.DESCRICAO, menu.getToolTipText()); Icon icone = menu.getIcon(); if (icone != null) { adicionaAtributo(novoElemento, XSMAtributo.ICONE, icone.toString()); } if (menu.getMnemonic() > 0) { adicionaAtributo(novoElemento, XSMAtributo.MNEMONICO, KeyEvent.getKeyText(menu.getMnemonic())); } if (!menu.isEnabled()) { adicionaAtributo(novoElemento, XSMAtributo.ATIVADO, "false"); } elemento.appendChild(novoElemento); ButtonGroup grupo = null; Element elementoGrupo = null; for (int i = 0; i < menu.getMenuComponentCount(); i++) { Component componente = menu.getMenuComponent(i); if (componente instanceof JMenu) { montaJMenu((JMenu) componente, doc, novoElemento); } else if (componente instanceof JSeparator) { montaJSeparator(doc, novoElemento); } else if (componente instanceof JRadioButtonMenuItem) { JRadioButtonMenuItem radioButtonMenuItem = (JRadioButtonMenuItem) componente; DefaultButtonModel dbm = (DefaultButtonModel) radioButtonMenuItem.getModel(); ButtonGroup bg = dbm.getGroup();

67

if (bg != null) { //se o radioButtonMenuItem possuir grupo... if (grupo == null) { //se grupo é nulo, cria elemento grupo... grupo = bg; elementoGrupo = doc.createElement(XSMElemento.GRUPO); montaJMenuItem(radioButtonMenuItem, doc, elementoGrupo); novoElemento.appendChild(elementoGrupo); } else { //se grupo não é nulo... if (bg.equals(grupo)) { //se os grupos são iguais, adiciona botao ao grupo existente montaJMenuItem(radioButtonMenuItem, doc, elementoGrupo); } else { //se os grupos forem diferentes, cria novo elemento grupo... grupo = bg; elementoGrupo = doc.createElement(XSMElemento.GRUPO); montaJMenuItem(radioButtonMenuItem, doc, elementoGrupo); novoElemento.appendChild(elementoGrupo); } } } } else if (componente instanceof JMenuItem) { montaJMenuItem((JMenuItem) componente, doc, novoElemento); } } } } private void montaJSeparator(Document doc, Element elemento) { Element novoElemento = doc.createElement(XSMElemento.SEPARADOR); elemento.appendChild(novoElemento); } private void montaJMenuItem(JMenuItem menuItem, Document doc, Element elemento) { Element novoElemento = null; if (menuItem instanceof JCheckBoxMenuItem) { novoElemento = doc.createElement(XSMElemento.CHECK_BOX_MENU_ITEM); } else if (menuItem instanceof JRadioButtonMenuItem) { novoElemento = doc.createElement(XSMElemento.RADIO_BUTTON_MENU_ITEM); } else { novoElemento = doc.createElement(XSMElemento.MENU_ITEM); } adicionaAtributo(novoElemento, XSMAtributo.ID, geraIdentificadorMenuItem()); adicionaAtributo(novoElemento, XSMAtributo.TEXTO, menuItem.getText()); adicionaAtributo(novoElemento, XSMAtributo.DESCRICAO, menuItem.getToolTipText()); Icon icone = menuItem.getIcon(); if (icone != null) { adicionaAtributo(novoElemento, XSMAtributo.ICONE, icone.toString()); } if (menuItem.getMnemonic() > 0) { adicionaAtributo(novoElemento, XSMAtributo.MNEMONICO, KeyEvent.getKeyText(menuItem.getMnemonic())); } if (menuItem.getAccelerator() != null) {

68

adicionaAtributo(novoElemento, XSMAtributo.ACELERADOR, formataAcelerador(menuItem.getAccelerator())); } if (!menuItem.isEnabled()) { adicionaAtributo(novoElemento, XSMAtributo.ATIVADO, "false"); } if (menuItem.isSelected()) { adicionaAtributo(novoElemento, XSMAtributo.SELECIONADO, "true"); } elemento.appendChild(novoElemento); } private String formataAcelerador(KeyStroke ks) { int mod = ks.getModifiers(); int cod = ks.getKeyCode(); String retorno = KeyEvent.getKeyModifiersText(mod); retorno = retorno.replace('+', ' '); retorno = retorno.toLowerCase(); retorno = retorno + " " + KeyEvent.getKeyText(cod); return retorno; } private void adicionaAtributo(Element elemento, String atributo, String valor) { if (elemento != null) { if (atributo != null && atributo.length() > 0) { if (valor != null && valor.length() > 0) { elemento.setAttribute(atributo, valor); } } } } private String geraIdentificadorMenu() { return "menu" + contadorMenu++; } private String geraIdentificadorMenuItem() { return "menuItem" + contadorMenuItem++; } private String geraIdentificadorCheckBoxMenuItem() { return "checkBoxMenuItem" + contadorCheckBoxMenuItem++; } private String geraIdentificadorRadioButtonMenuItem() { return "radioButtonMenuItem" + contadorRadioButtonMenuItem++; } }

XSMTransformador.java /* * XSMTransformador.java * * Created on 29 de Agosto de 2004, 20:01 */ package xswingmenu.engine; import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException;

69

import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMResult; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import org.apache.xerces.jaxp.DocumentBuilderFactoryImpl; import org.apache.xerces.jaxp.DocumentBuilderImpl; import org.w3c.dom.Document; /** Classe responsável pela transformação (via XSLT) de um documento XML. * * @author Francisco */ public class XSMTransformador { /** Creates a new instance of Transformador */ public XSMTransformador() { } /** Realiza transformação de um documento via xslt/adicionaIdentificador.xsl * (completa os id´s do documento) e depois via xslt/transformacao.xsl (faz a * transformação propriamente dita). * * @param doc Document * @param out OutputStream * @throws TransformerException * @throws TransformerConfigurationException * @throws FileNotFoundException * @throws IOException * @throws ParserConfigurationException */ public void transforma(Document doc, OutputStream out) throws TransformerException, TransformerConfigurationException, FileNotFoundException, IOException, ParserConfigurationException { TransformerFactory tFactory = TransformerFactory.newInstance(); Transformer transformer = tFactory.newTransformer(new StreamSource("xslt/adicionaIdentificador.xsl")); DocumentBuilderFactory dbfi = DocumentBuilderFactoryImpl.newInstance(); DocumentBuilderImpl dbi = (DocumentBuilderImpl)dbfi.newDocumentBuilder(); Document docComId = dbi.newDocument(); transformer.transform(new DOMSource(doc), new DOMResult(docComId)); transformer = tFactory.newTransformer(new StreamSource("xslt/transformacao.xsl")); transformer.transform(new DOMSource(docComId), new StreamResult(out)); } }

XSMValidador.java /* * XSMValidador.java * * Created on 2 de Junho de 2004, 14:53 */

70

package xswingmenu.engine; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.xerces.parsers.DOMParser; import org.w3c.dom.Document; import org.xml.sax.ErrorHandler; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; /** Classe responsável pela validação de um arquivo XML. * * @author Francisco */ public class XSMValidador implements ErrorHandler { private DOMParser parser; private List listaErrosValidacao; private boolean validou; /** Creates a new instance of Validador */ public XSMValidador() { parser = new DOMParser(); listaErrosValidacao = new ArrayList(); validou = false; try { parser.setFeature("http://apache.org/xml/features/validation/schema-full-checking", true); parser.setFeature("http://apache.org/xml/features/validation/schema", true); parser.setFeature("http://xml.org/sax/features/validation", true); parser.setProperty( "http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", "http://www.inf.ufsc.br/~hillen/schema.xsd"); } catch (Exception e) { e.printStackTrace(); } parser.setErrorHandler(this); } /** Método responsável pela validação de um arquivo XML. Se nenhuma exceção * for lançada, pode-se pegar o Documento resultante através do método * <method>getDocument()</method>. * * @param arquivo * @throws SAXException * @throws IOException */ public void valida(File arquivo) throws SAXException, IOException { this.valida(arquivo.getAbsolutePath()); } private void valida(String arquivo) throws SAXException, IOException { validou = true; listaErrosValidacao.clear(); parser.parse(arquivo); } /** Getter do documento gerado pelo parser. Deve ser chamado após a * validação de um arquivo XML. * * @return Document documento */ public Document getDocument() {

71

return validou ? parser.getDocument() : null; } /** Tratador de erros da validação. * * @param exception * @throws SAXException */ public void error(SAXParseException exception) throws SAXException { listaErrosValidacao.add(exception); validou = false; StringBuffer msg = new StringBuffer(); msg.append("Erro durante validação: "); msg.append("'" + exception.getMessage() + "'"); msg.append("\nLinha: " + exception.getLineNumber() + ", Coluna: " + exception.getColumnNumber()); System.out.println(msg.toString()); } /** Tratador de erros fatais da validação. * * @param exception * @throws SAXException */ public void fatalError(SAXParseException exception) throws SAXException { listaErrosValidacao.add(exception); validou = false; StringBuffer msg = new StringBuffer(); msg.append("Erro fatal durante a validação: "); msg.append("'" + exception.getMessage() + "'"); msg.append("\nLinha: " + exception.getLineNumber() + ", Coluna: " + exception.getColumnNumber()); System.out.println(msg.toString()); } /** Tratador de avisos da validação. * * @param exception * @throws SAXException */ public void warning(SAXParseException exception) throws SAXException { listaErrosValidacao.add(exception); validou = false; StringBuffer msg = new StringBuffer(); msg.append("Aviso: "); msg.append("'" + exception.getMessage() + "'"); msg.append("\nLinha: " + exception.getLineNumber() + ", Coluna: " + exception.getColumnNumber()); System.out.println(msg.toString()); } /** * Getter for property listaErrosValidacao. * @return Value of property listaErrosValidacao. */ public List getListaErrosValidacao() { return listaErrosValidacao; } }

GeradorXML.java /* * GeradorXML.java *

72

* Created on 18 de Setembro de 2004, 01:19 */ package xswingmenu.gui; import java.io.FileOutputStream; import java.io.StringWriter; import javax.swing.JMenuBar; import org.apache.xml.serialize.OutputFormat; import org.apache.xml.serialize.XMLSerializer; import org.w3c.dom.Document; import xswingmenu.engine.XSMGerador; /** Classe utilizada para gerar um documento XML a partir de um objeto * JMenuBar. Para seu funcionamento, é necessário especificar o classpath do * objeto a ser gerado no arquivo build.xml (property cvs). * * Em seguida, indique o JMenuBar de origem logo abaixo (linha 37). * * @author Francisco */ public class GeradorXML { /** Creates a new instance of GeradorXML */ public GeradorXML() { } /** * @param args the command line arguments */ public static void main(String[] args) throws Exception { //instancie a sua barra de menu aqui... JMenuBar barra = new exemplos.BarraMenu(); //fim instanciação... XSMGerador gerador = new XSMGerador(); //indique o nome da classe a gerar... Document doc = gerador.geraDocumento(barra, "MenubarGerado"); OutputFormat format = new OutputFormat(doc); format.setIndenting(true); StringWriter stringOut = new StringWriter(); //se desejar, escolha o nome do arquivo a ser gerado. Padrão: gerado.xml XMLSerializer serial = new XMLSerializer( new FileOutputStream("gerados/gerado.xml"), format ); serial.asDOMSerializer(); serial.serialize( doc.getDocumentElement() ); } }

JFramePrincipal.java /* * JFramePrincipal.java * * Created on 1 de Setembro de 2004, 19:20 */ package xswingmenu.gui; import java.awt.Color; import java.io.*; import java.util.Iterator; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JOptionPane;

73

import org.xml.sax.SAXParseException; import xswingmenu.engine.XSMEngine; import xswingmenu.util.*; /** * * @author Francisco */ public class JFramePrincipal extends JFrame { private XSMEngine engine = new XSMEngine(); private JFileChooser chooserArquivoEntrada; private JFileChooser chooserDiretorioSaida; private File arquivoEntrada; private File diretorioSaida; /** Creates new form JFramePrincipal */ public JFramePrincipal() { initComponents(); } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; jPanelCentro = new javax.swing.JPanel(); jTextFieldArquivoEntrada = new javax.swing.JTextField(); jButtonProcurarArquivoEntrada = new javax.swing.JButton(); jTextFieldDiretorioSaida = new javax.swing.JTextField(); jButtonProcurarDiretorioSaida = new javax.swing.JButton(); jLabelArquivoEntrada = new javax.swing.JLabel(); jLabelDiretorioSaida = new javax.swing.JLabel(); jScrollPane1 = new javax.swing.JScrollPane(); jTextAreaArquivoEntrada = new javax.swing.JTextArea(); jScrollPane2 = new javax.swing.JScrollPane(); jTextAreaSaida = new javax.swing.JTextArea(); jLabelArquivoEntrada1 = new javax.swing.JLabel(); jLabelArquivoEntrada2 = new javax.swing.JLabel(); jCheckBoxTeste = new javax.swing.JCheckBox(); jPanelRodape = new javax.swing.JPanel(); jButtonValidar = new javax.swing.JButton(); jButtonTransformar = new javax.swing.JButton(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setTitle("XSwingMenu 0.2"); addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent evt) { exitForm(evt); } }); jPanelCentro.setLayout(new java.awt.GridBagLayout()); jTextFieldArquivoEntrada.setColumns(30); jTextFieldArquivoEntrada.addKeyListener(new java.awt.event.KeyAdapter() { public void keyTyped(java.awt.event.KeyEvent evt) { jTextFieldArquivoEntradaKeyTyped(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1;

74

gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(5, 10, 0, 0); jPanelCentro.add(jTextFieldArquivoEntrada, gridBagConstraints); jButtonProcurarArquivoEntrada.setText("Procurar"); jButtonProcurarArquivoEntrada.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButtonProcurarArquivoEntradaActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(5, 15, 0, 0); jPanelCentro.add(jButtonProcurarArquivoEntrada, gridBagConstraints); jTextFieldDiretorioSaida.setColumns(30); jTextFieldDiretorioSaida.setEditable(false); jTextFieldDiretorioSaida.setEnabled(false); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 3; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(5, 10, 0, 0); jPanelCentro.add(jTextFieldDiretorioSaida, gridBagConstraints); jButtonProcurarDiretorioSaida.setText("Procurar"); jButtonProcurarDiretorioSaida.setEnabled(false); jButtonProcurarDiretorioSaida.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButtonProcurarDiretorioSaidaActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 3; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(5, 15, 0, 0); jPanelCentro.add(jButtonProcurarDiretorioSaida, gridBagConstraints); jLabelArquivoEntrada.setText("Selecione o arquivo fonte:"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(15, 10, 0, 0); jPanelCentro.add(jLabelArquivoEntrada, gridBagConstraints); jLabelDiretorioSaida.setText("Indique o diret\u00f3rio base:"); jLabelDiretorioSaida.setEnabled(false); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(15, 10, 0, 0); jPanelCentro.add(jLabelDiretorioSaida, gridBagConstraints); jScrollPane1.setPreferredSize(new java.awt.Dimension(500, 200)); jTextAreaArquivoEntrada.setEditable(false); jTextAreaArquivoEntrada.setForeground(new java.awt.Color(0, 0, 255)); jScrollPane1.setViewportView(jTextAreaArquivoEntrada); gridBagConstraints = new java.awt.GridBagConstraints();

75

gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 5; gridBagConstraints.gridwidth = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 1.0; gridBagConstraints.weighty = 2.0; gridBagConstraints.insets = new java.awt.Insets(5, 10, 0, 10); jPanelCentro.add(jScrollPane1, gridBagConstraints); jScrollPane2.setPreferredSize(new java.awt.Dimension(500, 100)); jTextAreaSaida.setEditable(false); jTextAreaSaida.setForeground(new java.awt.Color(255, 0, 0)); jScrollPane2.setViewportView(jTextAreaSaida); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 7; gridBagConstraints.gridwidth = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 1.0; gridBagConstraints.weighty = 1.0; gridBagConstraints.insets = new java.awt.Insets(5, 10, 15, 10); jPanelCentro.add(jScrollPane2, gridBagConstraints); jLabelArquivoEntrada1.setText("Arquivo:"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 4; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(15, 10, 0, 0); jPanelCentro.add(jLabelArquivoEntrada1, gridBagConstraints); jLabelArquivoEntrada2.setText("Sa\u00edda:"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 6; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(15, 10, 0, 0); jPanelCentro.add(jLabelArquivoEntrada2, gridBagConstraints); jCheckBoxTeste.setText("Criar teste execut\u00e1vel"); jCheckBoxTeste.setEnabled(false); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 4; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(5, 15, 0, 0); jPanelCentro.add(jCheckBoxTeste, gridBagConstraints); getContentPane().add(jPanelCentro, java.awt.BorderLayout.CENTER); jButtonValidar.setText("Validar"); jButtonValidar.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButtonValidarActionPerformed(evt); } }); jPanelRodape.add(jButtonValidar); jButtonTransformar.setText("Transformar"); jButtonTransformar.setEnabled(false); jButtonTransformar.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButtonTransformarActionPerformed(evt); } });

76

jPanelRodape.add(jButtonTransformar); getContentPane().add(jPanelRodape, java.awt.BorderLayout.SOUTH); pack(); } private void jButtonTransformarActionPerformed(java.awt.event.ActionEvent evt) { transforma(); } private void jTextFieldArquivoEntradaKeyTyped(java.awt.event.KeyEvent evt) { if (evt.getKeyChar() == evt.VK_ENTER) { habilitaTransformador(false); arquivoEntrada = new File(jTextFieldArquivoEntrada.getText()); if (!arquivoEntrada.exists()) { showAviso("Arquivo: " + arquivoEntrada.getAbsolutePath() + " não encontrado."); } else if (!arquivoEntrada.isFile()) { showAviso("Arquivo: " + arquivoEntrada.getAbsolutePath() + " é inválido."); } else { //Se o arquivo estiver correto... if (arquivoEntrada.canRead()) { carregaJTextAreaArquivoEntrada(); } } } } private void jButtonValidarActionPerformed(java.awt.event.ActionEvent evt) { valida(); } private void jButtonProcurarDiretorioSaidaActionPerformed(java.awt.event.ActionEvent evt) { if (chooserDiretorioSaida == null) { initChooserDiretorioSaida(); } int returnVal = chooserDiretorioSaida.showOpenDialog(this); if(returnVal == JFileChooser.APPROVE_OPTION) { diretorioSaida = chooserDiretorioSaida.getSelectedFile(); jTextFieldDiretorioSaida.setText(diretorioSaida.getAbsolutePath()); } } private void jButtonProcurarArquivoEntradaActionPerformed(java.awt.event.ActionEvent evt) { if (chooserArquivoEntrada == null) { initChooserArquivoEntrada(); } int returnVal = chooserArquivoEntrada.showOpenDialog(this); if(returnVal == JFileChooser.APPROVE_OPTION) { habilitaTransformador(false); arquivoEntrada = chooserArquivoEntrada.getSelectedFile(); carregaJTextAreaArquivoEntrada(); jTextFieldArquivoEntrada.setText(arquivoEntrada.getAbsolutePath()); } } /** Exit the Application */ private void exitForm(java.awt.event.WindowEvent evt) { System.exit(0); } private void initChooserArquivoEntrada() { chooserArquivoEntrada = new JFileChooser();

77

XmlFileFilter filter = new XmlFileFilter(); chooserArquivoEntrada.setFileSelectionMode(JFileChooser.FILES_ONLY); chooserArquivoEntrada.setFileFilter(filter); } private void initChooserDiretorioSaida() { chooserDiretorioSaida = new JFileChooser(); chooserDiretorioSaida.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); } private void habilitaTransformador(boolean ativa) { jLabelDiretorioSaida.setEnabled(ativa); jTextFieldDiretorioSaida.setEnabled(ativa); jButtonProcurarDiretorioSaida.setEnabled(ativa); jButtonTransformar.setEnabled(ativa); jCheckBoxTeste.setEnabled(ativa); } private void limparJTextAreas() { jTextAreaSaida.setText(""); jTextAreaArquivoEntrada.setText(""); } private void carregaJTextAreaArquivoEntrada() { try { limparJTextAreas(); FileInputStream fis = new FileInputStream(arquivoEntrada); byte[] dadosArquivo = new byte[(int) arquivoEntrada.length()]; fis.read(dadosArquivo); jTextAreaArquivoEntrada.insert(new String(dadosArquivo), 0); } catch (Exception e) { showErro("Não foi possível carregar o arquivo: " + arquivoEntrada.getAbsolutePath()); e.printStackTrace(); } } private String getPackageFormatado() { String retorno = engine.getDocMenuBarPackage(); if (retorno != null) { //troca todos os pontos(.) por separador de arquivo(/) retorno = retorno.replace('.', File.separatorChar); } return retorno; } private File criaArquivoSaida() { String packageFormatado = getPackageFormatado(); File diretorio = diretorioSaida; if (packageFormatado != null) { diretorio = new File(diretorioSaida.getAbsolutePath() + File.separator + packageFormatado); } if (!diretorio.exists()) { diretorio.mkdirs(); } File arquivoSaida = new File(diretorio.getAbsolutePath() + File.separator + engine.getDocMenuBarId() + ".java"); return arquivoSaida; } private void geraArquivoTestePara(File arquivoSaida) { String pack = engine.getDocMenuBarPackage(); String docId = engine.getDocMenuBarId(); try { //cria classe de teste... File arquivoTeste = GeradorTeste.geraTeste(pack, docId, arquivoSaida.getParentFile());

78

//compila classe de teste... String msgCompilacao = GeradorTeste.compilaTeste(diretorioSaida, arquivoTeste); jTextAreaSaida.append(msgCompilacao); //executa classe de teste... GeradorTeste.executaTeste(pack, diretorioSaida, arquivoTeste); } catch (Exception e) { showErro( "Não foi possível criar o arquivo de teste: " + e.getMessage() + "\nCertifique se os programa \"javac\" e \"java\"está definido no PATH do SO." ); e.printStackTrace(); } } private void transforma() { try { if (diretorioSaida != null && diretorioSaida.exists()) { File arquivoSaida = criaArquivoSaida(); FileOutputStream fos = new FileOutputStream(arquivoSaida); if (engine.transforma(fos)) { showMensagem("Arquivo: " + arquivoSaida.getAbsolutePath() + " foi gerado com sucesso."); } else { showErro("Não foi possível gerar o arquivo: " + arquivoEntrada.getAbsolutePath()); } //libera o arquivo criado... fos.close(); //verifica se deve gerar um arquivo executavel de teste... if (jCheckBoxTeste.isSelected()) { geraArquivoTestePara(arquivoSaida); } } else { showAviso("Selecione um diretório."); } } catch (Exception e) { showErro(e.getMessage()); e.printStackTrace(); } } private void valida() { jTextAreaSaida.setText(""); try { if (arquivoEntrada != null && arquivoEntrada.exists()) { if (engine.valida(arquivoEntrada)) { habilitaTransformador(true); showMensagem("Arquivo: " + arquivoEntrada.getAbsolutePath() + " foi validado."); } else { showErrosValidacao(); } } else { showAviso("Selecione um arquivo XML para validar."); } } catch (Exception e) { showErro(e.getMessage()); } } private void showErrosValidacao() { Iterator iter = engine.getListaErrosValidacao().iterator(); boolean primeiroErro = true; while (iter.hasNext()) { SAXParseException exception = (SAXParseException) iter.next(); StringBuffer msg = new StringBuffer();

79

msg.append("Erro na linha " + exception.getLineNumber() + ": "); msg.append("'" + exception.getMessage() + "'"); msg.append("\n"); jTextAreaSaida.append(msg.toString()); if (primeiroErro) { selecionaLinha(exception.getLineNumber() - 1); primeiroErro = false; } } jTextAreaSaida.append("\nForam encontrados " + engine.getListaErrosValidacao().size() + " erros."); } private void selecionaLinha(int linha) { try { jTextAreaArquivoEntrada.setSelectionColor(Color.RED); jTextAreaArquivoEntrada.setSelectedTextColor(Color.WHITE); int linhaStartOffSet = jTextAreaArquivoEntrada.getLineStartOffset(linha); int linhaEndOffSet = jTextAreaArquivoEntrada.getLineEndOffset(linha); jTextAreaArquivoEntrada.requestFocus(); jTextAreaArquivoEntrada.select(linhaStartOffSet, linhaEndOffSet-1); } catch (Exception e) { } } private void showAviso(String msg) { JOptionPane.showMessageDialog(this, msg, "Aviso", JOptionPane.WARNING_MESSAGE); } private void showMensagem(String msg) { JOptionPane.showMessageDialog(this, msg, "Mensagem", JOptionPane.INFORMATION_MESSAGE); } private void showErro(String msg) { JOptionPane.showMessageDialog(this, msg, "Erro", JOptionPane.ERROR_MESSAGE); } /** * @param args the command line arguments */ public static void main(String args[]) { new JFramePrincipal().show(); } /** * Getter for property engine. * @return Value of property engine. */ public XSMEngine getEngine() { return engine; } /** * Setter for property engine. * @param engine New value of property engine. */ public void setEngine(XSMEngine engine) { this.engine = engine; } // Variables declaration - do not modify private javax.swing.JButton jButtonProcurarArquivoEntrada; private javax.swing.JButton jButtonProcurarDiretorioSaida; private javax.swing.JButton jButtonTransformar; private javax.swing.JButton jButtonValidar;

80

private javax.swing.JCheckBox jCheckBoxTeste; private javax.swing.JLabel jLabelArquivoEntrada; private javax.swing.JLabel jLabelArquivoEntrada1; private javax.swing.JLabel jLabelArquivoEntrada2; private javax.swing.JLabel jLabelDiretorioSaida; private javax.swing.JPanel jPanelCentro; private javax.swing.JPanel jPanelRodape; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JTextArea jTextAreaArquivoEntrada; private javax.swing.JTextArea jTextAreaSaida; private javax.swing.JTextField jTextFieldArquivoEntrada; private javax.swing.JTextField jTextFieldDiretorioSaida; // End of variables declaration }

GeradorTeste.java /* * GeradorTeste.java * * Created on 27 de Outubro de 2004, 20:47 */ package xswingmenu.util; import java.io.*; /** Classe responsável pela geração, compilação e execução de * testes de um JMenuBar gerado pelo XSwingMenu. * * @author Francisco */ public class GeradorTeste { /** Creates a new instance of GeradorTeste */ public GeradorTeste() { } public static File geraTeste(String pack, String docId, File diretorio) throws Exception { File arquivoSaidaTeste = null; StringBuffer sb = new StringBuffer(); if (pack != null) { sb.append("package " + pack + ";"); } sb.append("\n"); sb.append("import java.awt.event.*;\n"); sb.append("import javax.swing.*;\n"); sb.append("\n\n"); sb.append("public class " + docId + "Teste extends JFrame implements ActionListener, ItemListener {\n"); sb.append("\n"); sb.append(" public static void main(String[] args) throws Exception {\n"); sb.append(" javax.swing.JFrame frame = new " + docId + "Teste();\n"); sb.append(" frame.setTitle(\"XSwingMenu Teste\");\n"); sb.append(" frame.setSize(frame.getToolkit().getScreenSize());\n"); sb.append(" frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);\n"); sb.append(" javax.swing.JMenuBar barra = new " + docId + "((ActionListener)frame, (ItemListener)frame);\n"); sb.append(" frame.setJMenuBar(barra);\n"); sb.append(" frame.show();\n");

81

sb.append(" }\n"); sb.append("\n"); sb.append(" public void actionPerformed(java.awt.event.ActionEvent e) {\n"); sb.append(" JOptionPane.showMessageDialog(this, \"'\" + e.getActionCommand() + \"' foi ACIONADO.\");\n"); sb.append(" }\n"); sb.append("\n"); sb.append(" public void itemStateChanged(java.awt.event.ItemEvent e) {\n"); sb.append(" String item = \"'\" + ((javax.swing.JMenuItem) e.getItem()).getActionCommand() + \"'\";\n"); sb.append(" item += \" foi \";\n"); sb.append(" item += (e.getStateChange() == e.SELECTED) ? \"SELECIONADO\" : \"DESELECIONADO\";\n"); sb.append(" javax.swing.JOptionPane.showMessageDialog(this, item);\n"); sb.append(" }\n"); sb.append("}\n"); Writer out = null; try { arquivoSaidaTeste = new File(diretorio.getAbsolutePath() + File.separator + docId + "Teste.java"); FileOutputStream fos = new FileOutputStream(arquivoSaidaTeste); out = new BufferedWriter(new OutputStreamWriter(fos)); out.write(sb.toString()); } catch (Exception e) { throw e; } finally { try { out.close(); } catch (Exception e) { throw e; } } return arquivoSaidaTeste; } public static String compilaTeste(File diretorio, File arquivoTeste) throws Exception { StringBuffer retorno = new StringBuffer(); String argumento = "\"" + diretorio.getAbsolutePath() + "\" \"" + arquivoTeste.getAbsolutePath() + "\""; retorno.append("Compilando arquivo (" + arquivoTeste.getAbsolutePath() + ")\n"); Process p = Runtime.getRuntime().exec("javac -classpath " + argumento); String buf = null; BufferedReader se = new BufferedReader(new InputStreamReader(p.getErrorStream())); while((buf = se.readLine()) != null) { retorno.append( " : " + buf + "\n"); } retorno.append("Finalizando (rc:" + p.waitFor() + ")"); return retorno.toString(); } public static InputStream executaTeste(String pack, File diretorio, File arquivoTeste) throws Exception { String nome = arquivoTeste.getName(); int i = nome.lastIndexOf('.'); String arquivoAExecutar = ""; if (pack != null && pack.trim().length() > 0) { arquivoAExecutar = pack + "." + nome.substring(0,i); } else { arquivoAExecutar = nome.substring(0,i); }

82

String argumento = "\"" + diretorio.getAbsolutePath() + "\" " + arquivoAExecutar; Process p = Runtime.getRuntime().exec("java -cp " + argumento); return p.getInputStream(); } }

XmlFileFilter.java /* * XmlFileFilter.java * * Created on 1 de Setembro de 2004, 19:56 */ package xswingmenu.util; import java.io.File; /** Classe responsável pela filtragem de arquivos XML. * * @author Francisco */ public class XmlFileFilter extends javax.swing.filechooser.FileFilter { /** Creates a new instance of XmlFileFilter */ public XmlFileFilter() { } /** Indica os tipos de arquivos aceitos pelo filtro. * * @param f * @return true Se o tipo de arquivo for aceito. */ public boolean accept(File f) { if(f != null) { if(f.isDirectory()) { return true; } String extension = getExtension(f); if(extension != null && extension.equalsIgnoreCase("xml")) { return true; }; } return false; } /** Descrição do filtro * * @return descrição do filtro */ public String getDescription() { return "Arquivos XML"; } private String getExtension(File f) { if(f != null) { String filename = f.getName(); int i = filename.lastIndexOf('.'); if(i>0 && i<filename.length()-1) { return filename.substring(i+1).toLowerCase(); }; } return null;

83

} }

exemplo1.xml <?xml version="1.0" encoding="UTF-8" ?> <menubar id ="Exemplo1"> <menu texto="Arquivo" mnemonico="O"> <menuitem id="abrir" texto="Abrir" mnemonico="A"/> <separador/> <menuitem id="salvar" texto="Salvar" mnemonico="S"/> <separador/> <menu texto="Arquivos em uso..."> <grupo> <radiobuttonmenuitem id="r1" texto="Arquivo1.xml"/> <radiobuttonmenuitem id="r2" texto="Arquivo2.xml" selecionado="true"/> </grupo> </menu> <separador/> <menuitem id="sair" texto="Sair" mnemonico="R"/> <separador/> </menu> </menubar>

exemplo2.xml <?xml version="1.0" encoding="UTF-8" ?> <menubar sid ="Exemplo2" a="sadfsfd"> <menu id ="Aa1" mnemonico="A" texto="teste" ativado="true"> <menuitem id="exemplda1" texto="teste"/> <checkboxmenuitem selecionado = "true" texto="teste"/> <radiobuttonmenuitem id ="a3" texto="teste"/> <separador/> <grupo id="grupo"> <radiobuttonmenuitem id ="a4" texto="teste"/> <radiobuttonmenuitem id ="a5" texto="teste"/> </grupo> <radiobuttonmenuitem id ="a6" texto="teste"/> <separador/> <menu id="menu2" texto="teste2" ativado="1"/> <separador/> </menu> </menubar>

mozillaMailMenu.xml <?xml version="1.0" encoding="UTF-8" ?> <menubar id ="BarraMenu" package="menu"> <menu texto="File" mnemonico="F" icone="icones/Open16.gif"> <menu texto="New" mnemonico="N"> <menuitem id="msg" texto = "Message" acelerador="control M" mnemonico="M" descricao="Cria mensagem..."/> <menuitem id="folder" texto = "Folder..." mnemonico="F"/> <menuitem id="account" texto = "Account..." mnemonico="A"/> <separador/> <menuitem id="navWind" texto = "Navigator Window" acelerador="control N" mnemonico="N"/> <menuitem id="adrBookCard" texto = "Adress Book Card..." mnemonico="C"/> <menuitem id="compPage" texto = "Composer Page" acelerador="control shift N" mnemonico="P"/> </menu>

84

<menuitem id="openMsg" texto = "Open Message" acelerador="control O" mnemonico="O" ativado="false" icone="icones/Open16.gif"/> <menuitem id="close" texto = "Close" acelerador="control W" mnemonico="C"/> <separador/> <menu texto="Save as" mnemonico="S" icone="icones/Save16.gif"> <menuitem id="file" texto = "File" ativado="false" acelerador="control S" mnemonico="F"/> <menuitem id="template" texto = "Template" ativado="false" mnemonico="T"/> </menu> <separador/> <menuitem id="pageSetup" texto = "Page Setup..." mnemonico="U"/> <menuitem id="printPreview" texto = "Print Preview" mnemonico="V"/> <menuitem id="print" texto = "Print..." acelerador="control P" mnemonico="P"/> </menu> <menu texto="View" mnemonico="V"> <menu texto="Show/Hide" mnemonico="W"> <checkboxmenuitem id="mailToolBar" texto = "Mail Tool Bar" mnemonico="O" selecionado="true"/> <checkboxmenuitem id="searchBar" texto = "Search Bar" mnemonico="E" selecionado="true"/> <checkboxmenuitem id="statusBar" texto = "Status Bar" mnemonico="S" selecionado="true"/> <separador/> <checkboxmenuitem id="msgPane" texto = "Message Pane" mnemonico="M" acelerador="F8" selecionado="true"/> </menu> <menu id="menuZoom" texto="Text Zoom (100%)" mnemonico="Z"> <menuitem id="smaller" texto = "Smaller" acelerador="control MINUS" mnemonico="S"/> <menuitem id="larger" texto = "Larger" acelerador="control PLUS" mnemonico="L"/> <separador/> <grupo> <radiobuttonmenuitem id="v50" texto = "50 %" selecionado="false" mnemonico="5"/> <radiobuttonmenuitem id="v75" texto = "75 %" selecionado="false" mnemonico="7"/> <radiobuttonmenuitem id="v90" texto = "90 %" selecionado="false" mnemonico="9"/> <radiobuttonmenuitem id="v100" texto = "100 % (Original Size)" selecionado="true" acelerador="control 0" mnemonico="Z"/> <radiobuttonmenuitem id="v120" texto = "120 %" selecionado="false" mnemonico="1"/> <radiobuttonmenuitem id="v150" texto = "150 %" selecionado="false" mnemonico="0"/> <radiobuttonmenuitem id="v200" texto = "200 %" selecionado="false" mnemonico="2"/> </grupo> <separador/> <menuitem id="other" texto = "Other (300 %)" mnemonico="O"/> </menu> </menu> </menubar>

85

9.2 Artigo

XSwingMenu: Uma Linguagem Baseada em XML para Construção de Menus Java Swing

Francisco de Assis Besen Hillesheim

Bacharelado em Ciências da Computação, 2004

Departamento de Informática e Estatística Universidade Federal de Santa Catarina (UFSC), Brasil, 88040-900

[email protected]

Resumo Este artigo apresenta apresenta a linguagem baseada em XML XSwingMenu cujo propósito é a criação de objetos gráficos Java Swing referentes a barras de menu. A partir da linguagem XSwingMenu foi desenvolvida uma ferramenta homônima que provê suporte a geração de código Java a partir de um documento XML por meio de transformações via XSLT. Além disso, a ferramenta também possui suporte ao processo inverso, ou seja, extração de um documento XML a partir de uma barra de menu codificada em Java Swing já existente.. Palavras-chave: Java, XML, interface gráfica.

Abstract This paper presents a XML-based language called XSwingMenu which focuson creating Java Swing graphical objects describing menu bars. Based on XswingMenu, a tool was devoloped to provide Java code generation from a XML document by means of transformations of the XML document through XSLT. Moreover, the tool also provides support to the inverse process, in another words, extration of a document XML from a pre-existent menu bar coded in Java Swing. Key-words: Java, XML, graphic interface.

Introdução

Com a ascensão da especificação XML [1] nos últimos anos e o surgimento de diversas ferramentas para sua utilização, principalmente em Java, é razoável que seu uso para especificação de interfaces gráficas de usuário seja uma alternativa para minimizar o esforço necessário no seu desenvolvimento.

O objetivo geral deste trabalho é definir uma linguagem baseada em XML para especificação de objetos visuais da biblioteca Swing de Java, juntamente com uma ferramenta para manipulação de documentos XML baseados nessa linguagem visando aumentar a produtividade com relação a codificação destes objetos visuais.

O objetivo específico deste trabalho limita-se a permitir a especificação de barras de menu através da linguagem a ser criada. Além disso, desenvolver uma biblioteca Java que, quando incorporada a uma aplicação, gere objetos Swing (interface gráfica em Java) relativos ao menu desta aplicação a partir de um documento XML. Assim, para o programador, a implementação do menu de seu programa se resumiria a especificar os seus itens no formato XML.

Estado da arte

A utilização de XML ao invés de bibliotecas gráficas no desenvolvimento de interface gráfica de aplicações representa uma

86

nova abordagem. Uma prova disso é a linguagem XUL [2] que faz parte do projeto Mozilla [3] e que já é utilizada, como por exemplo, no browser Mozilla. Outra linguagem é XAML [4] que é um dialeto XML que desenvolvedores utilizarão para construir aplicativos para o Longhorn, a nova versão do sistema operacional Microsoft Windows.

XUL é uma linguagem de interface de

usuário baseada em XML do projeto Mozilla que permite construir aplicativos multi-plataforma que podem rodar conectados ou desconectados da Internet. A seguir segue suas principais características [2]:

• Linguagem de marcação poderosa com suporte aos elementos clássicos de GUI (widgets); • L Baseada em padrões existentes (Ex: Javascript e Cascading Style Sheets); • Multi-plataforma; • Separação da apresentação da lógica da aplicação; • Fácil manutenção. XAML define uma UI de aplicação com

marcações representando controles padrões do Windows. A renderização do XAML não é multi-plataforma porque ele constrói, a partir dos documentos XML, objetos Avalon (que são nativos da nova versão do Microsoft Windows) que são responsáveis pela renderização. Tal fato torna essa tecnologia dependente da plataforma Windows. Atualmente, como o novo sistema operacional ainda não foi lançado, a utilização de XAML é incipiente.

A seguir, um exemplo de ferramenta que

utiliza XML para criação de GUI´s Java Swing:

SwiXml [5] é um pequeno motor de geração de interfaces gráficas de usuário para aplicações Java e applets. A interface gráfica é definida através de documentos XML que são analisados e renderizados em tempo de execução em objetos Swing.

Suas principais características são listadas a seguir:

• Focada exclusivamente na biblioteca javax.swing; • Programadores acostumados com a biblioteca Swing podem utilizar SwiXml sem maiores preocupações;

• SwiXml é rápido pois não adiciona novas camadas sob os objetos Swing; • SwiXml é pequeno visto que seus componentes, presentes no arquivo swixml.jar, ocupam 40 Kbytes. • Só se preocupa com a interface gráfica. O comportamento dinâmico da interface e a lógica de negócio devem ser implementados em Java.

Solução proposta

A seguir, será descrita uma maneira de

se alcançar os objetivos propostos utilizando-se de padrões de manipulação de documentos XML estabelecidos pelo W3C para elaboração da ferramenta XSwingMenu. Esta proposta de solução está divida em duas partes distintas:

A primeira parte da solução do problema

consistiria na geração de código Java a partir de um documento XML, o que representa um diferencial em relação às outras soluções existentes. Para que isto possa ser realizado, uma especificação de linguagem baseada em XML deve ser criada. Para isso será utilizada uma especificação definida em W3C XML Schema [6].

Com a especificação em mãos, uma ferramenta de verificação e validação dos documentos XML, de acordo com o esquema XML definido, será desenvolvida para encontrar possíveis erros nos documentos XML e assegurar que o processo de geração de código seja consistente.

Para a geração de código Java, considerada a tarefa mais complexa, a idéia inicial é utilizar a linguagem XSLT [7] para especificar como a transformação dos documentos XML, já checados e validados, será realizada. Caso a utilização da linguagem XSLT não abranger toda o processo de geração de código, parte da biblioteca, será responsável por esta tarefa.

Para o desenvolvimento de todas essas tarefas será criado um programa escrito na linguagem Java juntamente com as bibliotecas Xerces e Xalan [8], para a manipulação dos documentos XML. A escolha destas bibliotecas é em virtude do fato de pertencerem ao respeitável projeto Apache, por serem de código aberto, por proverem juntas suporte a W3C XML Schema e XSLT, e, finalmente, por serem largamente utilizadas

87

por várias outras aplicações. Com relação a W3C XML Schema e a XSLT, sua utilização foi escolhida por serem padrões W3C.

A segunda parte da solução seria

permitir o processo inverso da primeira parte, ou seja, gerar um documento XML a partir de uma classe Java existente. Para isso, uma idéia é utilizar reflexão computacional, além das bibliotecas já citadas na primeira parte.

Essa tarefa teria como objetivo automatizar, em partes, a migração de aplicações já existentes que possuem barra de menu definida para que a solução tenha uma maior abrangência. Além disso, esta parte pode ser considerada um bom desafio por envolver outras áreas.

XSwingMenu

Na primeira etapa foi realizada a criação da linguagem XSwingMenu foi baseada na linguagem dos documentos XML utilizados pelo SwiXml, porém com diversas modificações. Primeiramente, foi levado em consideração apenas as marcações referentes à barra de menu e seus subcomponentes que serão apresentados a seguir: <menubar> - filhos: <menu> <menu> - filhos: <grupo>, <menuitem>, <checkboxmenuitem>, <radiobuttonmenuitem>, <separador> e <menu> <grupo> - filhos: <radiobuttonmenuitem> <menuitem> <checkboxmenuitem> <radiobuttonmenuitem> <separador> A partir daí, foi definida a linguagem XSwingMenu, juntamente com o seu XML Schema que detalha os atributos utilizados por cada elemento (que representam as principais propriedades de uma barra de menu).

Com a linguagem definida, foi definido o validador que tem como função analisar um documento XML de acordo com a especificação Schema desenvolvida e, após essa análise, determinar se o documento XML é válido de acordo com a linguagem XSwingMenu ou não indicando, em caso negativo, onde estão as inconsistências. Vale

lembrar que um documento XML só pode ser validado se ele estiver bem-formado, ou seja, obece as regras básicas que todo documento XML deve obedecer.

Na segunda etapa foi desenvolvido os

scripts XSLT responsáveis pela geração de uma classe Java que estende de javax.swing.JMenuBar a partir de um documento XML já validado frente a linguagem XSwingMenu. Além disso, o refactoring das classes existentes referentes ao validador foi realizado, juntamente com uma GUI (Interface Gráfica de Usuário) englobando o validador e o transformador desenvolvidos.

Por fim, foram criadas duas

ferramentas adicionais: o gerador de XML a partir de objetos javax.swing.JMenuBar e automatizador do processo de teste de renderização.

Conclusão

O produto final deste trabalho,

XSwingMenu, representa mais uma maneira de se abordar um ponto crítico, com relação a produtividade, no desenvolvimento de software: a criação e manutenção de interfaces gráficas de usuário. Deve-se considerar, claro, que XSwingMenu não é uma ferramenta completa para solução de problema, e sim, para um determinado escopo: barras de menu da biblioteca Java Swing.

Neste sentido, a linguagem e a

ferramenta desenvolvidas atenderam o objetivo principal proposto por esse trabalho, o de simplificar a vida do desenvolvedor de software na criação de barras de menu. Como exemplo disso, visto no capítulo 6, pode-se verificar por meio do número de linhas utilizadas e organização dos elementos entre o documento XML de entrada e a classe Java gerada que o documento XML é mais claro e conciso na representação de uma barra de menu.

Para continuidade e aperfeiçoamento

deste trabalho, existem algumas sugestões que podem ser desenvolvidas. Entre estas sugestões, pode-se destacar:

88

Ampliação do escopo abordado: Neste trabalho, o escopo foi somente barras de menu. Pode-se, por meio de alterações basicamente do XML Schema e scripts XSLT produzidos, aumentar este escopo para, por exemplo, abranger popup menus ou qualquer outro componente de GUI.

Geração de código para outras

bibliotecas: Um trabalho interessante seria alterar o processo de geração de código via XSLT para produzir não só objetos Java Swing, e sim objetos de qualquer biblioteca de qualquer linguagem desejado. Um exemplo seria a geração de objetos SWT (que estão sendo amplamente utilizados) a partir do XSwingMenu.

Adição de um editor XML ao

XSwingMenu: Para aumentar a produtividade e simplificar o processo de criação de documentos XML para o XSwingMenu, a adição de um editor XML a ferramenta traria maior comodidade ao desenvolvedor visto que todo o processo poderia ser abordado dentro da própria ferramenta.

Realizar pesquisa bibliográfica mais

aprofundada sobre XUL: A questão da utilização de XML no desenvolvimento de interfaces gráficas está em alta nestes últimos. Com o lançamento iminente da nova versão do Microsoft Windows (LongHorn) e a crescente utilização do XUL proveniente do projeto Mozilla, este tema provavelmente será alvo de mais discussões sobre suas vantagens e desvantagens. Além disso, várias ferramentas (gratuitas ou não) foram e estão sendo desenvolvidas baseadas nesta tendência, o que justificaria uma pesquisa bibliográfica mais completa sobre esta área.

Referências [1] W3C . Extensible Markup Language

(XML) 1.0 (Third Edition). Disponível em: <http://www.w3c.org/TR/2004/REC-xml-20040204/>. Acessado em: 20 de setembro de 2004.

[2] BOJANIC, Peter. The Joy of XUL, Dezembro, 2003. Disponível em: <http://www.mozilla. org/ projects/xul/joy-of-xul.html>. Acessado em: 10 de setembro de 2004.

[3] THE MOZILLA ORGANIZATION. Mozilla - Home of the Firefox web browser, Thunderbird and the Mozilla Suite. Disponível em: <http://www.mozilla.org>. Acessado em: 3 de outrubro de 2004.

[4] MICROSOFT. "Longhorn" Markup Language (code-named "XAML") Overview. Disponível em: <http://longhorn.msdn.microsoft.com/lhsdk/core/overviews/ about%20xaml.aspx>. Acessado em: 20 de outubro de 2004.

[5] PAULUS, Wolf. SwiXml. Disponível em: <http://www.swixml.org/>. Acessado em: 1 de setembro de 2004.

[6] W3C. W3C XML Schema. Disponível em: <http://www.w3.org/XML/Schema>. Acessado em: 20 de setembro de 2004.

[7] W3C [4]. XSL Transformations (XSLT). Disponível em: <http://www.w3.org/TR/xslt>. Acessado em: 20 de setembro de 2004.

[8] THE APACHE XML PROJECT. xml.apache.org. Disponível em: <http://xml.apache.org/>. Acessado em: 1 de outrubro de 2004.