Mostrando postagens com marcador JFrame. Mostrar todas as postagens
Mostrando postagens com marcador JFrame. Mostrar todas as postagens

quarta-feira, 8 de janeiro de 2014

Data Binding

Olá, este post tem como função explicar o Data Binding, como usar e o por que. Então, lá vamos nós.

Data Binding é um processo que estabiliza uma conexão entre uma aplicação User Interface(JFrame) e a lógica do negócio. Se as configurações e notificações estiverem corretas, o Data Binding reflete as mudanças que elas fazem. Vamos supor que temos um AlunoFrame e nela um componente JTextField tNome, também temos a classe Aluno com o getNome e setNome. Se nós aplicarmos o Data Binding vamos fazer que quando seja digitado algo no TextField nome, automaticamente o setNome vai receber o que foi escrito, eles ficam sincronizados, as mudanças que ocorrem no nome ocorrem também no setNome e vice-versa. Mas então tu podes pensar, "por que não usar um setNome neste TextField?".

public class AlunoFrame extends javax.swing.JFrame{
     Aluno aluno = new Aluno();
     JTextField nome = new javax.swing.JTextField();
     /...

      private void tNomeActionPerformed(java.awt.event.ActionEvent evt){
         aluno.setNome(tNome.getText());         
     }

Podemos ver que fazendo assim não é nem um pouco elegante, deixamos o usuário com muita acessibilidade. Se por acaso ele quiser alterar para setMatricula ele pode, e não é isso que nós queremos. Nós temos que abstrair o usuário sobre o que está acontecendo. E também vale lembrar que para fazer espelhamento, deste modo fica muito "amador". Por isso vamos usar o Data Bindig, agora na prática vai ficar bem mais visível sua utilidade. Então vamos criar uma classe Bind que será a responsável por fazer a sincronização do JFrame com o negócio, so let's go.

public class Bind extends JTextField{    

    public Bind() {
        
    } 
    //criamos um método bind que vai receber os seguintes parametros
    //obj que será o objeto da classe que queremos alterar
    //atributo que será qual o atributo da classe que queremos mudar
    //campoFrame que é o que queremos onde a alteração seja feita
    //texto é a informação que vamos passar
    public void bind(Object obj, String atributo, Object campoFrame, String texto) throws NoSuchMethodException, IllegalAccessException...{

        //aqui nós vamos ver qual tipo é o campoFrame 
        //e depois repassamos para seu método correspondente
        if(campoFrame instanceof JTextField){
            JTextField tf = (JTextField) campoFrame;
            bindTextField(obj, atributo, tf, texto);
            return;
        }

        //exemplo com outros tipos de componentes
        if(campoFrame instanceof JComboBox){
            JComboBox cb = (JComboBox) campoFrame;
            bindComboBoxBinder(obj, atributo, cb, texto);            
            return;
        }
        if(campoFrame instanceof JRadioButton){
            JRadioButton rb = (JRadioButton) campoFrame;
            bindRadio(obj, atributo, rb, texto);
            return;
        }        
    }
Após implementar essa parte, nós precisamos fazer o bindTextField que terá como função ir lá no set da classe do objeto passado e alterar. Essa parte eu admito que é um pouco mais chatinha e complexa de entender pois vamos usar reflections e regex, então vou explicar por partes.

private void bindTextField(Object obj, String atributo, JTextField tf, String texto) throws NoSuchMethodException, IllegalAccessException... {
        tf.setText(texto);       
        
        //aqui nós vamos precisar usar reflections para saber os atributos
        //da classe do objeto que temos

        Field[] f = obj.getClass().getDeclaredFields(); //criamos um vetor de Field para pegar os atributos
        Field field = null; 
        
        //fazemos um for each para pesquisar dentro daquele nosso vetor 
        //para saber pegarmos o atributo que queremos alterar             
        for(Field campo : f){
            if(campo.getName().equals(atributo)){ //enquanto a variavel campo não for igual ao atributo continua o for
                field = campo; //a variavel field recebe o campo quando achado
                break;
            }
        }
        //agora que já achamos o atributo, nós precisamos encontrar o set dele
        //ATENÇÃO AGORA
        //Vamos criar uma String s que irá concatenar a palavra set com 
        //a primeira letra do atributo em maiuscula e o restante em minuscula
        String s = "set" + field.getName().toUpperCase().charAt(0)+ field.getName().substring(1);

        //no nosso exemplo fica s = "set"+N+ome
Depois que "formamos" o setNome, nós precisamos achar ele nos métodos da classe e fazer a alteração.
String tipo = field.getType().getSimpleName();//aqui criamos uma variavel tipo que irá
                                                      //pegar o nome do Tipo do campo field(que é nome)

        Method meth = null; //é criada uma variavel do tipo Method que será usada 
                            //para chegar ao método setNome
        
        //é feito um switch para ver qual é o Tipo do nosso atributo que será atualizado
        switch(tipo){
            case "String":
              //meth = aluno.getClass().getMethod(setNome, tipo String);
                meth = obj.getClass().getMethod(s, String.class);
                //usamos o metodo invoke para passar o objeto e a nova informação
                meth.invoke(obj, texto);
                break;
            case "int": case "Integer":
                meth = obj.getClass().getMethod(s,Integer.TYPE);
                meth.invoke(obj, Integer.parseInt(texto));
                break;
            case "float": case "Float": 
                meth = obj.getClass().getMethod(s,Float.TYPE);
                meth.invoke(obj, Float.parseFloat(texto));                
                break;
            case "double": case "Double":
                meth = obj.getClass().getMethod(s,Double.TYPE);
                meth.invoke(obj, Double.parseDouble(texto));  
                break;
            case "booelan": 
                Boolean.parseBoolean(texto);
                break;
            case "Date":
                 //OBSERVAÇÃO COM O DATE
                 //d{2}dias / d{2} mes / d{4} ano
                Pattern pattern = Pattern.compile("\\d{2}\\/\\d{2}\\/\\d{4}");
                        
                if(pattern.matcher(texto).find()){
                    SimpleDateFormat data = new SimpleDateFormat("dd/MM/yyyy");
                    meth = obj.getClass().getMethod(s, Date.class);
                    meth.invoke(obj, data.parse(texto));
                    
                }
                break;
        }       
    }
O case Date vou explicar por aqui pois é o mais complicado deles. Se por caso o nosso aluno tenha dataDeNascimento do tipo Date, vai ser necessário usar regex para formatar a data conforme for configurada pelo usuário, apartir do SimplesDateFormat(esqueçam todas gambiarras feitas até então). Criamos uma variável do tipo Pattern, quando colocamos o d{2} dizemos que aquela parte recebe até dois decimais. Mais a baixo temos um SimplesDateFormat que está separando por dia, mês e ano. Após isso, é igual aos outros.

Aqui terminamos nossa classe Bind, agora vamos ver como usar ela. No nosso formulário, no campo tNome nós precisamos usar o evento KeyReleased, fica da seguinte forma.

private void tNomeKeyReleased(java.awt.event.KeyEvent evt) {                                  
        Bind t = new Bind();
        t.bind(aluno2, "nome", tCampoParaMostrar, tNome.getText());
}

Admito que demorei para pegar a ideia do Data Binding, para entender como funciona essa sincronização via objeto, mas não é complicado de fazer, só é necessário tempo. Sobre reflections e regex, a ideia é bem fácil de entender.

terça-feira, 7 de janeiro de 2014

API Google Gson [JAVA SE7] Serializer and Deserializer Object

Neste post vou falar sobre a API Google Gson, desenvolvida pela google e disponibilizada gratuitamente neste link.
Esta API não tem muitos recursos, porém, é de grande importância ressaltar sua utilidade e rápida adaptação.

A Api do google gson, interpreta códigos enviados por arquivos Json ao software desenvolvido em JAVA e deserializa esses códigos para Classes java, instanciando assim: Objetos, classes, etc. Além disso, faz a engenharia reversa, onde recebe um objeto java e retorna um objeto JSON. Enfim, o uso dessa ferramente abre um leque de possibilidades dentro do java ao desenvolvedor, que pode usá-la para o que tiver necessidade em seu software.

Uma dica de uso é combinar esta biblioteca a uma já existente no Java SE7. A biblioteca java.lang.reflect.* na
qual você pode ler mais sobre clicando acima no link destacado.

Aqui irei demonstrar o uso da API para simples atribuição de Objetos, das duas formas.

lembrando que para usar o google Gson é necessário fazer o download da lib no site, e importá-lo no projeto corrente como biblioteca.

Exemplo1: 
    Neste caso, iremos serializar um Objeto Java, para transformá-lo num objeto Json.

Temos a classe Teste()
public class Teste {
    private String teste;
    private int numero;
    
    //+getters
    //+setter
    
    @Override
    public String toString() {
        return "teste = "+teste+" numero = "+numero;        
    }   
}

E temos a classe Principal TesteGson()
public class TesteGson {
    public static void main(String argumentos[]){
        Gson gson = new Gson();  //Instanciamos o uso do Gson
       
        Teste obj = new Teste("Gson", 1); // Criamos um obj do tipo Teste
        String s = gson.toJson(obj); //serializamos o obj
        System.out.println(s); //mostramos a string transformada em Json.
       
    }
   
}

Com este código temos a seguinte saída:
{"teste":"Gson","numero":1}

Exemplo 2:
  Neste exemplo iremos ver como Transformar um objeto Json em um Objeto Java. Vamos instanciar a mesma classe Teste() declarada acima.

Na janela Principal executaremos:
public class TesteGson {
    public static void main(String argumentos[]){
        Gson gson = new Gson();  //Instanciamos o uso do Gson
        
        String s = "{\"teste\":\"objectName\",\"numero\":2}";
        Teste obj = gson.fromJson(s, Teste.class);
        System.out.println(obj.toString());
    }
    
}

Com este código temos a seguinte saída:
teste = objectName numero = 2

Esta foi uma pequena introdução a API Google Gson, para saber mais sobre ela, consulte:
Google Gson 2.2.4 API.

Referências:
Google Gson User Guide.

Autor: Vinicius Montenegro.
    Graduando do Curso de Tecnologia em Análise e Desenvolvimento de Sistemas.
    FURG/IFRS - RIO GRANDE/RS.