uma ferramenta para ediÇÃo de diagramas … · 2 alexandre schulter alexandre spagnol uma...
TRANSCRIPT
UNIVERSIDADE FEDERAL DE SANTA CATARINA
CENTRO TECNOLÓGICO
DEPARTAMENTO DE INFORMÁTICA E ESTATÍSTICA
CURSO DE BACHARELADO EM CIÊNCIAS DA COMPUTAÇÃO
UMA FERRAMENTA PARA EDIÇÃO DE DIAGRAMAS DE
INTERAÇÃO DO USUÁRIO
ALEXANDRE SCHULTER
ALEXANDRE SPAGNOL
Florianópolis, fevereiro 2004
2
ALEXANDRE SCHULTER
ALEXANDRE SPAGNOL
UMA FERRAMENTA PARA EDIÇÃO DE DIAGRAMAS DE
INTERAÇÃO DO USUÁRIO
Relatório final das atividades e pesquisas desenvolvidas para o
trabalho de conclusão de curso
Orientadora: Patrícia Vilain
Banca examinadora:
Antônio Carlos Mariani
Ricardo Pereira e Silva
Florianópolis, fevereiro 2004
3
Sou CCO992 sim! E daí ?
Arliones
4
SUMÁRIO
LISTA DE FIGURAS...................................................................................................7
ABSTRACT .................................................................................................................9
1 INTRODUÇÃO .................................................................................................. 10
2 DIAGRAMA DE INTERAÇÃO DO USUÁRIO................................................. 11
2.1 Definição........................................................................................................... 11
2.2 Características ................................................................................................... 12
2.3 Notação............................................................................................................. 12
2.3.1 Estado da interação..................................................................................... 12
2.3.2 Entrada do usuário e saída do sistema ......................................................... 15
2.3.3 Transição do estado de interação................................................................. 18
2.3.3.1 Transição com seleção de N elementos ................................................ 18
2.3.3.2 Transição com seleção de opção .......................................................... 19
2.3.3.3 Transição com condição....................................................................... 20
2.3.4 Chamadas................................................................................................... 21
2.3.5 Componentes adicionais ............................................................................. 23
2.4 UIDs parametrizados......................................................................................... 23
2.5 Relacionamentos entre UIDs ............................................................................. 24
2.6 UIDs no processo de software ........................................................................... 25
2.7 Exemplo de UID ............................................................................................... 26
3 UNIFIED PROCESS ........................................................................................... 29
3.1 Dirigido por casos de uso .................................................................................. 30
3.2 Centrado na arquitetura ..................................................................................... 30
3.3 Iterativo e incremental ....................................................................................... 31
3.4 Ciclo de vida no Unified Process....................................................................... 31
4 GRAPH EDITING FRAMEWORK .................................................................... 34
4.1 Características ................................................................................................... 35
4.2 Pacotes e principais classes................................................................................ 36
4.2.1 Pacote org.tigris.gef.base ............................................................................ 37
4.2.1.1 Classe Editor........................................................................................ 38
4.2.1.2 Classe Cmd.......................................................................................... 39
4.2.1.3 Classe Layer ........................................................................................ 40
5
4.2.1.4 Classe Mode ........................................................................................ 41
4.2.1.5 Classe Selection................................................................................... 43
4.2.2 Pacote org.tigris.gef.graph .......................................................................... 43
4.2.3 Pacote org.tigris.gef.graph.presentation ...................................................... 45
4.2.4 Pacote org.tigris.gef.presentation ................................................................ 45
5 ATIVIDADES E RESULTADOS ....................................................................... 48
5.1 Levantamento de requisitos ............................................................................... 49
5.1.1 Contexto do sistema.................................................................................... 49
5.1.1.1 Visão geral........................................................................................... 49
5.1.1.2 Modelo do domínio.............................................................................. 50
5.1.2 Lista de funcionalidades ............................................................................. 51
5.1.2.1 Prioridade alta...................................................................................... 52
5.1.2.2 Prioridade média.................................................................................. 52
5.1.2.3 Prioridade baixa ................................................................................... 52
5.1.3 Requisitos funcionais.................................................................................. 53
5.1.3.1 Lista de requisitos ................................................................................ 53
5.1.3.1.1 Edição de um UID......................................................................... 53
5.1.3.1.2 Edição dos diagramas de relacionamentos ..................................... 55
5.1.3.1.4 Ambiente de edição....................................................................... 56
5.1.3.2 Casos de uso ........................................................................................ 57
5.1.3.2.1 Atores ........................................................................................... 58
5.1.3.2.2 Modelo de casos de uso................................................................. 58
5.1.3.2.3 Detalhamento dos casos de uso ..................................................... 60
5.1.4 Requisitos não-funcionais ........................................................................... 67
5.1.5 Alocação de casos de uso............................................................................ 67
5.2 Primeira iteração: Análise.................................................................................. 68
5.2.1 Realização do caso de uso Manipular projeto ............................................. 70
5.2.2 Realização do caso de uso Editar UID ........................................................ 71
5.2.3 Descrição das classes de análise identificadas ............................................. 72
5.3 Primeira iteração: Projeto .................................................................................. 73
5.3.1 Realização do caso de uso Manipular projeto ............................................. 75
5.3.2 Realização do caso de uso Editar UID ........................................................ 76
5.3.3 Sub-sistemas............................................................................................... 80
5.4 Primeira iteração: Implementação...................................................................... 81
6
5.5 Segunda iteração: Análise.................................................................................. 81
5.5.1 Realização do caso de uso Manipular projeto 2 .......................................... 82
5.5.2 Realização do caso de uso Editar UID 2 ..................................................... 83
5.5.3 Realização do caso de uso Editar DR.......................................................... 84
5.5.4 Realização do caso de uso Imprimir diagrama............................................ 85
5.5.5 Descrição das classes de análise identificadas ............................................. 86
5.6 Segunda iteração: Projeto .................................................................................. 88
5.6.1 Realização do caso de uso Manipular projeto 2 .......................................... 89
5.6.2 Realização do caso de uso Editar UID 2 ..................................................... 89
5.6.3 Realização do caso de uso Editar DR.......................................................... 91
5.6.4 Realização do caso de uso Imprimir diagrama............................................ 93
5.6.5 Sub-sistemas............................................................................................... 93
5.7 Segunda iteração: Implementação...................................................................... 94
6 CONCLUSÕES .................................................................................................. 96
7 REFERÊNCIAS.................................................................................................. 97
ANEXO A Classes de projeto .................................................................................. 98
ANEXO B Diagramas de interação de projeto........................................................ 104
ANEXO C Código fonte ........................................................................................ 119
ANEXO D Artigo .................................................................................................. 153
7
LISTA DE FIGURAS
Figura 2.1. Um estado de interação ............................................................................. 13
Figura 2.2 Tipos de estados de interação ..................................................................... 13
Figura 2.3 Exemplo de estados alternativos de interação ............................................. 14
Figura 2.4 Exemplo de sub-estados de interação.......................................................... 14
Figura 2.5 Entradas de usuário e saídas de sistema ...................................................... 15
Figura 2.6 Exemplo de entradas de usuário enumeradas .............................................. 18
Figura 2.7 Tipos de transições..................................................................................... 18
Figura 2.8 Exemplo de transição com seleção de elementos ........................................ 19
Figura 2.9 Exemplo de transição com seleção de elementos e sem mudança de foco ... 20
Figura 2.10 Chamadas................................................................................................. 21
Figura 2.11 Exemplo de chamada................................................................................ 21
Figura 2.12 Exemplo de chamada................................................................................ 22
Figura 2.13 Exemplo de um UID com chamadas......................................................... 22
Figura 2.14 Exemplo de UID parametrizado ............................................................... 24
Figura 2.15 Levantamento de requisitos com UIDs em um processo de desenvolvimento
de aplicações hirpermídia .................................................................................... 26
Figura 2.16 UID Saque em caixa eletrônico ................................................................ 28
Figura 3.1 A vida do Unified Process consiste de ciclos .............................................. 32
Figura 3.2 Os cinco workflows se encaixam nas quatro fases....................................... 32
Figura 4.1 Exemplo de programa aplicativo usando o GEF ......................................... 34
Figura 4.2 Exemplo de grafo com nodos, portas e arcos .............................................. 35
Figura 4.3 Diagrama de pacotes do GEF ..................................................................... 37
Figura 4.4 Um Editor em sua própria janela ................................................................ 38
Figura 4.5 Um editor e seu LayerManager com 2 camadas: um LayerGrid desenhando o
fundo de tela e um LayerDiagram contendo 2 figuras e mantendo a ordenação de
trás para frente..................................................................................................... 40
Figura 4.6 Camadas .................................................................................................... 41
Figura 4.7 ModeSelect desenhando um retângulo de seleção....................................... 42
Figura 4.8 Seleções ..................................................................................................... 43
Figura 4.9 Interfaces para representar grafos ............................................................... 44
Figura 4.10 Primitivas do nível de rede ....................................................................... 45
8
Figura 4.11 Figuras ..................................................................................................... 46
Figura 4.12 Figuras representando primitivas do nível de rede .................................... 47
Figura 5.1 Seqüência de tarefas ao longo do tempo ..................................................... 48
Figura 5.2 Modelo de domínio .................................................................................... 51
Figura 5.3 Modelo de casos de uso.............................................................................. 59
Figura 5.4 Tipos de classes de análise ......................................................................... 69
Figura 5.5 Manipular projeto - diagrama de classes participantes................................ 71
Figura 5.6 Editar UID - diagrama de classes participantes........................................... 72
Figura 5.7 Classes participantes da realização do caso de uso Manipular projeto ........ 76
Figura 5.8 Classes participantes da realização do caso de uso Editar UID ................... 78
Figura 5.9 Informações trocadas em estados de interação ............................................ 79
Figura 5.10 Exemplo de estado de interação................................................................ 80
Figura 5.11 Sub-sistemas de projeto............................................................................ 81
Figura 5.12 Manipular projeto 2 - diagrama de classes participantes ........................... 83
Figura 5.13 Editar UID 2 - diagrama de classes participantes...................................... 84
Figura 5.14 Editar DR - diagrama de classes participantes .......................................... 85
Figura 5.15 Imprimir diagrama - diagrama de classes participantes ............................ 85
Figura 5.16 Classes participantes da realização do caso de uso Manipular projeto 2 ... 89
Figura 5.17 Exemplo de UID com portas visíveis........................................................ 90
Figura 5.18 Classes participantes da realização do caso de uso Editar UID 2 .............. 91
Figura 5.19 Classes participantes da realização do caso de uso Editar DR ................... 92
Figura 5.20 Classes participantes da realização do caso de uso Imprimir diagrama ..... 93
Figura 5.21 Sub-sistemas de projeto............................................................................ 94
9
RESUMO Este trabalho trata do desenvolvimento de uma ferramenta que dê suporte à
edição de diagramas de interação do usuário (UIDs). O processo de desenvolvimento
usado para construção da ferramenta é baseado em recomendações do Unified Process,
sendo dirigido por casos de uso, iterativo e incremental. Um framework (GEF) para
construção de programas editores de grafos foi usado como base para as atividades de
projeto e implementação.
ABSTRACTThis work describes the development of a tool which supports the editing of user
interaction diagrams (UIDs). The development process used for building the tool is
based on the Unified Process, thus being use-case driven, iterative and incremental. A
framework (GEF) for building graph editing software was used as a basis for the design
and implementation workflows.
10
1 INTRODUÇÃO Este é um trabalho prático. O tema é o desenvolvimento de uma ferramenta que
dê suporte à edição de diagramas de interação do usuário (User Interaction Diagram -
UIDs), que é uma notação gráfica para representar a interação entre um usuário e um
sistema. O objetivo do trabalho é a análise, projeto e implementação de um software
aplicativo para proporcionar a edição de UIDs através de um ambiente com facilidades
específicas para a sua sintaxe. Mais especificamente, o objetivo é facilitar a edição de
UIDs.
A motivação para este trabalho surgiu da carência de uma ferramenta específica
para a criação de UIDs. Um analista que usa os UIDs em seu trabalho tem de recorrer a
ferramentas gráficas genéricas, dispendendo tempo com detalhes relativos a sintaxe em
si e não ao seu conteúdo.
As atividades de análise e projeto para o desenvolvimento da ferramenta foram
realizadas seguindo algumas das recomendações do processo de desenvolvimento
Unified Process [Jacobson 99]. O projeto da ferramenta foi realizado levando-se em
conta o uso do Graph Editing Framework (GEF) [Robbins 03], um framework para
construção de programas de alta qualidade que envolvem edição de grafos. A
implementação foi feita na linguagem Java, a mesma do GEF.
No capítulo 2 é descrito o que é um Diagrama de Interação do Usuário (UID),
para que serve e quais suas características. Um exemplo completo de UID é dado no
final desse capítulo. No capítulo 3 é apresentado o processo de desenvolvimento usado
como base para o desenvolvimento da ferramenta, mostrando seus principais aspectos.
No capítulo 4 são descritas as características do GEF, principais pacotes e classes,
mostrando sua viabilidade para este trabalho. No capítulo 5, são detalhados as
atividades e resultados atingidos no processo de desenvolvimento. Para cada atividade
do processo, é mostrada a sua necessidade e a sua relação com as demais atividades.
11
2 DIAGRAMA DE INTERAÇÃO DO USUÁRIO A comunicação que ocorre entre um usuário e um sistema computacional pode
ser chamada de interação. A análise e modelagem desta interação é importante para se
descobrir as informações que este sistema manipula, assim como as funcionalidades que
este deve oferecer.
A principal técnica que representa a interação entre um usuário e um sistema,
para especificação de requisitos do sistema, é a descrição textual, como por exemplo os
casos de uso e cenários. Esta técnica pode gerar especificações completas e detalhadas,
e ao mesmo tempo facilmente entendíveis pelos usuários. No entanto, estas
especificações podem ser descrições ambíguas e muito extensas.
O Digrama de Interação do Usuário, ou UID (User Interaction Diagram),
proposto em [Vilain 00], é uma notação gráfica para representar a interação entre um
usuário e um sistema. Como será visto nas seções 2.3 a 2.5, o UID é uma notação capaz
de apresentar grandes quantidades de informação por meio de diagramas simples.
O UID surgiu da necessidade de uma técnica de representação de interação que
seja diagramática e tenha alto nível de abstração. A técnica é voltada para levantamento
de requisitos de sistemas de informação ou sistemas com suporte à navegação, como em
aplicações hipermídia.
Em [Vilain 00] é mostrado como o UID pode ser incorporado nos workflows de
requisitos e análise do Unified Process [Jacobson 99]. Em [Güell 00] e [Schwabe 02] é
mostrado como o UID pode ser usado no processo de desenvolvimento de aplicações
Web, integrando as etapas de levantamento de requisitos, de projeto conceitual e de
navegação.
Neste capítulo são apresentadas a definição do UID, suas características e sua
notação, juntamente com exemplos. Também são mostradas a definição de UID
parametrizado e os relacionamentos entre UIDs.
2.1 Definição A definição de UID é dada em [Vilain 02]:
Um UID representa a interação entre o usuário e uma aplicação com intensa
troca de informações e suporte à navegação. Este diagrama descreve somente a troca
de informações entre o usuário e a aplicação, sem considerar aspectos específicos da
interface com o usuário nem da navegação .
12
Um UID é composto por um conjunto de estados conectados através de
transições. Os estados representam as informações que são trocadas entre o usuário e
a aplicação, enquanto as transições são responsáveis pela troca do foco da interação
de um estado para outro. Diz-se que um estado da interação é o foco da interação
quando as informações contidas nesse estado representam as informações que estão
sendo trocadas entre o usuário e a aplicação em um dado momento. Transições são
disparadas, geralmente, por informações entradas ou selecionadas pelo usuário .
2.2 Características Os UIDs podem representar de forma diagramática as informações sobre a
interação que é descrita textualmente em um caso de uso. Os requisitos não-funcionais
são descritos separadamente dos diagramas, na forma de notas-textuais. A interação
representada limita-se apenas à interação entre o sistema e um usuário, excluindo-se
interações de vários usuários com o sistema (trabalho cooperativo).
Uma importante característica dos UIDs é o fato de focarem somente na
estrutura e organização das informações sobre a interação e não nos detalhes do projeto
de interface e navegação. As representações de conceitos como conjunto de elementos,
coleção de informações relacionadas, informação entrada pelo usuário e informação
retornada pelo sistema, não lembram símbolos de interface de usuário. A notação do
UID mostrou-se compreensível tanto por projetistas (que constroem os diagramas),
como por usuários (que revisam os diagramas) [Vilain 02].
2.3 Notação Para se construir um UID, deve-se seguir a notação descrita a seguir. Os
exemplos utilizados são de um estudo de caso Venda de CDs Musicais Online
(retirado de [Vilain 02]) e de um sistema de informação de uma empresa de transporte
de encomendas.
2.3.1 Estado da interação
Um estado é representado como uma elipse no UID (Figura 2.1). Ele contém as
informações que são trocadas entre o usuário e o sistema em um determinado momento.
Estas informações podem ser de dois tipos: entrada de usuário e saída de sistema (seção
2.3.2). Vale lembrar que um estado nunca pode ser vazio.
13
Figura 2.1. Um estado de interação
A partir de qualquer estado, o usuário pode interromper a interação com o
sistema. Se esta interrupção não for possível, isto deverá ser explicitado na forma de
uma nota-textual.
O estado inicial da interação (Figura 2.2a) entre o usuário e o sistema é apontado
por uma transição sem origem, com destino em um estado que normalmente está no
topo do diagrama.
Quando existem duas ou mais saídas alternativas a partir de um estado de
interação, usa-se o conceito de estados alternativos (Figura 2.2b). O estado que se
tornará foco da interação será escolhido com base na informação fornecida pelo usuário
ou da opção selecionada pelo mesmo.
Quando partes de um estado são excludentes, estas podem ser alocadas em sub-
estados diferentes (Figura 2.2c). Neste caso, o usuário deverá optar pelo sub-estado que
ele vai seguir durante sua interação com o sistema.
Figura 2.2 Tipos de estados de interação
O exemplo da figura 2.3 apresenta três estados alternativos a partir do estado
inicial da interação. O estado que se tornará o foco da interação será determinado pela
satisfação das condições (seção 2.3.3) associadas a cada transição, sendo que os três
estados apresentam informações distintas ao usuário. O usuário inicialmente fornece o
código de uma encomenda. O sistema, então, processa a informação e se esta
encomenda estiver armazenada em um depósito da transportadora, serão mostrados o
nome do depósito e a data de chegada da encomenda no depósito. Se a encomenda
(a) estado inicial (b) estados alternativos (c) sub-estados
14
estiver em um caminhão em trânsito no momento, serão mostrados o depósito de onde a
encomenda saiu, para qual depósito está indo e qual sua data de saída. Se a encomenda
já tiver sido entregue a seu destinatário, então o sistema mostrará uma mensagem.
Figura 2.3 Exemplo de estados alternativos de interação
A figura 2.4 apresenta um estado de interação que contém dois sub-estados. O
usuário deve seguir a interação apresentada em um dos dois sub-estados. Se ele optar
por seguir a interação do sub-estado que apresenta o texto Cliente Novo , então ele
deve selecionar a opção criar conta. Se ele optar por seguir a interação do sub-estado
que apresenta o texto Cliente Antigo , então ele deve fornecer o seu e-mail e senha, e
selecionar a opção login.
Figura 2.4 Exemplo de sub-estados de interação
código da encomenda
nome do depósito
data de chegada: Data
depósito de saída
depósito de destino
data de saída: Data
[está em depósito] [está em trânsito]
A encomenda já foi entregue
[já foi entregue]
Cliente Novo
Cliente Antigo
senha
(criar conta) (login)
15
2.3.2 Entrada do usuário e saída do sistema
Entradas de usuário representam informações fornecidas pelo usuário ao
sistema. Já saídas de sistema são informações apresentadas pelo sistema ao usuário.
Tanto entradas, como saídas, são informações que podem ser apresentadas como itens
de dado, estruturas ou conjuntos. Entradas de usuário são colocadas dentro de
retângulos no estado de interação (figura 2.5a). Já saídas de sistema são colocadas
diretamente no estado de interação (figura 2.5b).
Se a entrada de dois itens de dados são dependentes entre si e pelo menos um
deles precisa ser fornecido pelo usuário, é usado o conectivo lógico OR entre os dois
itens de dados (Figura 2.5c). Se somente um deles pode ser fornecido pelo usuário, é
usado o conectivo lógico XOR entre os dois itens de dados (Figura 2.5d).
Figura 2.5 Entradas de usuário e saídas de sistema
Item de dado é uma informação única que aparece durante a interação e que
pode pertencer a um domínio definido. O domínio deve ser de um tipo compreensível
ao usuário, como Número, Texto, Som, Imagem ou Vídeo. Um item de dado é
representado por um nome, seguido de dois pontos e um nome de domínio. O domínio
pode ter seus valores enumerados. Neste caso, ao invés do nome do domínio, seus
valores são listados entre chaves e separados por vírgula. O domínio pode não ser
especificado e, assim, será considerado como Texto. No caso de itens de dados com
domínios Som, Imagem ou Vídeo, o nome do item pode ser suprimido.
<item de dado1>
<item de dado2>
<item de dado1>
<item de dado2>
<item de dado1> OR <item de dado2>
<item de dado1> XOR <item de dado2>
(b) saídas de sistema(a) entradas de usuário
(c)
(d)
16
<item de dado>:<domínio>
<item de dado>
<item de dado>:{<valor1>, <valor2>, <valor3>}
Exemplos:peso:Número
:Som
tamanho:{pequeno, médio, grande}
Estrutura representa uma coleção de informações que se relacionam de alguma
maneira. Estas informações podem ser itens de dados, conjuntos e outras estruturas. A
estrutura é representada por um nome, seguido de suas informações entre parênteses e
separadas por vírgula. O nome é obrigatório, mas as informações podem ser suprimidas
nas versões iniciais do UID, para não mostrar todos os detalhes. Duas estruturas com
nomes iguais podem existir, representando diferentes visões que o usuário tem da
mesma informação. Por exemplo, abaixo é apresentado duas estruturas com nome CD
(Compact Disc), que poderiam ser apresentadas em estados de interação distintos,
representando visões diferentes das informações de um CD.
<Estrutura>()
<Estrutura>(<item de dado1>, <item de dado2>)
<Estrutura>(<item de dado>, <Estrutura>())
Exemplos:
Encomenda(endereço de entrega, peso, volume)
CD(nome)
CD(nome do CD, capa, gênero, nome do cantor, ano, preço)
Itens de dados e estruturas podem ser representados como conjuntos, bastando
adicionar uma multiplicidade na frente do item de dado ou estrutura. Esta multiplicidade
indicará a quantidade de elementos de um conjunto de itens de dados ou de um conjunto
de estruturas. A multiplicidade pode ser fixa, representada por um número qualquer;
pode ser um intervalo, representado por um valor mínimo e um valor máximo, ou pode
não ser definida, sendo então considerada como 1..N e representada no diagrama como
três pontos.
17
...<item de dado>
5 <item de dado>
1..3 <Estrutura>(<item de dado1>, <item de dado2>)
...Estrutura()
<Estrutura>(...<item de dado>, ...<Estrutura>())
Saídas de sistema do tipo Texto podem ser usadas para representar textos pré-
definidos de caráter explicativo, que serão apresentados pelo sistema durante a
interação.<texto>
Saídas de sistema e entradas de usuário podem ser opcionais. Estes são
representados como opcionais colocando-se um ponto de interrogação após sua
especificação, ou definindo-os como conjuntos de multiplicidade 0..1. Entradas de
usuário opcionais também podem ser representadas por um retângulo de linhas
pontilhadas.<item de dado>?
...<Estrutura>(<item de dado1>, <item de dado2>)?
<texto> ?
0..1 <item de dado>
Uma entrada do usuário pode ser selecionada a partir de uma lista de opções que
o sistema fornece. As opções são listadas entre colchetes e separadas por vírgula. Se a
quantidade de opções que o usuário pode fornecer não for especificada, será
considerada como apenas uma. Mas pode-se definir uma quantidade mínima e máxima
de opções que o usuário pode fornecer.
<item de dado>[<opção1>, <opção2>,<opção3>]
<min>..<max> <item de dado>[<opção1>, <opção2>,<opção3>]
A figura 2.6 apresenta um estado de interação com duas entradas enumeradas.
Na primeira entrada, o item de dado fornecido pelo usuário é o pagamento, que pode ser
<item de dado>
<item de dado>?
18
cheque ou cartão de crédito. Na segunda entrada, o item de dado fornecido pelo usuário
é o transporte, que pode ser aéreo, marítimo ou expresso.
Figura 2.6 Exemplo de entradas de usuário enumeradas
2.3.3 Transição do estado de interação
Uma transição (figura 2.7a) representa que o estado destino da transição torna-se
o foco da interação após alguma ação por parte do usuário ou após uma condição ser
satisfeita no foco de interação de origem. Transições também indicam que é necessário
processamento por parte do sistema antes das próximas informações serem
apresentadas.
Transições são implicitamente bidirecionais (figura 2.7a), mas pode-se dizer
explicitamente que ela é bidirecional (figura 2.7b), ou explicitamente unidirecional
(figura 2.7c).
Figura 2.7 Tipos de transições
A origem de uma transição pode ser todo um estado ou uma saída de sistema
dentro do estado. Como será visto a seguir, uma transição também pode ter mais de uma
origem, a partir de saídas de sistema do tipo conjunto. O destino da transição sempre é
um único estado de interação.
Rótulos podem estar associados às transições, os quais determinam o que deve
acontecer para que o foco de interação mude para o estado destino. São três os possíveis
rótulos: seleção de elementos, seleção de opção e condição.
2.3.3.1 Transição com seleção de N elementos
Transição com seleção de elementos tem origem em um conjunto. Representa
que N elementos devem ser selecionados do conjunto, pelo usuário, para que a transição
(a) (b) (c)
pagamento [cheque, cartão de crédito]
transporte [aéreo, marítimo, expresso]
19
aconteça. Os elementos selecionados podem pertencer a conjuntos diferentes do mesmo
estado.
A transição da figura 2.8 tem como rótulo a seleção de 1 elemento. Assim, o
usuário deverá selecionar uma encomenda, do conjunto de encomendas, para que sejam
mostrados o endereço de entrega, peso e volume da encomenda selecionada.
Figura 2.8 Exemplo de transição com seleção de elementos
2.3.3.2 Transição com seleção de opção
Uma transição com seleção de opção representa que o usuário deverá selecionar
uma determinada opção disponibilizada pelo sistema para que a transição seja disparada
e o do foco de interação mude para o estado de interação destino
Quando o rótulo de uma transição for somente uma seleção de opção, a origem
da transição deverá ser um estado de interação. Uma transição pode acontecer com
seleção de opção e seleção de elementos de um conjunto ao mesmo tempo. Neste caso,
a origem da transição será o conjunto de onde os elementos são selecionados. Uma
transição com seleção de opção também pode não mudar o foco de interação, como no
exemplo descrito a seguir.
No exemplo da figura 2.9, o usuário deverá selecionar 1 elemento do conjunto
de veículos e N elementos do conjunto de encomendas a serem entregues. Juntamente
com a seleção de elementos dos dois conjuntos, o usuário também deve selecionar a
<N><N>
<N>
(<opção>)
...Encomenda ( )
endereço de entrega
1
peso
volume
20
opção alocar para alocar as encomendas selecionadas ao veículo selecionado, que fará o
transporte e entrega das encomendas. Esta transição não muda o foco de interação, pois
o usuário pode continuar alocando encomendas a outros veículos.
Figura 2.9 Exemplo de transição com seleção de elementos e sem mudança de foco
2.3.3.3 Transição com condição
Uma transição com condição representa que o estado destino da interação torna-
se o foco se a condição especificada for satisfeita. Esta condição deve ser verificada
pelo sistema e é expressa em linguagem natural.
Se há mais de uma transição com condição partindo do mesmo estado, estas
condições devem ser excludentes. Por exemplo, na figura 2.3, a três condições
associadas às transições saindo do estado inicial são excludentes. Isso porque uma
encomenda sempre estará em um dos três estados: entregue, armazenada em depósito ou
em trânsito.
Se uma transição tiver como rótulo uma condição, ou uma condição e uma
seleção de opção, então a origem da transição deverá ser todo um estado. Se a transição
[<condição>]
Encomenda(endereço de entrega, peso, volume)
Veículo(placa, volume máximo, peso máximo)
(alocar)
1
N
Mapa de Carregamento e Guias de Entrega
...Carregamento(código da encomenda, placa do caminhão)
...Entrega(código da encomenda, endereço de entrega)
(gerar mapa)
(imprimir mapa)
(imprimir guias)
21
tiver como rótulo uma condição e uma seleção de elementos, então a origem da
transição deverá ser o conjunto de onde os elementos são selecionados.
2.3.4 Chamadas
A partir de um UID, pode-se fazer uma chamada para outro UID. Esta chamada
representa a transferência do foco de interação para o estado inicial do UID chamado
(veja figura 2.10a). No UID chamado, o UID que fez a chamada deverá ser identificado
por uma chamada a partir de outro UID (figura 2.10b). Se o UID chamado puder ser
executado independentemente, seu estado inicial pode ser um estado comum.
Figura 2.10 Chamadas
Após a execução do UID chamado, o foco de interação retorna ao estado de
interação a partir de onde foi feita a chamada. Na figura 2.11, o foco retorna para o
estado . Mas o foco poderia retornar para um estado específico, no caso de haver
uma transição de saída da chamada para um estado específico. Na figura 2.12 o foco
retorna para o estado .
Figura 2.11 Exemplo de chamada
UID <nome>
UID <nome>
UID <nome>
(a) Chamada para outro UID (b) Chamada a partir de outro UID
22
Figura 2.12 Exemplo de chamada
Se a chamada para o outro UID estiver solta, ou seja, sem transições chegando
ou saindo da chamada, então a chamada poderá ser feita a partir de qualquer estado do
UID. Este tipo de chamada também pode ser representada pelo relacionamento de
extensão no diagrama de relacionamentos entre UIDs.
No exemplo da figura 2.13, os UIDs Mostrar músicas de um CD e Comprar
CDs podem ser chamados. A partir do estado de interação <2>, o usuário pode
selecionar um CD do conjunto de CDs apresentado pelo sistema e a opção mostrar
músicas. Esta opção é reponsável em transferir o foco da interação para a interação
inicial do UID sendo chamado. A partir de qualquer estado deste UID, o UID Comprar
CDs pode ser chamado, interrompendo o UID corrente.
Figura 2.13 Exemplo de um UID com chamadas
UID <nome>
título do CD
...CD (título, nome cantor, ano, preço,disponibilidade, capa, gênero, gravadora)
UID Mostrar músicasde um CD
1 (mostrar músicas)
UID Comprar CDs
<1>
<2>
23
Chamadas para outros UIDs são particularmente úteis para tratamento de
exceções, onde o foco é transferido para outro UID onde a exceção é tratada.
2.3.5 Componentes adicionais
Existem dois tipos de componentes adicionais que podem ser anexados aos
UIDs, são eles notas textuais e condições (pré e pós-condições). Estes são normalmente
anexados na parte inferior do diagrama.
Nota: <nota textual>
Pré-condições e pós-condições são semelhantes às condições dos casos de uso,
sendo expressas em linguagem natural. Uma pré-condição estabelece que o UID
somente poderá ser executado se esta pré-condição for satisfeita. Uma pós-condição
estabelece a condição que deverá ser satisfeita após a interação descrita no UID.
Notas textuais descrevem alguma informação que não pode ser representada
graficamente no UID. Podem ser usadas para descrever requisitos não-funcionais.
2.4 UIDs parametrizados Dois ou mais UIDs com a mesma seqüência de interação, mas com algumas
informações distintas, podem ser representados como um único UID parametrizado. Isto
se faz criando-se um UID com a mesma seqüência de interação dos UIDs em que está
baseado, substituindo-se as informações que são distintas entre eles por um nome de
parâmetro, e anexando ao UID os possíveis valores que este parâmetro pode assumir.
O UID Seleção de um CD, mostrado na Figura 2.14, é parametrizado. O
Parâmetro 1 poderia assumir os valores cantor ou gênero, eliminando a necessidade de
se construir dois UIDs com a mesma seqüência de interação, ambos resultando em uma
saída de sistema mostrando um conjunto de CDs com suas informações.
Pré-condições: <condições>
Pós-condições: <condições>
24
Figura 2.14 Exemplo de UID parametrizado
2.5 Relacionamentos entre UIDs Um diagrama de relacionamentos apresenta os relacionamentos mais
significativos entre os UIDs. Ele salienta alguns relacionamentos que são descritos nos
casos de uso, mas que não são representados nos UIDs.
O diagrama de relacionamentos possibilita uma visualização de como os UIDs
interagem para dar suporte a tarefas maiores.
Um relacionamento de inclusão entre dois UIDs significa que um UID faz parte
de outro UID e que sua seqüência de interação é incluída no outro UID. Quando uma
parte de vários UIDs é comum, ela pode ser especificada separadamente em um outro
UID que será incluído nos vários UIDs. A interação do UID incluído não faz sentido
sozinha. Durante a especificação de um UID que inclui outro UID, o relacionamento de
inclusão é representado pela chamada do outro UID. Sua representação, assim como dos
outros relacionamentos, é parecida com a representação include da UML [Booch 98]. É
representada por uma dependência estereotipada com o rótulo adequado.
Parâmetro 1
...Parâmetro 1 (nome)
...CD (título, nome cantor, ano,preço, disponibilidade, capa, país,gênero, gravadora)
1
1..N (adicionar àcesta de compras)
Parâmetro 1: cantor ou gênero
25
Quando um UID é alternativo ou opcional, este será usado como extensão para
outros UIDs. Diferentemente do relacionamento de inclusão, um UID que extende outro
faz sentido sozinho e pode ser executado independentemente. Durante a especificação
de um UID, o relacionamento de extensão também pode ser representado através de
uma chamada ao outro UID. Durante a execução do UID que está sendo estendido, a
interação daquele UID será incluída no UID estendido quando for feita a chamada ao
outro UID.
Se um UID só pode ser executado se outro tiver sido executado com sucesso
anteriormente, então um relacionamento de precedência deverá existir entre os dois.
Durante a especificação de um UID, o relacionamento de precedência pode ser
representado através de uma pré-condição no UID que é precedido pelo outro.
Os atores que estão associados aos UIDs também podem ser especificados no
diagrama de relacionamentos entre os UIDs, criando-se uma associação entre um ator
em um UID.
2.6 UIDs no processo de softwareOs UIDs podem ser incorporados em um processo de desenvolvimento de
aplicações que em geral demandam intensa troca de informações e suporte à navegação.
Os UIDs podem ser aplicados em conjunto com outra técnica existente para levantar os
requisitos ou até mesmo substituí-la.
UID<nome do UID>
UID<nome do UID>
<<inclui>>
UID<nome do UID>
UID<nome do UID>
<<estende>>
UID<nome do UID>
UID<nome do UID>
<<precede>>
UID<nome do UID>
<nome do ator>
26
Durante algumas etapas de um método de desenvolvimento de aplicações os
UIDs podem ser utilizados. Esses UIDs são definidos durante o levantamento de
requisitos, a partir dos casos de uso, para auxiliar a representação da interação descrita
nestes casos de uso. Além disso, os UIDs servem como base para a especificação do
esquema conceitual e para definição do modelo de navegação, no caso de aplicações
hipermídia. Também podem comunicar os requisitos da aplicação ao projetista da
interface com o usuário. A figura 2.15 apresenta as etapas de um método de
desenvolvimento de aplicações hipermídia onde os UIDs são utilizados.
Em [Vilain 00] são apresentadas diretrizes para mapear um caso de uso para um
UID. Após a conclusão dessa etapa, ambos devem ser validados pelo usuário, cabendo
ao projetista mostrar-lhe cada caso de uso e seu respectivo UID para verificar se o
usuário concorda com eles. Também são apresentadas diretrizes para determinar um
diagrama de classes preliminar usando como base os UIDs definidos durante o
levantamento de requisitos.
Figura 2.15 Levantamento de requisitos com UIDs em um processo de
desenvolvimento de aplicações hirpermídia
2.7 Exemplo de UID A figura 2.16 apresenta um UID completo definido para representar a interação
entre um usuário e o sistema durante a operação de Saque em um caixa eletrônico. O
caso de uso que descreve tal operação está descrito abaixo.
Como pode-se observar, esse caso de uso não é de difícil entendimento para
quem lê, o que não justificaria de certo modo a criação de um UID. Porém, em certas
ocasiões, onde os casos de uso são extensos e com bastante troca de informações, ele
facilita a compreensão e pode evitar ambigüidades nos casos de uso.
Levantamentode Requisitos
ProjetoConceitual
Projeto deInterface
Projeto deNavegação
Implementação
27
Caso de Uso: Saque em caixa eletrônico
1. O cliente insere o cartão magnético no leitor do caixa eletrônico.
2. O sistema solicita que seja fornecida a senha de autenticação.
3. O cliente fornece a senha.
4. O sistema realiza uma validação e exibe uma lista de operações possíveis (saque,
extrato, saldo, transferência, outras operações) para o cliente.
5. O cliente seleciona a operação de "Saque".
6. O sistema pede para o usuário entrar com o valor a ser sacado.
7. O cliente fornece o valor a ser sacado.
8. O sistema pede para o cliente confirmar a operação.
9. O cliente confirma.
10. O sistema verifica se o cliente tem saldo suficiente e debita na conta do usuário.
Informa que o saque foi realizado com sucesso e pede para o usuário retirar seu
dinheiro.
11. O cliente retira o dinheiro fornecido.
12. O sistema detecta que o dinheiro foi retirado e informa que a operação foi
concluída com sucesso.
28
Figura 2.16 UID Saque em caixa eletrônico
identificador
senha
[senha correta][senha incorreta]
Senha incorreta,operação cancelada
valor
(confirma operação) [saldo suficiente]
Saque efetuadocom sucesso, retire
seu dinheiro
Insira o cartão
Entre com a senha
...Operação(saque, extrato,saldo, transferência, outras
operações)
1Entre com o valor
Operação concluídacom sucesso
[retirou o dinheiro]
29
3 UNIFIED PROCESS Um processo de desenvolvimento de software define quem faz o quê, quando e
como, para se chegar à construção de um produto de software ou melhorar um já
existente. Um processo efetivo guia o desenvolvedor para a produção de software de
qualidade, apresentando as melhores práticas para isto. Em consequência, ele reduz o
risco e aumenta a previsibilidade.
O processo guia todos os participantes: clientes, usuários, desenvolvedores e
gerentes administrativos. A designação de atividades aos participantes não será descrita
neste trabalho, pois são poucos os envolvidos e a equipe de desenvolvimento é
composta apenas pelos dois autores deste trabalho.
O Unified Process [Jacobson 99] foi o processo escolhido para o
desenvolvimento deste trabalho. Isto se deve ao fato deste ser um processo bem atual e
ser o produto final de três décadas de desenvolvimento e uso prático. O seu
desenvolvimento foi influenciado por muitos outros processos, como o Objectory
Process (1987), por exemplo.
O Unified Process se mostrou complexo demais para o domínio de problema
aqui tratado, sendo que vários de seus artefatos não foram produzidos e algumas
atividades não foram feitas. Entretanto, as principais tarefas (core workflows) e
iterações foram feitas.
A UML [Booch 98] é usada nos modelos do Unified Process. Esta linguagem
surgiu da necessidade de uma linguagem visual uniforme e consistente para expressar os
resultados de inúmeras metodologias do paradigma de orientação a objeto.
A tendência atual é a produção de software cada vez mais complexo, pois os
usuários têm expectativas cada vez maiores em relação a sistemas computacionais,
acompanhado do grande crescimento do poder computacional nos últimos anos.
Para se chegar a um produto de software que cumpra os numerosos requisitos
dos usuários e que seja produzido rapidamente, os desenvolvedores precisam ter seu
trabalho organizado. A organização é alcançada com a definição das atividades dos
desenvolvedores, atribuição de tarefas a indivíduos e ao time como um todo, definição
de quais artefatos devem ser produzidos e critérios para monitoração e avaliação do
trabalho feito.
O Unified Process é baseado em componentes, mas o seu destaque está em três
aspectos: dirigido por casos de uso, centrado na arquitetura, iterativo e incremental.
30
3.1 Dirigido por casos de uso Um sistema de software é construído a partir das necessidades dos usuários.
Usuários humanos ou sistemas externos são os atores que interagem com o sistema. Um
caso de uso descreve os eventos envolvidos em um caso de utilização do sistema por um
ou mais atores. Casos de uso capturam, textualmente, os requisitos funcionais do
sistema.
No Unified Process, casos de uso não são apenas uma ferramenta para
especificação dos requisitos do sistema. As atividades do processo, como análise,
projeto e teste, são executadas iniciando-se pelos casos de uso. Por causa disto, o
Unified Process é dito ser dirigido por casos de uso.
3.2 Centrado na arquitetura A arquitetura de um sistema de software pode ser descrita como várias visões do
sistema sendo construído. Ela compreende os aspectos estáticos e dinâmicos mais
significativos do sistema.
A arquitetura cresce das necessidades dos usuários e clientes, como refletida nos
casos de uso. No entanto, é influenciada por outros fatores:
• Plataforma de software (arquitetura de hardware, sistema operacional, sistemas
gerenciadores de banco de dados, protocolos de comunicação);
• Blocos reusáveis de construção (frameworks);
• Sistemas legados;
• Requisitos não funcionais (performance, confiabilidade, etc).
A relação entre casos de uso e arquitetura vem do fato que um produto necessita
de forma e função. A função corresponde aos casos de uso e a forma corresponde à
arquitetura. Os casos de uso, quando realizados em termos de artefatos de análise e
projeto, devem se encaixar na arquitetura. E a arquitetura deve deixar espaço para
realização de todos os casos de uso existentes e que podem ser requisitados no futuro.
Para se chegar à forma (ou arquitetura), os arquitetos devem trabalhar a partir do
entendimento geral das funções mais importantes: os casos de uso chave. Os casos de
uso chave, apesar de constituírem de 5 a 10% de todos os casos, são os mais
significativos e constituem as funcionalidades do núcleo o sistema (core functions).
31
Nas visões do sistema, descritas na arquitetura, as características mais
significantes são destacadas, deixando os detalhes de lado. Escolher o que é mais
significante em um sistema depende do julgamento do desenvolvedor, que vem de sua
experiência.
3.3 Iterativo e incremental É prático dividir o trabalho de desenvolvimento em pedaços menores ou mini-
projetos. Cada mini-projeto é uma iteração que resulta em um incremento. Iterações se
referem aos passos em cada fluxo de trabalho e incrementos se referem ao crescimento
no produto resultante de cada iteração. As iterações devem ser controladas, selecionadas
e executadas de uma maneira planejada.
Dois fatores são levados em conta na escolha do que implementar em uma
iteração:
• A iteração lida com um grupo de casos de uso que junto estendem a usabilidade
do produto desenvolvido até o momento;
• A iteração lida com os riscos mais importantes, que ainda não foram resolvidos.
Iterações sucessivas se constroem a partir do estado dos artefatos de
desenvolvimento resultantes da iteração anterior. Em cada iteração, os desenvolvedores
identificam e especificam os casos de uso relevantes e, então, seguem com a análise,
projeto, implementação e teste, dirigidos por estes casos.
As três características: direcionamento por casos de uso, centrado na arquitetura
e iterativo e incremental são igualmente importantes. A arquitetura providencia a
estrutura na qual guiar o trabalho das iterações e os casos de uso definem as metas e
guiam o trabalho em cada iteração. A remoção de qualquer dos três aspectos reduziria o
valor do Unified Process.
3.4 Ciclo de vida no Unified Process O Unified Process repete-se por vários ciclos, que constituem a vida do sistema
(figura 3.1). Cada ciclo corre sobre o tempo e termina com o lançamento de uma versão
do produto para os clientes. Cada ciclo consiste de quatro fases: incepção, elaboração,
construção e transição. Cada fase, por sua vez, pode ser sub-dividida em iterações, que
32
foram discutidas anteriormente. Uma iteração típica, passa por todas as cinco
atividades: requisitos, análise, projeto, implementação e teste.
Figura 3.1 A vida do Unified Process consiste de ciclos
A figura 3.2 esquematiza um ciclo. Pode-se ver a divisão do ciclo em fases, as
quais podem ser sub-divididas em uma ou mais iterações. As atividades (core
workflows) estão listadas na primeira coluna. As curvas do gráfico aproximam a
quantidade de tempo que o workflow é trabalhado em cada fase. Por exemplo, na
primeira iteração da fase de incepção, o trabalho concentra-se apenas no levantamento
de requisitos. Já na fase de elaboração, todos os workflows são seguidos.
Figura 3.2 Os cinco workflows se encaixam nas quatro fases
Tempo
Nascimento Morte
Ciclos concluídos com lançamentosde versões do produto
33
Durante a fase de incepção, uma visão do produto final é alcançada. Nesta fase,
é feita a descoberta do que o sistema fará para cada um de seus principais usuários. Uma
visão geral da arquitetura do sistema também é alcançada, podendo-se ter uma idéia de
quanto vai custar o desenvolvimento do produto.
Na fase de elaboração, a maioria dos casos de uso são detalhados e a arquitetura
é projetada. A arquitetura é expressa como visões de todos os modelos do sistema, que
em conjunto representam o sistema como um todo. Nesta fase, os casos de uso mais
críticos são realizados nos modelos de análise e projeto, dando condições à pessoa
responsável pelo projeto planejar as atividades e estimar os recursos requeridos para
completá-lo.
Durante a fase de construção, o produto é construído ao redor da arquitetura, que
é o esqueleto do sistema. A maior parte dos recursos do projeto são usados nesta fase,
resultando em um produto pronto para ser transferido aos usuários. A arquitetura nesta
fase está estável, mas não livre de defeitos, que serão consertados na fase de transição.
A fase de transição cobre o período onde o produto chega em uma versão beta.
Nesta fase, alguns usuários experimentam o produto e comunicam defeitos. Estes
defeitos são consertados e melhorias são feitas, resultando numa versão adequada para
todos os usuários. Esta fase também envolve atividades como treinamento, assistência
de usuários e conserto de defeitos encontrados após a entrega do produto final.
34
4 GRAPH EDITING FRAMEWORKO Graph Editing Framework (GEF) é um framework para criação de editores de
grafos e diagramas, como no exemplo da figura 4.1, constituindo-se de uma biblioteca
de classes escrita na linguagem Java. Um framework nada mais é do que uma estrutura
de classes inter-relacionadas que corresponde a uma implementação incompleta para um
conjunto de programas aplicativos de um domínio. Esta estrutura de classes deve ser
adaptada para geração de aplicações específicas [SILVA 00].
O objetivo do GEF é facilitar a criação de programas aplicativos envolvendo a
edição de diagramas e grafos conexos. O GEF sozinho não é um editor, ele apenas
suporta a criação de programas de desenho específicos.
Programas escritos na linguagem Java geralmente utilizam a biblioteca de
interface gráfica Swing, que inclui componentes para janelas, botões, menus, tabelas e
árvores. Mas não há suporte para edição de diagramas e grafos.
Figura 4.1 Exemplo de programa aplicativo usando o GEF
O GEF foi idealizado por um pesquisador da Universidade da Califórnia, Irvine
(UCI), EUA, para ser um produto com código fonte livre. É atualmente mantido por um
35
time virtual de desenvolvedores na Internet. A página na Internet1 deste framework
contém documentação, arquivos do programa, lista de discussão e oferece a
possibilidade de outras pessoas contribuírem com o projeto.
O conteúdo deste capítulo é resultado de nossa pesquisa sobre a viabilidade do
uso das classes deste framework para construção da ferramenta de edição de UIDs.
Chegou-se a conclusão de que o framework é adequado, pois ele pode atender todos os
requisitos desta ferramenta. Neste capítulo, apenas são mostrados os principais
características da implementação do framework. Os detalhes do seu uso, para o
cumprimento dos requisitos, é mostrado nos resultados das etapas de projeto (seção 5.3
e 5.6).
4.1 Características Este framework tem um projeto simples, sendo fácil de entender e estender. Os
grafos são modelados com nodos, portas e arcos, suportando a maioria das aplicações
com grafos conexos. Este modelo (figura 4.2) é mais flexível do que um modelo com
apenas nodos e arcos.
Figura 4.2 Exemplo de grafo com nodos, portas e arcos
Como qualidades do GEF, pode-se destacar:
• Simplicidade: fácil para desenvolvedores aprenderem e usarem.
• Usabilidade: interface gráfica simples para usuários finais.
• Adaptabilidade: adaptável a uma ampla variedade de aplicações.
• Escalabilidade: eficiente para diagramas com até mil elementos.
1 http://gef.tigris.org/
Nodo
PortasArco
36
Como principais objetivos do GEF, pode-se destacar:
• Dar suporte à edição de grafos conexos, usando um modelo de grafos
altamente flexível.
• Dar suporte à edição de gráficos não estruturados (círculos, retângulos,
linhas, etc.)
• Promover facilidade de uso para o usuário final.
• Dar suporte a múltiplas visões, de forma que grafos complexos possam
ser visualizados de formas diferentes.
• Promover fácil integração com código de aplicações já existentes, ou
seja, o GEF pode ser usado como camada gráfica para suas aplicações já
escritas.
Há relatos positivos de pessoas que utilizaram o GEF em projetos pequenos e
médios. Pode-se citar o Poseidon for UML2 como um projeto grande que usa este
framework.
4.2 Pacotes e principais classesNo GEF os grafos são representados em dois níveis: o nível de rede e o nível de
diagrama. No nível de rede há nodos que contém o comportamento e dados das
aplicações. No nível de diagrama há figuras (classe Fig) que representam visualmente
os objetos do nível de rede.
As classes do framework (cerca de 240) estão divididas em vários pacotes
(Figura 4.3). Há exemplos de classes do nível de rede no pacote
org.tigris.gef.graph.presentation, mas uma aplicação real usaria suas próprias classes
para o nível de rede. As classes do nível de representação são classes de figuras, que
estão no pacote org.tigris.gef.presentation. As classes relativas à edição das figuras e
dos objetos que estas figuras representam estão no pacote org.tigris.gef.base.
2 http://www.gentleware.com/
37
Figura 4.3 Diagrama de pacotes do GEF
A seguir os principais pacotes e suas principais classes, referentes à versão 0.9.6
do produto, serão descritos.
4.2.1 Pacote org.tigris.gef.base
A maior parte do código do framework está neste pacote. Inclui a maioria das
principais classes, que são relacionadas somente à edição de diagramas: Editor, Cmd,
Mode, Selection, Layer, Guide e respectivas sub-classes.
Uma das características do GEF é de que novas funcionalidades podem ser
adicionadas sem que o framework tenha de ser modificado. Esta característica tem
grande impacto no seu projeto. Um projeto pouco elaborado envolveria uma classe
Editor extensa, provendo grande funcionalidade, podendo ser estendida por sub-classes.
Mas ela foi projetada de outra maneira. Ela coordena outros objetos que fazem o
trabalho, passando eventos e mensagens. Esses outros objetos fazem o trabalho de
38
desenhar gráficos, processar eventos de entrada de usuário, determinar qual item o
usuário selecionou, etc.
4.2.1.1 Classe Editor
Esta classe providencia um editor para manipular documentos gráficos. Editor é
a classe central do framework, mas não contém muito código. Sua implementação é
pequena pois todos os modelos do nível de rede, objetos gráficos, camadas, modos de
edição, comandos de edição e componentes de suporte são implementados em suas
próprias classes.
Na figura 4.4, pode-se ver um Editor com sua própria janela (classe
org.tigris.gef.graph.presentation.JGraphFrame), mostrando um LayerGrid e
nenhuma figura (classe Fig). Um Editor também pode aparecer em uma janela de um
navegador Web, na forma de um Applet. Neste caso, toda a funcionalidade do
framework está disponível, com exceção da gravação de arquivos.
Figura 4.4 Um Editor em sua própria janela
O Editor mantém uma referência a um objeto genérico, o documento gráfico
com o qual o usuário está trabalhando no editor. Este objeto é genérico, pois o
framework não define que tipo de documento é este.
Outros atributos importantes que um Editor tem são: um LayerManager, um
SelectionManager e um ModeManager, todos instâncias de classes do pacote
org.tigris.gef.base.
LayerManager é o gerenciador da pilha de camadas do Editor (veja classe Layer,
seção 4.2.1.3). Camadas contém e são responsáveis por desenhar figuras e estas figuras
podem estar associadas a primitivas do nível de rede (NetPrimitive), como nodos, portas
ou arcos.
39
SelectionManager é o gerenciador de seleções, que guarda objetos de seleção
(classe Selection) referentes a figuras ou conjuntos de figuras que são selecionados no
Editor.
O comportamento do Editor é determinado pelo seu modo atual (veja classe
Mode, seção 4.2.1.4). O ModeManager de um Editor fica a par de todos os modos
ativos. Modos interpretam eventos de entrada e decidem como modificar o estado do
diagrama.
Uma função importante do Editor é dar acesso às figuras que são desenhadas
pelas suas camadas. Por exemplo, o Editor possibilita a remoção da figura que o usuário
está apontando com o mouse.
O Editor tem também a tarefa de executar comandos (classe Cmd), que são
criados em resposta a certos eventos. Os comandos são executados pelo Editor em um
ambiente seguro, de forma que ações mal implementadas não afetem todo o Editor.
4.2.1.2 Classe Cmd
Comandos modificam o documento ou o ambiente de edição de alguma forma,
por exemplo, deletar uma figura (CmdDelete), salvar um documento (CmdSave) ou
modificar o modo do editor (CmdSetMode). Comandos deveriam guardar informação
suficiente para se desfazerem, mas isto ainda não é suportado na versão atual.
O editor serve como um "shell" para executar ações de forma similar como uma
"shell" de comandos DOS ou UNIX serve para executar programas. Cada comando
pode ter uma tabela de argumentos e também pode consultar variáveis globais (seu
ambiente). Assim que um comando é instanciado, uma mensagem doIt() pode ser
enviada para que este execute sua ação.
Cmd é uma classe abstrata para todos os comandos do editor. A classe abstrata
Cmd não implementa o método doIt(). As subclasses de Cmd devem implementar este
método para executar a ação necessária no editor. Basicamente, as atuais 45 subclasses
de Cmd apenas implementam o método doIt().
Alguns comandos importantes são os comandos de salvamento. Estes dão
suporte para gravação dos diagramas em arquivos no formato PGML (Precision
Graphics Markup Language) e SVG (Scalable Vector Graphics), ambos baseados na
linguagem XML, sendo o PGML um formato já obsoleto. O SVG é uma recomendação
atual da World Wide Web Consortium W3C e sua especificação pode ser obtida no
40
site oficial do W3C3. Os diagramas também podem ser exportados como imagens nos
formatos GIF e PostScript.
4.2.1.3 Classe Layer
Uma camada é como uma folha de plástico transparente que contém parte da
figura sendo desenhada. Múltiplas camadas colocadas uma em cima da outra formam a
figura completa. Diferentes camadas podem ser ocultadas, travadas ou acinzentadas
independentemente.
No GEF, a classe Layer é mais abstrata do que o descrito acima. LayerDiagram é
uma subclasse de Layer que faz o que foi descrito acima. Outras subclasses de Layer
podem prover funcionalidade. Por exemplo, o "grid" que aparece no fundo da tela da
figura 4.5 é uma subclasse de Layer que computa sua própria visualização, ao invés de
apresentar o que está armazenado em uma estrutura de dados.
Figura 4.5 Um editor e seu LayerManager com 2 camadas: um LayerGrid
desenhando o fundo de tela e um LayerDiagram contendo 2 figuras e mantendo a
ordenação de trás para frente.
Na figura 4.6 é apresentado o diagrama de classes de camadas. Como subclasses
importantes da classe abstrata Layer, pode-se citar:
• LayerGrid desenha um fundo de tela que serve como guia, consistindo de linhas
horizontais e verticais e uma cor neutra (veja figura 4.4).
• LayerPageBreaks é similar a LayerGrid, desenhando linhas representando
quebras de página, útil quando se está editando um diagrama a ser impresso.
• LayerDiagram é um tipo de camada que contém uma coleção de figuras (classe
Fig), ordenadas de trás para frente, como em muitos outros programas de
3 http://www.w3.org/
41
desenho. Cada figura tem seu nível dentro desta camada. Quando uma nova
figura é adicionada, o número de níveis incrementa e a figura é colocada no
último nível.
• LayerPerspective é uma especialização de LayerDiagram, que assume que um
grafo conexo está sendo editado, sendo este grafo representado por um
GraphModel (seção 4.2.2) e controlado por um GraphController (seção 4.2.2).
Figura 4.6 Camadas
Como já foi dito, um editor tem como atributo um LayerManager, que guarda a
coleção de camadas do editor. Este gerenciador, entre outras coisas, facilita o desenho
da visão completa de suas camadas, uma sobreposta a outra. Quando um editor é criado,
seu LayerManager é criado inicialmente com um LayerGrid e um LayerPageBreaks,
que funcionam como o fundo de tela do editor. Também é adicionada uma camada de
figuras, como por exemplo um LayerDiagram ou um LayerPerspective.
4.2.1.4 Classe Mode
Modos no GEF são objetos que definem um contexto para interpretação de
eventos de entrada gerados pelo usuário. Por exemplo, um objeto ModePopup abre um
menu de opções caso um evento de clique do botão direito do mouse for gerado. Modos
podem instanciar comandos para serem executados no editor.
42
Como dito anteriormente, um editor possui um ModeManager, o qual mantém
uma lista dos modos ativos do editor. O último modo adicionado a este gerenciador é o
que têm prioridade. Um editor pode ter mais de um modo interpretando entrada de
usuário, pois apenas um modo não cobre todas as possibilidades.
Dentre as várias classes que implementam os modos do GEF, as principais são:
ModeSelect, ModeModify e ModeCreate.
• ModeSelect interpreta entrada de usuário quando uma ou mais figuras são
selecionadas. Clicar em uma figura irá selecioná-la. Shift + clique em uma
figura inverte a seleção. Arrastar o mouse em espaço aberto irá desenhar um
retângulo de seleção (veja figura 4.7). Arrastar uma figura fará com que o modo
de modificação seja chamado (ModeModify). Arrastar a partir de uma porta de
um nodo fará com o que o modo de criação de arco seja chamado
(ModeCreateEdge).
• ModeModify processa eventos quando o usuário está modificando uma figura.
Os eventos tratados são relativos ao arrastamento ou redimensionamento de
figuras.
• ModeCreate e suas várias subclasses tratam os eventos relacionados à criação
das várias formas de figuras, como círculos, retângulos, linhas, texto, etc. Cada
subclasse interpreta eventos de sua forma. Por exemplo, um modo de criação de
linha desenha uma linha a medida que se arrasta o mouse, enquanto um modo de
criação de círculo desenha um círculo.
Figura 4.7 ModeSelect desenhando um retângulo de seleção
43
4.2.1.5 Classe Selection
Seleções são objetos usados pelo Editor quando o usuário seleciona uma figura,
ou um grupo de figuras, da área de edição. Seleções são responsáveis por desenhar
"manipuladores" (handles), tratar eventos de arraste do mouse nos manipuladores e
passar mensagens às figuras selecionadas. Seleções também representam o alvo do
próximo comando. Na figura 4.5 há duas figuras selecionadas. Pode-se ver que as
seleções desenharam vários manipuladores na forma de pequenos quadrados.
Como pode-se ver no diagrama da figura 4.8, a classe Selection é abstrata, sendo
que suas subclasses implementam seleções de acordo com o tipo da figura selecionada.
Por exemplo, se for possível que uma figura seja movida e redimensionada, um objeto
SelectionResize (subclasse de Selection) será criado para esta seleção. Pode-se
selecionar múltiplas figuras no editor, sendo que para cada figura é criado um objeto de
seleção específico. O editor mantém um SelectionManager, que tem a função de
gerenciar a coleção de seleções atual. Por exemplo, se foi pressionada uma tecla de
movimentação, o SelectionManager avisa todas as seleções que estas devem se mover.
Figura 4.8 Seleções
4.2.2 Pacote org.tigris.gef.graph
Neste pacote há classes de interface a serem usadas para se representar grafos
conexos. Também há classes exemplificando a implementação destas interfaces. A
figura 4.9 mostra um diagrama com as classes deste pacote.
Como foi dito, o GEF pode ser usado para representar e editar graficamente
objetos de aplicações já existentes. Para isto, o desenvolvedor que deseja usar o GEF
para criar um editor de diagramas deve definir um modelo para o grafo de sua aplicação.
Este modelo é uma classe que implementa a interface GraphModel, de forma a dar
acesso aos dados da aplicações para, por exemplo, interfaces de usuário. Os dados não
44
ficam fora de sincronia, pois somente os objetos da aplicação guardam os dados e
interfaces de usuário acessam estes dados somente por meio do modelo.
Figura 4.9 Interfaces para representar grafos
A interface GraphModel é uma fachada para os objetos do nível de rede, ou seja,
é uma coleção de métodos que permitem consulta aos componentes do grafo, como
nodos e arcos. Exemplos de representação em nível de rede são as classes NetList,
NetNode, NetEdge e NetPort, descritas na seção 4.2.3.
A interface GraphModel é estendida pela interface MutableGraphModel, que
possibilita a modificação do grafo e não somente acesso. MutableGraphSupport é uma
classe abstrata que facilita ao desenvolvedor criar sua implementação do
MutableGraphModel, pois já fornece implementações genéricas para os métodos mais
comuns.
Algumas outras interfaces estão presentes neste pacote: GraphNodeHooks,
GraphEdgeHooks e GraphPortHooks são interfaces que objetos do nível de rede podem
implementar caso queiram executar ações específicas após conexão ou desconexão de
nodos ou queiram impor restrições sobre a conexão de nodos
45
GraphEvent e MutableGraphEvent são notificações de que um grafo sofreu
mudanças. Para uma classe reagir a estas notificações, deve implementar a interface
GraphListener.
4.2.3 Pacote org.tigris.gef.graph.presentation
Neste pacote há classes que implementam as interfaces do pacote
org.tigris.gef.graph. Esta implementação é um exemplo genérico, que pode ser usado
por algumas aplicações, mas não é adequada para todas. A classe DefaultGraphModel
deste pacote é uma implementação genérica de um grafo, sendo as classes NetNode,
NetEdge e NetPort os componentes do grafo (figura 4.10).
Também está presente neste pacote o JGraph: um componente de interface
gráfica que usa a classe Editor e muitas outras para apresentar grafos conexos e
possibilitar sua edição interativa.
Figura 4.10 Primitivas do nível de rede
4.2.4 Pacote org.tigris.gef.presentation
Este pacote contém classes definindo vários tipos de figuras usadas no editor
para apresentar graficamente grafos e outros objetos.
Fazem parte deste pacote a classe Fig e suas muitas subclasses, que representam
objetos de desenho básicos, como retângulos, linhas, textos, círculos, polígonos, etc.
Objetos da classe Fig podem ser mostrados por uma camada do tipo LayerDiagram e
manipulados a partir de um Editor.
Os atributos básicos de uma figura são posição (coordenadas x e y), largura,
altura, cor de preenchimento e cor de linha, entre outros. As subclasses de Fig (Figura
4.11) adicionam muitos outros atributos.
46
Figura 4.11 Figuras
Figuras têm a responsabilidade de tratar eventos de edição (remoção de um
vértice de um polígono, por exemplo) e notificar seus dependentes de mudanças de
estado.
Figuras podem ser usadas para definirem a aparência de nodos, arcos ou portas
da camada de rede. Para isso, a figura mantém uma referência para seu proprietário, o
objeto o qual representa. Figuras que representam nodos de um grafo devem ser da
classe FigNode. FigNode é uma subclasse de FigGroup, que representa uma
composição de figuras. Desta forma, um nodo pode ser representado por um conjunto
de figuras. Figuras que representam arcos de um grafo devem ser da classe FigEdge.
Qualquer figura pode representar uma porta. Na Figura 4.12 pode-se ver três nodos.
Estes nodos são representados por composições de figuras: um quadrado com fundo
branco, um círculo grande e pequenos círculos para portas.
47
Figura 4.12 Figuras representando primitivas do nível de rede
48
5 ATIVIDADES E RESULTADOS Este capítulo descreve a etapa de levantamento de requisitos e duas iterações,
incluindo análise, projeto e implementação, que foram executadas. Os testes foram
realizados juntamente com a implementação e não são documentados.
O levantamento de requisitos foi a primeira atividade. No Unified Process é feita
uma etapa de levantamento de requisitos em cada iteração. No entanto, neste trabalho
foi feito um levantamento extensivo inicial, o qual capturou a maior parte dos
requisitos. À medida que a análise e projeto foram feitos, os requisitos foram sendo
atualizados e estendidos.
O processo de desenvolvimento que adotamos é baseado no processo descrito no
capítulo 3. É dirigido por casos de uso, pois cada um dos casos de uso elaborados no
levantamento de requisitos é realizado primeiramente com artefatos de análise e, depois,
com artefatos de projeto. É um processo iterativo e incremental, pois foram feitas
iterações, cada uma sobre um conjunto de casos de uso. Cada iteração incrementa a
funcionalidade do sistema.
A figura 5.1 mostra a seqüência ao longo do tempo das tarefas executadas.
Como foi dito, os requisitos foram capturados inicialmente e modificados ao longo das
iterações. Os testes não foram documentados aqui e foram executados juntamente com a
implementação.
Figura 5.1 Seqüência de tarefas ao longo do tempo
O resultado final do levantamento de requisitos é apresentado na próxima seção.
Na seção 5.1.5, é descrita a alocação dos casos de uso em cada iteração. Em seguida, as
duas iterações são descritas. Na primeira iteração, uma descrição do que é análise e
projeto é feita, juntamente com os resultados. Na segunda iteração, somente os
resultados são apresentados.
AnáliseProjeto Impl.
e testes
Requisitos
Análise ProjetoImpl.
e testes
1ª Iteração
2ª Iteração
49
5.1 Levantamento de requisitos O levantamento de requisitos é uma tarefa que define o que deve ser construído.
Seu propósito é direcionar o desenvolvimento de um sistema correto. Isto se alcança
com uma descrição dos requisitos do sistema de forma que seja suficiente para um
acordo entre os clientes ou usuários e os desenvolvedores sobre o que o sistema deve ou
não fazer. A linguagem do cliente ou usuário deve ser usada nesta descrição.
5.1.1 Contexto do sistema
Cada projeto de software é único e há diferentes pontos de partida para a captura
de requisitos. O analista deve ser capaz de adaptar seu método de captura para cada
situação. Neste trabalho optou-se por iniciar entendendo o contexto do sistema. Para isto
foi escrito um texto (próxima seção) sobre a visão que o usuário tem do sistema final.
Este texto apresenta simples descrições das funcionalidades que o usuário imagina que o
sistema deve ter. Cabe ressaltar que os autores deste trabalho fazem tanto o papel de
usuário como de analista.
5.1.1.1 Visão geral
No editor de UIDs trabalha-se com um projeto de UIDs, o qual consiste de
várias áreas de edição destes UIDs e, opcionalmente, áreas de edição de diagramas de
relacionamentos (DR).
O projeto de UIDs, com suas várias áreas de edição, é tratado como uma única
entidade e apenas um projeto pode estar sendo editado no programa em um determinado
momento. O projeto como um todo pode ser gravado como um arquivo único e
posteriormente recuperado. O conteúdo individual de uma área de edição pode ser
exportado para um arquivo de imagem. O projeto ainda pode ser impresso em folhas de
papel.
Dentro das áreas de edição de UIDs, o usuário insere estados e transições entre
estes estados. Dentro dos estados, informações de saída de sistema ou de entrada de
usuário podem ser inseridas. Notas textuais e condições são inseridas fora de estados. À
medida que UIDs estão sendo criados pelo usuário, o projeto mantém uma lista
atualizada destes, que então podem ser adicionados ao DR. Pode-se criar
relacionamentos e associações entre os UIDs no DR.
50
O editor deve ser flexível e possibilitar a modificação de qualquer das
informações já inseridas. Os estados podem ser movimentados pela área de edição,
sendo que as informações dentro do estado e as suas transições se movem de acordo. As
informações podem ser modificadas e removidas.
5.1.1.2 Modelo do domínio
No Unified Process, o contexto do sistema pode ser expresso de uma forma mais
usável como um modelo de domínio ou um modelo de negócio. Neste trabalho optou-se
pelo modelo de domínio, pois o modelo de negócio é aplicável a sistemas que dão
suporte a negócios de uma organização.
O modelo de domínio (figura 5.2) descreve conceitos importantes do contexto
como objetos de domínio, que são interligados por associações e organizados em um
diagrama de classes da UML. Os objetos de domínio representam as coisas ou eventos
do ambiente que o sistema trabalha.
Este modelo de domínio apresenta de maneira simples os conceitos do diagrama
de interação do usuário, que foram descritos em detalhe no capítulo 2.
O conceito de projeto é introduzido aqui como uma entidade que reúne vários
diagramas. O diagrama de relacionamentos é parte do projeto e contém atores e
relacionamentos. Neste diagrama pode-se editar as associações entre atores e UIDs, e os
tipos de relacionamentos entre UIDs.
Os UIDs contém estados, transições entre os estados e anexos. Anexos são na
forma de notas textuais, pré e pós-condições. Um estado contém uma coleção de
informações trocadas, na forma de entradas de usuário e saídas de sistema.
Pode haver transições com origem em estados ou com origem em saídas de
sistema. Uma transição pode ter origem em uma saída de sistema quando esta saída
apresenta um conjunto de dados. Ou melhor, uma transição pode ter origem em várias
saídas que apresentam conjuntos.
51
Figura 5.2 Modelo de domínio
As classes apresentadas no modelo acima são úteis na descrição dos casos de uso
e servem como sugestão para classes internas desenvolvidas durante as atividades de
análise.
5.1.2 Lista de funcionalidades
Durante o levantamento de requisitos, idéias do que o sistema poderia fazer
foram anotadas e são apresentadas abaixo. Estas idéias são uma lista de funcionalidades
ou requisitos candidatos, que é mantida atualizada durante todo o processo, como forma
de planejamento de trabalho.
Esta lista representa todas as idéias que apareceram até o momento e como são
em pequena quantidade, foram aprovadas e alocadas para as primeiras iterações do
52
processo. A classificação por prioridades serve para se decidir em quais iterações as
funcionalidades serão implementadas.
5.1.2.1 Prioridade alta
• Edição dos UIDs com os seguintes componentes: item de dado, estrutura,
conjunto, dado opcional, entrada do usuário, entrada do usuário enumerada,
saída do sistema, texto, estado, estado inicial, sub-estados, chamada para outro
UID, chamada a partir de outro UID, transição, pré-condição, pós-condição,
notas textuais e parâmetros.
• Modificação do conteúdo dos componentes.
• Renomeação e remoção de componentes.
• Movimentação individual ou em grupo de componentes em uma área de edição.
• Edição de vários diagramas: ambiente com possibilidade de se editar vários
diagramas (UIDs) de um projeto ao mesmo tempo.
5.1.2.2 Prioridade média
• Edição do diagrama de relacionamentos.
• Salvamento e recuperação dos diagramas.
• Exportação dos diagramas para arquivos de imagem.
• Desfazer/Refazer última ação: ações como inserção, renomeação e remoção
podem ser desfeitas e refeitas.
5.1.2.3 Prioridade baixa
• Copiar, recortar e colar figuras.
• Redimensionamento do tamanho da imagem (zoom).
• Impressão.
• Vizualização e configuração de impressão.
• Localização de componentes por nome.
• Formatação de fontes e espessura de linhas.
53
5.1.3 Requisitos funcionais
5.1.3.1 Lista de requisitos
Cada funcionalidade originou um ou mais requisitos funcionais descritos a
seguir. Os requisitos funcionais são melhor capturados pelos casos de uso (seção
4.1.3.2.3), mas estes ficariam muito extensos e numerosos se capturassem todos os
requisitos da sintaxe do UID. Assim, foi definida a lista de requisitos que serve de
referência para a criação de alguns casos de uso. Esta lista também serve de referência
para as atividades de projeto e implementação.
Esta lista de requisitos cobre tudo que o sistema deve fazer, obedecendo a
sintaxe do UID, na forma de O sistema deve ... . São classificados em três categorias:
edição de um UID, edição do diagrama de relacionamentos e ambiente de edição em
geral.
5.1.3.1.1 Edição de um UID
R1.1 Em uma área de edição de UID, o sistema deverá possibilitar a inserção de
estados em branco ou chamadas para outros UIDs.
R1.2 Em um estado, o sistema deverá possibilitar a inserção de estados em branco
(sub-estado).
Em um estado, o sistema deverá possibilitar a inserção das seguintes saídas de
sistema:
R1.3 item de dado, opcionalmente com seu domínio, podendo o domínio ser
enumerado;
R1.4 estrutura, opcionalmente com a coleção de informações desta: itens de dado ou
outras estruturas;
R1.5 conjunto de itens de dados ou de estruturas, juntamente com sua multiplicidade;
R1.6 texto.
R1.7 O sistema deverá possibilitar a declaração das saídas de sistema item de dado ,
estrutura e conjunto como opcionais e/ou parametrizadas, tendo o usuário
capacidade de enumerar os parâmetros.
54
R1.8 O sistema deverá possibilitar a declaração da saída de sistema texto como
opcional.
Em um estado, o sistema deverá possibilitar a inserção das seguintes entradas de
usuário, que podem ser declaradas como opcionais e/ou parametrizadas, tendo o
usuário a capacidade de enumerar os parâmetros:
R1.9 item de dado, opcionalmente com seu domínio;
R1.10 estrutura, opcionalmente com a coleção de informações desta: itens de dado ou
outras estruturas;
R1.11 conjunto de itens de dados ou de estruturas, juntamente com sua multiplicidade;
R1.12 entrada enumerada, especificando a lista de opções e a quantidade que deve ser
selecionada.
R1.13 A partir de um estado, ou de um sub-estado, o sistema deverá possibilitar a
criação de uma transição sem rótulo, ou com condição e/ou seleção de opção,
sendo o destino um estado qualquer, que pode ser o de origem, ou uma chamada
de outro UID.
R1.14 A partir de uma chamada de outro UID, o sistema deverá possibilitar a criação
de uma transição sem rótulo, sendo o destino um estado qualquer.
R1.15 A partir de uma saída de sistema do tipo conjunto , o sistema deverá
possibilitar a criação de uma transição sem rótulo, ou com seleção de N
elementos e/ou seleção de opção e/ou com condição, sendo o destino um estado
qualquer, um estado de origem, ou uma outra transição saindo de outro conjunto
do mesmo estado.
R1.16 Em uma área de edição, o sistema deverá possibilitar a inserção de pré-
condições, pós-condições e notas textuais.
R1.17 O sistema deverá possibilitar a renomeação do UID, assim como a renomeação
dos componentes item de dado, estrutura e conjunto.
55
O sistema deverá possibilitar a modificação das seguintes informações dos
componentes:
R1.18 nome do UID em uma chamada de UID;
R1.19 domínio de um item de dado;
R1.20 conteúdo do domínio enumerado de um item de dado;
R1.21 conteúdo da coleção de informações de um estrutura;
R1.22 multiplicidade de um conjunto;
R1.23 se uma entrada de usuário ou saída de sistema é opcional e/ou parametrizada;
R1.24 lista de parâmetros de um componente parametrizado;
R1.25 lista de opções de uma entrada de usuário enumerada;
R1.26 número de opções a serem selecionadas de uma entrada de usuário enumerada;
R1.27 conteúdo de um componente de texto de um estado;
R1.28 se uma transição é explicitamente retornável ou explicitamente não retornável;
R1.29 nome da opção, especificação da condição ou número de elementos a serem
selecionados em uma transição;
R1.30 conteúdo de uma pré-condição, pós-condição ou nota textual.
R1.31 O sistema deverá possibilitar a remoção dos componentes estado, saída de
sistema, entrada de usuário, transição, pré-condição, pós-condição e nota
textual.
R1.32 A movimentação de um estado na área de edição de um UID deverá acarretar na
movimentação das transições e dos componentes contidos no estado, de forma a
manter a configuração original do UID.
5.1.3.1.2 Edição dos diagramas de relacionamentos
Em uma área de edição de um DR, o sistema deverá possibilitar:
R2.1 a criação de um relacionamento de inclusão, extensão ou precedência entre dois
UIDs;
R2.2 a modificação do tipo de um relacionamento existente;
R2.3 a remoção de um relacionamento;
R2.4 a inserção de atores, juntamente com o seu nome;
R2.5 a renomeação ou remoção de um ator;
R2.6 a remoção de uma associação.
56
R2.7 A partir de um UID, o sistema deverá possibilitar a criação de uma associação
com um ator.
R2.8 A movimentação de um UID ou um ator na área de edição de um DR deverá
acarretar na movimentação dos relacionamentos e associações conectados a
estes, de forma a manter a configuração original do diagrama.
5.1.3.1.4 Ambiente de edição
No ambiente de edição, o sistema deverá possibilitar:
R3.1 a edição de apenas um projeto (projeto aberto );
R3.2 a criação de um novo projeto de diagramas;
R3.3 o carregamento de um projeto salvo em disco;
R3.4 o fechamento de um projeto;
R3.5 o salvamento do projeto com seus diagramas nos formatos SVG e PGML.
Em um projeto, o sistema deverá possibilitar
R3.5 a criação de um novo UID;
R3.6 a renomeação de um UID;
R3.7 a remoção de um UID.
O sistema deverá:
R3.7 possibilitar o salvamento e recuperação de projetos a partir de arquivos;
R3.8 ser capaz de desfazer as últimas 20 ações, assim como refazer todas as ações
desfeitas;
R3.9 ser capaz de exportar o conteúdo de uma área de edição para um arquivo de
imagem;
R3.10 ser capaz de copiar, colar ou recortar notas textuais, pré-condições e pós-
condições na área de edição de um UID ou entre áreas deste tipo;
R3.11 ser capaz de copiar, colar ou recortar estados juntamente com seus componentes
na área de edição de um UID, ou entre áreas;
R3.12 possibilitar o redimensionamento da imagem (zoom) de uma área de edição;
R3.13 possibilitar a impressão do conteúdo de uma área de edição, ou de todas as áreas
do projeto, em uma folha de impressão;
57
R3.14 possibilitar a configuração do tamanho do papel, margens e orientação do papel
(retrato ou paisagem);
R3.15 possibilitar a visualização da impressão no tamanho de papel selecionado.
5.1.3.2 Casos de uso
Requisitos funcionais são naturalmente estruturados em casos de uso, pois faz
com que o analista pense nos termos de quem são os usuários e quais as tarefas
realizadas por estes. Os casos de uso são muito importantes no Unified Process, pois
direcionam o resto do processo.
Casos de uso são pedaços de funcionalidade que o sistema oferece a seus atores.
Nos casos de uso são especificadas as sequências de ações, incluindo alternativas da
sequência, que os atores podem executar, interagindo com o sistema.
Atores, por sua vez, são representações das atuações de usuários ou sistemas
externos, que interagem com o sistema.
Segundo o Unified Process, identificar atores e casos de uso é a atividade mais
crucial para se alcançar uma especificação correta dos requisitos. O único ator deste
sistema é descrito na próxima seção.
Antes de se fazer o detalhamento dos casos de uso, um modelo de casos de uso é
apresentado (seção 5.1.3.2.2), juntamente com uma descrição textual. O modelo de
casos de uso serve como um contrato entre os clientes e os desenvolvedores, e é
essencial para as atividades de análise, projeto e teste. Este modelo contém todos os
atores, casos de uso e suas relações.
No modelo elaborado para este sistema, as relações existentes são a de iniciador
e de extensão. A relação de iniciador acontece entre um caso de uso e um ator e serve
para identificar qual ator inicia o caso de uso, em situações onde há vários atores
relacionados a um caso de uso.
Quando vários casos de uso têm certas ações em comum, estas ações podem ser
descritas em um caso de uso separado (caso de uso abstrato). Casos de uso reais (não
abstratos) então podem ter sua funcionalidade estendida por casos de uso abstratos. A
relação usada no modelo de casos de uso deste trabalho é a relação de extensão, que é
mostrada no modelo pela relação de dependência estereotipada <<extend>> da UML
[Booch 98]. O caso de uso que estende é considerado como opcional. Cabe ressaltar que
um caso de uso abstrato sozinho não faz sentido e deve ser usado em conjunto com
outro real.
58
5.1.3.2.1 Atores
Existe um único ator neste sistema, denominado Analista, que fará uso de todas
as funcionalidades do sistema. O analista usará o sistema para editar UIDs, que serão
usados em conjunto outra técnica adequada de levantamento de requisitos e análise para
o trabalho que ele estiver desenvolvendo.
5.1.3.2.2 Modelo de casos de uso
Na figura 5.3 abaixo, é apresentado o modelo de casos de uso. O usuário usa o
editor para criar diagramas de interação do usuário (UID). Primeiramente ele pode criar
um projeto novo, seguindo os passos do caso de uso Manipular projeto. A qualquer
momento, o usuário pode seguir os passos do caso de uso Imprimir diagrama, para
imprimir o conteúdo de uma área de edição em papel. Tendo um projeto parcialmente
completo, o usuário pode seguir os passos do caso de uso Manipular projeto 2, exportar
imagens dos diagramas e salvá-lo em um arquivo em disco.
O usuário segue os passos dos casos de uso Editar UID e Editar UID 2 para
criar ou editar um UID, sendo que vários UIDs podem ser criados. Estes casos de uso
têm sua funcionalidade estendida por uma série de casos de uso abstratos. Os casos de
uso abstratos têm o objetivo de capturar as funcionalidades do sistema quanto à criação
de componentes do UID.
Após criar alguns UIDs, o usuário edita o diagrama de relacionamento seguindo
os passos do caso de uso Editar DR.
59
Figura 5.3 Modelo de casos de uso
Observações sobre os casos de uso:
Como este sistema se trata de um editor, várias sequências diferentes podem ser
seguidas para a criação de diagramas e os casos de uso descritos aqui demonstram
apenas algumas sequências. Estas sequências cobrem todos os principais requisitos, que
são os de criação dos componentes dos diagramas. Para os casos de uso identificados
até o momento, ações de remoção, modificação e movimentação de componentes não
contribuem para a identificação de classes de análise e projeto. Assim, estas ações só
virão a ser tratadas a partir das atividades de implementação.
Manipular projeto e Editar UID são casos de uso que foram divididos em duas
partes (veja C2 - Manipular projeto 2 e C5 - Editar UID 2). Isto foi feito com o objetivo
de tratar as funcionalidades que eles capturam em iterações diferentes, pois se fossem
únicos, seriam muitos extensos. Veja a seção 5.1.5 para um detalhamento da alocação
dos casos de uso nas iterações.
Na seção seguinte é detalhado cada caso de uso. Abaixo um resumo do que cada
caso de uso aborda:
60
• Manipular projeto: criar novo projeto, fechar projeto aberto, criar novo UID;
• Manipular projeto 2: abrir projeto salvo, salvar projeto aberto, exportar
diagrama;
• Editar UID: criar estado, sub-estado, anexos e informações trocadas (saídas de
sistema e entradas de usuário);
• Editar UID 2: marcar estado inicial, inserir chamada de UID, criar transições;
• Editar DR: criar relacionamento, criar ator, criar associação;
• Imprimir diagrama: configuração e impressão de diagrama.
5.1.3.2.3 Detalhamento dos casos de uso
C1 Manipular projeto
Fluxo de eventos padrão:
1. O analista invoca o caso de uso quando pede para criar um novo projeto,
informando o nome do novo projeto de diagramas.
2. Um projeto não deve estar aberto no momento. Se há um projeto aberto,
este será fechado. Assim, o sistema cria um projeto vazio com o nome
designado pelo usuário. Neste momento, é possibilitada a criação de UIDs
e RDs que serão associados ao projeto.
3. O analista seleciona a opção Novo UID , informando o nome do mesmo.
4. O sistema pede para informar o nome do UID
5. O analista informa o nome.
6. O sistema cria o novo UID vazio, o adiciona ao projeto e abre uma área de
edição para ele.
7. Neste momento o analista tem a possibilidade de editar o UID seguindo os
passos descritos pelo caso de uso C4 - Editar UID e C5 Editar UID 2, ou
editar um diagrama de relacionamentos, seguindo os passos descritos pelo
caso de uso C6 Editar DR.
8. O analista pede para fechar o projeto.
9. O sistema pergunta ao usuário se é para salvar o projeto e, então, fecha
todas as suas áreas de edição.
61
C2 Manipular projeto 2
Pré-condições: Há um projeto salvo em disco, com pelo menos 1 diagrama.
Fluxo de eventos padrão:
1. O caso de uso inicia com o analista pedindo para abrir um projeto salvo
anteriormente em um arquivo.
2. O sistema lê o arquivo e abre áreas de edição para todos os seus
diagramas.
3. O analista seleciona uma área de edição qualquer (UID ou DR) e então
pede para exportar, informando o nome do arquivo e o formato de
codificação da imagem.
4. O sistema grava o arquivo de imagem com o conteúdo da área de edição
selecionada.
5. O analista pede para salvar o projeto, informando o nome do arquivo.
6. O sistema grava um arquivo contendo todos os diagramas do projeto para
uso posterior.
C3 Imprimir diagrama
Pré-condições: Há um projeto aberto no editor.
Fluxo de eventos padrão:
1. O analista pede para configurar a página.
2. O sistema mostra as propriedades do papel e da impressora, para que o
usuário altere.
3. O analista escolhe um tamanho de papel de uma lista de tamanhos pré-
definidos. Também altera o valor das margens superior, inferior, esquerda
e direita; e seleciona a orientação do papel como retrato.
4. As configurações são atribuídas.
5. O analista pede para imprimir o diagrama atual e o sistema envia a página
para impressão.
Sequências alternativas:
Os passos 1, 2, 3 e 4 podem ser omitidos em conjunto, já que o analista
pode optar por não configurar a página, e sim deixar as configurações padrão.
62
C4 Editar UID
Pré-condições: Há um UID no projeto, com alguns estados e componentes de
todos os tipos.
Fluxo de eventos padrão:
1. Insere um estado no UID. Também insere um estado dentro deste estado
(sub-estado).
2. No estado, o analista pede para inserir uma saída de sistema do tipo item
de dado, informando as propriedades desta seguindo os passos do caso de
uso abstrato C7 - Informar propriedades de um item de dado.
3. O sistema insere a saída de sistema no estado.
4. No sub-estado, o analista pede para inserir uma saída de sistema do tipo
estrutura. Informa que é um conjunto de estruturas, seguindo os passos do
caso de uso abstrato C8 - Informar propriedades de uma estrutura.
5. O sistema insere a saída de sistema no sub-estado.
6. Em um estado qualquer, pede para inserir uma entrada de usuário
enumerada, seguindo os passos do caso de uso abstrato C9 Informar
propriedades de uma entrada enumerada.
7. O sistema insere a entrada de usuário no estado selecionado.
Sequências alternativas:
Qualquer passo executado pelo analista pode ser omitido, sendo a
resposta do sistema desconsiderada.
Nos passos 3, 5 ou 7, se as saídas de sistema ou entradas de usuário
forem informadas como parametrizadas, os valores dos parâmetros
informados pelo usuário são adicionados ao UID.
C5 Editar UID 2
Pré-condições: Há uma área de edição de UID selecionada no projeto.
Fluxo de eventos padrão:
1. O analista pede para inserir uma nota-textual, uma pré-condição e uma
pós-condição, informando apenas o conteúdo das mesmas.
2. O sistema insere estes elementos no topo do diagrama, possibilitando que
o analista movimente eles para qualquer lugar.
3. O analista pede para inserir um chamada de outro UID, informando o
nome do UID chamado.
63
4. O sistema insere a chamada no local apontado pelo analista.
5. O analista escolhe um estado ou chamada qualquer e pede para marcar este
como inicial.
6. O sistema verifica se já há algum estado ou chamada inicial no diagrama.
Se houver, este é desmarcado, pois há somente um estado inicial em cada
UID.
7. Em um estado qualquer, pede para criar uma transição com origem neste,
seguindo os passos do caso de uso abstrato C10 - Criar transição a partir
de um estado.
8. Em um conjunto qualquer de itens de dados ou de estruturas, pede para
criar uma transição com origem neste, seguindo os passos do caso de uso
abstrato C11 Criar transição a partir de um conjunto.
C6 Editar DR
Pré-condições: Há pelo menos 2 UIDs no projeto.
Fluxo de eventos padrão:
1. O analista seleciona um UID da área de edição de DR e solicita a criação
de um relacionamento.
2. O analista aponta outro UID para a criação do relacionamento entre dois
UIDs distintos e o sistema cria o relacionamento.
3. O sistema pede para informar o tipo de relacionamento e o analista escolhe
um dos três: inclusão, extensão ou precedência.
4. O analista repete os passos de 1 à 3 até que todos os relacionamentos entre
UIDs sejam especificados.
5. O analista insere um ou mais atores no DR, informando seus nomes.
6. O analista seleciona um UID da área de edição e solicita a criação de uma
associação com ator. Em seguida, aponta um ator existente na área de
edição.
7. O analista repete os passos 5 e 6, até que todas as associações de atores
para UIDs estejam especificadas.
Sequências alternativas:
No passo 2, se o analista apontar o mesmo UID, a operação é cancelada.
No passo 6, a associação também pode ser criada a partir do ator.
64
No passo 6, se o analista apontar outro UID para se associar, a operação
é cancelada.
Os passos 4 e 7 podem ser omitidos, já que não importa para o sistema
se foram definidos todos os relacionamentos entre UIDs e todas as associações
entre atores e UIDs.
C7 Informar propriedades de um item de dado (abstrato)
Fluxo de eventos padrão:
1. O caso de uso inicia com o sistema pedindo para o analista informar as
propriedades do item de dado.
2. Informa o nome do item de dado.
3. Informa que o domínio do item de dado é enumerado e então adiciona
vários valores à este domínio.
4. Ignora as opções de item de dado opcional, parametrizado, ou conjunto de
itens de dados.
Sequências alternativas:
No passo 3, o analista pode não definir um domínio para o item de dado.
Pode também definir um domínio qualquer, como Som, Vídeo, Número ou
Imagem.
No passo 4, o analista pode informar que o item de dado é opcional.
Também pode informar que é parametrizado, adicionando vários valores para
o parâmetro. Neste caso, o nome do item de dado representa o nome do
parâmetro. Ainda poderia informar que este item de dado é na verdade um
conjunto de itens de dados e, para isto, apenas definiria uma multiplicidade
para o conjunto. Se a multiplicidade não for definida pelo analista, será 1..N
por default.
C8 Informar propriedades de uma estrutura (abstrato)
Fluxo de eventos padrão:
1. O caso de uso inicia com o sistema pedindo para o analista informar as
propriedades da estrutura.
2. Informa o nome da estrutura.
65
3. Adiciona itens de dado à estrutura várias vezes, informando as
propriedades destes seguindo os passos do caso de uso abstrato C5
Informar propriedades de um item de dado.
4. Ignora as opções de estrutura opcional, parametrizada, ou de conjunto de
estruturas.
Sequências alternativas:
No passo 3, o analista pode deixar a estrutura vazia.
Ainda no passo 3, o analista também pode adicionar estruturas à esta
estrutura.
No passo 4, o analista pode informar que a estrutura é opcional.
Também pode informar que é parametrizada, adicionando vários valores para
o parâmetro. Neste caso, o nome da estrutura representa o nome do parâmetro.
Ainda poderia informar que esta estrutura é na verdade um conjunto de
estruturas e, para isto, apenas definiria uma multiplicidade para o conjunto. Se
a multiplicidade não for definida pelo analista, será 1..N por default.
C9 Informar propriedades de uma entrada enumerada (abstrato)
Fluxo de eventos padrão:
1. O caso de uso inicia com o sistema pedindo para o analista informar as
propriedades da entrada enumerada.
2. Informa o nome da entrada.
3. Adiciona opções à lista de opções da entrada.
4. Informa uma quantidade mínima e/ou máxima de opções a serem
selecionadas.
5. Ignora a opção de entrada de usuário opcional e parametrizada.
Sequências alternativas:
No passo 4, o analista pode informar um número fixo de opções a serem
selecionadas, ou não informar nada.
No passo 5, o analista pode informar que a entrada enumerada é
opcional. Também pode informar que esta é parametrizada, adicionando
vários valores para o parâmetro. Neste caso, o nome da entrada representa o
nome do parâmetro.
No passo 3, o analista pode informar que a entrada enumerada não é
opcional. Também pode informar que esta é parametrizada, adicionando
66
vários valores para o parâmetro. Neste caso, o nome da entrada representa o
nome do parâmetro.
C10 Criar transição a partir de um estado (abstrato)
Fluxo de eventos padrão:
1. O caso de uso inicia quando o analista solicita a criação de uma transição a
partir de um estado, sendo este estado a origem da transição.
2. O analista aponta um outro estado para ser o destino da transição.
3. O sistema pede para o analista informar as propriedades da transição.
4. Informa uma opção a ser selecionada pelo usuário e especifica uma
condição para a transição ocorrer.
5. O sistema cria a transição entre os dois estados, com o rótulo de acordo
com o informado no passo 4.
Sequências alternativas:
No passo 2, o analista pode apontar o mesmo estado de origem para ser
o destino da transição. A transição sem mudança de foco é então criada pelo
sistema.
Ainda no passo 2, o analista pode apontar uma chamada para outro UID
para ser o destino da transição.
No passo 4, o analista pode somente informar uma opção ou somente
especificar uma condição.
C11 Criar transição a partir de um conjunto (abstrato)
Fluxo de eventos padrão:
1. O caso de uso inicia quando o analista solicita a criação de uma transição a
partir de um conjunto, sendo este conjunto a origem da transição.
2. O analista aponta um estado diferente do estado que contém o conjunto de
origem para ser o destino da transição.
3. O sistema pede para o analista informar as propriedades da transição.
4. Informa a quantidade de elementos a serem selecionados pelo usuário.
Também especifica uma opção a ser selecionada.
5. O sistema cria a transição com seleção de elementos do conjunto e seleção
de opção.
Sequências alternativas:
67
No passo 2, poderia ser apontado o estado que contém o conjunto de
origem da transição para ser o destino. Neste caso, uma transição sem
mudança de foco seria criada.
No passo 2, o analista poderia apontar uma outra transição com origem
em outro conjunto do mesmo estado para ser o destino da transição. Neste
caso, o sistema criaria uma transição com múltiplas origens.
Ainda no passo 2, uma chamada para outro UID poderia ser escolhida
como destino da transição.
No passo 4, a especificação de opção poderia ser omitida, assim como
uma especificação de condição poderia ser feita ao invés de uma opção.
5.1.4 Requisitos não-funcionais
Foram identificados os seguintes requisitos não-funcionais:
• Nomes de classes, métodos e atributos da implementação escritos em Inglês.
Como o código fonte será disponibilizado em um site na Internet, é quase que
obrigatória a implementação em Inglês, para que qualquer pessoa possa entendê-
lo.
• Documentação (manual) do usuário em Português e Inglês.
• Implementação em linguagem Java.
• Implementação baseada no Graph Editing Framework (GEF).
5.1.5 Alocação de casos de uso
Cada iteração do processo de desenvolvimento deste trabalho lida com um
conjunto de casos de uso, de maneira que cada iteração incrementa a funcionalidade do
sistema. Os casos de uso foram elaborados levando em conta este aspecto.
Para a primeira iteração foram alocados os seguintes casos de uso:
• Manipular projeto;
• Editar UID.
E para a segunda iteração foram alocados os seguintes:
• Manipular projeto 2;
68
• Editar UID 2;
• Editar DR;
• Imprimir diagrama.
Alguns dos casos de uso acima citados têm sua funcionalidade estendida por
casos de uso abstratos (veja figura 5.3). Estes casos de uso abstratos estão
implicitamente alocados nas mesmas iterações dos casos que eles estendem.
Como foi visto no detalhamento dos casos de uso da seção 5.1.3.2.3, Manipular
projeto e Editar UID tratam de ações de edição relacionadas à criação de um projeto
novo e criação e edição de UIDs com estados de interação contendo informações
trocadas (saídas de sistema e entradas de usuário). Estes dois casos de uso são os mais
críticos do sistema e por isso foram trabalhados na primeira iteração.
Editar UID 2 também é crítico, pois trata da criação de transições e chamadas,
que é parte importante dos UIDs. No entanto, não foi alocado na primeira iteração
porque esta ficou muito extensa já com os dois casos de uso. Manipular projeto 2 trata
do salvamento e recuperação de projetos, assim como a exportação de diagramas para
imagens. Editar DR trata da criação dos diagramas de relacionamentos, que são
opcionais, e por isso foi alocado na segunda iteração.
5.2 Primeira iteração: Análise Na análise, os requisitos descritos na fase de levantamento de requisitos são
analisados fazendo-se um refinamento e estruturando-os de forma a atingir um
entendimento mais preciso dos mesmos.
No Unified Process, a linguagem usada na análise é baseada em um modelo de
objetos conceituais, chamado de modelo de análise. A linguagem usada no
levantamento de requisitos é a linguagem do cliente, enquanto que aqui a linguagem é
do desenvolvedor. O modelo de análise ajuda no refinamento dos requisitos e possibilita
a racionalização sobre as partes internas do sistema, resolvendo problemas de
interferência nos casos de uso.
O modelo de análise faz abstrações, deixa de tratar alguns problemas e
manipular alguns requisitos que são mais bem tratados nas fases de projeto e
implementação.
69
No modelo de análise do Unified Process há:
• classes de análise;
• realizações de casos de uso análise;
• pacotes de análise.
Classes de análise representam abstrações de uma ou muitas classes ou sub-
sistemas do sistema. Estas classes focam no manuseio dos requisitos funcionais,
deixando de lado os requisitos não-funcionais, sendo assim mais conceituais. O
comportamento da classe é definido por suas responsabilidades, que são dadas em um
nível pouco formal. As classes de análise desta iteração estão definidas nas realizações
de casos de uso na seção 5.2.1.
As classes de análise devem se adequar em um dos três estereótipos: interface
(boundary), controle, ou entidade (figura 5.4). Classes de interface modelam a interação
entre o sistema e seus atores, recebendo e apresentando informações. Cabe ressaltar que,
durante a análise, estas não devem ser especializadas nos vários componentes de
interface gráfica de usuário.
Classes de entidade modelam informações de vida-longa e freqüentemente
persistentes. Elas modelam informações e comportamentos de objetos reais e eventos
reais, sendo quase sempre obtidas diretamente do modelo de domínio ou do modelo de
negócio.
Classes de controle representam coordenação, seqüenciamento, transações e
controle de outros objetos, e são frequentemente utilizadas para encapsular controle
relacionado a um caso de uso específico.
Figura 5.4 Tipos de classes de análise
Realizações de casos de uso na análise são colaborações dentro do modelo de
análise que descrevem como um caso de uso específico é realizado e executado em
termos de classes de análise e seus objetos de análise que interagem. A realização do
caso de uso focaliza nos requisitos funcionais.
70
Uma realização de um caso de uso é composta de:
• um diagrama de classes que mostra as classes de análise participantes;
• diagramas de interação que mostram fluxos do caso de uso;
• descrições textuais dos fluxos de eventos.
Neste trabalho as realizações de casos de uso (seções 5.2.1 e 5.2.2), consistem
apenas de diagramas de classes, acompanhados de descrições textuais dos atributos e
responsabilidades de cada classe.
Pacotes de análise ajudam na organização do modelo de análise em pedaços
gerenciáveis e, possivelmente, em subsistemas na fase de projeto. Dentro de pacotes há
classes, realizações de casos de uso e possivelmente outros pacotes. O conteúdo dos
pacotes deve ser muito relacionado e a dependência entre pacotes deve ser pequena.
Os pacotes são inicialmente identificados pelos casos de uso. Foi constatado que
não há necessidade da separação dos dois casos uso desta etapa de análise em pacotes.
Como foi dito na seção 5.1.5, os casos de uso alocados para esta primeira
iteração são Manipular projeto e Editar UID. Nas próximas seções, as realizações na
análise destes casos de uso são detalhadas.
5.2.1 Realização do caso de uso Manipular projeto
O Unified Process aconselha a identificação de classes de análise iniciando-se
pela identificação de classes de entidade a partir do modelo de domínio (seção 5.1.1.2).
Em seguida, a identificação de classes pode ser feita a partir da descrição dos casos de
uso (seção 5.1.3.2).
A figura 5.5 abaixo apresenta o diagrama de classes participantes na realização
do caso de uso Manipular projeto. Na seção 5.2.3, é feita uma descrição dos atributos e
responsabilidades de cada classe identificada nesta etapa de análise.
Descrição da realização:
O Analista interage com InterfaceProjeto para solicitar a criação de um projeto,
informando seu nome. InterfaceProjeto solicita a criação de um projeto ao
GerenciadorProjeto, o qual verifica se há um projeto aberto no momento. Se houver um
projeto aberto, a InterfaceProjeto pergunta ao usuário se é para fechar e salvar este
projeto aberto. O GerenciadorProjeto então fecha o projeto aberto anteriormente e cria
um Projeto novo.
71
Quando há um projeto aberto, o analista pode solicitar à InterfaceProjeto a
criação de um novo UID, informando o nome deste. O GerenciadorProjeto cria o UID
com o nome informado, adicionando-o ao Projeto. Quando um UID novo é criado,
também é criada uma InterfaceUID, que mostra graficamente os componentes do UID
ao analista.
Figura 5.5 Manipular projeto - diagrama de classes participantes
5.2.2 Realização do caso de uso Editar UID
A figura 5.6 apresenta o diagrama de classes participantes na realização do caso
de uso Editar UID.
Descrição da realização:
O Analista interage com a InterfaceUID para solicitar a criação de um estado
novo. O EditorUID cria o estado e o adiciona ao UID. O analista também pode interagir
com a InterfaceUID para solicitar a criação de um sub-estado dentro de um estado
existente. O EditorUID cria um estado e o adiciona ao estado escolhido pelo Analista,
criando assim um sub-estado.
O Analista solicita a InterfaceUID a criação de informações a serem inseridas
num estado escolhido. Os atributos da informação são definidos pelo Analista e então
InterfaceUID pede ao EditorUID para que crie a informação e adicione ao estado.
Toda vez que alguma coisa é modificada no UID, o EditorUID notifica a
InterfaceUID sobre isso, a qual consulta o UID para pegar as informações modificadas e
atualizar a sua vizualização.
72
Figura 5.6 Editar UID - diagrama de classes participantes
5.2.3 Descrição das classes de análise identificadas
Nesta seção são descritos os atributos e responsabilidades de cada classe
identificada na realização dos casos de uso Manipular projeto e Editar UID, que foram
alocados para esta primeira iteração. Estes atributos e responsabilidades são necessários
para a realização dos casos de uso.
InterfaceProjeto
Atributos:• Campo de texto do nome do projeto;• Campo de texto do nome do UID;• Opções de criar e fechar.
Responsabilidades da classe:• Solicitar ao GerenciadorProjeto a criação e fechamento de
projetos;• Perguntar ao analista sobre o salvamento de projetos.
GerenciadorProjeto
Atributos:• Projeto aberto.
Responsabilidades da classe:• Criar projetos;• Verificar se há projeto aberto;• Fechar projetos;• Criar e adicionar UIDs ao projeto aberto.
Projeto
Atributos:• Nome;• Coleção de UIDs.
Projeto
73
5.3 Primeira iteração: Projeto Durante o projeto, o sistema adquire forma que satisfaça todos os requisitos. Ele
tenta preservar a estrutura definida pelo modelo de análise tanto quanto o possível. É
criado um plano detalhado para o modelo de implementação, de maneira que a
implementação possa ser um refinamento direto do projeto.
InterfaceUID
Atributos:• Representação gráfica do UID (uma coleção de figuras);• Opções de criação de estado, sub-estado e informação;• Campos de preenchimento dos atributos de uma informação.
Responsabilidades da classe:• Manter-se atualizada em relação ao UID que representa;• Mostrar ao analista a representação gráfica do UID;• Solicitar ao EditorUID a criação de estados, sub-estados e
informações.
EditorUID
Atributos:• Coleção de UIDs.
Responsabilidades da classe:• Criar, e adicionar a um UID, estados, sub-estados e informações.
UID
Atributos:• Nome;• Visualização gráfica (do tipo InterfaceUID);• Coleção de estados.
Estado
Atributos:• Coleção de sub-estados;• Coleção de informações.
Informação
Atributos:• Tipo;• Conteúdo.
74
Um dos objetivos do projeto é adquirir um entendimento profundo sobre
questões relacionadas com os requisitos não-funcionais e com as tecnologias de
implementação. O modelo do projeto é mais formal que o modelo de análise, sendo
específico para uma implementação.
No modelo de projeto do Unified Process há:
• classes de projeto;
• realizações de casos de uso projeto;
• sub-sistemas de projeto;
• descrição da arquitetura.
Classes de projeto são abstrações de classes na implementação do sistema em
uma linguagem específica. A linguagem usada para especificar uma classe de projeto é
a mesma que a linguagem de programação. Portanto, as operações, parâmetros,
atributos e tipos são especificados usando a sintaxe da linguagem de programação
escolhida.
A visibilidade dos atributos e operações de uma classe de projeto é geralmente
especificada. Os métodos de uma classe de projeto são mapeados diretamente para os
métodos correspondentes na implementação. Os estereótipos das classes de projeto são
mapeados para construtores da linguagem de programação.
Realizações de casos de uso no projeto são colaborações dentro do modelo de
projeto que descrevem como um caso de uso é realizado e executado em termos de
classes de projeto e seus objetos que interagem. Uma realização de um caso de uso é
composta de:
• um diagrama de classes que mostra as classes de projeto participantes;
• diagramas de interação que mostram as interações dos objetos;
• descrições textuais dos fluxos de eventos;
• requisitos de implementação.
Para cada realização de um caso de uso na análise, há uma realização
correspondente no projeto. As realizações dos casos de uso alocados para esta iteração
são descritas nas sessões 5.3.1 e 5.3.2. Estas realizações são compostas de diagramas de
classes participantes e diagramas de interação. Os requisitos de implementação são
75
comentados em cada realização, onde necessário. As classes de projeto são identificadas
principalmente a partir de classes de análise e a partir de requisitos especiais de casos de
uso. Diagramas de interação descrevem como os objetos de projeto interagem,
mostrando os atores participantes, objetos de projeto e as mensagens transmitidas entre
eles.
A descrição da arquitetura feita no projeto consiste basicamente de um modelo
de deployment e da descrição dos subsistemas. O modelo de deployment descreve a
distribuição física do sistema em termos de como a funcionalidade é distribuída entre
nodos computacionais. Como o sistema sendo construído neste trabalho não é
distribuído em nodos, não foi feito este modelo. A descrição da arquitetura feita aqui
consiste somente da descrição dos sub-sistemas (seção 5.3.3). Sub-sistemas
proporcionam uma maneira de organizar o modelo de projeto em pedaços gerenciáveis.
Alguns sub-sistemas representam produtos reusados, como é o caso do GEF (capítulo
4), que é usado neste trabalho.
A etapa de análise feita anteriormente serviu como um meio para se entender
claramente o domínio do problema e não influenciou muito no projeto das classes. O
projeto foi direcionado pelo GEF, pois as classes projetadas devem se adequar com as
classes desse framework. As classes que abordam a edição de UIDs foram projetadas
como comandos e modos de edição, como nos comandos e modos do GEF (veja
capítulo 4).
Nas realizações descritas abaixo, as classes de cor cinza são classes do
framework GEF ou da biblioteca de classes Java. As principais classes são detalhadas
no Anexo A, sendo seus atributos e métodos o resultado final de todas as iterações, pois
uma classe pode ganhar novos atributos e métodos a cada iteração. Os diagramas de
interação de projeto, que descrevem o fluxo de execução dos casos de uso em termos de
objetos de projeto e mensagens, estão detalhados no Anexo B.
5.3.1 Realização do caso de uso Manipular projeto
A figura 5.7 apresenta as classes participantes na realização do caso de uso
Manipular projeto, que foi detalhado na seção 5.1.3.2.3. Manipular projeto cobre
funcionalidades de criação de projetos e novos UIDs.
A classe UIDEditor é a única classe do sistema que tem um fluxo de execução
(thread). Esta classe possui uma interface gráfica com um menu de opções. Os
comandos de edição CmdNewProject, CmdCloseProject e CmdNewUID são usados
76
para criação do menu. Esses comandos são sub-classes da classe Cmd do framework
GEF (veja capítulo 4). UIDEditor tem uma referência para o projeto aberto (Project), o
qual possui vários editores de UIDs. Os editores de UIDs são formados por objetos da
classe JGraph, a qual é uma interface gráfica para a classe Editor. Editor é criada a
partir de um modelo de grafos (UIDGraphModel) e a camada LayerUID (veja camadas
em 4.2.1.3) que apresenta figuras que visualizam graficamente os elementos do grafo.
Assim, o UIDEditor apresenta vários UIDs por meio de vários JGraph, que o Analista
pode selecionar e editar.
O UIDGraphModel é uma classe que dá acesso aos elementos de um UID
(estados, transições, anexos ou chamadas) como se estes fossem um grafo. O GEF dá
suporte à edição de grafos, facilitando a criação de programas que editem nodos e arcos
entre estes nodos. Como foi visto na seção 4.1, os grafos do GEF devem ter nodos,
portas e arcos. Assim, os estados de interação do UID foram projetados com portas,
onde são conectadas as transições.
Figura 5.7 Classes participantes da realização do caso de uso Manipular projeto
5.3.2 Realização do caso de uso Editar UID
A figura 5.8 apresenta as classes participantes na realização do caso de uso
Editar UID. As classes de cor cinza são classes do framework GEF. As informações
77
trocadas (ExchangedInformation) num estado de interação são melhor detalhadas na
figura 5.9.
Como foi visto na seção 5.1.2.1.3, Editar UID cobre as funcionalidades da
criação de estados de interação, sub-estados e informações trocadas nos estados. O
UIDEditor tem uma barra de ferramentas (UIDEditorToolbar), a qual é inicializada com
3 botões, criados a partir de CmdCreateNode e CmdCreateStateContent.
CmdCreateNode é uma classe do GEF que possibilita a criação de nodos de
grafos. Ela toma como parâmetro qual a classe do nodo a ser criado, que no caso é de
um estado de interação do UID (InteractionState).
O GEF não tem suporte para a modificação de nodos já inseridos no grafo e,
assim, foi projetada a classe CmdCreateStateContent, que toma como parâmetros a
classe InteractionSubState, para criar sub-estados, ou ExchangedInformation, para criar
informações trocadas em um estado.
Quando o Analista aciona os comandos pela barra de ferramentas, o editor muda
seu modo de edição para ModePlace ou ModePlaceStateContent. Estes modos
interpretam os eventos de mouse gerados pelo analista para a criação e posicionamento
dos componentes na janela de edição (JGraph). ModePlace cria e posiciona os estados
de interação, enquanto ModePlaceStateContent posiciona sub-estados e informações
dentro de estados existentes.
78
Figura 5.8 Classes participantes da realização do caso de uso Editar UID
A figura 5.9 apresenta as classes que modelam todos os tipos de informações
que podem ser trocadas em um estado de interação (como visto no capítulo 2). Estas
classes apenas armazenam e dão acesso às informações.
O CmdCreateStateContent, quando configurado para criar informações trocadas,
abre uma janela de diálogo (ExchangedInformationDialog) para que o analista escolha
qual o tipo de informação é para ser inserida.
ExchangedInformationDialog é uma interface de usuário com projeto complexo,
pois deve possibilitar acesso à edição de informações, dando suporte a todas as
combinações possíveis de tipos de informação, domínios, multiplicidades, etc. Ao
79
mesmo tempo, deve ser intuitiva ao usuário. Ela impede a criação de informações que
não seguem a notação do UID.
Figura 5.9 Informações trocadas em estados de interação
Como pode-se ver na figura 5.8, a camada LayerUID contém várias
FigInteractionState, que são as figuras que representam os estados de interação. Esta
classe foi projetada de maneira que o analista não precise ficar re-dimensionando a
elipse do estado, pois toda vez que um conteúdo é inserido no estado, a classe é
notificada pela camada e se atualiza.
FigInteractionState é uma sub-classe da classe FigGroup do GEF, ou seja, é um
conjunto de figuras. Cada elemento de um estado de interação (informações ou sub-
estados) é uma figura. O estado de interação da figura 5.10 é formado por uma elipse,
um retângulo e duas caixas de texto. Os sub-estados são elipses posicionadas na parte
superior, uma do lado da outra. As informações são centralizadas logo abaixo dos sub-
80
estados. Cada figura do conjunto tem sua posição e tamanho calculados
automaticamente pela classe, de forma a aliviar esta tarefa do analista.
Figura 5.10 Exemplo de estado de interação
5.3.3 Sub-sistemas
A figura 5.11 abaixo apresenta o diagrama de sub-sistemas e dependências
definidos para esta etapa de projeto. As classes identificadas nas realizações dos casos
de uso nas seções anteriores são melhor organizadas em três sub-sistemas: Aplicação,
UID e Apresentação UID. O sub-sistema Aplicação contém as classes relativas a
manipulação de projetos de UIDs, interfaces gráficas de usuário, comandos e modos de
edição necessários para a realização dos casos de uso Manipular projeto e Editar UID,
que estão sendo tratados nesta iteração.
O sub-sistema UID contém as classes de projeto que representam componentes
de UIDs e o sub-sistema Apresentação contém as classes de figuras necessárias para a
visualização dos componentes dos UIDs.
Os sub-sistemas GEF e Biblioteca de classes Java compõem a camada de
middleware do sistema.
Os sub-sistemas Aplicação e Apresentação UID são dependentes do framework
GEF e o projeto de suas classes é bastante influenciado por essa dependência.
81
Figura 5.11 Sub-sistemas de projeto
5.4 Primeira iteração: Implementação Durante a implementação, as classes de projeto e sub-sistemas encontrados no
projeto são implementados em uma linguagem de programação. O modelo de
implementação, constituído de componentes da linguagem de programação, é mantido
em sincronia com o modelo de projeto.
Neste trabalho, cada classe de projeto foi mapeada para um arquivo contendo
uma classe escrita na linguagem Java. Muitas das classes foram testadas
individualmente. Em seguida, a execução dos casos de uso foi testado.
Na seção 5.7 são apresentadas figuras demonstrando a interface gráfica da
ferramenta desenvolvida por nós.
As classes de projeto e seus comportamentos são detalhados nos Anexos A e B.
O código fonte é listado no Anexo C.
5.5 Segunda iteração: AnáliseA primeira iteração teve como resultado final a implementação dos casos de uso
Manipular projeto e Editar UID, que dão ao sistema sendo produzido uma certa
82
usabilidade. Esta usabilidade se restringiu a criação de projetos de UIDs contendo
apenas estados e suas informações.
Como foi dito na seção 5.1.5, os casos de uso alocados para esta segunda
iteração são: Manipular Projeto 2, Editar UID 2, Editar DR, e Imprimir diagrama.
Estes lidam com abertura e salvamento de projetos; criação de transições, anexos e
chamadas; criação de diagramas de relacionamentos e impressão. Assim, o incremento
gerado pela segunda iteração resulta em um sistema com a usabilidade mínima para
edição de UIDs.
Também nesta iteração não foi reconhecida a necessidade da definição de
pacotes de análise. Nas próximas sessões, as realizações dos casos de uso são descritas.
Na seção 5.5.5, é feita uma descrição dos atributos e responsabilidades de cada classe
identificada nas realizações desta etapa de análise.
5.5.1 Realização do caso de uso Manipular projeto 2
A figura 5.12 abaixo apresenta o diagrama de classes participantes na realização
do caso de uso Manipular projeto 2.
Descrição da realização:
O Analista pede a InterfaceProjeto para abrir um projeto salvo em disco
anteriormente, informando o nome do arquivo. O GerenciadorProjeto então abre o
ArquivoProjeto pelo nome informado, carregando o Projeto e todos os seus diagramas
(UIDs e RDs).
O Analista seleciona uma das InterfaceUID e solicita a exportação para um
arquivo de imagem, informando o nome e formato de imagem. O EditorUID então
consulta o conteúdo da InterfaceUID para escrever o ArquivoImagem.
O Analista pede para InterfaceProjeto salvar o Projeto aberto. O
GerenciadorProjeto então consulta o conteúdo de Projeto e o salva em ArquivoProjeto.
83
Figura 5.12 Manipular projeto 2 - diagrama de classes participantes
5.5.2 Realização do caso de uso Editar UID 2
A figura 5.13 abaixo apresenta o diagrama de classes participantes na realização
do caso de uso Editar UID 2.
Descrição da realização:
O Analista solicita à InterfaceUID a inserção de um anexo (uma nota-textual ou
condição), informando seu conteúdo. O EditorUID cria o anexo e o adiciona ao UID.
O Analista solicita a InterfaceUID a criação de uma Chamada, informando o
nome do UID chamado. O EditorUID cria a Chamada apontando para o UID
especificado pelo Analista e a adiciona ao UID.
O Analista escolhe um estado na InterfaceUID e pede para marcar este como
inicial. O EditorUID verifica se há outro estado inicial no UID e o desmarca. Após isto,
marca o Estado escolhido pelo Analista como inicial.
O Analista seleciona um estado na InterfaceUID e pede para criar uma Transição
com origem nele; aponta o destino da transição e o EditorUID cria e insere a Transição
no UID.
84
Toda vez que alguma coisa é modificada no UID, o EditorUID notifica a
InterfaceUID sobre isso, a qual consulta o UID para pegar as informações modificadas e
atualizar a sua vizualização.
Figura 5.13 Editar UID 2 - diagrama de classes participantes
5.5.3 Realização do caso de uso Editar DR
A figura 5.14 abaixo apresenta o diagrama de classes participantes na realização
do caso de uso Editar DR.
Descrição da realização:
O Analista solicita à InterfaceDR a criação de um relacionamento entre dois
UIDs apontados por ele. O EditorDR cria o Relacionamento com o estereótipo definido
pelo Analista e o adiciona ao DR.
O Analista solicita à InterfaceDR a criação de um Ator com determinado nome.
O EditorDR cria o Ator e o adiciona ao DR. O Analista solicita à InterfaceDR a criação
de uma associação entre um UID e um Ator apontados por ele. O EditorDR cria a
Associação e a adiciona ao DR.
Sempre que um relacionamento, associação ou ator é adicionado ao DR ou
modificado, o EditorDR notifica a InterfaceDR sobre isso, a qual consulta o DR para
pegar as informações modificadas e se atualizar.
85
Figura 5.14 Editar DR - diagrama de classes participantes
5.5.4 Realização do caso de uso Imprimir diagrama
A figura 5.15 abaixo apresenta o diagrama de classes participantes na realização
do caso de uso Imprimir diagrama.
Descrição da realização:
O Analista seleciona uma InterfaceUID ou uma InterfaceRD entre as várias
disponíveis e, então, pede à InterfaceProjeto para configurar a página de impressão.
InterfaceProjeto repassa a configurações para o GerenciadorProjeto armazenar no
Projeto. O Analista então solicita a InterfaceProjeto que o diagrama seja impresso.
Figura 5.15 Imprimir diagrama - diagrama de classes participantes
86
5.5.5 Descrição das classes de análise identificadas
Nesta seção são descritos os atributos e responsabilidades de cada classe
identificada na realização dos casos de uso Manipular projeto 2, Editar UID 2, Editar
DR e Imprimir diagrama, que foram alocados para esta segunda iteração. Para as
classes que já foram identificadas na primeira iteração, somente os atributos e
responsabilidades adicionais são descritos.
InterfaceProjeto
Atributos:• Opções para abrir e salvar projeto;• Opção para configurar página de impressão.•
Responsabilidades da classe:• Solicitar ao GerenciadorProjeto a abertura e salvamento de
projetos.
GerenciadorProjeto
Responsabilidades da classe:• Abrir projetos;• Salvar projetos.
Projeto
Atributos:• Configurações de impressão.
InterfaceUID
Atributos:• Opções de criação de transições, anexos e chamadas;• Opção para exportação de imagem;• Opção para marcar um estado ou chamada como inicial.
Responsabilidades da classe:• Solicitar ao EditorUID a criação de chamadas, anexos e
transições.
EditorUID
Responsabilidades da classe:• Salvar um arquivo de imagem consultando o conteúdo de
InterfaceUID;• Marcar um estado ou chamada de um UID como inicial;• Manter apenas um estado ou chamada de cada UID como inicial;• Criar chamadas, anexos e transições e adicioná-los a um UID.
87
UID
Atributos:• Coleção de transições, anexos e chamadas.
Anexo
Atributos:• Tipo;• Conteúdo.
Chamada
Atributos:• UID Chamado.
Transição
Atributos:• Origens;• Destino;• Rótulo.
InterfaceDR
Atributos:• Representação gráfica do DR (uma coleção de figuras);• Opções de criação de relacionamentos, atores e associações;• Campo de preenchimento de nome de ator;• Campo de preenchimento de estereótipo de relacionamento.
Responsabilidades da classe:• Manter-se atualizada em relação ao RD que representa;• Mostrar ao analista a representação gráfica do RD;• Solicitar ao EditorDR a criação de relacionamentos, atores e
associações.
88
5.6 Segunda iteração: Projeto Cada caso de uso alocado para a segunda iteração é realizado em termos de
artefatos de projeto. A descrição da realização de cada caso de uso é feita nas seções
5.6.1 a 5.6.4. Novos sub-sistemas de projeto foram definidos e apresentados na seção
5.6.5.
EditorDR
Atributos:• Coleção de RDs.
Responsabilidades da classe:• Criar relacionamentos, atores e associações e adicioná-los a um
RD;• Salvar um arquivo de imagem consultando o conteúdo de
InterfaceRD.
DR
Atributos:• Coleção de UIDs, atores, associações e relacionamentos.
Relacionamento
Atributos:• UIDs relacionados;• Estereótipo (inclusão, extensão ou precedência).
Ator
Atributos:• Nome.
Associação
Atributos:• Ator associado;• UID associado.
89
5.6.1 Realização do caso de uso Manipular projeto 2
A figura 5.16 apresenta as classes participantes na realização do caso de uso
Manipular projeto 2.
Descrição da realização:
Os comandos de edição CmdOpenProject, CmdSaveProject e
CmdExportDiagram são usados para a criação do menu do UIDEditor. Estes comandos,
quando acionados pelo Analista, são responsáveis pela abertura e salvamento de
projetos em arquivo e pela exportação de diagramas em arquivo de imagem no formato
GIF. O CmdExportDiagram exporta a imagem do diagrama que estiver selecionado no
UIDEditor.
Figura 5.16 Classes participantes da realização do caso de uso Manipular projeto 2
5.6.2 Realização do caso de uso Editar UID 2
A figura 5.18 apresenta as classes participantes na realização do caso de uso
Editar UID 2.
Descrição da realização:
Como foi visto na seção 4.1, os grafos do GEF devem ter nodos, portas e arcos.
Assim, os estados de interação do UID foram projetados com portas, onde são
conectadas as transições.
A figura 5.17 é um exemplo de um UID com portas, como modelado neste
sistema. Estas portas só aparecem quando o usuário aponta os estados com o mouse.
Pode-se ver que há portas nos estados e em uma informação trocada do tipo conjunto.
90
Figura 5.17 Exemplo de UID com portas visíveis
Como foi visto na seção 5.1.2.1.3, Editar UID 2 cobre as funcionalidades de
criação de anexos (pré-condições, pós-condições ou notas textuais), criação de
chamadas de UIDs, marcação de estados iniciais e criação de transições a partir de
estados ou conjuntos.
UIDEditor é construído com uma barra de ferramentas (UIDEditorToolbar), a
qual é inicializada com botões criados a partir dos comandos CmdCreateNode,
CmdCreateEdge e CmdCreateAttachment.
CmdCreateNode é o comando de criação de nodos do GEF. É inicializado com o
argumento de tipo de nodo UIDCall , para que possibilite a criação de chamadas de
UIDs. CmdCreateEdge é o comando de criação de arcos entre nodos no GEF e é
inicializado de forma a criar arcos com a classe Transition. CmdCreateUIDAttachment
é o comando projetado para criar anexos.
Quando o Analista aciona os comandos pela barra de ferramentas, o editor muda
seu modo de edição para ModePlace, ModeCreateEdge ou ModePlaceUIDAttachment.
Estes modos interpretam os eventos de mouse gerados pelo Analista para a criação e
posicionamento das figuras na janela de edição (JGraph). ModePlace cria e posiciona
as chamadas. ModeCreateEdge interpreta os cliques de mouse do Analista de forma a
conectar portas de estados e chamadas. ModePlaceUIDAttachment cria e posiciona
anexos.
título do CD
...CD (título, nome cantor, ano, preço,disponibilidade, capa, gênero, gravadora)
UID Mostrar músicasde um CD
1 (mostrar músicas)
91
Figura 5.18 Classes participantes da realização do caso de uso Editar UID 2
5.6.3 Realização do caso de uso Editar DR
A figura 5.19 apresenta as classes participantes na realização do caso de uso
Editar DR.
Descrição da realização:
O caso de uso Editar DR cobre as funcionalidades de edição de diagramas de
relacionamentos (DR). Diagramas de relacionamentos são constituídos de UIDs (classe
UID) e relacionamentos entre eles (classe Relationship). Atores (classe Actor) também
podem ser associados a UIDs (classe Association).
Como o UIDGraphModel, o RDGraphModel é uma classe que modela um DR
como um grafo, de forma a ser compatível com a criação de editores de diagramas no
GEF. Assim, um projeto (Project) também pode conter editores de DR, que são
92
construídos a partir de um RDGraphModel e um LayerDR, o qual contém as figuras
representando os componentes de um DR.
Actor e UID são nodos do grafo RDGraphModel. Relationship e Association são
os arcos. Actor e UID possuem 4 portas (Port) cada um, onde são conectados os arcos.
Assim como na edição de UIDs, a edição de RDs é realizada com comandos e
modos de edição.
Figura 5.19 Classes participantes da realização do caso de uso Editar DR
93
5.6.4 Realização do caso de uso Imprimir diagrama
A figura 5.20 apresenta as classes participantes na realização do caso de uso
Imprimir diagrama.
Descrição da realização:
O menu de opções do UIDEditor é construído com os comandos CmdPrint e
CmdPrintPageSetup. Ambos são comandos do GEF e permitem que o analista acesse as
configurações de impressão e imprima diagramas selecionados no UIDEditor.
Figura 5.20 Classes participantes da realização do caso de uso Imprimir diagrama
5.6.5 Sub-sistemas
A figura 5.21 apresenta o diagrama dos novos sub-sistemas e suas dependências
definidas nesta etapa de projeto.
As classes relativas a edição de diagramas de relacionamentos estão contidas no
sub-sistema DR e Apresentação DR.
94
Figura 5.21 Sub-sistemas de projeto
5.7 Segunda iteração: Implementação Cada classe nova ou atualizada na segunda etapa de projeto foi mapeada para um
arquivo contendo uma classe escrita na linguagem Java. Algumas classes foram testadas
individualmente, antes de serem executados testes de integração.
As classes de projeto e seus comportamentos são detalhados nos Anexos A e B.
O código fonte é listado no Anexo C.
A classe UIDEditor foi implementada com uma interface gráfica de usuário que
é mostrada na figura 5.22.
95
Figura 5.22 Interface gráfica de UIDEditor
96
6 CONCLUSÕES Este trabalho descreveu os resultados do processo de desenvolvimento de uma
ferramenta de edição de UIDs. A maioria dos requisitos de alta e média prioridade
foram implementados, mas alguns requisitos levantados não foram implementados por
restrição de tempo.
O uso do framework GEF facilitou bastante o trabalho, pois muitas idéias de
projeto foram obtidas do mesmo. Outro aspecto a ressaltar foi a reutilização de código,
pois a maioria das classes projetadas neste trabalho derivam de classes do framework.
Como destaque da ferramenta desenvolvida, pode-se citar sua interface de
usuário intuitiva, que permite a rápida edição de UIDs. Por exemplo, o usuário não
precisa acessar menus ou clicar em botões para criar transições. Ele pode
simplesmente clicar e arrastar o mouse a partir de uma porta localizada em um estado
de interação. Além disso, o usuário somente precisa se preocupar com a elaboração das
informações trocadas nos estados de interação, pois o posicionamento e
dimensionamento das figuras que compõem estes estados é feito automaticamente pela
ferramenta.
As recomendações do Unified Process serviram de guia para o desenvolvimento
da ferramenta, definindo as melhores práticas para a produção de um software de
qualidade. Foram executadas duas iteração dos seus workflows, sendo que 30% do
tempo total de desenvolvimento foi gasto na tarefa de levantamento de requisitos. A
análise foi relativamente rápida, demandando 10% do tempo. A tarefa mais trabalhosa
foi o projeto, com 40% do tempo. Como a implementação é um refinamento direto do
projeto, apenas 20% do tempo foi gasto com ela.
A experiência prática adquirida com este trabalho contribuiu para o nossa
formação em Ciências da Computação com ênfase em análise e projeto de sistemas. Foi
um trabalho difícil, mas recompensador, pois construiu-se um sistema que funciona e
que é fácil de se entender.
97
7 REFERÊNCIAS
[Booch 98] BOOCH, G.; RUMBAUGH, J.; JACOBSON, I. The unifiedmodeling language user guide. Addison-Wesley: 1998. 482p.
[Güell 00] GÜELL, N.; SCHWABE, D.; and VILAIN, P. Modeling interactions and navigation in web applications. In: Proceedings of the World Wide Web and Conceptual Modeling 2000.
[Jacobson 99] JACOBSON, I.; BOOCH, G.; RUMBAUGH, J. The unifiedsoftware development process. Addison-Wesley: 1999. 463p.
[Robbins 03] ROBBINS, Jason. The design of GEF (the graph editing framework). Disponível em: http://gef.tigris.org/v0.6/docs/designslides/. Acesso em: 10 fev. 2004.
[Schwabe 02] VILAIN, P.; SCHWABE, D. Improving the web application design process with UIDs. In: Proceedings of the 2nd International Workshop on Web Oriented Software Technology 2002.
[Silva 00] SILVA, Ricardo Pereira e. Suporte ao desenvolvimento e uso de frameworks e componentes. 2000. Tese de Doutorado. Programa de Pós-Graduação em Computação. Universidade Federal do Rio Grande do Sul.
[Vilain 00] VILAIN, P.; SCHWABE, D.; SOUZA, C.S. de. A diagrammatic tool for representing user interaction in UML. In: Proceedings of the UML2000 Conference, York, England, October, 2000. p.133-147.
[Vilain 02] VILAIN, P. Modelagem da interação com o usuário em aplicações hipermídia. Rio de janeiro: DI/PUC-Rio, 2002. (Tese de Doutorado)
98
ANEXO A Classes de projeto
Os sub-sistemas de projeto foram mapeados para pacotes de classes Java. Odiagrama de pacotes é apresentado na figura abaixo.
Figura 1. Pacotes de classes Java
A seguir, as principais classes de projeto são detalhadas. As associações não sãomostradas.
99
A.1 Pacote br.ufsc.uid.application
100
A.2 Pacote br.ufsc.uid
A ExchangedInformation e suas sub-classes já tiveram seus atributos eassociações detalhados na figura 5.9. Seus métodos não são mostrados, pois sãosomente métodos de acesso aos atributos.
101
102
103
A.3 Pacote br.ufsc.uid.presentation
104
ANEXO B Diagramas de interação de projeto
Neste anexo apresentam-se os diagramas de interação de objetos de projeto pararealização de casos de uso. A maioria dos casos de uso tem seus diagramas de interaçãodivididos em várias partes, que são mostradas em figuras subseqüentes. As interações ocorrem entre o Analista e as classes projetadas neste trabalho (corbranca), as classes do GEF (cor cinza) e as classes da biblioteca de classes do Java (corcinza também).
Figura 1. Caso de uso Manipular projeto
Figura 2. Caso de uso Editar UID, ação de inserir estado, parte 1
105
Figura 3. Caso de uso Editar UID, ação de inserir estado, parte 2
Figura 4. Caso de uso Editar UID, ação de inserir estado, parte 3
106
Figura 5. Caso de uso Editar UID, ação de inserir estado, parte 4
Figura 6. Caso de uso Editar UID, ação de inserir estado, parte 5
107
Figura 7. Caso de uso Editar UID, ação de inserir estado, parte 6
Figura 8. Caso de uso Editar UID, ação de inserir sub-estado, parte 1
Figura 9. Caso de uso Editar UID, ação de inserir sub-estado, parte 2
108
Figura 10. Caso de uso Editar UID, ação de inserir sub-estado, parte 3
Figura 11. Caso de uso Editar UID, ação de inserir saída de sistema do tipo item dedado, parte 1
A segunda parte da ação inserir saída de sistema do tipo item de dado, do casode uso Editar UID, é igual a Figura 9.
109
Figura 12. Caso de uso Editar UID, ação de inserir saída de sistema do tipo item dedado, parte 3
Figura 13. Caso de uso Editar UID, ação de inserir saída de sistema do tipo item dedado, parte 4
110
Figura 14. Caso de uso Editar UID, ação de inserir saída de sistema do tipo item dedado, parte 5
Os diagramas de interação da ação inserir saída de sistema do tipo estrutura, docaso de uso Editar UID, tem todas as suas partes em comum com a ação inserir saídade sistema do tipo item de dado (figuras 11 a 14), com exceção da parte 4, apresentadana figura 15.
Figura 15. Caso de uso Editar UID, ação de inserir saída de sistema do tipo estrutura,parte 4
Os diagramas de interação da ação inserir entrada de usuário do tipo entradaenumerada, do caso de uso Editar UID, tem todas as suas partes em comum com a açãoinserir saída de sistema do tipo item de dado (figuras 11 a 14), com exceção da parte 4,apresentada na figura 16.
111
Figura 16. Caso de uso Editar UID, ação de inserir entrada de usuário do tipo entradaenumerada, parte 4
Figura 17. Caso de uso Manipular projeto 2, ação de abrir projeto
112
Figura 18. Caso de uso Manipular projeto 2, ação de exportar diagrama
113
Figura 19. Caso de uso Manipular projeto 2, ação de salvar projeto
114
Figura 20. Caso de uso Editar UID 2, ação de criar uma transição a partir de um estado,parte 1
Figura 21. Caso de uso Editar UID 2, ação de criar uma transição a partir de um estado,parte 2
115
Figura 22. Caso de uso Editar UID 2, ação de criar uma transição a partir de um estado,parte 3
116
Figura 23. Caso de uso Editar UID 2, ação de criar uma transição a partir de um estado,parte 4
117
Figura 24. Caso de uso Editar UID 2, ação de criar uma transição a partir de um estado,parte 5
Figura 25. Caso de uso Editar UID 2, ação de criar uma transição a partir de um estado,parte 6
118
Figura 21. Caso de uso Imprimir diagrama
119
ANEXO C Código fonte
As principais classes têm seu códigos fonte listados nesta seção
C.1 Pacote br.ufsc.uid.application///////////////////////////////////////////////////////////////// arquivo: br/ufsc/uid/application/UIDEditor.javapackage br.ufsc.uid.application;import java.awt.*;import java.util.*;import java.awt.*;import java.awt.event.*;import javax.swing.*;import javax.swing.event.*;import javax.swing.border.*;import org.tigris.gef.event.*;import org.tigris.gef.util.*;import org.tigris.gef.ui.IStatusBar;import org.tigris.gef.ui.PaletteFig;import org.tigris.gef.base.*;import org.tigris.gef.graph.presentation.*;
public class UIDEditor extends JFrameimplements IStatusBar, ModeChangeListener{ //////////////////////////////////////////////////////////////// // instance variables protected Project _project; protected JPanel _mainPanel = new JPanel(new BorderLayout()); protected JPanel _uidPanel = new JPanel(new BorderLayout()); protected JTabbedPane _tabbedUIDPane = new JTabbedPane(); protected UIDEditorToolbar _toolbar; protected JMenuBar _menubar = new JMenuBar(); protected JLabel _statusbar = new JLabel(" ");
protected JGraph _graph1; protected JGraph _graph2;
//////////////////////////////////////////////////////////////// // constructors public UIDEditor() { super("UID Editor v0.992"); // init localizer and resourceloader
Localizer.addResource("UIDEditor","br.ufsc.uid.application.ResourceBundle"); Localizer.addLocale(Locale.getDefault()); Localizer.switchCurrentLocale(Locale.getDefault()); ResourceLoader.addResourceExtension("gif"); ResourceLoader.addResourceLocation("/br/ufsc/uid/images"); _toolbar = new UIDEditorToolbar(this); Container content = getContentPane(); setUpMenus(); disableEditingMenus(); content.setLayout(new BorderLayout()); content.add(_menubar, BorderLayout.NORTH); _uidPanel.add(_tabbedUIDPane, BorderLayout.CENTER); _uidPanel.setBorder(new EtchedBorder(EtchedBorder.LOWERED)); _mainPanel.add(_toolbar, BorderLayout.NORTH); _mainPanel.add(_uidPanel, BorderLayout.CENTER); content.add(_mainPanel, BorderLayout.CENTER); content.add(_statusbar, BorderLayout.SOUTH); setBounds(10, 10, 500, 380); setVisible(true);
addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent event) { dispose(); } public void windowClosed(WindowEvent event) { System.exit(0); }
120
}); }
//////////////////////////////////////////////////////////////// // accessors public Project getProject() { return _project; }
//////////////////////////////////////////////////////////////// // ModeChangeListener implementation public void modeChange(ModeChangeEvent mce) { // VERIFICAR NECESSIDADE !!! if (!Globals.getSticky() && Globals.mode() instanceof ModeSelect) _toolbar.unpressAllButtons(); }
/** Set up the menus and keystrokes for menu items. */ protected void setUpMenus() { JMenuItem exitItem, newProjectItem, closeProjectItem; JMenu file = new JMenu(Localizer.localize("UIDEditor","File")); file.setMnemonic('F'); newProjectItem = file.add(new CmdNewProject(this)); closeProjectItem = file.add(new CmdCloseProject(this)); exitItem = file.add(new CmdExit()); KeyStroke ctrlN = KeyStroke.getKeyStroke(KeyEvent.VK_N,KeyEvent.CTRL_MASK); KeyStroke altF4 = KeyStroke.getKeyStroke(KeyEvent.VK_F4,KeyEvent.ALT_MASK); KeyStroke ctrlF4 = KeyStroke.getKeyStroke(KeyEvent.VK_F4,KeyEvent.CTRL_MASK); exitItem.setAccelerator(altF4); newProjectItem.setAccelerator(ctrlN); closeProjectItem.setAccelerator(ctrlF4); _menubar.add(file); JMenuItem newUIDItem; JMenu uid = new JMenu("UID"); uid.setMnemonic('U'); newUIDItem = uid.add(new CmdNewUID(this)); KeyStroke ctrlU = KeyStroke.getKeyStroke(KeyEvent.VK_U,KeyEvent.CTRL_MASK); newUIDItem.setAccelerator(ctrlU); _menubar.add(uid); }
protected void enableEditingMenus() { _menubar.getMenu(1).setEnabled(true); }
protected void disableEditingMenus() { _menubar.getMenu(1).setEnabled(false); }
//////////////////////////////////////////////////////////////// // display related methods public void setVisible(boolean b) { super.setVisible(b); if (b) Globals.setStatusBar(this); }
//////////////////////////////////////////////////////////////// // IStatusListener implementation /** Show a message in the statusbar. */ public void showStatus(String msg) { if (_statusbar != null) _statusbar.setText(msg); }
//////////////////////////////////////////////////////////////// // Project related methods public void closeProject() { int option; option = JOptionPane.showConfirmDialog(this, "Save project beforeclosing?", "Save project", JOptionPane.YES_NO_CANCEL_OPTION); switch(option) { case JOptionPane.YES_OPTION: saveProject(); _project = null; _tabbedUIDPane.removeAll(); break;
121
case JOptionPane.NO_OPTION: _project = null; _tabbedUIDPane.removeAll(); break; default: //do nothing: cancel and exit options break; } this.setTitle("UID Editor"); disableEditingMenus(); }
public void newProject() { String name = JOptionPane.showInputDialog(this, "Name for the project","New project name", JOptionPane.QUESTION_MESSAGE); if (name == null) { return; } if (name.equals("")) { name = "untitled"; } _project = new Project(name); this.setTitle("UID Editor - " + name); enableEditingMenus(); }
public void saveProject() { }
//////////////////////////////////////////////////////////////// // UID related methods public void newUID() { String name = JOptionPane.showInputDialog(this, "Name for the new UID","New UID name", JOptionPane.QUESTION_MESSAGE); if (name == null) { return; } if (name.equals("")) { name = "untitled"; } _tabbedUIDPane.add(name, _project.newUID(name));
}
//////////////////////////////////////////////////////////////// // main public static void main(String args[]) { UIDEditor uide = new UIDEditor(); }}
///////////////////////////////////////////////////////////////// arquivo: br/ufsc/uid/application/UIDEditorToolbar.javapackage br.ufsc.uid.application;import org.tigris.gef.ui.ToolBar;import org.tigris.gef.base.*;import javax.swing.JFrame;
public class UIDEditorToolbar extends ToolBar{ private JFrame _parent; public UIDEditorToolbar(JFrame parent) { _parent = parent; defineButtons(); }
private void defineButtons() { add(new CmdSetMode(ModeSelect.class, "Select")); add(new CmdSetMode(ModeBroom.class, "Broom")); addSeparator(); add(new CmdCreateNode(br.ufsc.uid.InteractionState.class, false,"UIDEditor", "InteractionState")); add(new CmdCreateStateContent(br.ufsc.uid.InteractionSubState.class,"InteractionSubState", _parent)); add(new CmdCreateStateContent(br.ufsc.uid.ExchangedInformation.class,"ExchangedInformation", _parent)); }};
///////////////////////////////////////////////////////////////// arquivo: br/ufsc/uid/application/Project.java
122
package br.ufsc.uid.application;import org.tigris.gef.base.*;import org.tigris.gef.graph.presentation.*;import br.ufsc.uid.UIDGraphModel;import br.ufsc.uid.presentation.LayerUID;import java.util.*;
public class Project{ protected Vector _uidEditors; protected String _name;
public Project(String name) { _name = name; _uidEditors = new Vector(); }
public JGraph newUID(String name) { UIDGraphModel uid = new UIDGraphModel(name); LayerUID lay = new LayerUID(null, uid); Editor ed = new Editor(uid, null, lay); JGraph uide = new JGraph(ed); _uidEditors.add(uide); return uide; }};
///////////////////////////////////////////////////////////////// arquivo: br/ufsc/uid/application/CmdCreateStateContent.javapackage br.ufsc.uid.application;import java.util.Hashtable;import javax.swing.JFrame;import org.tigris.gef.base.*;import br.ufsc.uid.*;
public class CmdCreateStateContent extends Cmd{ //////////////////////////////////////////////////////////////// // constructors public CmdCreateStateContent(Class contentClass, String name, JFrame parentFrame) { super(new Hashtable(), "UIDEditor", name); setArg("className", contentClass); setArg("shouldBeSticky", Boolean.TRUE); setArg("parentFrame", parentFrame); }
//////////////////////////////////////////////////////////////// // Cmd API public void doIt() { Object actionName = getValue(javax.swing.Action.NAME); String instructions = null; if(actionName != null){ instructions = "Click inside a interaction state to place a" +(String)actionName; } Mode placeMode = new ModePlaceStateContent(this, instructions); Object shouldBeSticky = getArg("shouldBeSticky"); Globals.mode(placeMode, shouldBeSticky == Boolean.TRUE); }
public void undoIt(){ System.out.println("undo is not implemented"); }
public Object getArg(String key) { return super.getArg(key); }
//////////////////////////////////////////////////////////////// // Operations public Object makeContent(InteractionState owner) { Class contentClass = (Class) getArg("className"); JFrame parentFrame = (JFrame) getArg("parentFrame"); if(contentClass == br.ufsc.uid.InteractionSubState.class) { InteractionSubState newContent = new InteractionSubState();
123
((InteractionSubState)newContent).initialize(); ((InteractionSubState)newContent).setOwner(owner); return newContent; } else { if(contentClass == br.ufsc.uid.ExchangedInformation.class) { ExchangedInformation exchangedInfo = null; ExchangedInformationDialog d = newExchangedInformationDialog(parentFrame, exchangedInfo, owner); return d.getInfo(); } } return null; }}
///////////////////////////////////////////////////////////////// arquivo: br/ufsc/uid/application/ModePlaceStateContent.javapackage br.ufsc.uid.application;import java.awt.*;import java.util.*;import java.awt.event.*;import org.tigris.gef.base.*;import org.tigris.gef.presentation.*;import br.ufsc.uid.presentation.FigInteractionState;import br.ufsc.uid.*;
public class ModePlaceStateContent extends FigModifyingModeImpl{ //////////////////////////////////////////////////////////////// // instance variables protected Object _content; protected String _instructions; protected CmdCreateStateContent _contentCreator;
//////////////////////////////////////////////////////////////// // constructor public ModePlaceStateContent(CmdCreateStateContent contentCreator, Stringinstructions) { _contentCreator = contentCreator; _instructions = instructions; }
//////////////////////////////////////////////////////////////// // user feedback /** A string to be shown in the status bar of the Editor when this * mode is on top of the ModeManager. */ public String instructions() { if(_instructions == null) _instructions = ""; return _instructions; }
/** By default all creation modes use CROSSHAIR_CURSOR. */ public Cursor getInitialCursor() { return Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR); }
//////////////////////////////////////////////////////////////// // event handlers public void mousePressed(MouseEvent me) { if (me.isConsumed()) return; start(); editor = Globals.curEditor(); int x = me.getX(), y = me.getY(); Fig underMouse = editor.hit(x, y); if (underMouse == null) return; if (!(underMouse instanceof FigInteractionState)) return; FigInteractionState fig = (FigInteractionState)underMouse; Object owner = fig.getOwner(); if (!(owner instanceof InteractionState)) return; InteractionState state = (InteractionState)owner;
124
Class contentClass = (Class)_contentCreator.getArg("className"); if (contentClass == InteractionSubState.class) { InteractionSubState sub =(InteractionSubState)_contentCreator.makeContent(state); if (sub != null) { sub.setOwner(state); state.addSubState(sub); } }else { if (contentClass == ExchangedInformation.class) { ExchangedInformation info =(ExchangedInformation)_contentCreator.makeContent(state); if (info == null) return; InteractionSubState sub = fig.hitSubState(me.getX(),me.getY()); int position = fig.positionForNewInfo(x, y); //ainda naoimplementado if(sub != null) sub.addExchangedInformation(/*position,*/ info); else state.addExchangedInformation(/*position,*/ info); }else return; } fig.rebuild(); editor.damaged(underMouse); me.consume(); }
public void mouseExited(MouseEvent me) { me.consume(); }
public void mouseMoved(MouseEvent me) { me.consume(); }
public void mouseEntered(MouseEvent me) { me.consume(); }
public void mouseDragged(MouseEvent me) { mouseMoved(me); }
public void mouseReleased(MouseEvent me) { done(); me.consume(); }
public void done() { super.done(); _content = null; _instructions = null; }}
///////////////////////////////////////////////////////////////// arquivo: br/ufsc/uid/application/ExchangedInformationDialog.javapackage br.ufsc.uid.application;import br.ufsc.uid.*;import java.awt.*;import java.awt.event.*;import javax.swing.*;
public class ExchangedInformationDialog extends JDialog{ private ExchangedInformation exchangedInfo; private InteractionState ownerState; private DataItem dataItem; private Structure structure; private String text; private EnumeratedUserInput enumInput; private ButtonGroup bgExchangedType; private ButtonGroup bgInfoType; private ButtonGroup bgDomain; private ButtonGroup bgMultiplicity; private ButtonGroup bgSelection; private JRadioButton rbUserInput;
125
private JRadioButton rbSystemOutput; private JRadioButton rbDataItem; private JRadioButton rbStructure; private JRadioButton rbText; private JCheckBox chbExchangedInfoOptional; private JLabel lName; private JTextField tfText; private JTextField tfName; private JLabel lDomain; private JRadioButton rbDomainSimple; private JRadioButton rbDomainEnumerated; private JTextField tfDomainSimple; private JComboBox cmbDomainEnumerated; private JButton bDomainEnumeratedAdd; private JButton bDomainEnumeratedRemove; private JLabel lMultiplicity; private JRadioButton rbMultiplicityFixed; private JRadioButton rbMultiplicityRange; private JRadioButton rbMultiplicityUndefined; private JTextField tfMultiplicityFixed; private JTextField tfMultiplicityRangeMin; private JTextField tfMultiplicityRangeMax; private JLabel lStructureItem; private JComboBox cmbStructureItems; private JButton bStructureItemAdd; private JButton bStructureItemRemove; private JButton bOk; private JButton bCancel; private JCheckBox chbParametrized; private JComboBox cmbParametrized; private JButton bParametrizedAdd; private JButton bParametrizedRemove; private JLabel lMultiplicityRangeMin; private JLabel lMultiplicityRangeMax; private JRadioButton rbEnumeratedUserInput; private JLabel lEnumeratedOptions; private JComboBox cmbEnumeratedOptions; private JButton bEnumeratedOptionsAdd; private JButton bEnumeratedOptionsRemove; private JLabel lSelection; private JRadioButton rbSelectionSimple; private JRadioButton rbSelection; private JRadioButton rbSelectionUndefined; private JTextField tfSelectionMin; private JLabel lSelectionMax; private JTextField tfSelectionMax; private JLabel lParameterName; private JTextField tfParameterName; private JTextField tfSelectionSimple;
public ExchangedInformationDialog(JFrame parent, ExchangedInformation info,InteractionState owner) { super(parent, "Exchanged Information", true); exchangedInfo = info; info = exchangedInfo; // necessário? ownerState = owner; // primeiro constroi todos os componentes da interface, com localizacao etudo mais // dai dar set visible(false) em quase todos // se o info for nulo, deixa assim, senao, set visible true onde fornecessario, e preenche campos onde for necessario // qdo dah OK, checa todos os campos pra ver se ta tudo certo e cria oobjeto novo, atribuindo para info (exchangedinfo) ExchangedInformationDialogLayout customLayout = newExchangedInformationDialogLayout(); getContentPane().setFont(new Font("Helvetica", Font.PLAIN, 12)); getContentPane().setLayout(customLayout); bgExchangedType = new ButtonGroup(); bgInfoType = new ButtonGroup(); bgDomain = new ButtonGroup(); bgMultiplicity = new ButtonGroup(); bgSelection = new ButtonGroup(); rbUserInput = new JRadioButton("User input", false); bgExchangedType.add(rbUserInput); getContentPane().add(rbUserInput); rbSystemOutput = new JRadioButton("System output", false);
126
bgExchangedType.add(rbSystemOutput); getContentPane().add(rbSystemOutput); rbDataItem = new JRadioButton("Data item", false); bgInfoType.add(rbDataItem); getContentPane().add(rbDataItem); rbStructure = new JRadioButton("Structure", false); bgInfoType.add(rbStructure); getContentPane().add(rbStructure); rbText = new JRadioButton("Text", false); bgInfoType.add(rbText); getContentPane().add(rbText); chbExchangedInfoOptional = new JCheckBox("Optional"); getContentPane().add(chbExchangedInfoOptional); lName = new JLabel("Name"); getContentPane().add(lName); tfName = new JTextField(""); getContentPane().add(tfName); lDomain = new JLabel("Domain"); getContentPane().add(lDomain); rbDomainSimple = new JRadioButton("Simple", false); bgDomain.add(rbDomainSimple); getContentPane().add(rbDomainSimple); rbDomainEnumerated = new JRadioButton("Enumerated", false); bgDomain.add(rbDomainEnumerated); getContentPane().add(rbDomainEnumerated); tfDomainSimple = new JTextField(""); getContentPane().add(tfDomainSimple); cmbDomainEnumerated = new JComboBox(); getContentPane().add(cmbDomainEnumerated); bDomainEnumeratedAdd = new JButton("Add"); getContentPane().add(bDomainEnumeratedAdd); bDomainEnumeratedRemove = new JButton("Remove"); getContentPane().add(bDomainEnumeratedRemove); lMultiplicity = new JLabel("Multiplicity"); getContentPane().add(lMultiplicity); rbMultiplicityFixed = new JRadioButton("Fixed", false); bgMultiplicity.add(rbMultiplicityFixed); getContentPane().add(rbMultiplicityFixed); rbMultiplicityRange = new JRadioButton("Range", false); bgMultiplicity.add(rbMultiplicityRange); getContentPane().add(rbMultiplicityRange); rbMultiplicityUndefined = new JRadioButton("Undefined", false); bgMultiplicity.add(rbMultiplicityUndefined); getContentPane().add(rbMultiplicityUndefined); tfMultiplicityFixed = new JTextField(""); getContentPane().add(tfMultiplicityFixed); tfMultiplicityRangeMin = new JTextField(""); getContentPane().add(tfMultiplicityRangeMin); tfMultiplicityRangeMax = new JTextField(""); getContentPane().add(tfMultiplicityRangeMax); lStructureItem = new JLabel("Structure items"); getContentPane().add(lStructureItem); cmbStructureItems = new JComboBox(); getContentPane().add(cmbStructureItems); bStructureItemAdd = new JButton("Add"); getContentPane().add(bStructureItemAdd); bStructureItemRemove = new JButton("Remove"); getContentPane().add(bStructureItemRemove); bOk = new JButton("OK"); getContentPane().add(bOk); getRootPane().setDefaultButton(bOk); bCancel = new JButton("Cancel"); getContentPane().add(bCancel); chbParametrized = new JCheckBox("Parametrized"); getContentPane().add(chbParametrized); cmbParametrized = new JComboBox(); getContentPane().add(cmbParametrized); bParametrizedAdd = new JButton("Add"); getContentPane().add(bParametrizedAdd); bParametrizedRemove = new JButton("Remove"); getContentPane().add(bParametrizedRemove); lMultiplicityRangeMin = new JLabel("Min"); getContentPane().add(lMultiplicityRangeMin); lMultiplicityRangeMax = new JLabel("Max"); getContentPane().add(lMultiplicityRangeMax); rbEnumeratedUserInput = new JRadioButton("Enumerated user input", false); bgInfoType.add(rbEnumeratedUserInput);
127
getContentPane().add(rbEnumeratedUserInput); lEnumeratedOptions = new JLabel("Enumerated options"); getContentPane().add(lEnumeratedOptions); cmbEnumeratedOptions = new JComboBox(); getContentPane().add(cmbEnumeratedOptions); bEnumeratedOptionsAdd = new JButton("Add"); getContentPane().add(bEnumeratedOptionsAdd); bEnumeratedOptionsRemove = new JButton("Remove"); getContentPane().add(bEnumeratedOptionsRemove); lSelection = new JLabel("Selection"); getContentPane().add(lSelection); rbSelectionSimple = new JRadioButton("Simple", false); bgSelection.add(rbSelectionSimple); getContentPane().add(rbSelectionSimple); rbSelection = new JRadioButton("Min", false); bgSelection.add(rbSelection); getContentPane().add(rbSelection); rbSelectionUndefined = new JRadioButton("Undefined", false); bgSelection.add(rbSelectionUndefined); getContentPane().add(rbSelectionUndefined); tfSelectionMin = new JTextField(""); getContentPane().add(tfSelectionMin); lSelectionMax = new JLabel("Max"); getContentPane().add(lSelectionMax); tfSelectionMax = new JTextField(""); getContentPane().add(tfSelectionMax); lParameterName = new JLabel("Parameter name"); getContentPane().add(lParameterName); tfParameterName = new JTextField(""); getContentPane().add(tfParameterName); tfText = new JTextField(""); getContentPane().add(tfText); tfSelectionSimple = new JTextField(""); getContentPane().add(tfSelectionSimple); setSize(getPreferredSize());
ActionListener listenerUserInput = new ActionListener() { public void actionPerformed(ActionEvent event) { setDataItemEnabled(true); setStructureEnabled(true); setTextEnabled(false); setEnumeratedUserInputEnabled(true); setNameEnabled(false); setParameterNameEnabled(false); setDomainEnabled(false); setMultiplicityEnabled(false); setStructureItemsEnabled(false); setEnumeratedOptionsEnabled(false); setSelectionEnabled(false); setParametrizedEnabled(false); } }; rbUserInput.addActionListener(listenerUserInput);
ActionListener listenerSystemOutput = new ActionListener() { public void actionPerformed(ActionEvent event) { setDataItemEnabled(true); setStructureEnabled(true); setTextEnabled(true); setEnumeratedUserInputEnabled(false); setNameEnabled(false); setParameterNameEnabled(false); setDomainEnabled(false); setMultiplicityEnabled(false); setStructureItemsEnabled(false); setEnumeratedOptionsEnabled(false); setSelectionEnabled(false); setParametrizedEnabled(false); } }; rbSystemOutput.addActionListener(listenerSystemOutput);
ActionListener listenerDataItem = new ActionListener()
128
{ public void actionPerformed(ActionEvent event) { if(chbParametrized.isSelected()) { setNameEnabled(false); setParameterNameEnabled(true); }else { setNameEnabled(true); setParameterNameEnabled(false); } setDomainEnabled(true); setMultiplicityEnabled(true); setStructureItemsEnabled(false); setEnumeratedOptionsEnabled(false); setSelectionEnabled(false); setParametrizedEnabled(true); } }; rbDataItem.addActionListener(listenerDataItem);
ActionListener listenerStructure = new ActionListener() { public void actionPerformed(ActionEvent event) { if(chbParametrized.isSelected()) { setNameEnabled(false); setParameterNameEnabled(true); }else { setNameEnabled(true); setParameterNameEnabled(false); } setDomainEnabled(false); setMultiplicityEnabled(true); setStructureItemsEnabled(true); setEnumeratedOptionsEnabled(false); setSelectionEnabled(false); setParametrizedEnabled(true); } }; rbStructure.addActionListener(listenerStructure);
ActionListener listenerText = new ActionListener() { public void actionPerformed(ActionEvent event) { setEnumeratedUserInputEnabled(false); setNameEnabled(false); setParameterNameEnabled(false); setDomainEnabled(false); setMultiplicityEnabled(false); setStructureItemsEnabled(false); setEnumeratedOptionsEnabled(false); setSelectionEnabled(false); setParametrizedEnabled(false); } }; rbText.addActionListener(listenerText);
ActionListener listenerEnumeratedUserInput = new ActionListener() { public void actionPerformed(ActionEvent event) { setNameEnabled(true); setParameterNameEnabled(false); setDomainEnabled(false); setMultiplicityEnabled(false); setStructureItemsEnabled(false); setEnumeratedOptionsEnabled(true); setSelectionEnabled(true); setParametrizedEnabled(true); }
129
}; rbEnumeratedUserInput.addActionListener(listenerEnumeratedUserInput);
ActionListener listenerDomainEnumeratedAdd = new ActionListener() { public void actionPerformed(ActionEvent event) { if(rbDomainEnumerated.isSelected()) { String enumeratedDomainItem =JOptionPane.showInputDialog (null, "Enter the enumerated domainelement", "Domain Element", JOptionPane.QUESTION_MESSAGE); if(enumeratedDomainItem != null &&!enumeratedDomainItem.equals(""))
cmbDomainEnumerated.addItem(enumeratedDomainItem); } } }; bDomainEnumeratedAdd.addActionListener(listenerDomainEnumeratedAdd);
ActionListener listenerDomainEnumeratedRemove = new ActionListener() { public void actionPerformed(ActionEvent event) { if(rbDomainEnumerated.isSelected())
cmbDomainEnumerated.removeItem(cmbDomainEnumerated.getSelectedItem()); } };
bDomainEnumeratedRemove.addActionListener(listenerDomainEnumeratedRemove);
ActionListener listenerStructureItemAdd = new ActionListener() { public void actionPerformed(ActionEvent event) { // String structureItem = abre dialogo pra pegaritem ou estrutura } }; bStructureItemAdd.addActionListener(listenerStructureItemAdd);
ActionListener listenerStructureItemRemove = new ActionListener() { public void actionPerformed(ActionEvent event) {
cmbStructureItems.removeItem(cmbStructureItems.getSelectedItem()); } }; bStructureItemRemove.addActionListener(listenerStructureItemRemove);
ActionListener listenerEnumeratedOptionsAdd = new ActionListener() { public void actionPerformed(ActionEvent event) { String enumeratedOption =JOptionPane.showInputDialog (null, "Enter a option for user selection","Option", JOptionPane.QUESTION_MESSAGE); if(enumeratedOption != null &&!enumeratedOption.equals(""))
cmbEnumeratedOptions.addItem(enumeratedOption); } }; bEnumeratedOptionsAdd.addActionListener(listenerEnumeratedOptionsAdd);
ActionListener listenerEnumeratedOptionsRemove = new ActionListener() { public void actionPerformed(ActionEvent event) {
cmbEnumeratedOptions.removeItem(cmbEnumeratedOptions.getSelectedItem()); }
130
};
bEnumeratedOptionsRemove.addActionListener(listenerEnumeratedOptionsRemove);
ActionListener listenerParametrized = new ActionListener() { public void actionPerformed(ActionEvent event) { if(chbParametrized.isSelected()) { setParameterNameEnabled(true); setNameEnabled(false); }else { setParameterNameEnabled(false); setNameEnabled(true); } } }; chbParametrized.addActionListener(listenerParametrized);
ActionListener listenerParametrizedAdd = new ActionListener() { public void actionPerformed(ActionEvent event) { if(chbParametrized.isSelected()) { String parameter = JOptionPane.showInputDialog (null, "Enter a parameter value", "ParameterValue", JOptionPane.QUESTION_MESSAGE); if(parameter != null && !parameter.equals("")) cmbParametrized.addItem(parameter); } } }; bParametrizedAdd.addActionListener(listenerParametrizedAdd);
ActionListener listenerParametrizedRemove = new ActionListener() { public void actionPerformed(ActionEvent event) {
cmbParametrized.removeItem(cmbParametrized.getSelectedItem()); } }; bParametrizedRemove.addActionListener(listenerParametrizedRemove);
ActionListener listenerOk = new ActionListener() { public void actionPerformed(ActionEvent event) { if(rbDataItem.isSelected()) { if(validateName() && validateDomain() &&validateMultiplicity() && validateParametrized()) { String name = null; Domain domain = null; Multiplicity mult = null; boolean optional =chbExchangedInfoOptional.isSelected(); if(chbParametrized.isSelected()) name = tfParameterName.getText(); else name = tfName.getText(); if(rbDomainSimple.isSelected()) domain = newDomain(tfDomainSimple.getText()); if(rbDomainEnumerated.isSelected()) { domain = new Domain(); domain.setEnumerated(); for(int i = 0; i <cmbDomainEnumerated.getItemCount(); i++)
domain.addEnumerated((String)cmbDomainEnumerated.getItemAt(i));
131
} if(rbMultiplicityFixed.isSelected()) mult = newMultiplicity(Integer.parseInt(tfMultiplicityFixed.getText())); if(rbMultiplicityRange.isSelected()) mult = newMultiplicity(Integer.parseInt(tfMultiplicityRangeMin.getText()),Integer.parseInt(tfMultiplicityRangeMax.getText())); if(rbMultiplicityUndefined.isSelected()) mult = new Multiplicity(); dataItem = new DataItem(name, domain, mult); if(chbParametrized.isSelected()) { dataItem.setParametrized(true); for(int i = 0; i <cmbParametrized.getItemCount(); i++)
dataItem.addParameter((String)cmbParametrized.getItemAt(i)); }else dataItem.setParametrized(false); if(rbUserInput.isSelected()) exchangedInfo = newUserInput(dataItem); if(rbSystemOutput.isSelected()) exchangedInfo = newSystemOutput(dataItem); exchangedInfo.setOptional(optional); exchangedInfo.setOwner(ownerState); setVisible(false); // fecha diálogo comobjeto de informação criado } } if(rbStructure.isSelected()) { if(validateName() && validateMultiplicity() &&validateStructureItems() && validateParametrized()) { String name = null; Multiplicity mult = null; boolean optional =chbExchangedInfoOptional.isSelected(); if(chbParametrized.isSelected()) name = tfParameterName.getText(); else name = tfName.getText(); if(rbMultiplicityFixed.isSelected()) mult = newMultiplicity(Integer.parseInt(tfMultiplicityFixed.getText())); if(rbMultiplicityRange.isSelected()) mult = newMultiplicity(Integer.parseInt(tfMultiplicityRangeMin.getText()),Integer.parseInt(tfMultiplicityRangeMax.getText())); if(rbMultiplicityUndefined.isSelected()) mult = new Multiplicity(); for(int i = 0; i <cmbStructureItems.getItemCount(); i++) structure = new Structure(name, mult); if(chbParametrized.isSelected()) { structure.setParametrized(true); for(int i = 0; i <cmbParametrized.getItemCount(); i++)
structure.addParameter((String)cmbParametrized.getItemAt(i)); }else structure.setParametrized(false); if(rbUserInput.isSelected()) exchangedInfo = newUserInput(structure); if(rbSystemOutput.isSelected()) exchangedInfo = newSystemOutput(structure); exchangedInfo.setOptional(optional); exchangedInfo.setOwner(ownerState); setVisible(false); // fecha diálogo comobjeto de informação criado }
132
} if(rbEnumeratedUserInput.isSelected()) { if(validateName() && validateEnumeratedOptions() &&validateSelection() && validateParametrized()) { String name = null; Multiplicity selection = null; boolean optional =chbExchangedInfoOptional.isSelected(); if(chbParametrized.isSelected()) name = tfParameterName.getText(); else name = tfName.getText(); if(rbSelectionSimple.isSelected()) selection = newMultiplicity(Integer.parseInt(tfSelectionSimple.getText())); if(rbSelection.isSelected()) selection = newMultiplicity(Integer.parseInt(tfSelectionMin.getText()),Integer.parseInt(tfSelectionMax.getText())); if(rbSelectionUndefined.isSelected()) selection = new Multiplicity(); enumInput = new EnumeratedUserInput(name,selection); for(int i = 0; i <cmbEnumeratedOptions.getItemCount(); i++)
enumInput.addOption((String)cmbEnumeratedOptions.getItemAt(i)); if(chbParametrized.isSelected()) { enumInput.setParametrized(true); for(int i = 0; i <cmbParametrized.getItemCount(); i++)
enumInput.addParameter((String)cmbParametrized.getItemAt(i)); }else enumInput.setParametrized(false); exchangedInfo = new UserInput(enumInput); exchangedInfo.setOptional(optional); exchangedInfo.setOwner(ownerState); setVisible(false); // fecha diálogo comobjeto de informação criado } } if(rbText.isSelected()) { if(validateText()) { boolean optional =chbExchangedInfoOptional.isSelected(); exchangedInfo = newSystemOutput(tfText.getText()); exchangedInfo.setOptional(optional); exchangedInfo.setOwner(ownerState); setVisible(false); // fecha diálogo comobjeto de informação criado } } // ...nao selecionou nem user input nem system output } }; bOk.addActionListener(listenerOk);
ActionListener listenerCancel = new ActionListener() { public void actionPerformed(ActionEvent event) { exchangedInfo = null; setVisible(false); } }; bCancel.addActionListener(listenerCancel);
addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent we)
133
{ } });
setLocationRelativeTo(parent); setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); // Não fecha se clicar noX setResizable(false); pack(); //carrega informações de exchangedInfo, se necessário if(exchangedInfo == null) { // exchangedInfo vai ser criado pelo usuário rbDomainSimple.setSelected(true); tfDomainSimple.setText(""); rbMultiplicityFixed.setSelected(true); tfMultiplicityFixed.setText("1"); rbSelectionSimple.setSelected(true); tfSelectionSimple.setText("1"); setDataItemEnabled(false); setStructureEnabled(false); setTextEnabled(false); setEnumeratedUserInputEnabled(false); setNameEnabled(false); setParameterNameEnabled(false); setDomainEnabled(false); setMultiplicityEnabled(false); setStructureItemsEnabled(false); setEnumeratedOptionsEnabled(false); setSelectionEnabled(false); setParametrizedEnabled(false); rbDomainSimple.setSelected(true); }else { // carrega valores de exchangedInfo para que o usuário modifique if(exchangedInfo.getOptional()) chbExchangedInfoOptional.setSelected(true);
if(exchangedInfo instanceof UserInput) { // user input rbUserInput.setSelected(true); Information information =((UserInput)exchangedInfo).getInfo(); if(information instanceof DataItem) { setDataItemEnabled(true); dataItem = (DataItem)information; loadDataItem(); } if(information instanceof Structure) { setStructureEnabled(true); structure = (Structure)information; loadStructure(); } if(information instanceof EnumeratedUserInput) { setEnumeratedUserInputEnabled(true); enumInput = (EnumeratedUserInput)information; loadEnumeratedUserInput(); } }else { // system output if(exchangedInfo instanceof SystemOutput) { rbSystemOutput.setSelected(true); Object information =((SystemOutput)exchangedInfo).getInfo(); if(information instanceof String) { setTextEnabled(true); text = (String)information; loadText(); } if(information instanceof DataItem) { setDataItemEnabled(true); dataItem = (DataItem)information; loadDataItem();
134
} if(information instanceof Structure) { setStructureEnabled(true); structure = (Structure)information; loadStructure(); } } } } setVisible(true); }
private void setDataItemEnabled(boolean value) { rbDataItem.setEnabled(value); } private void setStructureEnabled(boolean value) { rbStructure.setEnabled(value);} private void setTextEnabled(boolean value) { rbText.setEnabled(value); tfText.setVisible(value); } private void setEnumeratedUserInputEnabled(boolean value) {rbEnumeratedUserInput.setEnabled(value); } private void setNameEnabled(boolean value) { lName.setEnabled(value); tfName.setVisible(value); } private void setParameterNameEnabled(boolean value) { lParameterName.setEnabled(value); tfParameterName.setVisible(value); } private void setDomainEnabled(boolean value) { lDomain.setEnabled(value); rbDomainSimple.setEnabled(value); rbDomainEnumerated.setEnabled(value); tfDomainSimple.setVisible(value); cmbDomainEnumerated.setVisible(value); bDomainEnumeratedAdd.setVisible(value); bDomainEnumeratedRemove.setVisible(value); } private void setMultiplicityEnabled(boolean value) { lMultiplicity.setEnabled(value); rbMultiplicityFixed.setEnabled(value); rbMultiplicityRange.setEnabled(value); rbMultiplicityUndefined.setEnabled(value); tfMultiplicityFixed.setVisible(value); lMultiplicityRangeMin.setVisible(value); tfMultiplicityRangeMin.setVisible(value); lMultiplicityRangeMax.setVisible(value); tfMultiplicityRangeMax.setVisible(value); rbMultiplicityUndefined.setEnabled(value); } private void setStructureItemsEnabled(boolean value) { lStructureItem.setEnabled(value); cmbStructureItems.setVisible(value); bStructureItemAdd.setVisible(value); bStructureItemRemove.setVisible(value); } private void setEnumeratedOptionsEnabled(boolean value) { lEnumeratedOptions.setEnabled(value); cmbEnumeratedOptions.setVisible(value); bEnumeratedOptionsAdd.setVisible(value); bEnumeratedOptionsRemove.setVisible(value); } private void setSelectionEnabled(boolean value) { lSelection.setEnabled(value); rbSelectionSimple.setEnabled(value); tfSelectionSimple.setVisible(value); rbSelection.setEnabled(value); tfSelectionMin.setVisible(value);
135
lSelectionMax.setVisible(value); tfSelectionMax.setVisible(value); rbSelectionUndefined.setEnabled(value); } private void setParametrizedEnabled(boolean value) { chbParametrized.setEnabled(value); cmbParametrized.setVisible(value); bParametrizedAdd.setVisible(value); bParametrizedRemove.setVisible(value); } private void loadDataItem() // carrega dataitem na interface {// setup name and parameters if(dataItem.getParametrized()) { setNameEnabled(false); setParameterNameEnabled(true); tfParameterName.setText(dataItem.getName()); chbParametrized.setSelected(true); for(int i = 0; i < dataItem.getParametersSize(); i++) cmbParametrized.addItem(dataItem.getParameter(i)); }else { setNameEnabled(true); setParameterNameEnabled(false); tfName.setText(dataItem.getName()); } // setup domain setDomainEnabled(true); switch(dataItem.getDomain().getType()) { case Domain.SIMPLE: rbDomainSimple.setSelected(true); tfDomainSimple.setText(dataItem.getDomain().getSimple()); break; case Domain.ENUMERATED: rbDomainEnumerated.setSelected(true); for(int i = 0; i <dataItem.getDomain().getEnumeratedSize(); i++)
cmbDomainEnumerated.addItem(dataItem.getDomain().getEnumerated(i)); break; case Domain.NOT_DEFINED: rbDomainSimple.setSelected(true); tfDomainSimple.setText(""); break; default: break; } // setup multiplicity setMultiplicityEnabled(true); switch(dataItem.getMultiplicity().getType()) { case Multiplicity.FIXED: rbMultiplicityFixed.setSelected(true);
tfMultiplicityFixed.setText(Integer.toString(dataItem.getMultiplicity().getFixedValue())); break; case Multiplicity.RANGE: rbMultiplicityRange.setSelected(true);
tfMultiplicityRangeMin.setText(Integer.toString(dataItem.getMultiplicity().getRangeValueLower()));
tfMultiplicityRangeMax.setText(Integer.toString(dataItem.getMultiplicity().getRangeValueUpper())); break; case Multiplicity.NOT_DEFINED: rbMultiplicityUndefined.setSelected(true); break; default: break; } } private void loadStructure() // carrega structure na interface {
136
// setup name and parameters if(structure.getParametrized()) { setNameEnabled(false); setParameterNameEnabled(true); tfParameterName.setText(structure.getName()); chbParametrized.setSelected(true); for(int i = 0; i < structure.getParametersSize(); i++) cmbParametrized.addItem(structure.getParameter(i)); }else { setNameEnabled(true); setParameterNameEnabled(false); tfName.setText(structure.getName()); } // setup multiplicity setMultiplicityEnabled(true); switch(structure.getMultiplicity().getType()) { case Multiplicity.FIXED: rbMultiplicityFixed.setSelected(true);
tfMultiplicityFixed.setText(Integer.toString(structure.getMultiplicity().getFixedValue())); break; case Multiplicity.RANGE: rbMultiplicityRange.setSelected(true);
tfMultiplicityRangeMin.setText(Integer.toString(structure.getMultiplicity().getRangeValueLower()));
tfMultiplicityRangeMax.setText(Integer.toString(structure.getMultiplicity().getRangeValueUpper())); break; case Multiplicity.NOT_DEFINED: rbMultiplicityUndefined.setSelected(true); break; default: break; } //setup structure items setStructureItemsEnabled(true); /*for(int i = 0; i < structure.getSize(); i++) cmbStructureItems.addItem(structure.getInfo(i)....toString e tal*/ } private void loadEnumeratedUserInput() // carrega enuminput na interface {// setup name and parameters if(enumInput.getParametrized()) { setNameEnabled(false); setParameterNameEnabled(true); tfParameterName.setText(enumInput.getName()); chbParametrized.setSelected(true); for(int i = 0; i < enumInput.getParametersSize(); i++) cmbParametrized.addItem(enumInput.getParameter(i)); }else { setNameEnabled(true); setParameterNameEnabled(false); tfName.setText(enumInput.getName()); } // setup enumerated options setEnumeratedUserInputEnabled(true); for(int i = 0; i < enumInput.getOptionsSize(); i++) cmbEnumeratedOptions.addItem(enumInput.getOption(i)); // setup selection setSelectionEnabled(true); switch(enumInput.getSelection().getType()) { case Multiplicity.FIXED: rbSelectionSimple.setSelected(true);
tfSelectionSimple.setText(Integer.toString(enumInput.getSelection().getFixedValue())); break; case Multiplicity.RANGE: rbSelection.setSelected(true);
137
tfSelectionMin.setText(Integer.toString(enumInput.getSelection().getRangeValueLower()));
tfSelectionMax.setText(Integer.toString(enumInput.getSelection().getRangeValueUpper())); break; case Multiplicity.NOT_DEFINED: rbSelectionUndefined.setSelected(true); break; default: break; } } private void loadText() {// setup text tfText.setText(text); } //validateName: checa o chbParametrized, se selected, nome é obrigatório, senaoem branco é permitido private boolean validateName() { if(chbParametrized.isSelected()) { if(tfParameterName.getText() == null ||(tfParameterName.getText()).equals("")) { JOptionPane.showMessageDialog(this, "Parameter name shouldnot be empty", "Error", JOptionPane.WARNING_MESSAGE); return false; } } if(tfName.getText() == null) tfName.setText(""); return true; } private boolean validateDomain() { if(rbDomainSimple.isSelected()) { if(tfDomainSimple.getText() == null) tfName.setText(""); return true; }else { if(cmbDomainEnumerated.getItemCount() < 1) { JOptionPane.showMessageDialog(this, "Enumerated domain isempty", "Error", JOptionPane.WARNING_MESSAGE); return false; } return true; } } private boolean validateMultiplicity() { if(rbMultiplicityFixed.isSelected()) { try { int x = Integer.parseInt(tfMultiplicityFixed.getText()); }catch(NumberFormatException nfe){ JOptionPane.showMessageDialog(this, "Value for fixedmultiplicity is invalid", "Error", JOptionPane.WARNING_MESSAGE); return false; } return true; } if(rbMultiplicityRange.isSelected()) { try { int x = Integer.parseInt(tfMultiplicityRangeMin.getText()); int y = Integer.parseInt(tfMultiplicityRangeMax.getText()); }catch(NumberFormatException nfe){ JOptionPane.showMessageDialog(this, "Value for rangemultiplicity is invalid", "Error", JOptionPane.WARNING_MESSAGE); return false; }
138
return true; } if(rbMultiplicityUndefined.isSelected()) return true; return false; } private boolean validateParametrized() { if(chbParametrized.isSelected()) { if(cmbParametrized.getItemCount() < 1) { JOptionPane.showMessageDialog(this, "Parametrized valuesare empty", "Error", JOptionPane.WARNING_MESSAGE); return false; } return true; } return true; } private boolean validateEnumeratedOptions() { if(cmbEnumeratedOptions.getItemCount() < 1) { JOptionPane.showMessageDialog(this, "Enumerated options areempty", "Error", JOptionPane.WARNING_MESSAGE); return false; } return true; } private boolean validateSelection() { if(rbSelectionSimple.isSelected()) { try { int x = Integer.parseInt(tfSelectionSimple.getText()); }catch(NumberFormatException nfe){ JOptionPane.showMessageDialog(this, "Value for simpleselection is invalid", "Error", JOptionPane.WARNING_MESSAGE); return false; } return true; } if(rbSelection.isSelected()) { try { int x = Integer.parseInt(tfSelectionMin.getText()); int y = Integer.parseInt(tfSelectionMax.getText()); }catch(NumberFormatException nfe){ JOptionPane.showMessageDialog(this, "Value for selection isinvalid", "Error", JOptionPane.WARNING_MESSAGE); return false; } return true; } if(rbSelectionUndefined.isSelected()) return true; return false; } private boolean validateStructureItems() { if(cmbStructureItems.getItemCount() < 1) { JOptionPane.showMessageDialog(this, "Structure items are empty","Error", JOptionPane.WARNING_MESSAGE); return false; } return true; } private boolean validateText() { if(tfText.getText() == null) tfText.setText(""); return true; }
public ExchangedInformation getInfo()
139
{ return exchangedInfo; }}
class ExchangedInformationDialogLayout implements LayoutManager {
public ExchangedInformationDialogLayout() { }
public void addLayoutComponent(String name, Component comp) { }
public void removeLayoutComponent(Component comp) { }
public Dimension preferredLayoutSize(Container parent) { Dimension dim = new Dimension(0, 0); Insets insets = parent.getInsets(); dim.width = 476 + insets.left + insets.right; dim.height = 524 + insets.top + insets.bottom; return dim; }
public Dimension minimumLayoutSize(Container parent) { Dimension dim = new Dimension(0, 0); return dim; }
public void layoutContainer(Container parent) { Insets insets = parent.getInsets(); Component c; c = parent.getComponent(0); if (c.isVisible()) {c.setBounds(insets.left+8,insets.top+8,104,24);} c = parent.getComponent(1); if (c.isVisible()) {c.setBounds(insets.left+8,insets.top+32,112,24);} c = parent.getComponent(2); if (c.isVisible()) {c.setBounds(insets.left+24,insets.top+56,216,24);} c = parent.getComponent(3); if (c.isVisible()) {c.setBounds(insets.left+24,insets.top+80,216,24);} c = parent.getComponent(4); if (c.isVisible()) {c.setBounds(insets.left+24,insets.top+104,56,24);} c = parent.getComponent(5); if (c.isVisible()) {c.setBounds(insets.left+120,insets.top+16,104,24);} c = parent.getComponent(6); if (c.isVisible()) {c.setBounds(insets.left+48,insets.top+152,40,24);} c = parent.getComponent(7); if (c.isVisible()) {c.setBounds(insets.left+88,insets.top+152,128,24);} c = parent.getComponent(8); if (c.isVisible()) {c.setBounds(insets.left+48,insets.top+192,48,24);} c = parent.getComponent(9); if (c.isVisible()) {c.setBounds(insets.left+96,insets.top+184,64,24);} c = parent.getComponent(10); if (c.isVisible()) {c.setBounds(insets.left+96,insets.top+208,96,24);} c = parent.getComponent(11); if (c.isVisible()) {c.setBounds(insets.left+160,insets.top+184,112,24);} c = parent.getComponent(12); if (c.isVisible()) {c.setBounds(insets.left+192,insets.top+208,136,24);} c = parent.getComponent(13); if (c.isVisible()) {c.setBounds(insets.left+328,insets.top+208,56,24);} c = parent.getComponent(14); if (c.isVisible()) {c.setBounds(insets.left+384,insets.top+208,88,24);} c = parent.getComponent(15); if (c.isVisible()) {c.setBounds(insets.left+48,insets.top+264,64,24);} c = parent.getComponent(16); if (c.isVisible()) {c.setBounds(insets.left+112,insets.top+240,64,24);} c = parent.getComponent(17); if (c.isVisible()) {c.setBounds(insets.left+112,insets.top+264,64,24);} c = parent.getComponent(18); if (c.isVisible()) {c.setBounds(insets.left+112,insets.top+288,96,24);} c = parent.getComponent(19); if (c.isVisible()) {c.setBounds(insets.left+176,insets.top+240,56,24);} c = parent.getComponent(20); if (c.isVisible()) {c.setBounds(insets.left+208,insets.top+264,48,24);} c = parent.getComponent(21); if (c.isVisible()) {c.setBounds(insets.left+296,insets.top+264,48,24);} c = parent.getComponent(22); if (c.isVisible()) {c.setBounds(insets.left+48,insets.top+320,96,24);} c = parent.getComponent(23); if (c.isVisible()) {c.setBounds(insets.left+144,insets.top+320,136,24);}
140
c = parent.getComponent(24); if (c.isVisible()) {c.setBounds(insets.left+280,insets.top+320,56,24);} c = parent.getComponent(25); if (c.isVisible()) {c.setBounds(insets.left+336,insets.top+320,88,24);} c = parent.getComponent(26); if (c.isVisible()) {c.setBounds(insets.left+336,insets.top+496,56,24);} c = parent.getComponent(27); if (c.isVisible()) {c.setBounds(insets.left+392,insets.top+496,80,24);} c = parent.getComponent(28); if (c.isVisible()) {c.setBounds(insets.left+40,insets.top+464,104,24);} c = parent.getComponent(29); if (c.isVisible()) {c.setBounds(insets.left+144,insets.top+464,136,24);} c = parent.getComponent(30); if (c.isVisible()) {c.setBounds(insets.left+280,insets.top+464,56,24);} c = parent.getComponent(31); if (c.isVisible()) {c.setBounds(insets.left+336,insets.top+464,88,24);} c = parent.getComponent(32); if (c.isVisible()) {c.setBounds(insets.left+176,insets.top+264,32,24);} c = parent.getComponent(33); if (c.isVisible()) {c.setBounds(insets.left+264,insets.top+264,32,24);} c = parent.getComponent(34); if (c.isVisible()) {c.setBounds(insets.left+24,insets.top+128,216,24);} c = parent.getComponent(35); if (c.isVisible()) {c.setBounds(insets.left+48,insets.top+352,120,24);} c = parent.getComponent(36); if (c.isVisible()) {c.setBounds(insets.left+168,insets.top+352,136,24);} c = parent.getComponent(37); if (c.isVisible()) {c.setBounds(insets.left+304,insets.top+352,56,24);} c = parent.getComponent(38); if (c.isVisible()) {c.setBounds(insets.left+360,insets.top+352,88,24);} c = parent.getComponent(39); if (c.isVisible()) {c.setBounds(insets.left+48,insets.top+408,64,24);} c = parent.getComponent(40); if (c.isVisible()) {c.setBounds(insets.left+112,insets.top+384,64,24);} c = parent.getComponent(41); if (c.isVisible()) {c.setBounds(insets.left+112,insets.top+408,48,24);} c = parent.getComponent(42); if (c.isVisible()) {c.setBounds(insets.left+112,insets.top+432,104,24);} c = parent.getComponent(43); if (c.isVisible()) {c.setBounds(insets.left+160,insets.top+408,48,24);} c = parent.getComponent(44); if (c.isVisible()) {c.setBounds(insets.left+216,insets.top+408,32,24);} c = parent.getComponent(45); if (c.isVisible()) {c.setBounds(insets.left+248,insets.top+408,48,24);} c = parent.getComponent(46); if (c.isVisible()) {c.setBounds(insets.left+240,insets.top+152,104,24);} c = parent.getComponent(47); if (c.isVisible()) {c.setBounds(insets.left+344,insets.top+152,128,24);} c = parent.getComponent(48); if (c.isVisible()) {c.setBounds(insets.left+80,insets.top+104,184,24);} c = parent.getComponent(49); if (c.isVisible()) {c.setBounds(insets.left+176,insets.top+384,56,24);} }}
C.2 Pacote br.ufsc.uid///////////////////////////////////////////////////////////////// arquivo: br/ufsc/uid/UIDGraphModel.javapackage br.ufsc.uid;import java.util.Vector;import org.tigris.gef.graph.MutableGraphSupport;
public class UIDGraphModel extends MutableGraphSupportimplements java.io.Serializable{ //////////////////////////////////////////////////////////////// // instance variables protected String _name; protected InteractionState _initialInteractionState; protected Vector _states = new Vector(); protected Vector _transitions = new Vector(); protected Vector _preConditions = new Vector(); protected Vector _postConditions = new Vector(); protected Vector _textualNotes = new Vector();
141
//////////////////////////////////////////////////////////////// // constructors public UIDGraphModel(String name) { _name = name; }
//////////////////////////////////////////////////////////////// // accessors public String getName() { return _name; } public void setName(String name) { _name = name; } public InteractionState getInitialInteractionState() { return_initialInteractionState; } public void setInitialInteractionState(InteractionState state) {_initialInteractionState = state; }
//////////////////////////////////////////////////////////////// // interface GraphModel /** Return all interaction states in the UID */ public Vector getNodes() { return _states; }
/** Return all transitions in the UID */ public Vector getEdges() { return _transitions;}
/** Return all ports on interaction state or transition */ public Vector getPorts(Object nodeOrEdge) { if (nodeOrEdge instanceof InteractionState) return ((InteractionState)nodeOrEdge).getPorts(); //if (nodeOrEdge instanceof Transition) // return ((Transition)nodeOrEdge).getPorts(); return null; // raise exception }
/** Return the state or transition that owns the given port */ public Object getOwner(Object port) { if (port instanceof Port) return ((Port)port).getOwner(); return null; // raise exception }
/** Return all transitions going to given port */ public Vector getInEdges(Object port) { // needs-more-work: only IN edges if (port instanceof Port) return ((Port)port).getTransitions(); return null; // raise exception }
/** Return all transitions going from given port */ public Vector getOutEdges(Object port) { // needs-more-work: only OUT edges if (port instanceof Port) return ((Port)port).getTransitions(); return null; // raise exception }
/** Return one end of an transition */ public Object getSourcePort(Object edge) { if (edge instanceof Transition) return ((Transition)edge).getSourcePort(); return null; // raise exception }
/** Return the other end of a transition */ public Object getDestPort(Object edge) { if (edge instanceof Transition) return ((Transition)edge).getDestPort(); return null; // raise exception }
//////////////////////////////////////////////////////////////// // interface MutableGraphModel /** Return true if the given object is a InteractionState */ public boolean canAddNode(Object node) { return (node instanceof InteractionState); }
/** Return true if the given object is a Transition */ public boolean canAddEdge(Object edge) { return (edge instanceof Transition); }
142
/** Remove the given state from the UID */ public void removeNode(Object node) { if (node instanceof InteractionState) { InteractionState s = (InteractionState) node; if (s != null && _states.contains(s)) _states.removeElement(s); fireNodeRemoved(s); } }
/** Add the given interaction state to the UID, if valid. */ public void addNode(Object node) { if (node instanceof InteractionState) { InteractionState s = (InteractionState) node; _states.addElement(s); fireNodeAdded(s); } }
/** Add the given transition to the UID, if valid. */ public void addEdge(Object edge) { if (edge instanceof Transition) { Transition t = (Transition) edge; _transitions.addElement(t); fireEdgeAdded(t); } }
public void addNodeRelatedEdges(Object node) { }
/** Remove the given edge from the graph. */ public void removeEdge(Object edge) { if (edge instanceof Transition) { Transition t = (Transition) edge; if (t != null && _transitions.contains(t)) _transitions.removeElement(t); fireEdgeRemoved(t); } }
public void dragNode(Object node) { addNode(node); }
public boolean canConnect(Object srcPort, Object destPort) { /*if (srcPort instanceof Port && destPort instanceof Port) { Port s = (Port) srcPort; Port d = (Port) destPort; return s.canConnectTo(this, d) && d.canConnectTo(this, s); } else return false;*/ return true; }
/** Return true if the two given ports can be connected by the given * kind of edge. */ public boolean canConnect(Object srcPort, Object destPort, Class edgeClass) { if(edgeClass == br.ufsc.uid.Transition.class) return canConnect(srcPort, destPort); else return false; }
/** Contruct and add a new transition */ public Object connect(Object srcPort, Object destPort) { if (!canConnect(srcPort, destPort)) return null; Transition t = new Transition(); if (srcPort instanceof Port && destPort instanceof Port) { Port s = (Port) srcPort; Port d = (Port) destPort; t.connect(s, d); System.out.println("calling Transition.connect(port, port)"); addEdge(t); return t; }else return null;
143
}
/** Contruct and add a new transition, ignores edgeClass parameter*/ public Object connect(Object srcPort, Object destPort, Class edgeClass) { if(edgeClass == br.ufsc.uid.Transition.class) { return connect(srcPort, destPort); }else return null; }}
///////////////////////////////////////////////////////////////// arquivo: br/ufsc/uid/Interaction.javapackage br.ufsc.uid;import org.tigris.gef.graph.*;import org.tigris.gef.base.Editor;import java.util.Vector;
public abstract class Interactionimplements java.io.Serializable{ //////////////////////////////////////////////////////////////// // instance variables protected Vector _exchangedInformation; protected Vector _ports; protected Port _north, _east, _west, _south;
//////////////////////////////////////////////////////////////// // constructors public void Interaction(){ }
public void initialize() { _ports = new Vector(); _east = new Port(this); _west = new Port(this); _north = new Port(this); _south = new Port(this); addPort(_east); addPort(_west); addPort(_north); addPort(_south); _exchangedInformation = new Vector(); }
//////////////////////////////////////////////////////////////// // acessors public Port getPort(int i) { return (Port) _ports.elementAt(i); } public Vector getPorts() { return _ports; } public void setPorts(Vector ports) { _ports = ports; } public void addPort(Port p) { _ports.addElement(p); } public void addExchangedInformation(ExchangedInformation info) {_exchangedInformation.addElement(info); } public void addExchangedInformation(int position, ExchangedInformation info) {_exchangedInformation.add(position, info); } public void removeExchangedInformation(ExchangedInformation info) {_exchangedInformation.remove(info); } public Vector getExchangedInformation() { return _exchangedInformation; } public Port getNorthPort() { return _north; }; public Port getSouthPort() { return _south; }; public Port getEastPort() { return _east; }; public Port getWestPort() { return _west; }; public void setNorthPort(Port port) { _north = port; }; public void setSouthPort(Port port) { _south = port; }; public void setEastPort(Port port) { _east = port; }; public void setWestPort(Port port) { _west = port; };};
///////////////////////////////////////////////////////////////// arquivo: br/ufsc/uid/InteractionState.javapackage br.ufsc.uid;import java.util.*;import org.tigris.gef.presentation.FigNode;import org.tigris.gef.base.*;import br.ufsc.uid.presentation.FigInteractionState;import org.tigris.gef.graph.*;import java.beans.*;
144
public class InteractionState extends Interactionimplements GraphNodeHooks, java.io.Serializable{ //////////////////////////////////////////////////////////////// // instance variables protected Vector _subStates;
//////////////////////////////////////////////////////////////// // constructors public InteractionState() { }
//////////////////////////////////////////////////////////////// // acessors public void addSubState(InteractionSubState s) { System.out.println("adicionou sub estado"); _subStates.addElement(s); } public void removeSubState(InteractionSubState s) { _subStates.remove(s); } public Vector getSubStates() { return _subStates; }
//////////////////////////////////////////////////////////////// // Visualization related methods public FigNode presentationFor(Layer lay) { FigNode fn; if (lay != null) { fn = (FigNode) lay.presentationFor(this); if (fn != null) return fn; } fn = makePresentation(); return fn; }
public FigNode makePresentation() { FigInteractionState fig = new FigInteractionState(this); return fig; }
//////////////////////////////////////////////////////////////// // interface graph node hooks public boolean canConnectTo(GraphModel gm, Object otherNode, Object otherPort,Object myPort) { return true; }
public void initialize(Hashtable props) { super.initialize(); _subStates = new Vector(); }
public void postPlacement(Editor ed) { } public void dispose() { } public void setHighlight(boolean b) { } public void addPropertyChangeListener(PropertyChangeListener l) { } public void removePropertyChangeListener(PropertyChangeListener l) { } public void postConnect(GraphModel gm, Object anotherNode, Object myPort, ObjectotherPort) { } public void postDisconnect(GraphModel gm, Object anotherNode, Object myPort,Object otherPort) { }}
///////////////////////////////////////////////////////////////// arquivo: br/ufsc/uid/InteractionSubState.javapackage br.ufsc.uid;
public class InteractionSubState extends Interactionimplements java.io.Serializable{ //////////////////////////////////////////////////////////////// // instance variables
145
protected InteractionState _owner;
//////////////////////////////////////////////////////////////// // constructors public InteractionSubState() { }
public void initialize() { super.initialize(); addPort(_east = new Port(this)); addPort(_west = new Port(this)); addPort(_north = new Port(this)); addPort(_south = new Port(this)); }
//////////////////////////////////////////////////////////////// // acessors public InteractionState getOwner() { return _owner; } public void setOwner(InteractionState owner) { _owner = owner; }
}
///////////////////////////////////////////////////////////////// arquivo: br/ufsc/uid/Transition.javapackage br.ufsc.uid;import org.tigris.gef.presentation.*;import java.util.Vector;import org.tigris.gef.base.Layer;import br.ufsc.uid.presentation.*;
public class Transition implements java.io.Serializable{ //////////////////////////////////////////////////////////////// // instance variables protected Vector _sourcePorts; protected Port _destPort; protected String _condition; protected String _option; protected Vector _selections; protected boolean explicityReturnable = false; protected boolean explicityNotReturnable = false;
//////////////////////////////////////////////////////////////// // constructors public Transition() { _sourcePorts = new Vector(); _destPort = null; explicityReturnable = false; explicityNotReturnable = false; }
//////////////////////////////////////////////////////////////// // accessors public void setSourcePort(Port s) { if(_sourcePorts.size() > 0) { _sourcePorts.removeElementAt(0); _sourcePorts.add(0, s); }else _sourcePorts.addElement(s); } public Port getSourcePort() { return (Port)_sourcePorts.elementAt(0); } public void addSourcePort(Port s) { _sourcePorts.addElement(s); } public void removeSourcePort(Port s) { _sourcePorts.remove(s); } public Vector getSourcePorts() { return _sourcePorts; } public void setDestPort(Port d) { _destPort = d; } public Port getDestPort() { return _destPort; } public boolean getExplicityReturnable() { return explicityReturnable; } public boolean getExplicityNotReturnable() { return explicityNotReturnable; } public void setExplicityReturnable(boolean value) { explicityReturnable = value; if (value) explicityNotReturnable = false; }
146
public void setExplicityNotReturnable(boolean value) { explicityNotReturnable = value; if (value) explicityReturnable = false; }
public Port otherEnd(Port oneEnd) { if(!(_destPort == oneEnd || _sourcePorts.contains(oneEnd))) return null;
if(_sourcePorts.contains(oneEnd)) return _destPort; else { if (_sourcePorts.size() > 0 && _destPort == oneEnd) return (Port)_sourcePorts.elementAt(0); else return null; } }
//////////////////////////////////////////////////////////////// // operations public void connect(Port srcPort, Port destPort) { setSourcePort(srcPort); setDestPort(destPort); srcPort.addTransition(this); destPort.addTransition(this); }
//////////////////////////////////////////////////////////////// // Visualization related methods public FigEdge presentationFor(Layer lay) { FigEdge ft; if (lay != null) { ft = (FigEdge) lay.presentationFor(this); // métodopresentationFor do Layer tá implementado?!?!?! if (ft != null) return ft; } ft = makePresentation(lay); InteractionState sourceNode =(InteractionState)(getSourcePort().getOwner()); InteractionState destNode = (InteractionState)(getDestPort().getOwner()); FigInteractionState sourceFigNode =(FigInteractionState)sourceNode.presentationFor(lay); FigInteractionState destFigNode =(FigInteractionState)destNode.presentationFor(lay); Fig sourcePortFig = sourceFigNode.getPortFig(getSourcePort()); Fig destPortFig = destFigNode.getPortFig(getDestPort()); ft.setSourcePortFig(sourcePortFig); ft.setDestPortFig(destPortFig); ft.setSourceFigNode(sourceFigNode); ft.setDestFigNode(destFigNode); ft.setOwner(this); return ft; }
public FigEdge makePresentation(Layer lay) { FigEdge foo = new FigEdgeLine(); foo.setDestArrowHead(new ArrowHeadTriangle()); return foo; }}
///////////////////////////////////////////////////////////////// arquivo: br/ufsc/uid/ExchangedInformation.javapackage br.ufsc.uid;
public abstract class ExchangedInformation{ //////////////////////////////////////////////////////////////// // atributes
147
protected Object _owner; protected boolean _optional = false;
/////////////////////////////////////// // acessors public void setOwner(InteractionState state) { _owner = state; } public void setOwner(InteractionSubState subState) { _owner = subState; } public Object getOwner() { return _owner; } public void setOptional(boolean value) { _optional = value; } public boolean getOptional() { return _optional; }
}
///////////////////////////////////////////////////////////////// arquivo: br/ufsc/uid/UserInput.javapackage br.ufsc.uid;
public class UserInput extends ExchangedInformation{ /////////////////////////////////////// // attributes private Information _info;
/////////////////////////////////////// // constructors public UserInput(Information info) { _info = info; }
/////////////////////////////////////// // acessors public Information getInfo() { return _info; } public void setInfo(DataItem item) { _info = item; } public void setInfo(Structure struct) { _info = struct; } public void setInfo(EnumeratedUserInput enumInput) { _info = enumInput; }}
///////////////////////////////////////////////////////////////// arquivo: br/ufsc/uid/SystemOutput.javapackage br.ufsc.uid;
public class SystemOutput extends ExchangedInformation{ /////////////////////////////////////// // attributes private Object _info;
/////////////////////////////////////// // constructors public SystemOutput(OutputInformation info) { _info = info; } public SystemOutput(String text) { _info = text; }
/////////////////////////////////////// // acessors public Object getInfo() { return _info; } public void setInfo(DataItem item) { _info = item; } public void setInfo(Structure struct) { _info = struct; } public void setInfo(String text) { _info = text; }}
C.3 Pacote br.ufsc.uid.presentation///////////////////////////////////////////////////////////////// arquivo: br/ufsc/uid/presentation/LayerUID.javapackage br.ufsc.uid.presentation;import org.tigris.gef.base.LayerPerspective;import org.tigris.gef.presentation.*;import org.tigris.gef.graph.*;import org.tigris.gef.graph.presentation.*;
public class LayerUID extends LayerPerspective{ protected GraphNodeRenderer _nodeRenderer = new InteractionStateRenderer(); protected GraphEdgeRenderer _edgeRenderer = new TransitionRenderer();
public LayerUID(String name, GraphModel gm) { super(name, gm);
148
_controller = null; _gm.addGraphEventListener(this); }
public GraphNodeRenderer getGraphNodeRenderer() { return _nodeRenderer; } public GraphEdgeRenderer getGraphEdgeRenderer() { return _edgeRenderer; }
public void edgeAdded(GraphEvent ge) { Object edge = ge.getArg(); Fig oldFig = presentationFor(edge); if (null == oldFig) { if (!shouldShow(edge)) { System.out.println("edge rejected"); return; } FigEdge newFigEdge = _edgeRenderer.getFigEdgeFor(_gm, this, edge); if (newFigEdge != null) { newFigEdge.setLayer(this); add(newFigEdge); newFigEdge.computeRoute(); newFigEdge.endTrans(); } } }};
///////////////////////////////////////////////////////////////// arquivo: br/ufsc/uid/presentation/FigInteractionState.javapackage br.ufsc.uid.presentation;import java.awt.*;import java.util.*;import br.ufsc.uid.*;import org.tigris.gef.presentation.*;
public class FigInteractionState extends FigNode{ //////////////////////////////////////////////////////////////// // instance variables private int FONT_SIZE = 12; private String FONT_NAME = "Lucida Console"; private Color FONT_COLOR = Color.black; private Color LINE_COLOR = Color.black; private Color BACKGROUND_COLOR = Color.white;
private Vector _info; //as informacoes trocadas no estado private Vector _subs; //os subestados do estado private FigGroup _infoFigs; //grupo de figuras das informacoes trocadas private FigGroup _subFigs; private FigCircle _north, _south, _east, _west;
//////////////////////////////////////////////////////////////// // constructors public FigInteractionState(InteractionState owner) { setOwner(owner); setBlinkPorts(true); _info = new Vector(); _subs = new Vector(); _infoFigs = new FigGroup(); _subFigs = new FigGroup(); rebuild(); }
public boolean isResizable() { return false; }
public void rebuild() { Point originalLocation = getLocation(); removeAll(); _infoFigs.removeAll(); _subFigs.removeAll(); _info = ((InteractionState)getOwner()).getExchangedInformation(); _subs = ((InteractionState)getOwner()).getSubStates(); _north = new FigCircle(0, 0, 10, 10, Color.blue, Color.blue); _south = new FigCircle(0, 0, 10, 10, Color.blue, Color.blue); _east = new FigCircle(0, 0, 10, 10, Color.blue, Color.blue); _west = new FigCircle(0, 0, 10, 10, Color.blue, Color.blue); _north.setOwner(((Interaction)getOwner()).getNorthPort()); _south.setOwner(((Interaction)getOwner()).getSouthPort()); _east.setOwner(((Interaction)getOwner()).getEastPort());
149
_west.setOwner(((Interaction)getOwner()).getWestPort()); setBlinkPorts(true);
if(_info.size() == 0) // se nao tiver nada no estado, cria um circulo detamanho fixo (150x80) { addFig(new FigCircle(0, 0, 150, 80, LINE_COLOR,BACKGROUND_COLOR)); _north.setCenter(new Point(75, 0)); _south.setCenter(new Point(75, 80)); _east.setCenter(new Point(150, 40)); _west.setCenter(new Point(0, 40)); addFig(_north); addFig(_south); addFig(_east); addFig(_west); } else { for (int i = 0; i < _info.size(); i++ )
_infoFigs.addFig(figFor((ExchangedInformation)_info.elementAt(i))); //centraliza infoFigs int centerX = (int)(_infoFigs.center().getX()); for(int i = 0; i < _infoFigs.getFigs().size(); i++) { Fig fig = (Fig)(_infoFigs.getFigs().elementAt(i)); fig.setX(centerX - fig.getWidth()/2); } //põe figs uma embaixo da outra int nextY = 0; for(int i = 0; i < _infoFigs.getFigs().size(); i++) { Fig fig = (Fig)(_infoFigs.getFigs().elementAt(i)); fig.setY(nextY); nextY = nextY + 5 + fig.getHeight(); } _infoFigs.calcBounds(); //a FigGroup nao se atualiza sozinha(bug?) FigCircle elipsis = elipsisFor(newRectangle(_infoFigs.getWidth()+6, _infoFigs.getHeight()+4)); elipsis.setLocation(0,0); _infoFigs.setCenter(elipsis.center()); _north.setCenter(new Point(elipsis.getWidth()/2, 0)); _south.setCenter(new Point(elipsis.getWidth()/2,elipsis.getHeight())); _east.setCenter(new Point(elipsis.getWidth(),elipsis.getHeight()/2)); _west.setCenter(new Point(0, elipsis.getHeight()/2)); addFig(elipsis); addFig(_infoFigs); addFig(_north); addFig(_south); addFig(_east); addFig(_west); setLocation(originalLocation); } }
private Fig figFor(InteractionSubState sub) { return new Fig(); }
private Fig figFor(ExchangedInformation info) { FigText textFig = new FigText(0, 0, 10, 10, FONT_COLOR, FONT_NAME,FONT_SIZE, false); textFig.setLineWidth(0); textFig.setJustification(FigText.JUSTIFY_CENTER); textFig.setText(stringFor(info)); if(info instanceof UserInput) { FigGroup groupFig = new FigGroup(); FigRect rect = new FigRect(0, 0, textFig.getWidth() + 10,textFig.getHeight() + 5); if(info.getOptional()) rect.setDashed(true); textFig.setCenter(rect.center());
150
groupFig.addFig(rect); groupFig.addFig(textFig); return groupFig; }else { if(info instanceof SystemOutput) { if(info.getOptional()) textFig.setText(textFig.getText() + "?"); return textFig; } } return(new Fig()); //nao deveria chegar aqui }
private String stringFor(ExchangedInformation exchangedInfo) { if(exchangedInfo instanceof UserInput) { Information info = ((UserInput)exchangedInfo).getInfo(); if(info instanceof DataItem) return stringFor((DataItem)info); if(info instanceof Structure) return stringFor((Structure)info); if(info instanceof EnumeratedUserInput) return stringFor((EnumeratedUserInput)info); }else { if(exchangedInfo instanceof SystemOutput) { Object info = ((SystemOutput)exchangedInfo).getInfo(); if(info instanceof String) { String textOutput = ""; textOutput = textOutput + "\""; textOutput = textOutput + ((String)info); textOutput = textOutput + "\""; return textOutput; } if(info instanceof DataItem) return stringFor((DataItem)info); if(info instanceof Structure) return stringFor((Structure)info); } } return ""; //nao deveria chegar aqui }
private String stringFor(DataItem dataItem) { String strDataItem = ""; Domain domain = dataItem.getDomain(); Multiplicity mult = dataItem.getMultiplicity(); String name = dataItem.getName(); switch(mult.getType()) { case Multiplicity.FIXED: int value = mult.getFixedValue(); if(value != 1) // nao é conjunto { strDataItem = strDataItem +Integer.toString(mult.getFixedValue()); strDataItem = strDataItem + " "; } break; case Multiplicity.RANGE: strDataItem = strDataItem +Integer.toString(mult.getRangeValueLower()); strDataItem = strDataItem + ".."; strDataItem = strDataItem +Integer.toString(mult.getRangeValueUpper()); strDataItem = strDataItem + " "; break; case Multiplicity.NOT_DEFINED: strDataItem = strDataItem + "..."; break; default:
151
break; } strDataItem = strDataItem + name; switch(domain.getType()) { case Domain.SIMPLE: strDataItem = strDataItem + ":"; strDataItem = strDataItem + domain.getSimple(); break; case Domain.ENUMERATED: strDataItem = strDataItem + ":"; strDataItem = strDataItem + "{"; for(int i = 0; i < domain.getEnumeratedSize(); i++) { strDataItem = strDataItem +domain.getEnumerated(i); if(i != (domain.getEnumeratedSize() - 1)) // naotem virgula depois do ultimo strDataItem = strDataItem + ", "; } strDataItem = strDataItem + "}"; break; default: // Domain.NOT_DEFINED break; } return strDataItem; }
private String stringFor(Structure structure) { String strStructure = ""; Multiplicity mult = structure.getMultiplicity(); String name = structure.getName(); switch(mult.getType()) { case Multiplicity.FIXED: int value = mult.getFixedValue(); if(value != 1) // nao é conjunto { strStructure = strStructure +Integer.toString(mult.getFixedValue()); strStructure = strStructure + " "; } break; case Multiplicity.RANGE: strStructure = strStructure +Integer.toString(mult.getRangeValueLower()); strStructure = strStructure + ".."; strStructure = strStructure +Integer.toString(mult.getRangeValueUpper()); strStructure = strStructure + " "; break; case Multiplicity.NOT_DEFINED: strStructure = strStructure + "..."; break; default: break; } strStructure = strStructure + name; strStructure = strStructure + "()"; // FALTA IMPLEMENTAR ITENS DAESTRUTURA return strStructure; }
private String stringFor(EnumeratedUserInput enumInput) { String strEnumInput = ""; Multiplicity selection = enumInput.getSelection(); String name = enumInput.getName(); switch(selection.getType()) { case Multiplicity.FIXED: int value = selection.getFixedValue(); strEnumInput = strEnumInput +Integer.toString(selection.getFixedValue()); strEnumInput = strEnumInput + " "; break;
152
case Multiplicity.RANGE: strEnumInput = strEnumInput +Integer.toString(selection.getRangeValueLower()); strEnumInput = strEnumInput + ".."; strEnumInput = strEnumInput +Integer.toString(selection.getRangeValueUpper()); strEnumInput = strEnumInput + " "; break; case Multiplicity.NOT_DEFINED: strEnumInput = strEnumInput + "..."; break; default: break; } strEnumInput = strEnumInput + name; strEnumInput = strEnumInput + "["; for(int i = 0; i < enumInput.getOptionsSize(); i++) { strEnumInput = strEnumInput + enumInput.getOption(i); if(i != enumInput.getOptionsSize() - 1) // nao tem virgula depoisdo ultimo strEnumInput = strEnumInput + ", "; } strEnumInput = strEnumInput + "]"; return strEnumInput; }
private FigCircle elipsisFor(Rectangle rect) { double a, b, x, y; x = rect.getWidth()/2; y = rect.getHeight()/2; if(rect.getWidth() >= rect.getHeight()) { double aspect = rect.getWidth()/rect.getHeight(); b = Math.sqrt(((x*x)/(aspect*aspect)) + y*y); a = b*aspect; return (new FigCircle(0, 0, (int)a*2, (int)b*2, LINE_COLOR,BACKGROUND_COLOR)); }else { double aspect = rect.getHeight()/rect.getWidth(); b = Math.sqrt(x*x + ((y*y)/(aspect*aspect))); a = b*aspect; return (new FigCircle(0, 0, (int)b*2, (int)a*2, LINE_COLOR,BACKGROUND_COLOR)); } }
public InteractionSubState hitSubState(int x, int y) { return null; }
public int positionForNewInfo(int x, int y) { return 0; }}
153
ANEXO D Artigo
UMA FERRAMENTA PARA EDIÇÃO DE DIAGRAMAS DEINTERAÇÃO DO USUÁRIO
Alexandre Schulter1, Alexandre Spagnol2, Patrícia Vilain3
1,2 Curso de Bacharelado em Ciências da Computação, 9ª fase, 2004Departamento de Informática e Estatística
Universidade Federal de Santa Catarina (UFSC), Brasil, 88040-900Fone (0XX48)333-9999, Fax (0XX48)333-9999
[email protected], [email protected], [email protected]
RESUMO
Este trabalho trata do desenvolvimento de uma ferramenta que dê suporte à edição dediagramas de interação do usuário (UIDs). O processo de desenvolvimento usado para construção daferramenta é baseado em recomendações do Unified Process, sendo dirigido por casos de uso, iterativo eincremental. Um framework (GEF) para construção de programas editores de grafos foi usado comobase para as atividades de projeto e implementação.
Palavras-chave: UID, Desenvolvimento de software, GEF.
ABSTRACT
This work describes the development of a tool which supports the editing of user interactiondiagrams (UIDs). The development process used for building the tool is based on the Unified Process,thus being use-case driven, iterative and incremental. A framework (GEF) for building graph editingsoftware was used as a basis for the design and implementation workflows.
Key-words: UID, Software development, GEF.
1 INTRODUÇÃO Este é um trabalho prático. O tema é o desenvolvimento de uma ferramenta que dê suporte àedição de diagramas de interação do usuário (User Interaction Diagram - UIDs), que é uma notaçãográfica para representar a interação entre um usuário e um sistema. O objetivo do trabalho é a análise,projeto e implementação de um software aplicativo para proporcionar a edição de UIDs através de umambiente com facilidades específicas para a sua sintaxe. Mais especificamente, o objetivo é facilitar aedição de UIDs. A motivação para este trabalho surgiu da carência de uma ferramenta específica para a criação deUIDs. Um analista que usa os UIDs em seu trabalho tem de recorrer a ferramentas gráficas genéricas,dispendendo tempo com detalhes relativos a sintaxe em si e não ao seu conteúdo. As atividades de análise e projeto para o desenvolvimento da ferramenta foram realizadasseguindo algumas das recomendações do processo de desenvolvimento Unified Process [Jacobson 99]. Oprojeto da ferramenta foi realizado levando-se em conta o uso do Graph Editing Framework (GEF)[Robbins 03], um framework para construção de programas de alta qualidade que envolvem edição degrafos. A implementação foi feita na linguagem Java, a mesma do GEF.
2 DIAGRAMA DE INTERAÇÃO DO USUÁRIO O Digrama de Interação do Usuário, ou UID (User Interaction Diagram), proposto em [Vilain00], é uma notação gráfica pra representar a interação entre um usuário e um sistema. Esta interaçãogeralmente tem intensa troca de informação. O UID é voltado pro levantamento de requisitos, e pode ser usado em conjunto com os casos deuso. Os casos de uso são descrições textuais que podem ser ambíguas e extensas, e o UID descrevegraficamente a troca de informações de um caso de uso. O UID foca na troca e na estrutura das
154
informações, não considerando aspectos específicos da interface e da navegação (como janelas, botões,páginas, etc). Podem dar suporte à comunicação entre projetistas e usuários para validar os casos de uso, epodem servir de entrada para se definir diagramas de classes preliminares, existindo diretrizes pra isso. Um UID é composto por um conjunto de estados conectados através de transições. Os estadosrepresentam as informações que são trocadas entre o usuário e a aplicação, enquanto as transições sãoresponsáveis pela troca do foco de interação.
Figura 1. Estados e transição de foco de interação do UID
A figura 2 apresenta os principais componentes da notação do UID.
Figura 2. Componentes da notação do UID
A figura 3 apresenta um exemplo de UID completo.
Figura 3. UID Saque em caixa eletrônico
Em [Vilain 00] é mostrado como o UID pode ser incorporado nos workflows de requisitos eanálise do Unified Process [Jacobson 99]. Em [Güell 00] e [Schwabe 02] é mostrado como o UID podeser usado no processo de desenvolvimento de aplicações Web, integrando as etapas de levantamento derequisitos, de projeto conceitual e de navegação.
155
3 GRAPH EDITING FRAMEWORK Para as atividades de projeto e implementação da ferramenta, foi utilizado o Graph EditingFramework (ou GEF) como ponto de partida. O GEF é formado por uma biblioteca de classes nalinguagem Java. O GEF dá suporte à edição de grafos e como será a seguir, o UID pode ser modelado como umgrafo. Também tem suporte à edição de gráficos não estruturados, como círculos, retângulos, linhas, etc.,que são necessários pra criação de alguns dos componentes da notação do UID. O GEF promove fácil integração com código de aplicações já existentes, e pode ser usado comocamada gráfica pra essas aplicações, pois fornece uma visualização e funções de edição que são separadosem uma camada diferente da camada de dados da aplicação. O modelo de grafos do GEF é composto por nodos, portas e arcos, que é um modelo maisflexível que grafos com apenas nodos e arcos (figura 4). A figura 5 mostra como o UID foi modelado de forma que o GEF possa editá-lo. Em cada estadode interação, há quatro portas. Em saídas de sistema do tipo conjunto, também há quatro portas. O usuáriocria as transições entre estados de interação editando as conexões entre as portas. Na ferramenta, essasportas só aparecem quando o usuário arrasta o mouse por cima dos estados
Figura 4. Modelo de grafos com nodos, arcos eportas Figura 5. UID com portas visíveis na ferramenta
4 DESENVOLVIMENTO Para guiar o desenvolvimento da ferramenta, foi seguido um processo de desenvolvimentobaseado no Unified Process. Como esse processo é um processo grande e rigoroso, e a nossa ferramenta érelativamente simples, não foi o executado o UP por completo, apenas as principais recomendações. O UP é dirigido por casos de uso, pois os casos de uso não são usados apenas no levantamentode requisitos. Eles guiam a análise, projeto, implementação e testes. É iterativo e incremental, porque nãoé feita toda a análise, depois todo o projeto, e depois toda implementação. O trabalho é divido em váriasiterações (figura 6), e cada iteração lida com um conjunto de casos de uso. Os casos de uso escolhidos sãoaqueles mais importantes que envolvem funcionalidades ainda não tratadas. Cada iteração entãoincrementa a funcionalidade geral do sistema.
Figura 6. Iterações do Unified Process
156
Neste trabalho, não foi feito um levantamento de requisitos em cada iteração, e sim umlevantamento extensivo inicial, capturando quase todos os requisitos. Em seguida, as iterações foraminiciadas, começando com análise, depois projeto e implementação. Os testes foram feitos juntamentecom a implementação, e não como uma etapa separada. Os requisitos foram sendo refinados ao longo dasiterações. No total, foram a executadas duas iterações, que chegaram a implementar praticamente todos osprincipais requisitos (figura 7).
Figura 7. Iterações executadas neste trabalho
4.1 Levantamento de requisitos O levantamento de requisitos feito incluiu:
• A descrição do contexto do sistema com um modelo de domínio.• Uma lista de funcionalidades que fez o papel de uma lista de idéias sobre tudo que sistema
deveria fazer.• Uma lista de requisitos funcionais e não-funcionais, que é bastante extensa, pois cada uma das
idéias gerou alguns requisitos funcionais.• E o mais importante, os casos de uso. Os casos de uso capturam os requisitos funcionais, mas
não todos. Eles capturam as ações de criação ou inserção de componentes da notação do UID.As ações de remoção, modificação, movimentação, etc, são citadas apenas na lista de requisitosfuncionais, e são tratados somente nas etapas de implementação.
Como o sistema trata-se de um editor gráfico, existem diversas sequências de passos diferentespra se usar o editor, e nesses casos de uso foram definidas sequências que capturam vários requisitosfuncionais. Mas não quer dizer que estas são as únicas sequências possíveis.
A lista de funcionalidades é apresentada abaixo, classificadas por prioridades:
Prioridade alta• Edição dos UIDs com os seguintes componentes: item de dado, estrutura, conjunto, dado
opcional, entrada do usuário, entrada do usuário enumerada, saída do sistema, texto, estado,estado inicial, sub-estados, chamada para outro UID, chamada a partir de outro UID, transição,pré-condição, pós-condição, notas textuais e parâmetros.
• Modificação do conteúdo dos componentes.• Renomeação e remoção de componentes.• Movimentação individual ou em grupo de componentes em uma área de edição.• Edição de vários diagramas: ambiente com possibilidade de se editar vários diagramas (UIDs) de
um projeto ao mesmo tempo.
Prioridade média• Edição do diagrama de relacionamentos.• Salvamento e recuperação dos diagramas.• Exportação dos diagramas para arquivos de imagem.• Desfazer/Refazer última ação: ações como inserção, renomeação e remoção podem ser desfeitas
e refeitas.
Prioridade baixa• Copiar, recortar e colar figuras.• Redimensionamento do tamanho da imagem (zoom).• Impressão.• Vizualização e configuração de impressão.
157
• Localização de componentes por nome.
Os casos de uso definidos são apresentados abaixo, alocados nas duas iterações executadas. Aolado de cada um, é motrado um pequeno resumo das ações de edição que cada um aborda.
Primeira iteração• Manipular projeto (criar e fechar projeto, criar UID)• Editar UID (criar estado de interação, sub-estado e informações trocadas na interação)
Segunda iteração• Manipular projeto 2 (abrir e salvar projeto, exportar imagem)• Editar UID 2 (marcar estado inicial, criar chamada e transições)• Editar DR (criar relacionamento, ator e associação)• Imprimir diagrama (configurar e imprimir)
Manipular projeto e Editar UID são casos de uso que foram divididos em duas partes (Manipularprojeto 2 e Editar UID 2). Isto foi feito com o objetivo de tratar as funcionalidades que eles capturam emiterações diferentes, pois se fossem únicos, seriam muitos extensos.
4.2 Análise Nas atividades de análise os requisitos são refinados. A etapa de análise serve pra se obter umentendimento do funcionamento interno do sistema, mas faz abstrações e não trata detalhes melhortratados na etapa de projeto. No Unified Process é criado um modelo de análise, que é constituído de classes de análise,pacotes e realizações de casos de uso. Os principais artefatos gerados na análise são as realizações doscasos de uso, que mostram como os objetos de análise colaboram de forma a executar um caso de uso. Por exemplo, figura 8 mostra o diagrama de classes participantes na realização do caso de usoEditar UID. Este caso de uso tem uma sequência de passos pra criação de um estado, um sub-estado einformações trocados nos estados. O analista, que é o nosso único ator, interage com a InterfaceUID pra solicitar a criação dosestados, sub-estados e informações. O EditorUID controla a criação desses componentes, criando eadicionando ao UID corretamente. Um UID tem uma coleção de estados. Cada estado pode ter uma coleção de outros estados (sub-estados), e uma coleção de informações trocadas. Toda vez que algo é inserido ou modificado no UID, o EditorUID notifica a InterfaceUID que oUID foi modificado, e a interface consulta o UID para pegar os componentes e atualizar a visualização,pois a InterfaceUID é responsável pela visualização do UID.
Figura 8. Diagrama de classes participantes na realização na análise do caso de uso Editar UID
4.3 Projeto Durante as atividades de projeto, o sistema adquire forma pra satisfazer todos os requisitos. Oprojeto tenta preservar a estrutura da análise, mas a análise, neste caso, serve para se obter apenas umentendimento melhor do problema. O projeto foi mais influenciado pelo framework GEF, porque oprojeto foi feito levando-se em conta o uso do framework.
158
Pra cada realização de caso de uso feita na análise, é feita a sua realização em termos de objetosde projeto. Por exemplo, essa figura mostra o digrama de classe participantes na realização do caso de usoEditar UID. As classes em cinza são as classes do framework GEF. As classes em branco são as classesprojetadas neste trabalho.
Figura 9. Diagrama de classes participantes na realização no projeto do caso de uso Editar UID
5 CONCLUSÃO Este trabalho descreveu os resultados do processo de desenvolvimento de uma ferramenta deedição de UIDs. A maioria dos requisitos de alta e média prioridade foram implementados, mas algunsrequisitos levantados não foram implementados por restrição de tempo. O uso do framework GEF facilitou bastante o trabalho, pois muitas idéias de projeto foramobtidas do mesmo. Outro aspecto a ressaltar foi a reutilização de código, pois a maioria das classesprojetadas neste trabalho derivam de classes do framework. As recomendações do Unified Process serviram de guia para o desenvolvimento da ferramenta,definindo as melhores práticas para a produção de um software de qualidade. Foram executadas duasiteração dos seus workflows, sendo que 30% do tempo total de desenvolvimento foi gasto na tarefa delevantamento de requisitos. A análise foi relativamente rápida, demandando 10% do tempo. A tarefa maistrabalhosa foi o projeto, com 40% do tempo. Como a implementação é um refinamento direto do projeto,apenas 20% do tempo foi gasto com ela.
6 REFERÊNCIAS [Güell 00] GÜELL, N.; SCHWABE, D.; and VILAIN, P. Modeling interactions and navigation in web applications. In: Proceedings of the World Wide Web and Conceptual Modeling 2000.
[Jacobson 99] JACOBSON, I.; BOOCH, G.; RUMBAUGH, J. The unified software development process. Addison-Wesley: 1999. 463p.
[Robbins 03] ROBBINS, Jason. The design of GEF (the graph editing framework). Disponível em: http://gef.tigris.org/v0.6/docs/designslides/. Acesso em: 10 fev. 2004.
159
[Schwabe 02] VILAIN, P.; SCHWABE, D. Improving the web application design process with UIDs. In: Proceedings of the 2nd International Workshop on Web Oriented Software Technology 2002.
[Vilain 00] VILAIN, P.; SCHWABE, D.; SOUZA, C.S. de. A diagrammatic tool for representing user interaction in UML. In: Proceedings of the UML2000 Conference, York, England, October, 2000. p.133-147.
[Vilain 02] VILAIN, P. Modelagem da interação com o usuário em aplicações hipermídia. Rio de janeiro: DI/PUC-Rio, 2002. (Tese de Doutorado)