/*
* Created on 22/05/2004
*
* Swing Components - visit http://sf.net/projects/gfd
*
* Copyright (C) 2004 Igor Regis da Silva Simes
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
package br.com.gfpshare.db;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
* @author Igor Regis da Silva Simoes
*/
public abstract class AbstractPersistentObject implements PersistentObject
{
/**
*
*/
private SQLParser sqlParser = null;
/**
*
*/
protected boolean autoPk = true;
/**
*
*/
private static HashMap<String, ArrayList<String>> allColumns = new HashMap<String, ArrayList<String>>(7);
/**
*
*/
private static HashMap<String, ArrayList<String>> colunas = new HashMap<String, ArrayList<String>>(7);
/**
*
*/
private static HashMap<String, ArrayList<String>> pks = new HashMap<String, ArrayList<String>>(2);
/**
*
*/
protected boolean[] crescente = null;
/**
*
*/
private ArrayList<SQLCondition> condicoesExtras = new ArrayList<SQLCondition>();
/**
*
*/
private String resultadoDesejado = null;
/**
*
*/
private String dataBase = null;
/**
* Dados a respeito da atual clausula de sql que ser executada por este persistent object
*/
private ParsedPreparedStatement currentStatement = new ParsedPreparedStatement();
/**
*
*/
public AbstractPersistentObject()
{
ArrayList<String> allColumns = new ArrayList<String>();
allColumns.addAll(getColumnsName());
allColumns.addAll(getPkNames());
crescente = new boolean[allColumns.size()];
for(int i=0; i<crescente.length; i++)
{
crescente[i] = true;
}
if (AbstractPersistentObject.allColumns.get(this.getClass().getName()) == null)
AbstractPersistentObject.allColumns.put(this.getClass().getName(), allColumns);
}
/**
* @see br.com.gfpshare.db.PersistentObject#getInsertSQL()
*/
public final String getInsertSQL()
{
if (autoPk)
currentStatement = getSqlParser().getInsertSQL(getTableName(), getAsMap(), getColumnsName());
else
currentStatement = getSqlParser().getInsertSQL(getTableName(), getAsMap(), AbstractPersistentObject.allColumns.get(this.getClass().getName()));
return currentStatement.sql;
}
/**
* @see br.com.gfpshare.db.PersistentObject#getUpdateSQL()
*/
public final String getUpdateSQL()
{
if (autoPk)
currentStatement = getSqlParser().getUpdateSQL(getTableName(), getAsMap(), getColumnsName(), getPkNames());
else
currentStatement = getSqlParser().getUpdateSQL(getTableName(), getAsMap(), AbstractPersistentObject.allColumns.get(this.getClass().getName()), getPkNames());
return currentStatement.sql;
}
/**
* @see br.com.gfpshare.db.PersistentObject#getSelectSQL()
*/
public final String getSelectSQL()
{
condicoesExtras.trimToSize();
currentStatement = getSqlParser().getSelectSQL(resultadoDesejado, getTableName(), getAsMap(), AbstractPersistentObject.allColumns.get(this.getClass().getName()), getOrderBy(), crescente, condicoesExtras);
return currentStatement.sql;
}
/**
* @see br.com.gfpshare.db.PersistentObject#getDeleteSQL()
*/
public final String getDeleteSQL()
{
currentStatement = getSqlParser().getDeleteSQL(getTableName(), getAsMap(), AbstractPersistentObject.allColumns.get(this.getClass().getName()), condicoesExtras, getPkNames());
return currentStatement.sql;
}
public ArrayList<Object> getParametrosSQL()
{
ArrayList<Object> retorno = new ArrayList<Object>();
for (SQLCondition<Object> condicao : condicoesExtras)
{
if (condicao.getCondicao() != SQLCondition.Condicao.IS_NULL)
retorno.add(condicao.getValor());
if (condicao.getCondicao() == SQLCondition.Condicao.BETWEEN)
retorno.add(condicao.getValor_2());
}
retorno.addAll(currentStatement.params);
currentStatement = new ParsedPreparedStatement();
return retorno;
}
/**
* @see br.com.gfpshare.db.PersistentObject#setOrderBy(java.lang.String[])
*/
public final void setOrderBy(String[] columns)
{
boolean swap;
ArrayList<String> allColumns = AbstractPersistentObject.allColumns.get(getClass().getName());
for(int n=columns.length-1; n>=0; n--)
{
for(int i=0; i<allColumns.size(); i++)
{
if (allColumns.get(i).toString().equals(columns[n]))
{
swap = this.crescente[i];
for(int j=i; j>0; j--)
{
String swap2 = allColumns.get(j-1);
allColumns.set(j-1, null);
allColumns.set(j, swap2);
this.crescente[j] = this.crescente[j-1];
}
allColumns.set(0, columns[n]);
this.crescente[0] = !swap;
}
}
}
AbstractPersistentObject.allColumns.put(this.getClass().getName(), allColumns);
}
/**
* @see br.com.gfpshare.db.PersistentObject#getOrderBy()
*/
public final String[] getOrderBy()
{
ArrayList<String> allColumns = AbstractPersistentObject.allColumns.get(this.getClass().getName());
return allColumns.toArray(new String[allColumns.size()]);
}
/*
* @see br.com.igor.db.PersistentObject#addCondicaoExtra(java.lang.String)
*/
public final void addCondicaoExtra(SQLCondition condicao)
{
condicoesExtras.add(condicao);
}
/**
* @see br.com.gfpshare.db.PersistentObject#removeCondicaoExtra(java.lang.String)
*/
public final void removeCondicaoExtra(SQLCondition condicao)
{
condicoesExtras.remove(condicao);
}
/**
* Retorna o parser a ser usado na formulao do sql.
* @return SQLParser.
*/
private SQLParser getSqlParser()
{
if (sqlParser == null)
sqlParser = SQLParserFactory.getSQLParserFactory().getParser(dataBase);
return sqlParser;
}
/**
* @see br.com.gfpshare.db.PersistentObject#setDataBase(java.lang.String)
*/
public void setDataBase(String dataBase)
{
this.dataBase = dataBase;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
Map objetoMap = getAsMap();
Object[] chaves = objetoMap.keySet().toArray();
String representacao = getTableName();
for (Object chave : chaves)
if(objetoMap.get(chave) != null)
representacao += ", " + chave + " = " + objetoMap.get(chave);
return representacao;
}
/**
* @see br.com.gfpshare.db.PersistentObject#getResultadoDesejado()
*/
public String getResultadoDesejado()
{
return resultadoDesejado;
}
/*
* @see br.com.igor.db.PersistentObject#setResultadoDesejado(java.lang.String)
*/
public void setResultadoDesejado(String resultadoDesejado)
{
this.resultadoDesejado = resultadoDesejado;
}
/**
* @see br.com.gfpshare.db.PersistentObject#getColumnsName()
*/
public final ArrayList<String> getColumnsName()
{
ArrayList<String> colunas = AbstractPersistentObject.colunas.get(this.getClass().getName());
if (colunas != null)
return colunas;
colunas = new ArrayList<String>();
ArrayList<Field> fields = getAllDeclaredFields(Column.class);
for (Field field : fields)
if (!field.getAnnotation(Column.class).isPk())
colunas.add(field.getAnnotation(Column.class).nome());
AbstractPersistentObject.colunas.put(this.getClass().getName(), colunas);
return colunas;
}
/**
* @see br.com.gfpshare.db.PersistentObject#getPkNames()
*/
public final ArrayList<String> getPkNames()
{
ArrayList<String> pks = AbstractPersistentObject.pks.get(this.getClass().getName());
if (pks != null)
return pks;
pks = new ArrayList<String>();
ArrayList<Field> fields = getAllDeclaredFields(Column.class);
for (Field field : fields)
{
Column column = field.getAnnotation(Column.class);
if (column.isPk())
{
pks.add(column.nome());
}
}
AbstractPersistentObject.pks.put(this.getClass().getName(), pks);
return pks;
}
/**
* Retorna todos campos da calsse (incluindo superclasses)
* que possuam a anotao passada como parametro
* @param annotation Anotao que os campos devem possuir para
* retornarem no ArrayList
* @return ArrayList com os atributos que atendem ao critrio
*/
private ArrayList<Field> getAllDeclaredFields(Class<Column> annotation)
{
ArrayList<Field> fields = new ArrayList<Field>();
Class<?> classe = getClass();
while(classe.isAnnotationPresent(Table.class))
{
Field[] campo = classe.getDeclaredFields();
for (int i = 0; i < campo.length; i++)
{
campo[i].getAnnotation(Column.class);
if (campo[i].isAnnotationPresent(annotation))
{
fields.add(campo[i]);
}
}
classe = classe.getSuperclass();
if (classe == null)
throw new InvalidSubClassException("Your class must define a @Tabela anotation");
}
return fields;
}
/**
* @see br.com.gfpshare.db.PersistentObject#getTableName()
*/
public final String getTableName()
{
Class<?> classe = getClass();
while(!classe.isAnnotationPresent(Table.class))
{
classe = classe.getSuperclass();
if (classe == null)
throw new InvalidSubClassException("Your class must define a @Tabela anotation");
}
return classe.getAnnotation(Table.class).name();
}
/**
* @see br.com.gfpshare.db.PersistentObject#getAsMap()
*/
public final Map<String, Object> getAsMap() throws DataAccessException
{
HashMap<String, Object> dados = new HashMap<String, Object>();
try{
ArrayList<Field> fields = getAllDeclaredFields(Column.class);
for (Field field : fields)
{
Column colunaAnnotation = field.getAnnotation(Column.class);
dados.put(colunaAnnotation.nome(), getClass().getMethod(colunaAnnotation.readMethodName(),new Class[]{}).invoke(this,(Object[])null));
}
} catch (Exception e)
{
throw new DataAccessException("Problemas ao converter objeto para Map.", e);
}
return dados;
}
/**
* @see br.com.gfpshare.db.PersistentObject#setDados(java.util.Map)
*/
public void setDados(Map<String, Object> dados) throws DataAccessException
{
ArrayList<Field> fields = getAllDeclaredFields(Column.class);
for (Field field: fields)
{
try{
Column colunaAnnotation = field.getAnnotation(Column.class);
Object valor = null;
if ((valor = dados.get(colunaAnnotation.nome())) != null)
{
//Os campos Float so uma exceo, caso ns no faamos a converso
//explicita a JVM vai tentar pass-lo como Double para o mtodo causando uma exceo
if (field.getType().isAssignableFrom(Float.class))
getClass().getMethod(colunaAnnotation.writeMethodName(), Float.class).invoke(this,Float.valueOf(valor.toString()));
else
getClass().getMethod(colunaAnnotation.writeMethodName(), field.getType()).invoke(this,valor);
}
} catch (Exception e)
{
throw new DataAccessException("Problemas ao converter Map para objeto, campo: " + field.getName(), e);
}
}
}
/**
* @param sql
* @param incluirWhere
* @param incluirOrderBy
* @return String
*/
public String getSQL(String sql, boolean incluirWhere, boolean incluirOrderBy)
{
currentStatement = new ParsedPreparedStatement();
if (incluirWhere)
{
ParsedPreparedStatement temp = ((AbstractSQLParser)getSqlParser()).getWhere(getAsMap(), AbstractPersistentObject.allColumns.get(this.getClass().getName()), " and ", condicoesExtras);
currentStatement.sql = sql + " " + temp.sql +
(incluirOrderBy ? ((AbstractSQLParser)getSqlParser()).getOrderBy(getOrderBy(), crescente) : "");
currentStatement.params = temp.params;
}
else
{
currentStatement.sql = sql + " " +
(incluirOrderBy ? ((AbstractSQLParser)getSqlParser()).getOrderBy(getOrderBy(), crescente) : "");
}
return getSqlParser().parse(currentStatement).sql;
}
public void clearAllFields()
{
currentStatement = new ParsedPreparedStatement();
ArrayList<Field> fields = new ArrayList<Field>();
Class classe = getClass();
while(classe != AbstractPersistentObject.class)
{
Field[] campo = classe.getDeclaredFields();
for (int i = 0; i < campo.length; i++)
{
fields.add(campo[i]);
}
classe = classe.getSuperclass();
if (classe == null)
throw new InvalidSubClassException("Your class must define a @Tabela anotation");
}
for (int i = 0; i < fields.size(); i++)
{
if (Modifier.isFinal(fields.get(i).getModifiers()))
continue;
fields.get(i).setAccessible(true);
try
{
fields.get(i).set(this, null);
}
catch (IllegalArgumentException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IllegalAccessException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
|