/*
* codjo.net
*
* Common Apache License 2.0
*/
package net.codjo.model;
import net.codjo.persistent.PersistenceException;
import net.codjo.persistent.Reference;
import net.codjo.persistent.sql.SimpleHome;
import net.codjo.utils.ConnectionManager;
import net.codjo.utils.SQLFieldList;
import net.codjo.utils.sql.event.DbChangeEvent;
import net.codjo.utils.sql.event.DbChangeListener;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import org.apache.log4j.Logger;
/**
* Classe Model des objets Table.
*
* <p>
* Pour obtenir une reference sur une table : <code>getReference(new Integer(5),
* Table.class))</code> .
* </p>
*
* @version $Revision: 1.5 $
*
*/
public class TableHome extends SimpleHome {
// Log
private static final Logger APP = Logger.getLogger(TableHome.class);
private ConnectionManager connectionManager;
/**
* Constructeur de TableHome
*
* @param con Une connexion
* @param cM Le connectionManager.
*
* @exception SQLException Impossible de creer les PreparedStatement
*/
public TableHome(Connection con, ConnectionManager cM)
throws SQLException {
super(con, ResourceBundle.getBundle("TableHome"));
connectionManager = cM;
}
/**
* Constructeur de TableHome en pr�cisant un ResourceBundle (nom du fichier
* properties).
*
* @param con Une connexion
* @param cM Le connectionManager.
* @param resource Le nom du fichier properties.
*
* @exception SQLException Impossible de creer les PreparedStatement
*/
public TableHome(Connection con, ConnectionManager cM, String resource)
throws SQLException {
super(con, ResourceBundle.getBundle(resource));
connectionManager = cM;
}
/**
* Retourne une reference sur une Table.
*
* @param id DB_TABLE_NAME_ID
*
* @return Une reference.
*/
public Reference getReference(int id) {
return getReference(new Integer(id));
}
/**
* Retourne la table ayant cet id.
*
* @param id DB_TABLE_NAME_ID
*
* @return The Table value
*
* @exception PersistenceException
*/
public Table getTable(int id) throws PersistenceException {
return (Table)getReference(id).getObject();
}
/**
* R�cup�re la d�finiton d'une table.
*
* @param dbTableName Nom physique de la table.
*
* @return Une table ou null si inconnue.
*
* @exception PersistenceException -
*/
public Table getTable(String dbTableName) throws PersistenceException {
try {
return getTableSQL(dbTableName);
}
catch (SQLException ex) {
ex.printStackTrace();
throw new PersistenceException(ex);
}
}
/**
* Retourne un listener mettant a jours la couche de persistance au niveau de
* PortfolioGroupHome lors des changements directe en Base.
*
* @return The DbChangeListener value
*
* @see net.codjo.persistent.sql.SimpleHome.DefaultDbChangeListener
*/
public DbChangeListener getDbChangeListener() {
return new TableDbChangeListener();
}
/**
* Determine les colonnes cles primaires. La determination se fait grace � l'API
* JDBC.
*
* @param dbTableName Le nom physique de la table.
*
* @return Description of the Returned Value
*/
public List determinePkNames(String dbTableName) {
try {
List keyDBNameList = new ArrayList();
Connection con = connectionManager.getConnection();
try {
DatabaseMetaData dbmd = con.getMetaData();
if (dbTableName.startsWith("#")) {
ResultSet rs =
dbmd.getColumns("tempdb", null,
dbTableName.substring(0, Math.min(13, dbTableName.length()))
+ "%", null);
rs.next();
keyDBNameList.add(rs.getString("COLUMN_NAME"));
rs.close();
}
else {
ResultSet rs = dbmd.getPrimaryKeys(null, null, dbTableName);
while (rs.next()) {
keyDBNameList.add(rs.getString("COLUMN_NAME"));
}
rs.close();
}
}
catch (SQLException ex) {
APP.error("Impossible de determiner les PK : " + dbTableName);
throw ex;
}
finally {
connectionManager.releaseConnection(con);
}
return keyDBNameList;
}
catch (SQLException ex) {
return null;
}
}
/**
* Determine les colonnes de la table (nom + type) .La determination se fait grace �
* l'API JDBC.
*
* @param dbTableName Le nom physique de la table.
*
* @return Map (clef = nom de la colonne) (valeur = type SQL)
*
* @see java.sql.Types
*/
public Map determineAllColumns(String dbTableName) {
// @bug : bizzarerie Sybase, des requetes MetaData sur une connection
// en autocommit=false, si on ne le fait pas en premier (haha),
// lance des exceptions.
// cf : exception JZ0R2
// http://ness:34500/dynaweb/jcg0400e/jconigrb/@Generic__BookView?DwebQuery=JZ0R2
try {
SQLFieldList fieldList;
Connection con = connectionManager.getConnection();
try {
if (dbTableName.startsWith("#")) {
fieldList =
new SQLFieldList(dbTableName.substring(0,
Math.min(13, dbTableName.length())) + "%", con, "tempdb");
}
else {
fieldList = new SQLFieldList(dbTableName, con);
}
Map allColumns = new HashMap();
for (Iterator iter = fieldList.fieldNames(); iter.hasNext();) {
String dbName = (String)iter.next();
allColumns.put(dbName, new Integer(fieldList.getFieldType(dbName)));
}
return allColumns;
}
finally {
connectionManager.releaseConnection(con);
}
}
catch (SQLException ex) {
return null;
}
}
/**
* R�cup�re la d�finiton d'une table � partir de son nom.
*
* @param dbTableName Nom physique de la table.
*
* @return Une table ou null si inconnue.
*
* @exception SQLException
* @exception PersistenceException
*/
private Table getTableSQL(String dbTableName)
throws SQLException, PersistenceException {
Statement stmt = null;
try {
stmt = getConnection().createStatement();
ResultSet rs =
stmt.executeQuery("select * from PM_TABLE where DB_TABLE_NAME='"
+ dbTableName + "'");
if (rs.next()) {
Reference ref = loadReference(rs);
return (Table)loadObject(rs, ref);
}
else {
// Cas particulier d'une table non definie dans PM_TABLE
Map columns = determineAllColumns(dbTableName);
if (columns.size() == 0) {
return null;
}
Reference ref = new Reference(this);
return new Table(ref, dbTableName, columns, determinePkNames(dbTableName));
}
}
finally {
if (stmt != null) {
stmt.close();
}
}
}
/**
* Classe offrant un comportement par defaut pour la mise a jours de ce Home, lors de
* modification en directe de la BD.
*
* <p>
* Ce listener recharge automatiquement la table modifie.
* </p>
*
* @author $Author: marcona $
* @version $Revision: 1.5 $
*/
/**
* DOCUMENT ME!
*
*/
public class TableDbChangeListener extends DefaultDbChangeListener {
/**
* DOCUMENT ME!
*
* @param evt Description of Parameter
*/
public void succeededChange(DbChangeEvent evt) {
super.succeededChange(evt);
if (evt.getEventType() == DbChangeEvent.MODIFY_EVENT) {
try {
getReference(evt.getPrimaryKey()).getObject();
}
catch (PersistenceException ex) {
ex.printStackTrace();
}
}
}
}
}