Www.3layer.com.br Merlin The First Runtime GUI Generator

Preview:

Citation preview

ww

w.3

layer.

com

.br

Merlin

ww

w.3

layer.

com

.br

The First Runtime GUI Generator

Merlin - The First Runtime GUI Generator slide 2 de 44

ww

w.3

layer.

com

.br

Sumário

Cenário A proposta Comparações Características e Funcionalidades O presente e o futuro EOF

>> panorama geral

Merlin - The First Runtime GUI Generator slide 4 de 44

ww

w.3

layer.

com

.br

Panorama geral Quanto custa construir um sistema

Meyers, Brad – User Interface Software Tools (1994,2002)

Referências

Sistema completo

Interface do usuário

TC

TC elementares

100%

50%

30%

18%

Custo de construção

2

2

1

1

12Pesquisas próprias (2005,2006)

>> a construção da IU hoje

Merlin - The First Runtime GUI Generator slide 5 de 44

ww

w.3

layer.

com

.br

A construção da IU hoje

O cenário atual

1. ( WYSIWYG: /wɪziwɪg/ ) What You See Is What You Get, ou seja o que você vê (ou o que você desenha no editor) é o que você tem quando o sistema estiver em execução.

As diversas formas de construir interface de usuário e os problemas em comum

Abordagens Problemas recorrentes

Escrita de código-fonte Uso de ferramentas

WYSIWYG1

Uso de assistentes de criação

Geração baseada em modelos Templates MDA

Tempo elevado de construção Quanto custa criar um template?

Demora nas alterações Como refatorar classes já geradas? E se o código já foi alterado?

Falta de reuso Posso reusar o label “Nome do

cliente” em projetos diferentes?

Gerência de código Código template ou não? E a versão?

>> a ferramenta proposta

Merlin - The First Runtime GUI Generator slide 6 de 44

ww

w.3

layer.

com

.br

A ferramenta proposta

Abdicar totalmente da geração do código-fonte Gerar a TC durante a execução do sistema,

através de um processo de interpretação de meta-informações oriundas das próprias classes da aplicaçãoA idéia-chave

CAFE

class Cliente { String codigo; String nome;}

new JFrame.add(Merlin.createIU(Pessoa.class)

).setVisible(true);

>> motivação

1 2 3

Tempo de projeto Tempo de execução

4

Merlin - The First Runtime GUI Generator slide 7 de 44

ww

w.3

layer.

com

.br

Motivação TC são funções do modelo de dados

consistência,aparência,validação,

organização,customizações,

etc.

A dependência da TC em relação ao modelo de dados

Modelo de classes Tela de Cadastro

>> motivação

Merlin - The First Runtime GUI Generator slide 8 de 44

ww

w.3

layer.

com

.br

Motivação Regras clássicas

>> motivação

O mapeamento básico entre os elementos

Modelo de dados Tela de Cadastro

Classe Tela

Atributo Controle

Relacionamento Navegação

Merlin - The First Runtime GUI Generator slide 9 de 44

ww

w.3

layer.

com

.br

Motivação Regras clássicas

Implementando as regras clássicasClasse Tela

Atributo Controle

Relacionamento Navegação

public class Cliente { String nome; Cidade naturalidade; boolean ativo;}

>> motivação

Nome

Cadastro de Clientes

Ativo

Naturalidade

SalvarCancelar

O cadastro gerado

A classe de dados

1

1

Merlin - The First Runtime GUI Generator slide 10 de 44

ww

w.3

layer.

com

.br

Motivação Regras clássicas

Implementando as regras clássicasClasse Tela

Atributo Controle

Relacionamento Navegação

public class Cliente { String nome; Cidade naturalidade; boolean ativo;}

>> motivação

Nome

Cadastro de Clientes

Ativo

SalvarCancelar

O cadastro gerado

A classe de dados

2

2

Naturalidade

Merlin - The First Runtime GUI Generator slide 11 de 44

ww

w.3

layer.

com

.br

Motivação Regras clássicas

Implementando as regras clássicasClasse Tela

Atributo Controle

Relacionamento Navegação

public class Cliente { String nome; Cidade naturalidade; boolean ativo;}

>> o objetivo da ferramenta

Nome

Cadastro de Clientes

Ativo

Naturalidade

SalvarCancelar

O cadastro gerado

A classe de dados

3

3

Merlin - The First Runtime GUI Generator slide 12 de 44

ww

w.3

layer.

com

.br

O objetivo da ferramenta Gerar TCs elementares com o menor esforço

possívelUm exemplo de interface elementar a ser gerada

>> algumas definições

O código essencial

new JFrame().add(Merlin.createUI(Cliente.class)).setVisible(true);

Merlin - The First Runtime GUI Generator slide 13 de 44

ww

w.3

layer.

com

.br

Algunas definições importantes Contexto

É a relação entre o elemento e o ambiente em que ele ocorre

Algo é importante dependendo do local onde ele está

Empirismo É o conhecimento baseado na experiência

Eu sei porque eu já fiz isso É reativo

Heurística É o conhecimento baseado em aproximações

Eu acho que sei porque eu já fiz algo parecido É pró-ativa

Inferência Obtém-se novos conhecimentos a partir de informações

existentes Quanto mais contexto, melhor

>> o processo

Merlin - The First Runtime GUI Generator slide 14 de 44

ww

w.3

layer.

com

.br

O processo

1. Criar as classes de dados2. Opcionalmente, decorar elas com

anotações3. Dentro da aplicação, invocar

Merlin.createUI

>> comparação

Merlin - The First Runtime GUI Generator slide 15 de 44

ww

w.3

layer.

com

.br

Uma pequena comparação

A mesma entrada e as diferentes saídas...

Uma classe de dados para teste ...

public class Usuario { long codigo; String nome; String observacoes; String logradouro; int numero; Cidade cidade; String complemento;}

... ou em notação UML

>> comparação

Merlin - The First Runtime GUI Generator slide 16 de 44

ww

w.3

layer.

com

.br

Uma pequena comparação

A mesma entrada e as diferentes saídas...Interfaces geradas por ferramentas tradicionais (a) e pelo Merlin (b)

Um gerador tradicional (a) Merlin (b)

Nome

Cadastro de Usuário

DicasDicasO campo nome é obrigatório.O campo logradouro é obrigatórioO campo número é obrigatório

Logradouro Rua São Sepé

Número 256 Complemento

Cidade Porto Alegre

Endereço

Observações

SalvarCancelar

nome

usuario

logradouro Rua São Sepé

numero 256

complemento

cidade Porto Alegre

observacoes

SalvarCancelar

codigo

>> comparação

Merlin - The First Runtime GUI Generator slide 17 de 44

ww

w.3

layer.

com

.br

Uma pequena comparação

A mesma entrada e as diferentes saídas...

>> comparação

Interfaces geradas por ferramentas tradicionais (a) e pelo Merlin (b)

Um gerador tradicional (a) Merlin (b)

Nome

Cadastro de Usuário

DicasDicasO campo nome é obrigatório.O campo logradouro é obrigatórioO campo número é obrigatório

Logradouro Rua São Sepé

Número 256 Complemento

Cidade Porto Alegre

Endereço

Observações

SalvarCancelar

nome

usuario

logradouro Rua São Sepé

numero 256

complemento

cidade Porto Alegre

observacoes

SalvarCancelar

codigo

Porque Observações é uma caixa de texto de múltiplas

linhas?

Merlin - The First Runtime GUI Generator slide 18 de 44

ww

w.3

layer.

com

.br

Uma pequena comparação

A mesma entrada e as diferentes saídas...

Nome

Cadastro de Usuário

DicasDicasO campo nome é obrigatório.O campo logradouro é obrigatórioO campo número é obrigatório

Logradouro Rua São Sepé

Número 256 Complemento

Cidade

Endereço

Observações

SalvarCancelar

nome

usuario

logradouro Rua São Sepé

numero 256

complemento

cidade

observacoes

SalvarCancelar

codigo

Porque é Observações e não Observacoes?

>> comparação

Interfaces geradas por ferramentas tradicionais (a) e pelo Merlin (b)

Um gerador tradicional (a) Merlin (b)

Merlin - The First Runtime GUI Generator slide 19 de 44

ww

w.3

layer.

com

.br

Uma pequena comparação

A mesma entrada e as diferentes saídas...

>> características gerais

Interfaces geradas por ferramentas tradicionais (a) e pelo Merlin (b)

Um gerador tradicional (a) Merlin (b)

Nome

Cadastro de Usuário

DicasDicasO campo nome é obrigatório.O campo logradouro é obrigatórioO campo número é obrigatório

Logradouro Rua São Sepé

Número 256 Complemento

Cidade Porto Alegre

Endereço

Observações

SalvarCancelar

nome

usuario

logradouro Rua São Sepé

numero 256

complemento

cidade Porto Alegre

observacoes

SalvarCancelar

codigo

Qual é o campo da cidade exibido na caixa de

seleção?

Merlin - The First Runtime GUI Generator slide 20 de 44

ww

w.3

layer.

com

.br

Características gerais Essência

Não produzir código-fonte, mas sim renderizar a interface do sistema em tempo de execução

Ser independente de framework gráfico Protótipo em Swing Previsão para JSF e GWT Outras aplicações podem ser SWT, XUL

Baseada no modelo de objetos do sistema Ter uma API minimalista

Anotações Merlin.createUI()

Reusar (e apostar em novos) padrões do Java 220, 317 e 318 – EJB e JPA 299 – Web Beans (JBoss Seam) 295 – Java Beans Binding 227 – Binding/Data Acess for J2EE 273 – DesignTime Bean 303 – Bean Validation (Hibernate Validator) 094 – Java Rules Engine (JBoss Drools)

>> características gerais

Merlin - The First Runtime GUI Generator slide 21 de 44

ww

w.3

layer.

com

.br

Características gerais

Não utilizar metamodelo externo Tudo reside nas classes compiladas do sistema

Utilizar ao máximo conceitos como heurísiticas, empirismo, inferência baseada em contexto, etc.

Configuração por exceção Reuso de histórico

>> características gerais

Merlin - The First Runtime GUI Generator slide 22 de 44

ww

w.3

layer.

com

.br

Características gerais

Não utilizar metamodelo externo Tudo reside nas classes compiladas do sistema

Utilizar ao máximo conceitos como heurísiticas, empirismo, inferência baseada em contexto, etc.

Configuração por exceção Reuso de histórico

O custo dos geradores tradicionais

Tempo

CustoS1 S2 S3 Sn

>> características gerais

Merlin - The First Runtime GUI Generator slide 23 de 44

ww

w.3

layer.

com

.br

Características gerais

Não utilizar metamodelo externo Tudo reside nas classes compiladas do sistema

Utilizar ao máximo conceitos como heurísiticas, empirismo, inferência baseada em contexto, etc.

Configuração por exceção Reuso de histórico

O custo do Merlin

Tempo

CustoS1

S2S3 Sn

>> histórico

Merlin - The First Runtime GUI Generator slide 24 de 44

ww

w.3

layer.

com

.br

O histórico

A busca por informações históricas pode ser feita no próprio classpath do sistema Em servidores de aplicação, tudo pode ser

compartilhado Em aplicações simples (standalone), as classes

com anotações podem ser exportadas juntoClasses nos servidores de aplicação

>> histórico

Root LIBs classes

S1

S2

Sn

C1

C2

Cn

classes

classes

classes

Merlin - The First Runtime GUI Generator slide 25 de 44

ww

w.3

layer.

com

.br

O histórico

A busca por informações históricas pode ser feita no próprio classpath do sistema Em servidores de aplicação, tudo pode ser

compartilhado Em aplicações simples (standalone), as classes

com anotações podem ser exportadas juntoClasses nos servidores de aplicação

>> slistaks

Root LIBs

Histórico

classes

S1

S2

Sn

C1

C2

Cn

classes

classes

classes

Merlin - The First Runtime GUI Generator slide 26 de 44

ww

w.3

layer.

com

.br

Slistaks

Informações de contexto, heurísticas, empirismo e inferência são utilizados para: Gerar corretamente nomes para labels Mapear os tipos de controles em função do tipo

de dado Adicionar validadores, tamanho, etc. AgrupamentosUtilizando a ocorrência de termos para produzir o conteúdo em comboboxes

12

110nome

status

codigo 110

>> slistaks de graça

Merlin - The First Runtime GUI Generator slide 27 de 44

ww

w.3

layer.

com

.br

Slistaks de graça

Google como fonte de informações Relevância de campos pode ser obtida de

forma onlineO maior contexto gratuito do mundo: A internet

nome : 212 milhões

codigo : 148 milhões

O termo nome é mais significativo, logo ele é

usado na caixa de seleção

>> mais slistaks de graça

Merlin - The First Runtime GUI Generator slide 28 de 44

ww

w.3

layer.

com

.br

Mais slistaks de graça

Dicionários de sinônimos Para inferir mapeamentos de controles

observacao = informacaoComplementar = outrasInformacoes

Todos geram textAreasUtilizando um dicionário de sinônimos gratuito para inferir mapeamentos

>> ainda slistaks de graça

Se observacao é (ou já foi) um textArea, é provável que outrasInformacoes também

o seja

Merlin - The First Runtime GUI Generator slide 29 de 44

ww

w.3

layer.

com

.br

Ainda slistaks de graça

Algoritmos de similaridade Para detectar aproximações e inferir

correspondências observacao = observacoes

Muitos frameworks na webUtilizando um framework externo para identificar similaridades

System.out.print( StringMetrics.compare(“observacao”,”observacoes”));//imprime 0.8 (entre 0 e 1)

Por exemplo, se o valor for maior que 0.5 assumimos que os termos são iguais. Assim, se observacao é (ou já foi) um textArea, é provável que observacoes também o seja.

>> eu adoro slistaks

Merlin - The First Runtime GUI Generator slide 30 de 44

ww

w.3

layer.

com

.br

Eu adoro slistaks

Corretores ortográficos Para gerar labels

observacao = observação

Utilizando corretores ortográficos disponíveis no próprio ambiente

>> agrupamentos

Merlin - The First Runtime GUI Generator slide 31 de 44

ww

w.3

layer.

com

.br

Agrupamentos

Agrupando controles nas telas Requisito

Os campos Cidade, Rua e Número devem ser exibidos em conjuntoCriando um agrupamento simples

A classe de dadosA tela

@Group(caption=“Endereço”,fields=“cidade,rua,numero”)

class Cliente { String nome; Cidade cidade; String rua; String numero;}

Cadastro de Cliente

Dicas

Nome

SalvarCancelar

Cadastro de Cliente 1

2

3

4

5

6

7

8

>> dependências

Rua

Número

Cidade

Endereço

Merlin - The First Runtime GUI Generator slide 32 de 44

ww

w.3

layer.

com

.br

Dependências

Vinculando controles nas telas Requisito

Se o cliente possuir cheque especial, habilitar limite de crédito

Criando dependências simples

A classe de dadosA tela

class Cliente { String nome; @Dependence(“limite”) boolean possuiCheque; double limite;}

Cadastro de Cliente

Dicas

Nome

SalvarCancelar

Cadastro de Cliente

Limite

Possui cheque

1

2

3

4

5

6

>> agentes

Merlin - The First Runtime GUI Generator slide 33 de 44

ww

w.3

layer.

com

.br

Agentes

Derivados da linguagem Eiffel, agentes são elementos que podem ser plugados na IU e executar funções diversas, como: Tratamento de eventos Invocação de regras de negócio Definição de propriedades Execução de Scripts

O conceito de agentes

Eventos

Scripts

Regras de negócio

Propriedades

Controlede

tela

>> agentes

?

Merlin - The First Runtime GUI Generator slide 34 de 44

ww

w.3

layer.

com

.br

Agentes

Derivados da linguagem Eiffel, agentes são elementos que podem ser plugados na IU e executar funções diversas, como: Tratamento de eventos Invocação de regras de negócio Definição de propriedades Execução de Scripts

O conceito de agentes

Eventos

Scripts

Regras de negócio

Propriedades

Controlede

telaAgentes

>> agentes

Merlin - The First Runtime GUI Generator slide 35 de 44

ww

w.3

layer.

com

.br

Agentes Agentes na execução de regras de negócio

Requisito Ao preencher o salário do cliente, se ele não tiver

débitos deve ser habilitado um cartão de crédito para ele.

Conectando eventos e regras de negócio

A classe de dadosA tela

class Cliente { String nome; @Agent( event={“focusLost”}, action={“habilitarCartao”}) float salario; boolean cartaoCredito;}

Cadastro de Cliente

Dicas

Nome

SalvarCancelar

Cadastro de Cliente

Salário

Cartão de crédito

1

2

3

4

5

6

7

8

>> agentes

Merlin - The First Runtime GUI Generator slide 36 de 44

ww

w.3

layer.

com

.br

Agentes

Agentes na execução de regras de negócio Requisito (agora de forma assíncrona)

Ao preencher o salário do cliente, se ele não tiver débitos deve ser habilitado um cartão de crédito para ele.

Conectando eventos e regras de negócio de forma assíncrona

A classe de dadosA tela

class Cliente { String nome; @Async @Agent( event={“focusLost”}, action={“habilitarCartao”}) float salario; boolean cartaoCredito;}

Cadastro de Cliente

Dicas

Nome

SalvarCancelar

Cadastro de Cliente

Salário

Cartão de crédito

1

2

3

4

5

6

7

8

>> agentes

Merlin - The First Runtime GUI Generator slide 37 de 44

ww

w.3

layer.

com

.br

Agentes

Agentes na execução de regras de negócio Requisito

Ao preencher o salário do cliente, se ele não tiver débitos deve ser habilitado um cartão de crédito para ele.

Implementando a regra de negócio

public class AlgumasRegras { public void habilitarCartao() { @In JTextField salario; @In JCheckBox cartao;

boolean debitos = true; //processa regra de negócio... cartao.setEnabled(!debitos); }}

123456789

10

>> agentes

Merlin - The First Runtime GUI Generator slide 38 de 44

ww

w.3

layer.

com

.br

Agentes

Agentes na definição de propriedades de controles Requisito

Aplicar uma borda verde saliente sobre o nome do cliente.

Uma interface com controle customizado

A classe de dadosA tela

class Cliente {

@Agent( property={“border=BorderFactory.createLineBorder(Color.green,2)”})

String nome; float salario; boolean cartaoCredito;}

Cadastro de Cliente

Dicas

Nome

SalvarCancelar

Cadastro de Cliente

Salário

Cartão de crédito

1

2

3

4

5

6

7

8

>> agentes

Merlin - The First Runtime GUI Generator slide 39 de 44

ww

w.3

layer.

com

.br

Agentes

Agentes na execução de scripts (BeanShell, Groovy, etc.) Requisito

Criar uma regra externa configurável para calcular o limite de crédito do cliente em função do valor do salário.Utilizando agentes para externalizar comportamentos através de scripts

A classe de dadosA tela

class Cliente { String nome; @Agent(

script={“/scripts/calc.js”}) float salario; float limiteCredito;}

Cadastro de Cliente

Dicas

Nome

SalvarCancelar

Cadastro de Cliente

Salário

Limite de crédito

1

2

3

4

5

6

>> agentes

7

Merlin - The First Runtime GUI Generator slide 40 de 44

ww

w.3

layer.

com

.br

Agentes

Agentes na execução de scripts (BeanShell, Groovy, etc.) Requisito

Criar uma regra externa configurável para calcular o limite de crédito do cliente.

O script externo escrito em BeanShell

var salario = new Float(this.caller.getText());

var limite = Merlin.getControle(“cliente.limiteCredito”);

limite.setText(salario * 0.3);

1

2

3

4

5

6

/scripts/calc.js

>> layout

Merlin - The First Runtime GUI Generator slide 41 de 44

ww

w.3

layer.

com

.br

Layout O posicionamento de controles é totalmente

executado por algoritmos, os quais utilizam Gerenciadores de layout (TableLayout, JGoodies Forms,

MigLayout) Heurísiticas, UI patterns, regras de usabilidade Configurações via anotações

Customizações Simples

Uso de anotações Complexas

Implementação de novos algoritmos Malucas

Design manual

>> layout

Merlin - The First Runtime GUI Generator slide 42 de 44

ww

w.3

layer.

com

.br

Layout

Alterando o layout via anotações Modificando algumas coisas

Redefinindo a ordem de controles e a posição de labels na tela

A classe de dadosA tela

class Cliente { @Order(after=“observacoes”) String nome; float salario; @Caption(pos=Caption.TOP_LEFT) String observacoes;}

Cadastro de ClienteCadastro de Cliente

Salário

1

2

3

4

5

6Nome

Observações

7

2

5Observações

>> layout

Merlin - The First Runtime GUI Generator slide 43 de 44

ww

w.3

layer.

com

.br

Layout

Alterando o layout via anotações Modificando tudo de uma vez

Redefinindo a ordem de controles e a posição de todos os labels na tela

A classe de dadosA tela

@Caption(pos=Caption.TOP_LEFT)class Cliente { @Order(after=“observacoes”) String nome; float salario; String observacoes;}

Cadastro de ClienteCadastro de Cliente

Salário

1

2

3

4

5

6Nome

Observações

7

>> layout

Merlin - The First Runtime GUI Generator slide 44 de 44

ww

w.3

layer.

com

.br

Layout

Um layout maluco Eu quero do meu jeito

>> layout

A tela desejadaCadastro de ClienteCadastro de Cliente

Salário

Nome

Observações

Merlin - The First Runtime GUI Generator slide 45 de 44

ww

w.3

layer.

com

.br

Layout

Criando um layout maluco1. Cria-se uma classe IU com o layout desejado

TemplateMaluco extends JPanel { //... }

Cadastro de Cliente

>> layout

A tela desejada

Merlin - The First Runtime GUI Generator slide 46 de 44

ww

w.3

layer.

com

.br

Layout

Criando um layout maluco2. Define-se nomes de controles idênticos aos

que serão gerados

Cadastro de Cliente

lblSalario

txtSalario

lblNome

cliente.nome

txtaObservacoes

lblObservacoes

>> layout

A tela desejada

TemplateMaluco extends JPanel { //... }

Merlin - The First Runtime GUI Generator slide 47 de 44

ww

w.3

layer.

com

.br

Layout

Criando um layout maluco3. Executa-se a geração passando o template

como parâmetroMerlin.createIhc(Cliente.class,

TemplateMaluco.class);

>> extensões

O resultado finalCadastro de ClienteCadastro de Cliente

Salário

Nome

Observações

Merlin - The First Runtime GUI Generator slide 48 de 44

ww

w.3

layer.

com

.br

Extensões Modificando os controles de tela gerados

Uma interface padrão

A classe de dados A tela geradaCadastro de Cliente

Dicas

Nome

Naturalidade

SalvarCancelar

Cadastro de Clienteclass Cliente { String nome; Cidade naturalidade}

1

2

3

4

>> extensões

Merlin - The First Runtime GUI Generator slide 49 de 44

ww

w.3

layer.

com

.br

Extensões Modificando os controles de tela gerados

Uma interface com controle customizado

A classe de dados A tela gerada

class Cliente { String nome; @RenderAs(Lookup.class) Cidade naturalidade}

Cadastro de Cliente

Dicas

Nome

Naturalidade

SalvarCancelar

Cadastro de Cliente1

2

3

4

5

>> extensões

Merlin - The First Runtime GUI Generator slide 50 de 44

ww

w.3

layer.

com

.br

Extensões Modificando os controles de tela gerados

Criando o controle customizado

class Lookup extends JPanel //faz como quiser}

Uma interface com controle customizado

A classe de dados A tela gerada

class Cliente { String nome; @RenderAs(Lookup.class) Cidade naturalidade}

Cadastro de Cliente

Dicas

Nome

Naturalidade

SalvarCancelar

Cadastro de Cliente1

2

3

4

5

1

2

3

>> demos

Merlin - The First Runtime GUI Generator slide 51 de 44

ww

w.3

layer.

com

.br

Demos

Dois demos simples Criando uma tela simples

http://3layer.no-ip.info:6666/confluence/pages/viewpage.action?pageId=6979626

Usando renderizadores e binders cutomizados http

://3layer.no-ip.info:6666/confluence/display/MERLIN/Renderizadores+e+Binders

>> estágio atual e perspectivas

Merlin - The First Runtime GUI Generator slide 52 de 44

ww

w.3

layer.

com

.br

Estágio atual e perspectivas Divulgação Alfa release disponível

Controles básicos, agentes, layout e anotações essenciais Telas de cadastro simples

Parte teórica em desenvolvimento Binding, telas mestre-detalhte, integração com outros

frameworks Captação de recursos financeiros 2008/2

Beta release em Swing, Alpha release em JSF 2009 em diante

Desenvolvimento efetivo do projeto, gerência de realimentação

2010 produto para o mercado

>> EOF

Merlin - The First Runtime GUI Generator slide 53 de 44

ww

w.3

layer.

com

.br

Fim

ww

w.3

layer.

com

.br

Conteúdo http://merlin.dev.java.net http://merlin.3layer.com.br http://treelayer.dev.java.net http://treelayer-merlin.blogspot.com

Contato http://groups.google.com/group/treelayer-merli

n

Histórias http://telasdecadastro.blogspot.com

Recommended