package org.compiere.model;
import java.lang.reflect.Constructor;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Properties;
import java.util.logging.Level;
import org.adempiere.model.GenericPO;
import org.compiere.util.CCache;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.DisplayType;
import org.compiere.util.Env;
import org.compiere.util.Util;
public class MTable extends X_AD_Table
{
private static final long serialVersionUID = -2367316254623142732L;
public static MTable
get (Properties ctx,
int AD_Table_ID)
{
Integer key = new Integer (AD_Table_ID);
MTable retValue = s_cache.get (key);
if (retValue != null && retValue.getCtx() == ctx) {
return retValue;
}
retValue = new MTable (ctx, AD_Table_ID, null);
if (retValue.get_ID () != 0) {
s_cache.put (key, retValue);
}
return retValue;
}
public static MTable
get (Properties ctx, String tableName)
{
if (tableName == null)
return null;
Iterator<MTable> it = s_cache.values().iterator();
while (it.hasNext())
{
MTable retValue = it.next();
if (tableName.equalsIgnoreCase(retValue.getTableName())
&& retValue.getCtx() == ctx
)
{
return retValue;
}
}
MTable retValue = null;
String sql = "SELECT * FROM AD_Table WHERE UPPER(TableName)=?";
PreparedStatement pstmt = null;
try
{
pstmt = DB.prepareStatement (sql, null);
pstmt.setString(1, tableName.toUpperCase());
ResultSet rs = pstmt.executeQuery ();
if (rs.next ())
retValue = new MTable (ctx, rs, null);
rs.close ();
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
s_log.log(Level.SEVERE, sql, e);
}
try
{
if (pstmt != null)
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
pstmt = null;
}
if (retValue != null)
{
Integer key = new Integer (retValue.getAD_Table_ID());
s_cache.put (key, retValue);
}
return retValue;
}
public static String
getTableName (Properties ctx,
int AD_Table_ID)
{
return MTable.get(ctx, AD_Table_ID).getTableName();
}
private static CCache<Integer,MTable> s_cache = new CCache<Integer,MTable>("AD_Table", 20);
private static CCache<String,Class<?>> s_classCache = new CCache<String,Class<?>>("PO_Class", 20);
private static CLogger s_log = CLogger.getCLogger (MTable.class);
private static final String[] s_packages = new String[] {
"org.compiere.model", "org.compiere.wf",
"org.compiere.report",
"org.compiere.print", "org.compiere.impexp",
"compiere.model",
"adempiere.model",
"org.adempiere.model"
};
private static final String[] s_special = new String[] {
"AD_Element", "org.compiere.model.M_Element",
"AD_Registration", "org.compiere.model.M_Registration",
"AD_Tree", "org.compiere.model.MTree_Base",
"R_Category", "org.compiere.model.MRequestCategory",
"GL_Category", "org.compiere.model.MGLCategory",
"K_Category", "org.compiere.model.MKCategory",
"C_ValidCombination", "org.compiere.model.MAccount",
"C_Phase", "org.compiere.model.MProjectTypePhase",
"C_Task", "org.compiere.model.MProjectTypeTask",
"AD_View_Column", "org.adempiere.model.MViewColumn",
"AD_View","org.adempiere.model.MView",
"AD_View_Definition","org.adempiere.model.MViewDefinition",
"AD_Browse","org.adempiere.model.MBrowse",
"AD_Browse_Field","org.adempiere.model.MBrowseField",
"T_Selection","org.adempiere.model.X_T_Selection"
};
public static Class<?>
getClass (String tableName)
{
if (tableName == null || tableName.endsWith("_Trl"))
return null;
Class<?> cache = s_classCache.get(tableName);
if (cache != null)
{
if (cache.equals(Object.class))
return null;
else
return cache;
}
MTable table = MTable.get(Env.getCtx(), tableName);
String entityType = table.getEntityType();
if (tableName.startsWith("I_"))
{
MEntityType et = MEntityType.get(Env.getCtx(), entityType);
String etmodelpackage = et.getModelPackage();
if (etmodelpackage == null || MEntityType.ENTITYTYPE_Dictionary.equals(entityType))
etmodelpackage = "org.compiere.model";
Class<?> clazz = getPOclass(etmodelpackage + ".X_" + tableName, tableName);
if (clazz != null)
{
s_classCache.put(tableName, clazz);
return clazz;
}
s_log.warning("No class for table: " + tableName);
return null;
}
for (int i = 0; i < s_special.length; i++)
{
if (s_special[i++].equals(tableName))
{
Class<?> clazz = getPOclass(s_special[i], tableName);
if (clazz != null)
{
s_classCache.put(tableName, clazz);
return clazz;
}
break;
}
}
if (!MEntityType.ENTITYTYPE_Dictionary.equals(entityType))
{
MEntityType et = MEntityType.get(Env.getCtx(), entityType);
String etmodelpackage = et.getModelPackage();
if (etmodelpackage != null)
{
Class<?> clazz = null;
clazz = getPOclass(etmodelpackage + ".M" + Util.replace(tableName, "_", ""), tableName);
if (clazz != null) {
s_classCache.put(tableName, clazz);
return clazz;
}
clazz = getPOclass(etmodelpackage + ".X_" + tableName, tableName);
if (clazz != null) {
s_classCache.put(tableName, clazz);
return clazz;
}
s_log.warning("No class for table with it entity: " + tableName);
}
}
String className = tableName;
int index = className.indexOf('_');
if (index > 0)
{
if (index < 3)
className = className.substring(index+1);
}
className = Util.replace(className, "_", "");
for (int i = 0; i < s_packages.length; i++)
{
StringBuffer name = new StringBuffer(s_packages[i]).append(".M").append(className);
Class<?> clazz = getPOclass(name.toString(), tableName);
if (clazz != null)
{
s_classCache.put(tableName, clazz);
return clazz;
}
}
Class<?> clazz = getPOclass("adempiere.model.X_" + tableName, tableName);
if (clazz != null)
{
s_classCache.put(tableName, clazz);
return clazz;
}
clazz = getPOclass("compiere.model.X_" + tableName, tableName);
if (clazz != null)
{
s_classCache.put(tableName, clazz);
return clazz;
}
clazz = getPOclass("org.compiere.model.X_" + tableName, tableName);
if (clazz != null)
{
s_classCache.put(tableName, clazz);
return clazz;
}
s_classCache.put(tableName, Object.class);
return null;
}
private static Class<?>
getPOclass (String className)
{
return getPOclass(className, null);
}
private static Class<?>
getPOclass (String className, String tableName)
{
try
{
Class<?> clazz = Class.forName(className);
if (tableName != null)
{
String classTableName = clazz.getField("Table_Name").get(null).toString();
if (!tableName.equals(classTableName))
{
s_log.finest("Invalid class for table: " + className+" (tableName="+tableName+", classTableName="+classTableName+")");
return null;
}
}
Class<?> superClazz = clazz.getSuperclass();
while (superClazz != null)
{
if (superClazz == PO.class)
{
s_log.fine("Use: " + className);
return clazz;
}
superClazz = superClazz.getSuperclass();
}
}
catch (Exception e)
{
}
s_log.finest("Not found: " + className);
return null;
}
public MTable (Properties ctx,
int AD_Table_ID, String trxName)
{
super (ctx, AD_Table_ID, trxName);
if (AD_Table_ID == 0)
{
setAccessLevel (ACCESSLEVEL_SystemOnly);
setEntityType (ENTITYTYPE_UserMaintained);
setIsChangeLog (false);
setIsDeleteable (false);
setIsHighVolume (false);
setIsSecurityEnabled (false);
setIsView (false);
setReplicationType (REPLICATIONTYPE_Local);
}
}
public MTable (Properties ctx, ResultSet rs, String trxName)
{
super(ctx, rs, trxName);
}
private MColumn[] m_columns = null;
{
if (m_columns != null && !requery)
return m_columns;
String sql = "SELECT * FROM AD_Column WHERE AD_Table_ID=? ORDER BY ColumnName";
ArrayList<MColumn> list = new ArrayList<MColumn>();
PreparedStatement pstmt = null;
try
{
pstmt = DB.prepareStatement (sql, get_TrxName());
pstmt.setInt (1, getAD_Table_ID());
ResultSet rs = pstmt.executeQuery ();
while (rs.next ())
list.add (new MColumn (getCtx(), rs, get_TrxName()));
rs.close ();
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
log.log(Level.SEVERE, sql, e);
}
try
{
if (pstmt != null)
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
pstmt = null;
}
m_columns = new MColumn[list.size ()];
list.toArray (m_columns);
return m_columns;
}
{
if (columnName == null || columnName.length() == 0)
return null;
getColumns(false);
for (int i = 0; i < m_columns.length; i++)
{
if (columnName.equalsIgnoreCase(m_columns[i].getColumnName()))
return m_columns[i];
}
return null;
}
{
String[] keys = getKeyColumns();
return keys.length == 1;
}
{
getColumns(false);
ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < m_columns.length; i++)
{
MColumn column = m_columns[i];
if (column.isKey())
return new String[]{column.getColumnName()};
if (column.isParent())
list.add(column.getColumnName());
}
String[] retValue = new String[list.size()];
retValue = list.toArray(retValue);
return retValue;
}
public PO
getPO (
int Record_ID, String trxName)
{
String tableName = getTableName();
if (Record_ID != 0 && !isSingleKey())
{
log.log(Level.WARNING, "(id) - Multi-Key " + tableName);
return null;
}
Class<?> clazz = getClass(tableName);
if (clazz == null)
{
log.log(Level.INFO, "Using GenericPO for " + tableName);
GenericPO po = new GenericPO(tableName, getCtx(), new Integer(Record_ID), trxName);
return po;
}
boolean errorLogged = false;
try
{
Constructor<?> constructor = null;
try
{
constructor = clazz.getDeclaredConstructor(new Class[]{Properties.class, int.class, String.class});
}
catch (Exception e)
{
String msg = e.getMessage();
if (msg == null)
msg = e.toString();
log.warning("No transaction Constructor for " + clazz + " (" + msg + ")");
}
PO po = (PO)constructor.newInstance(new Object[] {getCtx(), new Integer(Record_ID), trxName});
if (po != null && po.get_ID() != Record_ID && Record_ID > 0)
return null;
return po;
}
catch (Exception e)
{
if (e.getCause() != null)
{
Throwable t = e.getCause();
log.log(Level.SEVERE, "(id) - Table=" + tableName + ",Class=" + clazz, t);
errorLogged = true;
if (t instanceof Exception)
log.saveError("Error", (Exception)e.getCause());
else
log.saveError("Error", "Table=" + tableName + ",Class=" + clazz);
}
else
{
log.log(Level.SEVERE, "(id) - Table=" + tableName + ",Class=" + clazz, e);
errorLogged = true;
log.saveError("Error", "Table=" + tableName + ",Class=" + clazz);
}
}
if (!errorLogged)
log.log(Level.SEVERE, "(id) - Not found - Table=" + tableName
+ ", Record_ID=" + Record_ID);
return null;
}
public PO
getPO (ResultSet rs, String trxName)
{
String tableName = getTableName();
Class<?> clazz = getClass(tableName);
if (clazz == null)
{
log.log(Level.INFO, "Using GenericPO for " + tableName);
GenericPO po = new GenericPO(tableName, getCtx(), rs, trxName);
return po;
}
boolean errorLogged = false;
try
{
Constructor<?> constructor = clazz.getDeclaredConstructor(new Class[]{Properties.class, ResultSet.class, String.class});
PO po = (PO)constructor.newInstance(new Object[] {getCtx(), rs, trxName});
return po;
}
catch (Exception e)
{
log.log(Level.SEVERE, "(rs) - Table=" + tableName + ",Class=" + clazz, e);
errorLogged = true;
log.saveError("Error", "Table=" + tableName + ",Class=" + clazz);
}
if (!errorLogged)
log.log(Level.SEVERE, "(rs) - Not found - Table=" + tableName);
return null;
}
public PO
getPO (String whereClause, String trxName)
{
return getPO(whereClause, null, trxName);
}
public PO
getPO(String whereClause, Object[] params, String trxName)
{
if (whereClause == null || whereClause.length() == 0)
return null;
PO po = null;
POInfo info = POInfo.getPOInfo(getCtx(), getAD_Table_ID(), trxName);
if (info == null) return null;
StringBuffer sqlBuffer = info.buildSelect();
sqlBuffer.append(" WHERE ").append(whereClause);
String sql = sqlBuffer.toString();
PreparedStatement pstmt = null;
try
{
pstmt = DB.prepareStatement (sql, trxName);
if (params != null && params.length > 0)
{
for (int i = 0; i < params.length; i++)
{
pstmt.setObject(i+1, params[i]);
}
}
ResultSet rs = pstmt.executeQuery ();
if (rs.next ())
{
po = getPO(rs, trxName);
}
rs.close ();
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
log.log(Level.SEVERE, sql, e);
log.saveError("Error", e);
}
try
{
if (pstmt != null)
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
pstmt = null;
}
return po;
}
{
if (isView() && isDeleteable())
setIsDeleteable(false);
return true;
}
protected boolean afterSave (
boolean newRecord,
boolean success)
{
if (newRecord)
{
createMandatoryColumns();
MSequence seq = MSequence.get(getCtx(), getTableName(), get_TrxName());
if (seq == null || seq.get_ID() == 0)
MSequence.createTableSequence(getCtx(), getTableName(), get_TrxName());
}
else
{
MSequence seq = MSequence.get(getCtx(), getTableName(), get_TrxName());
if (seq == null || seq.get_ID() == 0)
MSequence.createTableSequence(getCtx(), getTableName(), get_TrxName());
else if (!seq.getName().equals(getTableName()))
{
seq.setName(getTableName());
seq.save();
}
}
return success;
}
{
StringBuffer sb = new StringBuffer("CREATE TABLE ")
.append(getTableName()).append(" (");
boolean hasPK = false;
boolean hasParents = false;
StringBuffer constraints = new StringBuffer();
getColumns(true);
for (int i = 0; i < m_columns.length; i++)
{
MColumn column = m_columns[i];
String colSQL = column.getSQLDDL();
if ( colSQL != null )
{
if (i > 0)
sb.append(", ");
sb.append(column.getSQLDDL());
}
else
continue;
if (column.isKey())
hasPK = true;
if (column.isParent())
hasParents = true;
String constraint = column.getConstraint(getTableName());
if (constraint != null && constraint.length() > 0)
constraints.append(", ").append(constraint);
}
if (!hasPK && hasParents)
{
StringBuffer cols = new StringBuffer();
for (int i = 0; i < m_columns.length; i++)
{
MColumn column = m_columns[i];
if (!column.isParent())
continue;
if (cols.length() > 0)
cols.append(", ");
cols.append(column.getColumnName());
}
sb.append(", CONSTRAINT ")
.append(getTableName()).append("_Key PRIMARY KEY (")
.append(cols).append(")");
}
sb.append(constraints)
.append(")");
return sb.toString();
}
int retValue = 0;
String SQL = "SELECT AD_Table_ID FROM AD_Table WHERE tablename = ?";
try
{
PreparedStatement pstmt = DB.prepareStatement(SQL, null);
pstmt.setString(1, tableName);
ResultSet rs = pstmt.executeQuery();
if (rs.next())
retValue = rs.getInt(1);
rs.close();
pstmt.close();
}
catch (Exception e)
{
s_log.log(Level.SEVERE, SQL, e);
retValue = -1;
}
return retValue;
}
public Query
createQuery(String whereClause, String trxName)
{
return new Query(this.getCtx(), this, whereClause, trxName);
}
{
MColumn column = null;
column =
new MColumn(
this, COLUMNNAME_AD_Client_ID
,
22 , DisplayType.TableDir ,
"@#[email protected]");
column.setUpdateable(false);
column.setAD_Val_Rule_ID(129);
column.saveEx();
column =
new MColumn(
this, COLUMNNAME_AD_Org_ID
,
22 , DisplayType.TableDir ,
"@#[email protected]");
column.setUpdateable(true);
column.setAD_Val_Rule_ID(104);
column.saveEx();
column = new MColumn(this, COLUMNNAME_IsActive , 1 , DisplayType.YesNo , "Y");
column.setUpdateable(true);
column.saveEx();
column = new MColumn(this, COLUMNNAME_Created , 7 , DisplayType.DateTime , "");
column.saveEx();
column = new MColumn(this, COLUMNNAME_Updated , 7 , DisplayType.DateTime , "");
column.saveEx();
column = new MColumn(this, COLUMNNAME_CreatedBy , 22 , DisplayType.TableDir, "");
column.setAD_Reference_Value_ID(110);
column.saveEx();
column = new MColumn(this, COLUMNNAME_UpdatedBy , 22 , DisplayType.TableDir, "");
column.setAD_Reference_Value_ID(110);
column.saveEx();
if(!isView())
{
if(getTableName().endsWith("_Trl") || getTableName().endsWith("_Access"))
return;
M_Element element = M_Element.get(getCtx(), getTableName()+"_ID", get_TrxName());
if(element != null)
return;
element = new M_Element(getCtx(), 0 , get_TrxName());
element.setColumnName(getTableName()+"_ID");
element.setName(getName() + " ID");
element.setPrintName(getName() + " ID");
element.setEntityType(getEntityType());
element.saveEx();
column = new MColumn(this, element.getColumnName(), 22 , DisplayType.ID, "");
column.setAD_Element_ID(element.get_ID());
column.setIsKey(true);
column.setUpdateable(false);
column.setIsMandatory(true);
column.saveEx();
}
}
{
StringBuffer sb = new StringBuffer ("MTable[");
sb.append (get_ID()).append ("-").append (getTableName()).append ("]");
return sb.toString ();
}
}