quinta-feira, 30 de abril de 2015

Caracteres especiais em Unicode

Para evitar problemas com encoding de caracteres especiais é bom utilizar em suas classes Java código unicode ao invés de letras acentuadas. Abaixo relaciono uma tabela de alguns dos caracteres especiais que mais usamos no dia a dia com seu cógigo unicode:

á = \u00e1
à = \u00e0
â = \u00e2
ã = \u00e3
ä = \u00e4
Á = \u00c1
À = \u00c0
 = \u00c2
à = \u00c3
Ä = \u00c4
é = \u00e9
è = \u00e8
ê = \u00ea
ê = \u00ea
É = \u00c9
È = \u00c8
Ê = \u00ca
Ë = \u00cb
í = \u00ed
ì = \u00ec
î = \u00ee
ï = \u00ef
Í = \u00cd
Ì = \u00cc
Î = \u00ce
Ï = \u00cf
ó = \u00f3
ò = \u00f2
ô = \u00f4
õ = \u00f5
ö = \u00f6
Ó = \u00d3
Ò = \u00d2
Ô = \u00d4
Õ = \u00d5
Ö = \u00d6
ú = \u00fa
ù = \u00f9
û = \u00fb
ü = \u00fc
Ú = \u00da
Ù = \u00d9
Û = \u00db
ç = \u00e7
Ç = \u00c7
ñ = \u00f1
Ñ = \u00d1
& = \u0026
' = \u0027

Para colocar o código Unicode em uma String basta substituir o caracter pelo código. Exemplo: String s = "Programando sem cafe\u00edna";

O código do método que usei para gerar essa tabela está abaixo:
public static String geraCodigoUnicode(char letra) {
    String hexa = Integer.toHexString( (int)letra );

    String prefix;
    if( hexa.length() == 1 ) {
        prefix = "\\u000";
    } else if( hexa.length() == 2 ) {
        prefix = "\\u00";
    } else if( hexa.length() == 3 ) {
        prefix = "\\u0";
    } else {
        prefix = "\\u";
    }

    return prefix + hexa;
}

quinta-feira, 12 de dezembro de 2013

Recursividade

Para entender um método recursivo, primeiro você deve entender um método recursivo.

Eu me orgulho de poucos códigos. ESTE é um deles.

--------------------------------------------

public class DataObjectMetadataService {

@Resource(name = "dataObjectMetadataDAOImpl")
private DataObjectMetadataDAO domDAO;
private List<Programa> progs = new ArrayList<Programa>();
private Boolean carregaCampos;

public List<DataObjectMetadata> createOrRetrieveByClassName(DataObjectMetadataFilter filter) {
List<DataObjectMetadata> newDatas = null;
this.carregaCampos = filter.getCarregaCampos();

filter.setNmPrograma(domDAO.buscaClassNameCompleto(filter));
progs = domDAO.pesquisaPrograma(filter);
if(filter.getNmPrograma() != null) {
List<DataObjectMetadata> impedeRetorno = new ArrayList<DataObjectMetadata>();
newDatas = criaEstruturaClasse(filter.getNmPrograma(), impedeRetorno);
if(this.carregaCampos){
percorreNivelCampos(newDatas);
while(newDatas.get(0).getLevel() == null) {
defineNivel(newDatas);
}
}

return newDatas;
}

private List<DataObjectMetadata> criaEstruturaClasse(String className, List<DataObjectMetadata> impedeRetorno) {

List<DataObjectMetadata> datas = null;

try {

AbstractEntityPersister persister = buscaPropriedadesBanco(Class.forName(className));

DataObjectMetadata data = new DataObjectMetadata();
data.setClassName(persister.getName());
impedeRetorno.add(data);
if(carregaCampos){
datas = montaDadosClasse(persister, impedeRetorno);
completaDadosData(datas);
} else {
datas = montaDadosProgs(persister, impedeRetorno);
}
} catch(ClassNotFoundException e) {
e.printStackTrace();
}

return datas;

}

private <T> AbstractEntityPersister buscaPropriedadesBanco(Object cls) {
AbstractEntityPersister persister = null;
ClassMetadata hibernateMetadata = domDAO.findHibernateMetadata((Class<?>) cls);

if(hibernateMetadata != null) {
if(hibernateMetadata instanceof AbstractEntityPersister) {
persister = (AbstractEntityPersister) hibernateMetadata;
}
}
return persister;
}

private List<DataObjectMetadata> montaDadosClasse(AbstractEntityPersister persister, List<DataObjectMetadata> impedeRetorno) {

List<DataObjectMetadata> ir = copiaListaRetorno(impedeRetorno);

List<DataObjectMetadata> datas = new ArrayList<DataObjectMetadata>();
DataObjectMetadata data = null;

if(persister != null) {
String[] columnKey = persister.getKeyColumnNames();
String[] columnNames = persister.getPropertyNames();
Type[] columnTypes = persister.getPropertyTypes();
boolean[] columnNullable = persister.getPropertyNullability();

if(columnKey != null) {
List<String> keys = new ArrayList<String>(Arrays.asList(columnKey));
for(String key : keys) {
data = new DataObjectMetadata();

data.setDataStamp(new Date());

data.setTableName(persister.getTableName());
data.setClassName(persister.getName());
data.setColumnName(key);
data.setColumnType("Integer");
data.setIsNullable(SimNao.NAO);
data.setIsClassAntara(SimNao.NAO);
data.setMustInspectElement(SimNao.NAO);

data.setDataObjectMetadata(verificaSubObjetos(data, ir));

datas.add(data);
}
}

if((columnNames != null) && (columnTypes != null)) {
List<String> colunas = new ArrayList<String>(Arrays.asList(columnNames));
List<Type> tipos = new ArrayList<Type>(Arrays.asList(columnTypes));

if((colunas != null) && (tipos != null)) {
for(int i = 0; i < colunas.size(); i++) {
data = new DataObjectMetadata();

data.setDataStamp(new Date());

data.setTableName(persister.getTableName());
data.setClassName(persister.getName());
data.setColumnName(colunas.get(i));
data.setColumnType(tipos.get(i).getName());
data.setIsNullable(columnNullable[i] ? SimNao.SIM : SimNao.NAO);
data.setIsClassAntara(isClasseAntara(data.getColumnType()));
if(SimNao.SIM.equals(data.getIsClassAntara())) {
data.setMustInspectElement(deveInspecionarElemento(data.getColumnType(), ir));
} else {
data.setMustInspectElement(SimNao.NAO);
}

data.setDataObjectMetadata(verificaSubObjetos(data, ir));

datas.add(data);

}
}
}
}

return datas;
}

private void completaDadosData(List<DataObjectMetadata> datas) {

List<DataObjectMetadata> loadDatas = new ArrayList<DataObjectMetadata>();
loadDatas = domDAO.loadMedatadas(datas);
if(loadDatas != null) {
for(ListIterator<DataObjectMetadata> it = datas.listIterator(); it.hasNext();) {
DataObjectMetadata dom = it.next();
for (DataObjectMetadata load : loadDatas) {
if(dom.getTableName().equals(load.getTableName()) && dom.getColumnName().equals(load.getColumnName())){
it.remove();
it.add(load);
load.setLevel(null);
load.setMustInspectElement(dom.getMustInspectElement());
load.setDataObjectMetadata(dom.getDataObjectMetadata());
if(!StrUtil.validateString(load.getProgramName()) || !StrUtil.validateString(load.getProgramCode())){
completaDadosCampos(load);
}
break;
}
}
}
}
loadDatas.clear();
}

private List<DataObjectMetadata> copiaListaRetorno(List<DataObjectMetadata> impedeRetorno) {

List<DataObjectMetadata> copia = new ArrayList<DataObjectMetadata>();
DataObjectMetadata c = null;

for(DataObjectMetadata dom : impedeRetorno) {
c = new DataObjectMetadata();

c.setClassName(dom.getClassName());

copia.add(c);

}
return copia;
}

private List<DataObjectMetadata> verificaSubObjetos(DataObjectMetadata data, List<DataObjectMetadata> impedeRetorno) {
List<DataObjectMetadata> datas = null;

if(SimNao.SIM.equals(data.getMustInspectElement())) {
datas = criaEstruturaClasse(data.getColumnType(), impedeRetorno);
}

return datas;

}

private SimNao isClasseAntara(String columnType) {
if(columnType.contains(".")) {
String[] caminho = columnType.split(Pattern.quote("."));
int tam = caminho.length;

for(int j = 0; j < tam; j++) {
if("domain".equals(caminho[j])) {
return SimNao.SIM;
} else {
if("util".equals(caminho[j])) {
return SimNao.NAO;
}
if("java".equals(caminho[j])) {
return SimNao.NAO;
}
if("hibernate".equals(caminho[j])) {
return SimNao.NAO;
}
}
}

return SimNao.SIM;

}

return SimNao.NAO;
}

private SimNao deveInspecionarElemento(String columnType, List<DataObjectMetadata> impedeRetorno) {

for(DataObjectMetadata tipoJaUsado : impedeRetorno) {
if(columnType.equals(tipoJaUsado.getClassName())) {
return SimNao.NAO;
}
}

DataObjectMetadata aux = new DataObjectMetadata();
aux.setClassName(columnType);
impedeRetorno.add(aux);

return SimNao.SIM;
}

private void percorreNivelCampos(List<DataObjectMetadata> datas) {

Boolean encontrouUltimoNivel = false;

for(DataObjectMetadata data : datas) {
if(SimNao.SIM.equals(data.getMustInspectElement())) {
percorreNivelCampos(data.getDataObjectMetadata());
encontrouUltimoNivel = false;
}
}

if(!encontrouUltimoNivel) {
for(DataObjectMetadata dom : datas) {
if(SimNao.NAO.equals(dom.getMustInspectElement())) {
encontrouUltimoNivel = true;
} else {
encontrouUltimoNivel = false;
break;
}
}
}

if(encontrouUltimoNivel) {
for(DataObjectMetadata data : datas) {
data.setLevel(new Integer(1));

if(data.getDataObjectMetadata() == null) {
List<DataObjectMetadata> dates = Collections.emptyList();
data.setDataObjectMetadata(dates);
}
}
}
}

private void defineNivel(List<DataObjectMetadata> datas) {

Boolean recebeuLevel = false;
Integer level = new Integer(0);
for(DataObjectMetadata data : datas) {
if(SimNao.SIM.equals(data.getIsClassAntara()) && SimNao.SIM.equals(data.getMustInspectElement())) {
if(data.getDataObjectMetadata().get(1).getLevel() != null) {
if(data.getLevel() == null) {
if(level < (data.getDataObjectMetadata().get(1).getLevel() + new Integer(1))) {
level = (data.getDataObjectMetadata().get(1).getLevel() + new Integer(1));
}
recebeuLevel = true;
} else if(data.getLevel() < (data.getDataObjectMetadata().get(1).getLevel() + new Integer(1))) {
if(level < (data.getDataObjectMetadata().get(1).getLevel() + new Integer(1))) {
level = (data.getDataObjectMetadata().get(1).getLevel() + new Integer(1));
}
recebeuLevel = true;
}
} else {
defineNivel(data.getDataObjectMetadata());
if(data.getLevel() == null) {
if(level < (data.getDataObjectMetadata().get(1).getLevel() + new Integer(1))) {
level = (data.getDataObjectMetadata().get(1).getLevel() + new Integer(1));
}
recebeuLevel = true;
}
}
}
}

if(recebeuLevel) {
for(DataObjectMetadata dom : datas) {
if(dom.getLevel() == null) {
dom.setLevel(level);

if(dom.getDataObjectMetadata() == null) {
List<DataObjectMetadata> dates = Collections.emptyList();
dom.setDataObjectMetadata(dates);
}
}
}
}
}

public void save(List<DataObjectMetadata> datas, String usuario) {

List<DataObjectMetadata> saves = new ArrayList<DataObjectMetadata>();

desmembraObjetos(datas, saves);

for(DataObjectMetadata save : saves) {
save.setUsuarioStamp(usuario);

domDAO.save(save);
}

}

private void desmembraObjetos(List<DataObjectMetadata> datas, List<DataObjectMetadata> saves) {

for(DataObjectMetadata dom : datas) {
if(SimNao.SIM.equals(dom.getMustInspectElement())) {
desmembraObjetos(dom.getDataObjectMetadata(), saves);
adicionaObj(saves, dom);
} else {
adicionaObj(saves, dom);
}
}
}

private void adicionaObj(List<DataObjectMetadata> saves, DataObjectMetadata dom) {
Boolean add = true;
for(DataObjectMetadata save : saves) {
if(save.getClassName().equals(dom.getClassName())) {
if(save.getColumnName().equals(dom.getColumnName())) {
add = false;
break;
}
}
}

if(add) {
saves.add(dom);
}
}

public List<DataObjectMetadata> findToExport(DataObjectMetadata data) {
return domDAO.findToExport(data);
}

public List<DataObjectMetadata> getEstruturaExportacaoXml(List<DataObjectMetadata> metadatasRequisitados) {
List<DataObjectMetadata> retorno = new ArrayList<DataObjectMetadata>(metadatasRequisitados);
List<DataObjectMetadata> metadatas = domDAO.findAll();
metadatas.removeAll(retorno);

adicionaSubNiveis(retorno, metadatas);
return retorno;
}

private void adicionaSubNiveis(List<DataObjectMetadata> niveisSelecionados, List<DataObjectMetadata> todosMetadatas) {
List<DataObjectMetadata> subniveis = new ArrayList<DataObjectMetadata>();
List<String> classesEsperadasSubniveis = getSubniveisEsperadosParaListaDeDatas(niveisSelecionados);

// adiciona os metadatas relacionados aos subníveis selecionados
for(DataObjectMetadata metadata : todosMetadatas) {
if(classesEsperadasSubniveis.contains(metadata.getClassName())) {
subniveis.add(metadata);
}
}

// remove os metadatas adicionados da lista geral
todosMetadatas.removeAll(subniveis);

if(!subniveis.isEmpty()) {
adicionaSubNiveis(subniveis, todosMetadatas);
}

niveisSelecionados.addAll(subniveis);
}

private List<String> getSubniveisEsperadosParaListaDeDatas(List<DataObjectMetadata> metadatasParaAnalisar) {
List<String> classesEsperadasSubniveis = new ArrayList<String>(metadatasParaAnalisar.size());

for(DataObjectMetadata metadata : metadatasParaAnalisar) {
if(isClasseAntara(metadata.getColumnType()) == SimNao.SIM) {
classesEsperadasSubniveis.add(metadata.getColumnType());
}
}

return classesEsperadasSubniveis;
}
private List<DataObjectMetadata> montaDadosProgs(AbstractEntityPersister persister, List<DataObjectMetadata> impedeRetorno) {
List<DataObjectMetadata> ir = copiaListaRetorno(impedeRetorno);
List<DataObjectMetadata> datas = new ArrayList<DataObjectMetadata>();
DataObjectMetadata data = null;
if(persister != null) {
String[]  columnNames    = persister.getPropertyNames();
Type[]    columnTypes    = persister.getPropertyTypes();
if((columnNames != null) && (columnTypes != null)) {
List<String> colunas = new ArrayList<String>(Arrays.asList(columnNames));
List<Type> tipos = new ArrayList<Type>(Arrays.asList(columnTypes));
if((colunas != null) && (tipos != null)) {
for(int i = 0; i < colunas.size(); i++) {
data = new DataObjectMetadata();
if(SimNao.SIM.equals(isClasseAntara(tipos.get(i).getName()))){
data.setDataStamp(new Date());
data.setTableName(persister.getTableName());
data.setClassName(persister.getName());
data.setColumnName(colunas.get(i));
data.setColumnType(tipos.get(i).getName());
data.setIsClassAntara(isClasseAntara(data.getColumnType()));
data.setMustInspectElement(deveInspecionarElemento(data.getColumnType(), ir));
data.setDataObjectMetadata(verificaSubObjetos(data, ir));
completaDadosProg(data);
datas.add(data);
}
}
}
}
}
return datas;
}


private void completaDadosCampos(DataObjectMetadata data) {
Integer indexInicio = data.getClassName().lastIndexOf(".");
Integer indexFinal  = data.getClassName().length();
String nmBean = data.getClassName().substring((indexInicio+1), (indexFinal));
for (Programa prog : progs) {
indexInicio = prog.getNmPrograma().lastIndexOf(".");
indexFinal  = prog.getNmPrograma().length();
String nmPrograma = prog.getNmPrograma().substring((indexInicio+1), (indexFinal));
if(!nmPrograma.contains("Rep")){
if("Frm".equals(prog.getNmPrograma().substring((indexFinal-3), indexFinal))){
nmPrograma = prog.getNmPrograma().substring((indexInicio+1), (indexFinal-3));
}
if(nmPrograma.equals(nmBean)){
data.setProgramName(prog.getProgramaIdioma(new Locale("pt", "BR")).getNmTituloPrograma());
data.setProgramCode(prog.getCdPrograma());
break;
}
}
}
}
private void completaDadosProg(DataObjectMetadata data) {
Integer indexInicio = data.getColumnType().lastIndexOf(".");
Integer indexFinal  = data.getColumnType().length();
String nmBean = data.getColumnType().substring((indexInicio+1), (indexFinal));
for (Programa prog : progs) {
indexInicio = prog.getNmPrograma().lastIndexOf(".");
indexFinal  = prog.getNmPrograma().length();
String nmPrograma = prog.getNmPrograma().substring((indexInicio+1), (indexFinal));
if("Frm".equals(prog.getNmPrograma().substring((indexFinal-3), indexFinal))){
nmPrograma = prog.getNmPrograma().substring((indexInicio+1), (indexFinal-3));
}
if(nmPrograma.equals(nmBean)){
if(carregaCampos){
data.setProgramName(prog.getProgramasIdiomas().get(0).getNmTituloPrograma());
} else {
data.setClassName(prog.getProgramaIdioma(new Locale("pt", "BR")).getNmTituloPrograma());
}
data.setProgramCode(prog.getCdPrograma());
break;
}
}
}
}


-------------------------------------------------

public String buscaClassNameCompleto(String className) {
SessionFactory sf = getSessionFactory();
Map<String, ClassMetadata> classes = sf.getAllClassMetadata();

for(Map.Entry<String, ClassMetadata> entry : classes.entrySet()) {
ClassMetadata classMetadata = (ClassMetadata) entry.getValue();
String clazz = classMetadata.getMappedClass(EntityMode.POJO).getName();
int indexInicio = clazz.indexOf("domain.");
indexInicio += "domain.".length();
String objetoRetornado = clazz.substring(indexInicio, clazz.length());
if(objetoRetornado.equals(className)) {
return clazz;
}
}
return null;
}

terça-feira, 15 de março de 2011

Trabalhando com EXTJS

Senhores,

O caso de uso era simples: colocar um Grid dentro de um Accordion.

Criei o grupo do grid, no modo tradicional:

    // Variávl "Modelo de coluna", cria as colunas do grid.
    var clModel = new Ext.grid.ColumnModel(this.gridColumns);

    // Variável "Modelo de número de registros" cria as linhas do grid de acordo com a quantidade de registros 
    var rsModel = new Ext.grid.RowSelectionModel(this.gridSelection);
    rsModel.addListener('rowselect', function(obj, rowIndex, record){
        fmPanel.getForm().loadRecord(record);
        formataPopups(record);
    }, this);

    // Variável "Guardadora de dados do banco", esta variável será colocada dentro do rsModel para popular o grid
    var dtStoree = new Ext.data.Store({
        url: '<<local onde está o reposítório>>',
        reader: new Ext.data.JsonReader({
            successProperty: 'success',
            root: 'data',
            totalProperty: 'total'
        }, this.gridData)
    });
   
    dtStoree.addListener('load', function(store, records, options){
        initView();
    }, this);

    dtStoree.addListener('beforeload', function(store, records, options){
        var instruction = "dtStore.baseParams = { ";
        var cont = 0;
        if(tela.filterField1 != null){
            cont++;
            instruction += "\"" + tela.filterField1 + "\" : \"" + Ext.getCmp(tela.filterField1).getValue().split(' - ')[0] + "\",";
        }
        if(tela.filterField2 != null){
            cont++;
            instruction += "\"" + tela.filterField2 + "\" : \"" + Ext.getCmp(tela.filterField2).getValue().split(' - ')[0] + "\",";
        }
        if(tela.filterField3 != null){
            cont++;
            instruction += "\"" + tela.filterField3 + "\" : \"" + Ext.getCmp(tela.filterField3).getValue().split(' - ')[0] + "\",";
        }
        instruction += " }"
        if(cont>0){
            eval(instruction);
        }
    }, this);

    // Variável de montagem do painel do grid. Essa variável junta todos os componentes
    // e cria uma referencia ao grid pronto
    var gdPanel = new Ext.grid.GridPanel({
        layout: 'fit',
        autoWidth: true,
        height: 500,
        anchor: '100% 100%',
        autoScroll: true,
        // trecho a seguir redesenha o grid após a pesquisa dos dados
        view: new Ext.grid.GridView({
            forceFit:true
        }),
        cm: clModel,
        sm: rsModel,
        store: dtStoree,
        bbar: new Ext.PagingToolbar({
           pageSize: this.gridSize,
           store: dtStoree,
           displayInfo: true,
           displayMsg: 'Mostrando registros {0} - {1} de {2}',
           emptyMsg: "Nenhum registro para mostrar",
       })
    });

Logo após, coloquei a variável gdPanel dentro do construtor do Accordion:
Aqui é importante mencionar que fiz algo que não encontrei em nenhum exemplo por ai:
Ajuste de Grid dentro de Accordion em EXTJS.
Ao tentar arrumar o Grid dentro do Accordion, comecei tentando pelo próprio Grid, afinal, era este objeto que não tinha o comportamento que eu desejava.
Porém, por mais que eu tratasse o Grid, não havia como fazê-lo aparecer completo, com scroll, de forma satisfatória para o usuário final.
Então, suspeitei que o objeto do Accordion estivesse "espremendo" o Grid, não fornecendo lugar adequado para sua apresentação.
Mas o problema não foi no objeto do Accordion. Embora este tenha grupo "defaults", indicado para o conteúdo ser extendido por todos os items, o layout é controlado diretamente dentro de cada item do accordion.
O código do accordion ficou assim:

    // Variável de montagem do painel dde Accordion's. Essa variável junta todos os componentes
    // e cria uma referencia ao accordion pronto   
    var accordion = new Ext.Panel({
        title: 'Accordion Layout',
        layout:'accordion',
        defaults: {
            // Aplicado para cada painel
            bodyStyle: 'padding:15px'
        },
        layoutConfig: {
            // Configurações específicas do Grupo Accordion vão aqui
            titleCollapse: false,
            animate: true,
            autoWidth: true,
            autoHeight: 600
        },
        items: [{
            title: 'Panel 1',
            autoScroll: true,
            autoWidth: true,
            autoHeight: true,
            items: gdPanel
        }
,{
            title: 'Panel 2',
            html: '<p>Panel content!</p>'
        },{
            title: 'Panel 3',
            html: '<p>Panel content!</p>'
        }]
    });

Por fim, utilizei o objeto do accordion para gerar um formField:

    // Objeto dos "Campos do Form". Ao invés de criá-los diretamente no painel, cria-se ou juntam-se os objetos aqui.
    // o nome da variável faz referência direta a todo grupo de elementos que aparecerão na tela.
    // neste caso em específico, criou-se um objeto de grid;
    // esse grid foi colocado dentro do objeto de accordion;
    // o accordion foi colocado dentro do formFields;
    // o formFields será utilizado dentro do fmPanel;
    // o fmPanel será um objeto do painel que será criado dentro do initView, objeto que cria, efetivamente, a tela.
    var formFields = [{
        autoScroll: true,
        layout: 'column',
        width: 465,
        heigth: 50,
        labelWidth: 1,
        items: [{
            layout: 'form',
            width: 350,
            labelWidth: 85,
            items: [ {
                xtype: 'textfield',
                id: 'id',
                title: 'id',
                fieldLabel: 'id',
                width: 244,
                scope: this,
                editable: false,
                allowBlank: false,
                tabIndex: 4,
                valueDto: null,
            }]
        },{
            layout: 'form',
            width: 115,
            labelWidth: 5,
            items: [{
                xtype: 'button',
                text: 'Botão',
                minWidth : 110,
                listeners:{
                    click:function(){
                        if ( Ext.getCmp('id').getValue() != '' && Ext.getCmp('id').getValue() != 'null') {
                            fmPanel.getForm().submit(searchAction);
                        } else {
                            Ext.Msg.alert('Atenção', 'Campo id em Branco.');
                        }
                    }
                }          
            }]
        }]
    },
    accordion
    ];

terça-feira, 15 de fevereiro de 2011

Iniciando com Hibernate 3 utilizando Annotations

Estava começando a escrever um tutorial "Aprenda Hibernate do Zero" e, pesquisando referencias, encontrei exatamente o que eu queria escrever.
Tutorial fácil, segui e funcionou perfeitamente, simples de ser ampliado.

Retirado daqui:
http://www.javaframework.org/portal/2010/03/17/iniciando-com-hibernate-3-utilizando-annotations/

-------------------------------------------------------------------

O Hibernate é um dos mais famosos frameworks de persistencia. Um framework de persistencia é uma ferramenta que ajudará a persistir, ou seja, salvar, os seus dados em algum local, um banco de dados por exemplo. O Hibernate faz o mapeamento das classes de sua aplicação em tabelas e colunas do banco de dados. Com isso é possível ler e salvar objetos no banco de forma transparente. Nesse tutorial aprenderemos a configurar um projeto básico com Hibernate e utilizaremos Annotations para fazer a configuração das classes.

O primeiro passo para fazermos um projeto com Hibernate, é definir qual é a estrutura de classes iremos utilizar. Depois, criaremos as tabelas de acordo com essas classes, e faremos o mapeamento no hibernate. Essas classes serão mapeadas em tabelas no banco de dados, o hibernate então fará a comunicação entre nossa aplicação e o banco de dados.
Iremos utilizar o hibernate para fazer o mapeamento de classes para tabelas em um banco de dados, então antes de trabalharmos na aplicação é necessário configurar algum SGBD para trabalhamos. Utilizaremos nesse tutorial o HSQLDB que é um banco de dados em memória escrito em Java e vai facilitar o nosso trabalho.

1. Baixando os pacotes necessários

Para esse tutorial precisaremos baixar vários arquivos:
  • Hibernate Core (3.3.2 GA): contém o núcleo do hibernate
  • Hibernate Annotations (3.4.0 GA): contém a API necessária para configurar as classes com annotations
  • SLF4J (1.5.x): sistema de log utilizado pelo hibernate
  • HSQLDB (2.0 RC 8): banco de dados que utilizaremos no nosso exemplo
Os arquivos podem ser baixados nas seguintes URLs
Hibernate Core:
http://sourceforge.net/projects/hibernate/files/hibernate3/3.3.2.GA/hibernate-distribution-3.3.2.GA-dist.zip/download
Hibernate Annotations:
http://sourceforge.net/projects/hibernate/files/hibernate-annotations/3.4.0.GA/hibernate-annotations-3.4.0.GA.zip/download
SLF4J:
http://www.slf4j.org/dist/slf4j-1.5.8.zip
HSQLDB:
http://sourceforge.net/projects/hsqldb/files/alpha_beta/hsqldb_2_0_0_rc8/hsqldb-2.0.0-rc8.zip/download
Se desejar baixar versões diferentes será necessário verificar a compatibilidade das versões das bibliotecas. No site do hibernate existe uma planilha com a compatibilidade de versões. A versão do HSQLDB não deve influenciar na compatibilidade. A versão do SLF4J deve ser a mesma do JAR contido no hibernate core.
Baixe todos os arquivos e extraia o conteúdo para uma pasta qualquer.

2. Executando o HSQLDB

O HSQLDB, também conhecido como HyperSQL, é um banco de dados bem simples e não necessita instalação. Utilizaremos ele apenas para ser possível experimentar o hibernate. Antes de executar a aplicação que iremos montar será necessário ligar o banco de dados. Para ligar o banco de dados basta executar o arquivo runServer.bat que está dentro da pasta /hsqldb/bin. Nenhuma configuração é necessária.
Caso o banco de dados não esteja rodando quando executar a sua aplicação, um erro como o seguinte será lançado:
java.sql.SQLTransientConnectionException: java.net.ConnectException: Connection refused: connect

3. Criando um projeto e configurando as bibliotecas na aplicação

Crie um projeto no seu ambiente de desenvolvimento, é importante que seja um projeto Java 1.5 ou superior pois utilizaremos annotations. Copie e adicione ao classpath as bibliotecas das seguintes pastas dos arquivos baixados anteriormente:
\hsqldb-2.0.0-rc8\hsqldb\lib
        hsqldb.jar
\hibernate-distribution-3.3.2.GA
        hibernate3.jar
\hibernate-distribution-3.3.2.GA\lib\required (todas as bibliotecas)
        antlr-2.7.6.jar
        commons-collections-3.1.jar
        dom4j-1.6.1.jar
        javassist-3.9.0.GA.jar
        jta-1.1.jar
        slf4j-api-1.5.8.jar
\hibernate-annotations-3.4.0.GA
        hibernate-annotations.jar
\hibernate-annotations-3.4.0.GA\lib
        ejb3-persistence.jar
        hibernate-commons-annotations.jar
\slf4j-1.5.8
        slf4j-simple-1.5.8.jar
Totalizando 12 arquivos JAR.

4. Definindo a estrutura

Vamos criar apenas uma classe nessa aplicação, para ver como o hibernate funciona. Crie uma classe Produto conforme o exemplo:
package org.javaframework.persistencia;
import static javax.persistence.GenerationType.*;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Produto {

    @Id @GeneratedValue(strategy=SEQUENCE)
    Integer id;
    String nome;

    public Produto(Integer id, String nome) {
        this.id = id;
        this.nome = nome;
    }
    public Produto(){
    }

    public Integer getId() {
        return id;
    }
    public String getNome() {
        return nome;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public void setNome(String nome) {
        this.nome = nome;
    }
}

Essa classe produto possui dois atributos. O primeiro é o id, o id será utilizado apenas como a chave primária do produto, não terá utilidade na nossa aplicação. Mas para o hibernate trabalhar, precisamos definir esse atributo na classe. Escolhemos a classe Integer para o atributo id, pois utilizaremos um sequencial numérico para os registros do banco. O outro atributo é o nome do produto. Repare que foi criado um construtor sem nenhum parâmetro, esse construtor é obrigatório (caso crie um outro construtor com vários argumentos, como no exemplo).
A configuração dessa classe está nas anotações que utilizamos. A anotação @Entity define uma entidade, e deve ser utilizada em todas as classes que forem mapeadas pelo hibernate. A anotação @Id define o campo que será o primary key no banco de dados. E a anotação @GeneratedValue indica que deve ser gerado um valor quando for salvar um novo produto a estratégia utilizada é a SEQUENCE, que criará um novo sequencial para cada produto. Dependendo do banco de dados utilizado podem ser utilizadas outras estratégias, consulte a documentação do hibernate para mais informações.
Atenção para o pacote da anotação @Entity, deve ser utilizado o pacote javax.persistence. Existe outra anotação com o mesmo nome no pacote org.hibernate.annotations mas não servirá para mapear a classe, apenas para adicionar informações extras. Se utilizar a anotação do pacote errado o hibernate lançará exceções dizendo que a classe não foi mapeada.

5. Configurando o hibernate

Existem duas formas de configurar o hibernate, através de um XML ou de um arquivo de properties. Por sem mais simples, utilizaremos o arquivo de properties. Crie um arquivo chamado hibernate.properties na sua aplicação, ele deve ficar na raiz dos fontes (SRC no eclipse por exemplo) e deve estar na raiz do classpath quando executar sua aplicação (se estiver utilizando um editor, basta colocar o arquivo na pasta raiz dos fontes). O arquivo deve ficar assim:
hibernate.connection.driver_class=org.hsqldb.jdbcDriver
hibernate.connection.url=jdbc:hsqldb:hsql://localhost
hibernate.connection.username=sa
hibernate.connection.password=

# Echo all executed SQL to stdout
hibernate.show_sql=true

# Drop and re-create the database schema on startup
hibernate.hbm2ddl.auto=update

Nesse arquivo temos nas quatro primeiras linhas as informações de conexão JDBC com o banco de dados. Configuramos também a exibição de queries e que o hibernate deve criar a estrutura do banco de dados automaticamente.
Com esse arquivo o Hibernate estará configurado. Caso você nao coloque o arquivo no lugar certo com o nome correto um erro como o seguinte pode acontecer: Exception in thread "main" org.hibernate.HibernateException: ‘hibernate.dialect’ must be set when no Connection avalable.
Vamos agora criar uma classe que utilizará o hibernate.

6. Executando um programa com o Hibernate

Crie na sua aplicação a seguinte classe para podermos testar o hibernate:
package org.javaframework.persistencia;
import java.util.List;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.classic.Session;

public class HelloWorldHibernate {
    public static void main(String[] args) {
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(Produto.class);
        SessionFactory sessionFactory = config.buildSessionFactory();
        Session session = sessionFactory.openSession();
        inserirProduto(session);
        listarProdutos(session);
        session.close();
        sessionFactory.close();
    }

    private static void inserirProduto(Session session) {
        Produto produto = new Produto();
        produto.setNome("Shampoo");
        Transaction tx = session.beginTransaction();
        session.persist(produto);
        tx.commit();
        System.out.println("Produto inserido");
    }

    private static void listarProdutos(Session session) {
        List<Produto> produtos = session.createQuery("from Produto").list();
        for (Produto p: produtos) {
            System.out.printf("%4d \t %s %n", p.getId(), p.getNome());
        }
    }

}
A classe HelloWorldHibernate é apenas para efeito didádico, é interessante você estruturar a sua aplicação de maneira mais elegante.
Nesse código criamos um AnnotationConfiguration que permite a configuração de classes anotadas no Hibernate. Adicionamos a classe Produto para ser adicionada a configuração. O arquivo hibernate.properties será lido automaticamente. Com essa configuração construimos um SessionFactory. Um SessionFactory serve para criamos sessões do hibernate. Devemos ter apenas um SessionFactory na aplicação mas podemos ter vários Sessions (geralmente um para cada thread, ou um por requisição no caso de aplicações web). Um SessionFactory é como um DataSource e um Session é como um Connection.
Temos dois métodos bastante simples, um é o inserirProduto, que salva um novo produto no banco de dados, inclusive utilizando uma transação. E um método listarProdutos que lista todos os produtos encontrados no banco de dados.
Se executarmos o programa veremos algo semelhante ao seguinte:
Hibernate: call next value for hibernate_sequence
Hibernate: insert into Produto (nome, id) values (?, ?)
Produto salvo
Hibernate: select produto0_.id as id0_, produto0_.nome as nome0_ from Produto produto0_
  10      Shampoo

Pronto! Já pode agora utilizar o hibernate nos seus projetos. Veja a documentação de referencia no site http://www.hibernate.org para mais exemplos de consultas, operações e mapeamentos.

sexta-feira, 11 de fevereiro de 2011

Aplicação SOA

Caso de Uso:

Tínhamos que buscar alguns dados de tabelas diferentes para utilizarmos em nosso aplicativo.
Para isso, fizemos um barramento SOA (que não vou postar por motivo de sigilo da empresa...) e conectamos este cliente a ele.

Problemas resolvidos com este código:
Swing: Utilização de tabelas dentro de abas, sem a utilização de containers.
Popular tabelas com array bidimensional de strings

SOA: Transportar strings entre o barramento e o Cliente.


-----------------------------------------------------------------------------------------------------------------



-----------------------------------------------------------------------------------------------------------------
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.xml.rpc.ParameterMode;
import javax.xml.rpc.encoding.XMLType;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;

public class Unitizacao implements ActionListener{
   
    JFrame tela = new JFrame();
    JTextField TfOdex;
    JTable tbData1, tbData2, tbData3, tbData4, tbData5;
    JTextArea area6 = new JTextArea();
       
    public static void main(String args[]){
       
        // Cria o Objeto para tirar o swing de um método static
        Unitizacao u = new Unitizacao();
        u.run();
    }
   
    public void run(){
       
        // Tenta utilizar uma biblioteca de aparencia para o Swing
        try{
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
        }catch(Exception e){
            area6.setText(e.getMessage());
        }
       
        // Layout null para posicionamento manual dos itens
        tela.setLayout(null);
       
        // INÍCIO GRUPO DE OBJETOS DO CABEÇALHO
       
        // Objeto do texto Odex
        JLabel LbOdex = new JLabel("ODEX");
        // Objeto Font para ajustar o tipo, estilo e tamanho da fonte
        Font t = new Font("Arial", Font.BOLD, 20);
        // Atribuindo o Objeto Font ao Objeto do texto Odex
        LbOdex.setFont(t);
     // ajustar posição do elemento no JPanel: (coluna, linha, largura, altura)
        LbOdex.setBounds(10, 40, 60, 30);
               
        // Objeto da caixa de diálogo
        TfOdex = new JTextField("");
        // ajustar posição do elemento no JPanel: (coluna, linha, largura, altura)
        TfOdex.setBounds(80, 40, 370, 30);
               
        // Objeto do botão Consultar
        JButton consulta = new JButton("Consultar");
        consulta.setBounds(480, 40, 120, 30);
        // Adiciona o listner ao Botão
        consulta.addActionListener(this);
        // Determina o comando que o listener recebe ao clicar no Botão
        consulta.setActionCommand("consultar");
       
        // Objeto do botão Sair
        JButton sair = new JButton("Sair");
        sair.setBounds(630, 40, 120, 30);
        sair.addActionListener(this);
        sair.setActionCommand("sair");
       
        // FIM DO GRUPO DE OBJETOS DO CABEÇALHO
       
        // INÍCIO DO GRUPO DE OBJETOS DE ABAS
       
        // Cria o Objeto do conjunto de Abas
        JTabbedPane tabelaDePaineis = new JTabbedPane(JTabbedPane.TOP);
        tabelaDePaineis.setBounds(0, 100, 800, 500); 
       
        // ABA 1
        // Objeto da Aba 1
        JPanel painel01 = new JPanel(null);
       
        // Objeto da Tabela
        tbData1 = new JTable();
        tbData1.setBounds(5,5,685,360);
        tbData1.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
       
        // Crio o objeto do Scroll e coloco a tabela dentro dele.
        JScrollPane sc = new JScrollPane(tbData1);
        sc.setBounds(5,5,780,430);
        // Indica que a scroll bar vertical é necessária
        sc.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        // Indica que a scroll bar horizontal é necessária
        sc.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
       
        // Adiciona a Scroll (com a tabela dentro) no objeto da primeira aba.
        painel01.add(sc);
     
        // ABA 2
        JPanel painel02 = new JPanel(null);
       
        tbData2 = new JTable();
        tbData2.setBounds(5,5,685,360);
        tbData2.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
       
        JScrollPane sc2 = new JScrollPane(tbData2);
        sc2.setBounds(5,5,780,430);
        sc2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); 
        sc2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
               
        painel02.add(sc2);
       
        // ABA 3
       
        JPanel painel03 = new JPanel(null);
       
        tbData3 = new JTable();
        tbData3.setBounds(5,5,685,360);
        tbData3.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
       
        JScrollPane sc3 = new JScrollPane(tbData3);
        sc3.setBounds(5,5,780,430);
        sc3.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); 
        sc3.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
               
        painel03.add(sc3);
       
        // ABA 4
       
        JPanel painel04 = new JPanel(null);
        tbData4 = new JTable();
        tbData4.setBounds(5,5,685,360);
        tbData4.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
       
        JScrollPane sc4 = new JScrollPane(tbData4);
        sc4.setBounds(5,5,780,430);
        sc4.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); 
        sc4.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
               
        painel04.add(sc4);
       
        // ABA 5
       
        JPanel painel05 = new JPanel(null);
        tbData5 = new JTable();
        tbData5.setBounds(5,5,685,360);
        tbData5.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
       
        JScrollPane sc5 = new JScrollPane(tbData5);
        sc5.setBounds(5,5,780,430);
        sc5.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); 
        sc5.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
               
        painel05.add(sc5);
       
        // ABA 6 - LOG
       
        JPanel painel06 = new JPanel(null);
       
        area6.setBounds(5,5,685,360);
         
        JScrollPane sc6 = new JScrollPane(area6);
        sc6.setBounds(5,5,780,430);
        sc6.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); 
        sc6.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
       
        painel06.add(sc6);
       
        // adiciona as abas no objeto de abas
        tabelaDePaineis.addTab("Informações",painel01);
        tabelaDePaineis.addTab("Detalhes",painel02);
        tabelaDePaineis.addTab("MaterialUC",painel03);
        tabelaDePaineis.addTab("MaterialCOM",painel04);
        tabelaDePaineis.addTab("Serviços",painel05);
        tabelaDePaineis.addTab("Log",painel06);
       
        // ADICIONANDO OS OBJETOS AO FRAME
       
        tela.add(LbOdex);
        tela.add(TfOdex);
        tela.add(consulta);
        tela.add(sair);
        tela.add(tabelaDePaineis);
               
        // SETANDO DETALHES DO FRAME
        tela.setTitle("Unitização"); 
        tela.setSize(800, 600);
        tela.setBounds(100,100, 800, 600);
        tela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        tela.setResizable(false);
        tela.setVisible(true);   
    }
   
    public void actionPerformed(ActionEvent e){
        if(e.getActionCommand().equals("consultar")){
           
            String[][] resposta = null;
           
            // chama o método de conexão, passando o método que será invocado.
            resposta = conecta("Informacoes");
            // ajusta a tabela com o array retornado pela conexão.
            tbData1.setModel(new DefaultTableModel(resposta, new String[]{"1","2","3","4","5","6","7","8","9","10","11","12","13"}));
           
            resposta = conecta("Detalhes");
            tbData2.setModel(new DefaultTableModel(resposta, new String[]{"1","2","3","4","5","6","7","8","9","10","11","12","13"}));
           
            resposta = conecta("MaterialUC");
            tbData3.setModel(new DefaultTableModel(resposta, new String[]{"1","2","3","4","5","6","7","8","9","10","11","12","13"}));
           
            resposta = conecta("MaterialCOM");
            tbData4.setModel(new DefaultTableModel(resposta, new String[]{"1","2","3","4","5","6","7","8","9","10","11","12","13"}));
           
            resposta = conecta("Servicos");
            tbData5.setModel(new DefaultTableModel(resposta, new String[]{"1","2","3","4","5","6","7","8","9","10","11","12","13"}));

        }  
        if(e.getActionCommand().equals("sair")){
            System.exit(0);
        }
    }
   
    public String[][] conecta(String operacao){
       
        String[][] resposta = null;
        Service  service  = new Service();
        Call call;
        String odex = TfOdex.getText();
       
        try {

            call = (Call) service.createCall();
           
            // Atribuindo a URL do Servico
            // Importante: é necessário um serviço SOA para conexão
            call.setTargetEndpointAddress(new java.net.URL("<<INSERIR AQUI A URL DO BARRAMENTO SOA IMPLEMENTADO>>"));

            // Definindo o metodo a ser invocado
            call.setOperationName(operacao);

            // Definindo os parametros de entrada
            call.addParameter("odex", XMLType.XSD_STRING, ParameterMode.IN);

            // Definindo o tipo do parametro de retorno
            call.setReturnType(org.apache.axis.encoding.XMLType.SOAP_ARRAY);
           
            // Invocando o servico
            resposta = (String[][]) call.invoke(new Object[] {odex});

        } catch (Exception ex) {
           
            String a = "Serviço "+operacao+" "+ex.getMessage();
            area6.setText(a);
        }
        return resposta;
    }
}