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

GenericTableModel com Reflection e Annotation


GenericTableModel com Reflection e Annotations

Vou falar um pouco sobre TableModel, Reflection e Annotation.

O que é o TableModel? 
A maioria dos componentes swing possuem uma arquitetura que separa model e view, de forma que é definida uma interface para cada model. Dentro deste contexto, TableModel é a interface que representa o model da JTable. Se não informarmos qual será o model, a JTable usará por padrão uma instância de DefaultTableModel.

Ai que muitas discussões ocorrem. A quem diga para nunca usar DefaultTableModel, alguns já garantiram a sua morte, mas como poucos tirariam tempo para desenvolver o seu TableModel muitos o utilizam e não veem problema nisso. Mas uma coisa é certa, a complexidade de manter um DefaultTableModel é grande. 

Segundo VinnyGodoy, moderador do maior forum java do Brasil(www.guj.com.br), esses seriam os argumentos para não usar esse modelo.

Não use DefaultTableModel!!!!
Motivos:
1. É mais difícil que escrever seu próprio TableModel;
2. É mais lento (usa classes sincronizadas);
3. Ocupa mais espaço em memória (duplica seus dados);
4. Deixa o código mais confuso e difícil de manter;
5. Usa casts inseguros;
6. Força que você tenha que exibir informações desnecessárias (como o ID) na tabela, ou controlar o ID numa lista separada;
7. Faz a sua mulher te deixar, o leite da sua geladeira azedar, e pessoas apontarem o dedo para você na rua;


Por que a JTable precisa de um TableModel?
A JTable chama os métodos do TableModel para obter informações sobre o conteúdo da tabela, como número de linhas e colunas, conteúdo de cada célula, etc.

Qual o papel da classe AbstractTableModel? 
AbstractTableModel é uma classe abstrata que oferece a implementação de alguns métodos da interface TableModel, além de um conjunto de métodos úteis. Portanto o usual é estender esta classe ao invés de implementar TableModel diretamente.

Ok, entendi. Tenho que Criar meu próprio TableModel extendendo a classe AbstractTableModel e cumprindo o contrato sobrescrevendo seus métodos. Mas a onde entra Reflection nisso?

Bom, se você assim como eu, também não tinha ideia de o que era Reflection e como ela funciona, posso garantir, e mais fácil do que parece.

Por que Reflection? 
Java permite que, enquanto escrevemos nosso código, tenhamos total controle sobre exatamente o que vai ser executado, o que faz parte do nosso sistema.
Em tempo de desenvolvimento, olhando nosso código, sabemos quantos atributos uma classe tem, quais métodos ela tem, qual chamada de método está sendo feita e assim por diante.
O que a reflection faz é isso. Olhar para dentro de nossa classe e descobrir seu conteúdo.

O ponto de partida de reflection é a classe "Class".
Através dela conseguimos obter informações como os atributos dela, os métodos, os construtores etc.

Reflection é um pacote do Java que permite chamadas dinâmicas em tempo de execução sem precisar conhecer as classes e objetos envolvidos quando escrevemos nosso código (tempo de compilação).

É ideal para resolvermos determinadas coisas que nosso programa só descobre quando realmente estiver o rodando.

Neste caso, ao criar uma GenericTableModel, ela deve estar pronta a receber qualquer list("Genérico, não?") como parâmetro e mostrar a partir de uma jTable seus dados contidos.
O TableModel não sabe que atributos tem esse list, mas através de reflection, ela consegue "descobrir" esses campos e gerar a jTable.

É possível fazer muitas coisas usando reflection. Apenas para citar algumas possibilidades:
* Listar todos os atributos de uma classe e pegar seus valores em um objeto específico;
* Instanciar classes cujo nome só vamos conhecer em tempo de execução;
* Invocar métodos dinamicamente baseado no nome do método como String;
* Descobrir se determinados pedaços do código foram anotados com as anotações do Java 5.

Ex:
public class Pessoa {
 private String nome;
 private String email;
 private int idade;
 // Getters, setters, métodos de pessoa...
}

Class classe = Pessoa.class;
for (Field field : classe.getDeclaredFields()) {
System.out.println(field.getName());
}

A saída Será:
nome
email
idade

Dessa maneira, posso deixar o TableModel Genérico.
A cada execução, a cada classe distinta, ele descobre seus atributos e age sobre eles da mesma forma. 

Ok. Funcional. Mas e se eu quiser que meu GenericTabelModel não atue sobre todos os atributos, como eu faço para "marcar" um atributo ignorado? Como eu Faço para marcar apenas o Atributo que quero que apareça na jTable?

Bom, e ai que entra as Annotations. 
Não vou explicar o funcionamento de annotation, ja que o colega Bruno Lima, fez um post sobre o seu funcionamento. (@Annotations "metadados" que não interferem diretamente no código anotado) 

Posso criar anotações e usar na minha classe, onde em tempo de execução e de acordo com a annotation criada o programa age da maneira que eu especificar. 

No casso do GenericTableModel trabalhei com as Seguintes Annotations: 
@TableModel - Anotação de classe, atua sobre todos os seus atributos, coloca todos na jTable.
@ColumnIgnore - Anotação de campo. o Atributo que possuir essa anotação, não irá aparecer na jTable.
@Column - Anotação de Campo e Metodos. O atributo que possuir essa anotação vai aparecer na jTable.     * colName() = Pode-se alterar o nome da coluna, 
    * colPosition() = Posição de coluna na jTable 
    * formatt() = formatar um campo, sendo sua saida uma String. 


Funcionamento:
         GenericTableModel tableModel = new GenericTableModel(getData(), 
            Pessoa.class);
 JTable table = new JTable(tableModel);
 JFrame frame = new JFrame("GenericTableModel");
 table.setModel(tableModel);



private List getData() {
List list = new ArrayList();
list.add(new Pessoa("Marcos", "viny_scholl@hotmail.com", 21, "xxxxx", 1000.5));
list.add(new Pessoa("Marco", "tony_scholl@hotmail.com", 21, "bbbbbb", 21.75 ));
list.add(new Pessoa("Felipe", "felipe_scholl@hotmail.com", 27, "qwert", 75.40));
return list;
}

Exemplos de Execução da GenericTableModel com diferentes Annotations.
Ex1:
  
@TableModel(includeAll=true)
public class CopyOfPessoa {
 private String nome;
 private String email;
 @ColumnIgnore
 private int idade;
 private String senha;
 private double saldo;
}
Saída: 

 ----------------------------------------
Ex2:
 
@TableModel(includeAll=true)
public class CopyOfPessoa {
 @ColumnIgnore
 private String nome;
 @ColumnIgnore
 private String email;
 @ColumnIgnore
 private int idade;
 @ColumnIgnore
 private String senha;
 private double saldo;
}
Saída: 

----------------------------------------
Ex3:
 
@TableModel(includeAll=false)
public class CopyOfPessoa {

 private String nome;
 @Column
 private String email;
 private int idade;
 @Column
 private String senha;
 @Column
 private double saldo;
}
Saída: 

---------------------------------------- 
Ex4:
Com a Formatação possivel Pelo @Column
 
@TableModel(includeAll=false)
public class CopyOfPessoa {

 @Column(colName = "Nome", colPosition = 0)
 private String nome;
 @Column(colName = "Email", colPosition = 1)
 private String email;
 @Column(colName = "Idade", colPosition = 4)
 private int idade;
 @Column(colName = "Pass", colPosition = 3)
 private String senha;
 @Column(colName = "Saldo", colPosition = 2, formatter="R$ %,#.2f")
 private double saldo;
}
Saída: 



Assim, posso trabalhar de diferentes formas e com diferentes resultados de saída, a partir de uma unica classe usando Reflection e Annotations. 

Temos uma tabela Dinâmica. Uma GenerictableModel.

Referencias:
http://www.guj.com.br/java/199067-redimensionar-jtable---pra-variar--resolvido-/2#1001295
http://www.guj.com.br/java/149861-recuperar-id-de-jtable/2#813171
http://devsv.wordpress.com/2012/07/08/como-implementar-um-tablemodel/
http://markytechs.wordpress.com/2009/05/29/objecttablemodel/
http://www.guj.com.br/java/231928-morte-definitiva-ao-default-table-model#1399642
Caelum FJ-16 -Laboratório Java com Testes, XML e Design Patterns


Marcos Vinicius Scholl:
Graduando em Tecnologia em Análise e Desenvolvimento de Sistemas - TADS 
Universidade Federal do Rio Grande - FURG 
Instituto Federal de Educação, Ciência e Tecnologia do Rio Grande do Sul IFRS - Campus Rio Grande 
Rua Eng. Alfredo Huch, 475 - Rio Grande, RS - Brasil - 96201-460 

Sobre o autor:
Marcos Vinicius Scholl estuda na área de Tecnologia de Informação. É entusiasta na área de tecnologia. Gremista de paixão e anticolorado por prazer!

Post Sobre armazenamento de objetos em um Cache

o que é um cache?

Nos dias atuais cada vez mais acessamos sites, usamos banco de dados, e nossos proprios

computadores tem grande capacidade de armazenamento de processamento.Com a finalidade

de agilizar essas consultas e processamentos que existe a memoria cache, sendo uma

memoria de acesso muito rapido, que guarda pequenas quantidades de informações, as mais

acessadas por nós, seja em sites, no nosso HD ou ate mesmo um banco de dados.


Tipos mais típicos de cache

Como falado anteriormente, alguns tipos mais tipicos de caches sao:

1-Cache de sites: são caches guardados pelo navegador que usamos, guardam informaçoes

de uma pagina que visitamos na web, para que ao acessa-las novamente nao precisamos

carregar a pagina completamente, e sim informaçoes que foram atualizadas nela, assim

agilzando o processo de carregamento.

2-Cache no processador: uma memoria de alto desenpenho que fica embutida dentro do

processador, é utilizada para que o processador acesse dados mais rapidos, evitando a

busca na memoria ram que é mais lenta.Normalmente utilizada em 3 niveis no processador.
Nivel L1, L2 e alguns processadores chegam a ter o nivel L3.

3- Cache do disco : fica localizada junto ao disco rigido do nosso computador, ela

armazena as ultimas trilhas feita pelo HD assim evitando que a cabeça de leitura e

gravação passe varias vezes pelo mesmo lugar.


Características de um cache:
E uma memoria de velocidade de leitura e escrita muito mais rapido, por isso é

utilizado para armazenar dados que são lidos ou gravados varias vezes.
Possui um tempo de vida, assim nada fica sempre armazenado no cache para sempre.

Sobre meu projeto:

Bom, tendo explicado um pouco sobre memoria cache, vou mostrar um pouco do meu projeto

de cache, mostrando os codigos em java, o projeto tem como finalidade criar um toolkit

que atraves de anotaçoes feitas por quem desenvolve uma classe seja colocado na memoria

ram utilizada pela maquina virtual do java, assim evitando por exemplo o acesso a um

banco de dados utilizado por um sistema.



Alguns Métodos da minha classe cache :

Essa classe manipula o cache, ela possui um objeto cache estatico que só pode ser

instancia dentro dela mesmo, e todos os metodos necessario para adicionar, remover,ou

até mesmo limpar todo o cache.

verifica se uma chave existe :
   
      public  boolean hasKey(String chave){
 boolean chaveExisteNoCache = true;
 if(chaveEhValida(chave)&&temEssaChaveNaListaDeObjetos(chave)) return chaveExisteNoCache;
 return  chaveExisteNoCache=false;
      }


retorna um objeto do cache :
     
 public Object get(String chave){
  
  if(chaveEhValida(chave)==false){
   System.out.println("chave invalida");
   return chave;
  }
  if(temEssaChaveNaListaDeObjetos(chave)==false){
   System.out.println("objeto inexistente na lista");
   return chave;
  }
  
  
  Object objeto = listaObjetosNoCache.get(chave);
  return objeto;
 }

metodo que adiciona um objeto no cache :
/**
    
 public  void add(String chave,Object objeto,int tempo){
  
  if(chaveEhValida(chave) && validaObjeto(objeto)){
   addChaveObjetoNoCache(chave,objeto);
   addChaveParaMonitorar(chave,tempo);
  }
  
  
 }


metodo altera o tempo de um objeto no cache :
public void alteraTempoDoObjeto(String chave,int tempoEmMinutos){
    if(chaveEhValida(chave)&&(temEssaChaveNaListaDeObjetos(chave))){
       long novoTempo = calculaTempoDeDuracaoNoCache(tempoEmMinutos);
       atualizaTempoDaChave(chave, novoTempo);
       System.out.println("tempo alterado da chave para : "+tempoEmMinutos +" minutos");
    }
    else System.out.println("chave invalida ou objeto inexistente no cache ");
}



Devido ao tamanho da classe deixo os outros métodos para outra hora : )

Abaixo sobre a classe da anotação:

Anotação que inclui um objeto no cache feita em cima de um metodo, por meio de uma

interface, é uma anotaçao que deve ser inserida em um metodo de uma interface, que sera

reconhecida pelo metodo proxy utilizado na classe cache.

package cache;

/**
 *Classe utilitaria para anotar metodos que serao inseridos no cache da JVM
 *@author Andrei Garcia (andrei_garcia2@hotmail.com)
 *@since JDK.7
*/


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 *Anotação para ser utilizada sobre uma interface ,sendo anotada
 * em cima de um método,metodo o qual sera inserido no cache da JVM seu objeto de 

retorno
 *
 *@author Andrei Garcia
 *@category anotação
 *
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ColocarNoCache {

 int tempo() default 60;


}




Bom era isso, espero que tenham curtido o posto : )





Referencias

http://www.tecmundo.com.br/tira-duvidas/21555
http://pt.wikipedia.org/wiki/Cache

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.

Annotations e Reflection em um ORM

ORM é uma técnica de desenvolvimento utilizada para reduzir a impedância da programação orientada aos objetos utilizando bancos de dados relacionais. As tabelas do banco de dados são representadas através de classes e os registros de cada tabela são representados como instâncias das classes correspondentes.

Para que seja possível o desenvolvimento de uma ferramenta de ORM é necessário um conhecimento de Annotations e de Reflection.
As anotações neste caso são utilizadas para fazer a configuração dos atributos por parte de quem utiliza a ferramenta, fazendo com que a ferramenta interprete essa anotação e se comporte de acordo com a anotação utilizada. Para que seja mais simples entender vamos  ver um exemplo: Supondo que quem está utilizando a ferramenta tenha um objeto Pessoa e dentro dele tem um outro objeto Endereco, os dados desse objeto podem ser salvos tanto em uma tabela endereco ou na própria tabela pessoa,  então cria-se uma anotação para determinar se o endereço dever ser salvo na mesma tabela com os dados das pessoas ou não.
 public class Pessoa {
    @PrimaryKey
    public Integer id;
    public String nome;
    @Embutido
    public Endereco end;
   
                 .
                 .
                 .
}

Como o nosso colega de curso Bruno já fez uma post sobre anotações não irei me extender neste assunto.

Reflection permite um programa Java examinar ou fazer a introspecção nele mesmo, ou seja, olhar e examinar suas propriedades e estrutura. Com isso, você pode, por exemplo obter o nome de todos os membros de uma classe, como atributos e métodos, bem como executar um método usando a Introspection. É deste modo que os aplicativos de ambiente de desenvolvimento (as IDEs) conseguem examinar e exibir a estrutura e conteúdo das classes e beans.
É necessário a utilização desta tecnologia, pois a ferramenta de ORM deve ser genérica para funcionar com qualquer tipo de objeto, com este recurso a ferramenta recebe um objeto como parâmetro sem saber quem é ele e descobre seus atributos e suas configurações através da reflexão,   assim possibilitando o tratamento de cada atributo  de acordo com as suas configurações. Como exemplo vou mostrar uma função que recebe um objeto genérico como parâmetro e descobre qual  atributo é chave primária e o retorna. 

 private Field primaryKey(Object objeto){
  Field[] campos = objeto.getClass().getDeclaredFields();
  for (Field campo : campos) {
   if(campo.isAnnotationPresent(PrimaryKey.class))
   {
    return campo;
   }
  }
  return null;
 }
 
Era wilson pessoal... 

@Annotations "metadados" que não interferem diretamente no código anotado

Muito pensam que a anotação só serve para fazer com que a IDE pare de dar avisos sobre a falta das mesmas, pois são as mais comuns utilizadas por quem programa em java, um exemplo é a @Override que serve para informar ao compilador que o elemento esta sobrescrevendo um outro elemento declarado na superclasse. Mas existem vários tipos de anotações, como as que fornecem informações para o compilador ou as Compiler-time and deployment-time que servem para ser usadas em frameworks que geram códigos como o xml e para realizar validações em campos entre outras, existe também as de runtime que são lidas em tempo de execução.
Mas para que possamos usar as anotações de uma maneira mais abrangente podemos também criar nossas próprias anotações, a regra é a mesma da interface com o detalhe que devemos colocar o "@" antes da palavra "interface".

Exemplo:
public @interface MinhaInterface{

}

Ainda é possível declarar métodos que devem ser obrigatoriamente implementados na anotação, assim como nas interfaces, mas estes métodos não devem possuir quaisquer parâmetros, não devem lançar quaisquer exceções e o tipo de retorno deve ser do tipo primitivo, um String, um Class, um Enum ou ainda um array de um destes tipos.

Exemplo:

public @interface MinhaInterface{

String nome();
String valor();

}


Mas além das annotations existem também as Meta-annotations que servem para definir o comportamento da anotação, são elas: Target, Retention, Documented, Inherited

@Target Indica em qual elemento da classe a anotação pode ser aplicada

@Target(ElementType.TYPE) Pode ser aplicada a qualquer elemento da classe.
@Target(ElementType.FIELD) Pode ser aplicada a um campo ou propriedade.
@Target(ElementType.METHOD) Pode ser aplicada a um método.
@Target(ElementType.PARAMETER) Pode ser aplicada a parâmetros de um método
@Target(ElementType.CONSTRUCTOR) Pode ser aplicada a construtores.
@Target(ElementType.LOCAL_VARIABLE) Pode ser aplicada a variáveis locais.
@Target(ElementType.ANNOTATION_TYPE) Indica que o próprio tipo declarado é uma anotação de anotação.

@Retention Indica onde e quando as anotações deste tipo serão obtidas.

@Retention(RetentionPolicy.SOURCE) Serão obtidas somente em nível de fonte e serão ignoradas pelo compilador.
@Retention(RetentionPolicy.CLASS) Serão obtidas somente em nível de compilação e serão ignoradas pela VM.
@Retention(RetentionPolicy.RUNTIME) Obtidas pela VM e serão lidas apenas em runtime.

@Documented Indica se a anotação pertencerá ao javadoc ou algum outro gerador de documentação por padrão.

@Inherited Indica se a anotação sera herdada pelas subclasses automaticamente, sendo assim, caso haja uma consulta procurando por uma anotação qualquer, se a classe consultada não possuir a anotação a classe pai sera consultada por padrão.

Exemplo:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE
public @interface MinhaInterface{

String nome();
String valor();

}
Exemplo de uso:

@MinhaInterface(nome = "Bruno", valor = "R$ 0,00")
public class Pessoa {

private String nome;
private String telefone;

public Pessoa(){
}
}



Bom pessoal aqui fica um breve post de como usar annotation, qualquer duvida www.google.com

Internacionalização (I18N)


Internationalization ou I18N como é chamado (devido ao fato de desde a primeira letra até a última ter um total de 18 letras entre elas nessa palavra), é um processo de adaptação dinâmica de textos e mensagens em softwares de computadores para uma língua e cultura de um país.
A utilização desse processo é relativamente simples, sendo utilizado essencialmente a classe ResourceBundle para buscar os arquivos de texto de tradução (que é usado na extensão .properties) e a classe Locale para definir o idioma que será traduzido.

Nesse post, irei mostrar um pouco sobre o seu funcionamento utilizando a linguagem de programação Java.

Para começar, vamos ver como funciona o arquivo properties. Ele nada mais é do que um arquivo de texto que irá conter as palavras (ou chaves) e suas traduções correspondentes salvado com a extensão .properties. Considere um arquivo properties contendo as seguintes palavras, na exata forma escrita:

                                                nome = Name
                                                end = Address

nesse caso, quando buscarmos pela chave "nome" passando como parâmetro no método getString da classe ResourceBundle, vamos obter a palavra "Name" e quando buscarmos por "end", vamos obter "Address" de dentro do nosso arquivo properties.


Agora que já vimos como exatamente é o arquivo properties, vamos ver um exemplo simples de utilização do I18N traduzindo a palavra "cadastro" para o inglês.

O primeiro passo a ser dado é criar o arquivo properties com a palavra "cadastro" seguido de sua tradução em inglês, logo ficaria assim:

                                               cadastro = Register

depois, devemos criar objetos do tipo ResourceBundle e Locale.


 public class I18nExemplo{
  
  public static void main(String[] args){
   Locale locale;
   ResourceBundle palavra;
  }
 }
  

A seguir, temos que definir no objeto locale o idioma a ser usado, inserindo como parâmetro a identificação do país e idioma entre aspas. No nosso caso, "en" e "US" (já que queremos traduzir para o inglês).

  locale = new Locale("en", "US");
  

O próximo passo então é atribuir ao objeto "palavra" a localização do arquivo .properties que vamos utilizar para traduzi-la para o ingles, utilizando o método getBundle da classe ResourceBundle e recebendo como parâmetros o arquivo properties de tradução e a váriavel do tipo locale.

Vamos supor que temos um pacote chamado "properties", e nele colocamos nosso arquivo de tradução para o ingles que se chama "ingles_en_US.properties". Então nosso código ficaria assim:

     palavra = ResourceBundle.getBundle("properties.ingles_en_US", locale);
  

Agora, usamos o método getString da classe ResourceBundle no objeto "palavra", passando como parâmetro a chave do arquivo properties
que vamos traduzir, que é "cadastro" nesse caso.
Se colocarmos isso dentro de um System.out.println() ou de uma janela já vamos obter a palavra traduzida.

    System.out.println(palavra.getString(cadastro)); //Register
  

Como pode perceber, não é difícil utilizar o I18N.
I18N ainda tem várias outras formas de utilização para horário, unidade monetária e etc.
Se interessou? dê mais uma lida sobre o assunto nesse link da Oracle:

http://docs.oracle.com/javase/tutorial/i18n/TOC.html