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:
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
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.