diff --git a/base/src/org/compiere/model/I_AD_Column.java b/base/src/org/compiere/model/I_AD_Column.java index e6259d7690..bf7669d6b8 100644 --- a/base/src/org/compiere/model/I_AD_Column.java +++ b/base/src/org/compiere/model/I_AD_Column.java @@ -509,4 +509,13 @@ public interface I_AD_Column * Version of the table definition */ public BigDecimal getVersion(); + + /** Column name IsAllowLogging */ + public static final String COLUMNNAME_isAllowLogging = "IsAllowLogging"; + + + /** Get IsAllowLogging . + * Determines, if a column must be recorded into the change log + */ + public boolean IsAllowLogging() ; } diff --git a/base/src/org/compiere/model/MChangeLog.java b/base/src/org/compiere/model/MChangeLog.java index ad57bb11bd..4dfe13426d 100644 --- a/base/src/org/compiere/model/MChangeLog.java +++ b/base/src/org/compiere/model/MChangeLog.java @@ -1,222 +1,231 @@ -/****************************************************************************** - * Product: Adempiere ERP & CRM Smart Business Solution * - * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * - * This program is free software; you can redistribute it and/or modify it * - * under the terms version 2 of the GNU General Public License as published * - * by the Free Software Foundation. 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. * - * For the text or an alternative of this public license, you may reach us * - * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * - * or via info@compiere.org or http://www.compiere.org/license.html * - *****************************************************************************/ -package org.compiere.model; - -import java.sql.*; -import java.util.*; -import java.util.logging.*; - -import org.compiere.*; -import org.compiere.util.*; - -/** - * Change Log Model - * - * @author Jorg Janke - * @version $Id: MChangeLog.java,v 1.3 2006/07/30 00:58:18 jjanke Exp $ - */ -public class MChangeLog extends X_AD_ChangeLog -{ - /** - * Do we track changes for this table - * @param AD_Table_ID table - * @return true if changes are tracked - */ - public static boolean isLogged (int AD_Table_ID) - { - if (s_changeLog == null || s_changeLog.length == 0) - fillChangeLog(); - // - int index = Arrays.binarySearch(s_changeLog, AD_Table_ID); - return index >= 0; - } // trackChanges - - /** - * Fill Log with tables to be logged - */ - private static void fillChangeLog() - { - ArrayList list = new ArrayList(40); - String sql = "SELECT t.AD_Table_ID FROM AD_Table t " - + "WHERE t.IsChangeLog='Y'" // also inactive - + " OR EXISTS (SELECT * FROM AD_Column c " - + "WHERE t.AD_Table_ID=c.AD_Table_ID AND c.ColumnName='EntityType') " - + "ORDER BY t.AD_Table_ID"; - PreparedStatement pstmt = null; - ResultSet rs = null; - try - { - pstmt = DB.prepareStatement(sql, null); - rs = pstmt.executeQuery(); - while (rs.next()) - list.add(new Integer(rs.getInt(1))); - } - catch (Exception e) - { - s_log.log(Level.SEVERE, sql, e); - } - finally - { - DB.close(rs, pstmt); - rs = null; pstmt = null; - } - // Convert to Array - s_changeLog = new int [list.size()]; - for (int i = 0; i < s_changeLog.length; i++) - { - Integer id = (Integer)list.get(i); - s_changeLog[i] = id.intValue(); - } - s_log.info("#" + s_changeLog.length); - } // fillChangeLog - - /** Change Log */ - private static int[] s_changeLog = null; - /** Logger */ - private static CLogger s_log = CLogger.getCLogger(MChangeLog.class); - /** NULL Value */ - public static String NULL = "NULL"; - - - /************************************************************************** - * Load Constructor - * @param ctx context - * @param rs result set - * @param trxName transaction - */ - public MChangeLog(Properties ctx, ResultSet rs, String trxName) - { - super(ctx, rs, trxName); - } // MChangeLog - - /** - * Standard Constructor - * @param ctx context - * @param AD_ChangeLog_ID id - * @param trxName transaction - */ - public MChangeLog (Properties ctx, int AD_ChangeLog_ID, String trxName) - { - super (ctx, 0, trxName); - } // MChangeLog - - /** - * Preserved for backward compatibility - *@deprecated - */ - public MChangeLog (Properties ctx, - int AD_ChangeLog_ID, String TrxName, int AD_Session_ID, - int AD_Table_ID, int AD_Column_ID, int Record_ID, - int AD_Client_ID, int AD_Org_ID, - Object OldValue, Object NewValue) - { - this(ctx, AD_ChangeLog_ID, TrxName, AD_Session_ID, AD_Table_ID, - AD_Column_ID, Record_ID, AD_Client_ID, AD_Org_ID, OldValue, - NewValue, (String) null /*event*/ ); - } // MChangeLog - - /** - * Full Constructor - * @param ctx context - * @param AD_ChangeLog_ID 0 for new change log - * @param TrxName transaction - * @param AD_Session_ID session - * @param AD_Table_ID table - * @param AD_Column_ID column - * @param Record_ID record - * @param AD_Client_ID client - * @param AD_Org_ID org - * @param OldValue old - * @param NewValue new - */ - public MChangeLog (Properties ctx, - int AD_ChangeLog_ID, String TrxName, int AD_Session_ID, - int AD_Table_ID, int AD_Column_ID, int Record_ID, - int AD_Client_ID, int AD_Org_ID, - Object OldValue, Object NewValue, String event) - { - this (ctx, 0, TrxName); - if (AD_ChangeLog_ID == 0) - { - AD_ChangeLog_ID = DB.getNextID (AD_Client_ID, Table_Name, TrxName); - if (AD_ChangeLog_ID <= 0) - log.severe("No NextID (" + AD_ChangeLog_ID + ")"); - } - setAD_ChangeLog_ID (AD_ChangeLog_ID); - setTrxName(TrxName); - setAD_Session_ID (AD_Session_ID); - // - setAD_Table_ID (AD_Table_ID); - setAD_Column_ID (AD_Column_ID); - setRecord_ID (Record_ID); - // - setClientOrg (AD_Client_ID, AD_Org_ID); - // - setOldValue (OldValue); - setNewValue (NewValue); - setEventChangeLog(event); - // EVENT / Release 3.3.1t_2007-12-05 ADempiere - // Drop description from AD_ChangeLog - pass it to AD_Session to save disk space - // setDescription(Adempiere.MAIN_VERSION + "_" + Adempiere.DATE_VERSION + " " + Adempiere.getImplementationVersion()); - } // MChangeLog - - - /** - * Set Old Value - * @param OldValue old - */ - public void setOldValue (Object OldValue) - { - if (OldValue == null) - super.setOldValue (NULL); - else - super.setOldValue (OldValue.toString()); - } // setOldValue - - /** - * Is Old Value Null - * @return true if null - */ - public boolean isOldNull() - { - String value = getOldValue(); - return value == null || value.equals(NULL); - } // isOldNull - - /** - * Set New Value - * @param NewValue new - */ - public void setNewValue (Object NewValue) - { - if (NewValue == null) - super.setNewValue (NULL); - else - super.setNewValue (NewValue.toString()); - } // setNewValue - - /** - * Is New Value Null - * @return true if null - */ - public boolean isNewNull() - { - String value = getNewValue(); - return value == null || value.equals(NULL); - } // isNewNull - -} // MChangeLog +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Properties; +import java.util.logging.Level; + +import org.compiere.util.CLogger; +import org.compiere.util.DB; + +/** + * Change Log Model + * + * @author Jorg Janke + * @version $Id: MChangeLog.java,v 1.3 2006/07/30 00:58:18 jjanke Exp $ + */ +public class MChangeLog extends X_AD_ChangeLog +{ + /** + * + */ + private static final long serialVersionUID = -7156972859181201446L; + + + /** + * Do we track changes for this table + * @param AD_Table_ID table + * @return true if changes are tracked + */ + public static boolean isLogged (int AD_Table_ID) + { + if (s_changeLog == null || s_changeLog.length == 0) + fillChangeLog(); + // + int index = Arrays.binarySearch(s_changeLog, AD_Table_ID); + return index >= 0; + } // trackChanges + + /** + * Fill Log with tables to be logged + */ + private static void fillChangeLog() + { + ArrayList list = new ArrayList(40); + String sql = "SELECT t.AD_Table_ID FROM AD_Table t " + + "WHERE t.IsChangeLog='Y'" // also inactive + + " OR EXISTS (SELECT * FROM AD_Column c " + + "WHERE t.AD_Table_ID=c.AD_Table_ID AND c.ColumnName='EntityType') " + + "ORDER BY t.AD_Table_ID"; + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement(sql, null); + rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new Integer(rs.getInt(1))); + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + finally + { + DB.close(rs, pstmt); + rs = null; pstmt = null; + } + // Convert to Array + s_changeLog = new int [list.size()]; + for (int i = 0; i < s_changeLog.length; i++) + { + Integer id = (Integer)list.get(i); + s_changeLog[i] = id.intValue(); + } + s_log.info("#" + s_changeLog.length); + } // fillChangeLog + + /** Change Log */ + private static int[] s_changeLog = null; + /** Logger */ + private static CLogger s_log = CLogger.getCLogger(MChangeLog.class); + /** NULL Value */ + public static String NULL = "NULL"; + + + /************************************************************************** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MChangeLog(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MChangeLog + + /** + * Standard Constructor + * @param ctx context + * @param AD_ChangeLog_ID id + * @param trxName transaction + */ + public MChangeLog (Properties ctx, int AD_ChangeLog_ID, String trxName) + { + super (ctx, 0, trxName); + } // MChangeLog + + /** + * Preserved for backward compatibility + *@deprecated + */ + public MChangeLog (Properties ctx, + int AD_ChangeLog_ID, String TrxName, int AD_Session_ID, + int AD_Table_ID, int AD_Column_ID, int Record_ID, + int AD_Client_ID, int AD_Org_ID, + Object OldValue, Object NewValue) + { + this(ctx, AD_ChangeLog_ID, TrxName, AD_Session_ID, AD_Table_ID, + AD_Column_ID, Record_ID, AD_Client_ID, AD_Org_ID, OldValue, + NewValue, (String) null /*event*/ ); + } // MChangeLog + + /** + * Full Constructor + * @param ctx context + * @param AD_ChangeLog_ID 0 for new change log + * @param TrxName transaction + * @param AD_Session_ID session + * @param AD_Table_ID table + * @param AD_Column_ID column + * @param Record_ID record + * @param AD_Client_ID client + * @param AD_Org_ID org + * @param OldValue old + * @param NewValue new + */ + public MChangeLog (Properties ctx, + int AD_ChangeLog_ID, String TrxName, int AD_Session_ID, + int AD_Table_ID, int AD_Column_ID, int Record_ID, + int AD_Client_ID, int AD_Org_ID, + Object OldValue, Object NewValue, String event) + { + this (ctx, 0, TrxName); + if (AD_ChangeLog_ID == 0) + { + AD_ChangeLog_ID = DB.getNextID (AD_Client_ID, Table_Name, TrxName); + if (AD_ChangeLog_ID <= 0) + log.severe("No NextID (" + AD_ChangeLog_ID + ")"); + } + setAD_ChangeLog_ID (AD_ChangeLog_ID); + setTrxName(TrxName); + setAD_Session_ID (AD_Session_ID); + // + setAD_Table_ID (AD_Table_ID); + setAD_Column_ID (AD_Column_ID); + setRecord_ID (Record_ID); + // + setClientOrg (AD_Client_ID, AD_Org_ID); + // + setOldValue (OldValue); + setNewValue (NewValue); + setEventChangeLog(event); + // EVENT / Release 3.3.1t_2007-12-05 ADempiere + // Drop description from AD_ChangeLog - pass it to AD_Session to save disk space + // setDescription(Adempiere.MAIN_VERSION + "_" + Adempiere.DATE_VERSION + " " + Adempiere.getImplementationVersion()); + } // MChangeLog + + + /** + * Set Old Value + * @param OldValue old + */ + public void setOldValue (Object OldValue) + { + if (OldValue == null) + super.setOldValue (NULL); + else + super.setOldValue (OldValue.toString()); + } // setOldValue + + /** + * Is Old Value Null + * @return true if null + */ + public boolean isOldNull() + { + String value = getOldValue(); + return value == null || value.equals(NULL); + } // isOldNull + + /** + * Set New Value + * @param NewValue new + */ + public void setNewValue (Object NewValue) + { + if (NewValue == null) + super.setNewValue (NULL); + else + super.setNewValue (NewValue.toString()); + } // setNewValue + + /** + * Is New Value Null + * @return true if null + */ + public boolean isNewNull() + { + String value = getNewValue(); + return value == null || value.equals(NULL); + } // isNewNull + +} // MChangeLog diff --git a/base/src/org/compiere/model/MColumn.java b/base/src/org/compiere/model/MColumn.java index 8fc9e69cf5..d8bfcda3b2 100644 --- a/base/src/org/compiere/model/MColumn.java +++ b/base/src/org/compiere/model/MColumn.java @@ -1,542 +1,550 @@ -/****************************************************************************** - * Product: Adempiere ERP & CRM Smart Business Solution * - * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * - * This program is free software; you can redistribute it and/or modify it * - * under the terms version 2 of the GNU General Public License as published * - * by the Free Software Foundation. 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. * - * For the text or an alternative of this public license, you may reach us * - * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * - * or via info@compiere.org or http://www.compiere.org/license.html * - *****************************************************************************/ -package org.compiere.model; - -import java.sql.*; -import java.util.*; -import java.util.logging.Level; - -import org.compiere.util.*; - -/** - * Persistent Column Model - * - * @author Jorg Janke - * @version $Id: MColumn.java,v 1.6 2006/08/09 05:23:49 jjanke Exp $ - */ -public class MColumn extends X_AD_Column -{ - /** - * Get MColumn from Cache - * @param ctx context - * @param AD_Column_ID id - * @return MColumn - */ - public static MColumn get (Properties ctx, int AD_Column_ID) - { - Integer key = new Integer (AD_Column_ID); - MColumn retValue = (MColumn) s_cache.get (key); - if (retValue != null) - return retValue; - retValue = new MColumn (ctx, AD_Column_ID, null); - if (retValue.get_ID () != 0) - s_cache.put (key, retValue); - return retValue; - } // get - - /** - * Get Column Name - * @param ctx context - * @param AD_Column_ID id - * @return Column Name or null - */ - public static String getColumnName (Properties ctx, int AD_Column_ID) - { - MColumn col = MColumn.get(ctx, AD_Column_ID); - if (col.get_ID() == 0) - return null; - return col.getColumnName(); - } // getColumnName - - /** Cache */ - private static CCache s_cache = new CCache("AD_Column", 20); - - /** Static Logger */ - private static CLogger s_log = CLogger.getCLogger (MColumn.class); - - /************************************************************************** - * Standard Constructor - * @param ctx context - * @param AD_Column_ID - * @param trxName transaction - */ - public MColumn (Properties ctx, int AD_Column_ID, String trxName) - { - super (ctx, AD_Column_ID, trxName); - if (AD_Column_ID == 0) - { - // setAD_Element_ID (0); - // setAD_Reference_ID (0); - // setColumnName (null); - // setName (null); - // setEntityType (null); // U - setIsAlwaysUpdateable (false); // N - setIsEncrypted (false); - setIsIdentifier (false); - setIsKey (false); - setIsMandatory (false); - setIsParent (false); - setIsSelectionColumn (false); - setIsTranslated (false); - setIsUpdateable (true); // Y - setVersion (Env.ZERO); - } - } // MColumn - - /** - * Load Constructor - * @param ctx context - * @param rs result set - * @param trxName transaction - */ - public MColumn (Properties ctx, ResultSet rs, String trxName) - { - super(ctx, rs, trxName); - } // MColumn - - /** - * Parent Constructor - * @param parent table - */ - public MColumn (MTable parent) - { - this (parent.getCtx(), 0, parent.get_TrxName()); - setClientOrg(parent); - setAD_Table_ID (parent.getAD_Table_ID()); - setEntityType(parent.getEntityType()); - } // MColumn - - - /** - * Is Standard Column - * @return true for AD_Client_ID, etc. - */ - public boolean isStandardColumn() - { - String columnName = getColumnName(); - if (columnName.equals("AD_Client_ID") - || columnName.equals("AD_Org_ID") - || columnName.equals("IsActive") - || columnName.startsWith("Created") - || columnName.startsWith("Updated") ) - return true; - - return false; - } // isStandardColumn - - /** - * Is Virtual Column - * @return true if virtual column - */ - public boolean isVirtualColumn() - { - String s = getColumnSQL(); - return s != null && s.length() > 0; - } // isVirtualColumn - - /** - * Is the Column Encrypted? - * @return true if encrypted - */ - public boolean isEncrypted() - { - String s = getIsEncrypted(); - return "Y".equals(s); - } // isEncrypted - - /** - * Set Encrypted - * @param IsEncrypted encrypted - */ - public void setIsEncrypted (boolean IsEncrypted) - { - setIsEncrypted (IsEncrypted ? "Y" : "N"); - } // setIsEncrypted - - /** - * Before Save - * @param newRecord new - * @return true - */ - protected boolean beforeSave (boolean newRecord) - { - int displayType = getAD_Reference_ID(); - if (DisplayType.isLOB(displayType)) // LOBs are 0 - { - if (getFieldLength() != 0) - setFieldLength(0); - } - else if (getFieldLength() == 0) - { - if (DisplayType.isID(displayType)) - setFieldLength(10); - else if (DisplayType.isNumeric (displayType)) - setFieldLength(14); - else if (DisplayType.isDate (displayType)) - setFieldLength(7); - else - { - log.saveError("FillMandatory", Msg.getElement(getCtx(), "FieldLength")); - return false; - } - } - - /** Views are not updateable - UPDATE AD_Column c - SET IsUpdateable='N', IsAlwaysUpdateable='N' - WHERE AD_Table_ID IN (SELECT AD_Table_ID FROM AD_Table WHERE IsView='Y') - **/ - - // Virtual Column - if (isVirtualColumn()) - { - if (isMandatory()) - setIsMandatory(false); - if (isUpdateable()) - setIsUpdateable(false); - } - // Updateable - if (isParent() || isKey()) - setIsUpdateable(false); - if (isAlwaysUpdateable() && !isUpdateable()) - setIsAlwaysUpdateable(false); - // Encrypted - if (isEncrypted()) - { - int dt = getAD_Reference_ID(); - if (isKey() || isParent() || isStandardColumn() - || isVirtualColumn() || isIdentifier() || isTranslated() - || DisplayType.isLookup(dt) || DisplayType.isLOB(dt) - || "DocumentNo".equalsIgnoreCase(getColumnName()) - || "Value".equalsIgnoreCase(getColumnName()) - || "Name".equalsIgnoreCase(getColumnName())) - { - log.warning("Encryption not sensible - " + getColumnName()); - setIsEncrypted(false); - } - } - - // Sync Terminology - if ((newRecord || is_ValueChanged ("AD_Element_ID")) - && getAD_Element_ID() != 0) - { - M_Element element = new M_Element (getCtx(), getAD_Element_ID (), get_TrxName()); - setColumnName (element.getColumnName()); - setName (element.getName()); - setDescription (element.getDescription()); - setHelp (element.getHelp()); - } - return true; - } // beforeSave - - - - /** - * After Save - * @param newRecord new - * @param success success - * @return success - */ - protected boolean afterSave (boolean newRecord, boolean success) - { - // Update Fields - if (!newRecord) - { - if ( is_ValueChanged(MColumn.COLUMNNAME_Name) - || is_ValueChanged(MColumn.COLUMNNAME_Description) - || is_ValueChanged(MColumn.COLUMNNAME_Help) - ) { - StringBuffer sql = new StringBuffer("UPDATE AD_Field SET Name=") - .append(DB.TO_STRING(getName())) - .append(", Description=").append(DB.TO_STRING(getDescription())) - .append(", Help=").append(DB.TO_STRING(getHelp())) - .append(" WHERE AD_Column_ID=").append(get_ID()) - .append(" AND IsCentrallyMaintained='Y'"); - int no = DB.executeUpdate(sql.toString(), get_TrxName()); - log.fine("afterSave - Fields updated #" + no); - } - } - return success; - } // afterSave - - /** - * Get SQL Add command - * @param table table - * @return sql - */ - public String getSQLAdd (MTable table) - { - StringBuffer sql = new StringBuffer ("ALTER TABLE ") - .append(table.getTableName()) - .append(" ADD ").append(getSQLDDL()); - String constraint = getConstraint(table.getTableName()); - if (constraint != null && constraint.length() > 0) { - sql.append(DB.SQLSTATEMENT_SEPARATOR).append("ALTER TABLE ") - .append(table.getTableName()) - .append(" ADD ").append(constraint); - } - return sql.toString(); - } // getSQLAdd - - /** - * Get SQL DDL - * @return columnName datataype .. - */ - public String getSQLDDL() - { - if (isVirtualColumn()) - return null; - - StringBuffer sql = new StringBuffer (getColumnName()) - .append(" ").append(getSQLDataType()); - // Default +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.sql.*; +import java.util.*; +import java.util.logging.Level; + +import org.compiere.util.*; + +/** + * Persistent Column Model + * + * @author Jorg Janke + * @version $Id: MColumn.java,v 1.6 2006/08/09 05:23:49 jjanke Exp $ + */ +public class MColumn extends X_AD_Column +{ + /** + * Get MColumn from Cache + * @param ctx context + * @param AD_Column_ID id + * @return MColumn + */ + public static MColumn get (Properties ctx, int AD_Column_ID) + { + Integer key = new Integer (AD_Column_ID); + MColumn retValue = (MColumn) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MColumn (ctx, AD_Column_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** + * Get Column Name + * @param ctx context + * @param AD_Column_ID id + * @return Column Name or null + */ + public static String getColumnName (Properties ctx, int AD_Column_ID) + { + MColumn col = MColumn.get(ctx, AD_Column_ID); + if (col.get_ID() == 0) + return null; + return col.getColumnName(); + } // getColumnName + + /** Cache */ + private static CCache s_cache = new CCache("AD_Column", 20); + + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MColumn.class); + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param AD_Column_ID + * @param trxName transaction + */ + public MColumn (Properties ctx, int AD_Column_ID, String trxName) + { + super (ctx, AD_Column_ID, trxName); + if (AD_Column_ID == 0) + { + // setAD_Element_ID (0); + // setAD_Reference_ID (0); + // setColumnName (null); + // setName (null); + // setEntityType (null); // U + setIsAlwaysUpdateable (false); // N + setIsEncrypted (false); + setIsIdentifier (false); + setIsKey (false); + setIsMandatory (false); + setIsParent (false); + setIsSelectionColumn (false); + setIsTranslated (false); + setIsUpdateable (true); // Y + setVersion (Env.ZERO); + } + } // MColumn + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MColumn (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MColumn + + /** + * Parent Constructor + * @param parent table + */ + public MColumn (MTable parent) + { + this (parent.getCtx(), 0, parent.get_TrxName()); + setClientOrg(parent); + setAD_Table_ID (parent.getAD_Table_ID()); + setEntityType(parent.getEntityType()); + } // MColumn + + + /** + * Is Standard Column + * @return true for AD_Client_ID, etc. + */ + public boolean isStandardColumn() + { + String columnName = getColumnName(); + if (columnName.equals("AD_Client_ID") + || columnName.equals("AD_Org_ID") + || columnName.equals("IsActive") + || columnName.startsWith("Created") + || columnName.startsWith("Updated") ) + return true; + + return false; + } // isStandardColumn + + /** + * Is Virtual Column + * @return true if virtual column + */ + public boolean isVirtualColumn() + { + String s = getColumnSQL(); + return s != null && s.length() > 0; + } // isVirtualColumn + + /** + * Is the Column Encrypted? + * @return true if encrypted + */ + public boolean isEncrypted() + { + String s = getIsEncrypted(); + return "Y".equals(s); + } // isEncrypted + + /** + * Set Encrypted + * @param IsEncrypted encrypted + */ + public void setIsEncrypted (boolean IsEncrypted) + { + setIsEncrypted (IsEncrypted ? "Y" : "N"); + } // setIsEncrypted + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + int displayType = getAD_Reference_ID(); + if (DisplayType.isLOB(displayType)) // LOBs are 0 + { + if (getFieldLength() != 0) + setFieldLength(0); + } + else if (getFieldLength() == 0) + { + if (DisplayType.isID(displayType)) + setFieldLength(10); + else if (DisplayType.isNumeric (displayType)) + setFieldLength(14); + else if (DisplayType.isDate (displayType)) + setFieldLength(7); + else + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "FieldLength")); + return false; + } + } + + /** Views are not updateable + UPDATE AD_Column c + SET IsUpdateable='N', IsAlwaysUpdateable='N' + WHERE AD_Table_ID IN (SELECT AD_Table_ID FROM AD_Table WHERE IsView='Y') + **/ + + // Virtual Column + if (isVirtualColumn()) + { + if (isMandatory()) + setIsMandatory(false); + if (isUpdateable()) + setIsUpdateable(false); + } + // Updateable + if (isParent() || isKey()) + setIsUpdateable(false); + if (isAlwaysUpdateable() && !isUpdateable()) + setIsAlwaysUpdateable(false); + // Encrypted + if (isEncrypted()) + { + int dt = getAD_Reference_ID(); + if (isKey() || isParent() || isStandardColumn() + || isVirtualColumn() || isIdentifier() || isTranslated() + || DisplayType.isLookup(dt) || DisplayType.isLOB(dt) + || "DocumentNo".equalsIgnoreCase(getColumnName()) + || "Value".equalsIgnoreCase(getColumnName()) + || "Name".equalsIgnoreCase(getColumnName())) + { + log.warning("Encryption not sensible - " + getColumnName()); + setIsEncrypted(false); + } + } + + // Sync Terminology + if ((newRecord || is_ValueChanged ("AD_Element_ID")) + && getAD_Element_ID() != 0) + { + M_Element element = new M_Element (getCtx(), getAD_Element_ID (), get_TrxName()); + setColumnName (element.getColumnName()); + setName (element.getName()); + setDescription (element.getDescription()); + setHelp (element.getHelp()); + } + return true; + } // beforeSave + + + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + // Update Fields + if (!newRecord) + { + if ( is_ValueChanged(MColumn.COLUMNNAME_Name) + || is_ValueChanged(MColumn.COLUMNNAME_Description) + || is_ValueChanged(MColumn.COLUMNNAME_Help) + ) { + StringBuffer sql = new StringBuffer("UPDATE AD_Field SET Name=") + .append(DB.TO_STRING(getName())) + .append(", Description=").append(DB.TO_STRING(getDescription())) + .append(", Help=").append(DB.TO_STRING(getHelp())) + .append(" WHERE AD_Column_ID=").append(get_ID()) + .append(" AND IsCentrallyMaintained='Y'"); + int no = DB.executeUpdate(sql.toString(), get_TrxName()); + log.fine("afterSave - Fields updated #" + no); + } + } + return success; + } // afterSave + + /** + * Get SQL Add command + * @param table table + * @return sql + */ + public String getSQLAdd (MTable table) + { + StringBuffer sql = new StringBuffer ("ALTER TABLE ") + .append(table.getTableName()) + .append(" ADD ").append(getSQLDDL()); + String constraint = getConstraint(table.getTableName()); + if (constraint != null && constraint.length() > 0) { + sql.append(DB.SQLSTATEMENT_SEPARATOR).append("ALTER TABLE ") + .append(table.getTableName()) + .append(" ADD ").append(constraint); + } + return sql.toString(); + } // getSQLAdd + + /** + * Get SQL DDL + * @return columnName datataype .. + */ + public String getSQLDDL() + { + if (isVirtualColumn()) + return null; + + StringBuffer sql = new StringBuffer (getColumnName()) + .append(" ").append(getSQLDataType()); + // Default if (getDefaultValue() != null && getDefaultValue().length() > 0) - { - sql.append(" DEFAULT "); - // if (DisplayType.isText(getAD_Reference_ID())) - // sql.append(DB.TO_STRING(getDefaultValue())); - // else - // sql.append(getDefaultValue()); - String defaultValue = getDefaultValue(); - if (defaultValue != null - && defaultValue.length() > 0 - && defaultValue.indexOf('@') == -1) // no variables - { - if (DisplayType.isText(getAD_Reference_ID()) - || getAD_Reference_ID() == DisplayType.List - || getAD_Reference_ID() == DisplayType.YesNo - // Two special columns: Defined as Table but DB Type is String - || getColumnName().equals("EntityType") || getColumnName().equals("AD_Language") - || (getAD_Reference_ID() == DisplayType.Button && - !(getColumnName().endsWith("_ID")))) - { - if (!defaultValue.startsWith("'") && !defaultValue.endsWith("'")) - defaultValue = DB.TO_STRING(defaultValue); - } - } else { - defaultValue = " NULL "; - } - sql.append(defaultValue); - } - // Inline Constraint - if (getAD_Reference_ID() == DisplayType.YesNo) - sql.append(" CHECK (").append(getColumnName()).append(" IN ('Y','N'))"); - - // Null - if (isMandatory()) - sql.append(" NOT NULL"); - return sql.toString(); - } // getSQLDDL - - /** - * Get SQL Modify command - * @param table table - * @param setNullOption generate null / not null statement - * @return sql separated by ; - */ - public String getSQLModify (MTable table, boolean setNullOption) - { - StringBuffer sql = new StringBuffer(); - StringBuffer sqlBase = new StringBuffer ("ALTER TABLE ") - .append(table.getTableName()) - .append(" MODIFY ").append(getColumnName()); - - // Default - StringBuffer sqlDefault = new StringBuffer(sqlBase) - .append(" ").append(getSQLDataType()) - .append(" DEFAULT "); - String defaultValue = getDefaultValue(); - if (defaultValue != null - && defaultValue.length() > 0 - && defaultValue.indexOf('@') == -1) // no variables - { - if (DisplayType.isText(getAD_Reference_ID()) - || getAD_Reference_ID() == DisplayType.List - || getAD_Reference_ID() == DisplayType.YesNo - // Two special columns: Defined as Table but DB Type is String - || getColumnName().equals("EntityType") || getColumnName().equals("AD_Language") - || (getAD_Reference_ID() == DisplayType.Button && - !(getColumnName().endsWith("_ID")))) - { - if (!defaultValue.startsWith("'") && !defaultValue.endsWith("'")) - defaultValue = DB.TO_STRING(defaultValue); - } - sqlDefault.append(defaultValue); - } - else - { - sqlDefault.append(" NULL "); - defaultValue = null; - } - sql.append(sqlDefault); - - // Constraint - - // Null Values - if (isMandatory() && defaultValue != null && defaultValue.length() > 0) - { - StringBuffer sqlSet = new StringBuffer("UPDATE ") - .append(table.getTableName()) - .append(" SET ").append(getColumnName()) - .append("=").append(defaultValue) - .append(" WHERE ").append(getColumnName()).append(" IS NULL"); - sql.append(DB.SQLSTATEMENT_SEPARATOR).append(sqlSet); - } - - // Null - if (setNullOption) - { - StringBuffer sqlNull = new StringBuffer(sqlBase); - if (isMandatory()) - sqlNull.append(" NOT NULL"); - else - sqlNull.append(" NULL"); - sql.append(DB.SQLSTATEMENT_SEPARATOR).append(sqlNull); - } - // - return sql.toString(); - } // getSQLModify - - /** - * Get SQL Data Type - * @return e.g. NVARCHAR2(60) - */ - public String getSQLDataType() - { - String columnName = getColumnName(); - int dt = getAD_Reference_ID(); - return DisplayType.getSQLDataType (dt, columnName, getFieldLength()); - } // getSQLDataType - - /** - * Get SQL Data Type - * @return e.g. NVARCHAR2(60) - */ - /* - private String getSQLDataType() - { - int dt = getAD_Reference_ID(); - if (DisplayType.isID(dt) || dt == DisplayType.Integer) - return "NUMBER(10)"; - if (DisplayType.isDate(dt)) - return "DATE"; - if (DisplayType.isNumeric(dt)) - return "NUMBER"; - if (dt == DisplayType.Binary) - return "BLOB"; - if (dt == DisplayType.TextLong) - return "CLOB"; - if (dt == DisplayType.YesNo) - return "CHAR(1)"; - if (dt == DisplayType.List) - return "NVARCHAR2(" + getFieldLength() + ")"; - if (dt == DisplayType.Button) - return "CHAR(" + getFieldLength() + ")"; - else if (!DisplayType.isText(dt)) - log.severe("Unhandled Data Type = " + dt); - - return "NVARCHAR2(" + getFieldLength() + ")"; - } // getSQLDataType - */ - - /** - * Get Table Constraint - * @param tableName table name - * @return table constraint - */ - public String getConstraint(String tableName) - { - if (isKey()) { - String constraintName; - if (tableName.length() > 26) - // Oracle restricts object names to 30 characters - constraintName = tableName.substring(0, 26) + "_Key"; - else - constraintName = tableName + "_Key"; - return "CONSTRAINT " + constraintName + " PRIMARY KEY (" + getColumnName() + ")"; - } - /** - if (getAD_Reference_ID() == DisplayType.TableDir - || getAD_Reference_ID() == DisplayType.Search) - return "CONSTRAINT " ADTable_ADTableTrl - + " FOREIGN KEY (" + getColumnName() + ") REFERENCES " - + AD_Table(AD_Table_ID) ON DELETE CASCADE - **/ - - return ""; - } // getConstraint - - /** - * String Representation - * @return info - */ - public String toString() - { - StringBuffer sb = new StringBuffer ("MColumn["); - sb.append (get_ID()).append ("-").append (getColumnName()).append ("]"); - return sb.toString (); - } // toString - - //begin vpj-cd e-evolution - /** - * get Column ID - * @param String windowName - * @param String columnName - * @return int retValue - */ - public static int getColumn_ID(String TableName,String columnName) { - int m_table_id = MTable.getTable_ID(TableName); - if (m_table_id == 0) - return 0; - - int retValue = 0; - String SQL = "SELECT AD_Column_ID FROM AD_Column WHERE AD_Table_ID = ? AND columnname = ?"; - try - { - PreparedStatement pstmt = DB.prepareStatement(SQL, null); - pstmt.setInt(1, m_table_id); - pstmt.setString(2, columnName); - ResultSet rs = pstmt.executeQuery(); - if (rs.next()) - retValue = rs.getInt(1); - rs.close(); - pstmt.close(); - } - catch (SQLException e) - { - s_log.log(Level.SEVERE, SQL, e); - retValue = -1; - } - return retValue; - } - //end vpj-cd e-evolution - - /** - * Get Table Id for a column - * @param ctx context - * @param AD_Column_ID id - * @param trxName transaction - * @return MColumn - */ - public static int getTable_ID(Properties ctx, int AD_Column_ID, String trxName) - { - String sqlStmt = "SELECT AD_Table_ID FROM AD_Column WHERE AD_Column_ID=?"; - return DB.getSQLValue(trxName, sqlStmt, AD_Column_ID); - } - - -} // MColumn + { + sql.append(" DEFAULT "); + // if (DisplayType.isText(getAD_Reference_ID())) + // sql.append(DB.TO_STRING(getDefaultValue())); + // else + // sql.append(getDefaultValue()); + String defaultValue = getDefaultValue(); + if (defaultValue != null + && defaultValue.length() > 0 + && defaultValue.indexOf('@') == -1) // no variables + { + if (DisplayType.isText(getAD_Reference_ID()) + || getAD_Reference_ID() == DisplayType.List + || getAD_Reference_ID() == DisplayType.YesNo + // Two special columns: Defined as Table but DB Type is String + || getColumnName().equals("EntityType") || getColumnName().equals("AD_Language") + || (getAD_Reference_ID() == DisplayType.Button && + !(getColumnName().endsWith("_ID")))) + { + if (!defaultValue.startsWith("'") && !defaultValue.endsWith("'")) + defaultValue = DB.TO_STRING(defaultValue); + } + } else { + defaultValue = " NULL "; + } + sql.append(defaultValue); + } + // Inline Constraint + if (getAD_Reference_ID() == DisplayType.YesNo) + sql.append(" CHECK (").append(getColumnName()).append(" IN ('Y','N'))"); + + // Null + if (isMandatory()) + sql.append(" NOT NULL"); + return sql.toString(); + } // getSQLDDL + + /** + * Get SQL Modify command + * @param table table + * @param setNullOption generate null / not null statement + * @return sql separated by ; + */ + public String getSQLModify (MTable table, boolean setNullOption) + { + StringBuffer sql = new StringBuffer(); + StringBuffer sqlBase = new StringBuffer ("ALTER TABLE ") + .append(table.getTableName()) + .append(" MODIFY ").append(getColumnName()); + + // Default + StringBuffer sqlDefault = new StringBuffer(sqlBase) + .append(" ").append(getSQLDataType()) + .append(" DEFAULT "); + String defaultValue = getDefaultValue(); + if (defaultValue != null + && defaultValue.length() > 0 + && defaultValue.indexOf('@') == -1) // no variables + { + if (DisplayType.isText(getAD_Reference_ID()) + || getAD_Reference_ID() == DisplayType.List + || getAD_Reference_ID() == DisplayType.YesNo + // Two special columns: Defined as Table but DB Type is String + || getColumnName().equals("EntityType") || getColumnName().equals("AD_Language") + || (getAD_Reference_ID() == DisplayType.Button && + !(getColumnName().endsWith("_ID")))) + { + if (!defaultValue.startsWith("'") && !defaultValue.endsWith("'")) + defaultValue = DB.TO_STRING(defaultValue); + } + sqlDefault.append(defaultValue); + } + else + { + sqlDefault.append(" NULL "); + defaultValue = null; + } + sql.append(sqlDefault); + + // Constraint + + // Null Values + if (isMandatory() && defaultValue != null && defaultValue.length() > 0) + { + StringBuffer sqlSet = new StringBuffer("UPDATE ") + .append(table.getTableName()) + .append(" SET ").append(getColumnName()) + .append("=").append(defaultValue) + .append(" WHERE ").append(getColumnName()).append(" IS NULL"); + sql.append(DB.SQLSTATEMENT_SEPARATOR).append(sqlSet); + } + + // Null + if (setNullOption) + { + StringBuffer sqlNull = new StringBuffer(sqlBase); + if (isMandatory()) + sqlNull.append(" NOT NULL"); + else + sqlNull.append(" NULL"); + sql.append(DB.SQLSTATEMENT_SEPARATOR).append(sqlNull); + } + // + return sql.toString(); + } // getSQLModify + + /** + * Get SQL Data Type + * @return e.g. NVARCHAR2(60) + */ + public String getSQLDataType() + { + String columnName = getColumnName(); + int dt = getAD_Reference_ID(); + return DisplayType.getSQLDataType (dt, columnName, getFieldLength()); + } // getSQLDataType + + /** + * Get SQL Data Type + * @return e.g. NVARCHAR2(60) + */ + /* + private String getSQLDataType() + { + int dt = getAD_Reference_ID(); + if (DisplayType.isID(dt) || dt == DisplayType.Integer) + return "NUMBER(10)"; + if (DisplayType.isDate(dt)) + return "DATE"; + if (DisplayType.isNumeric(dt)) + return "NUMBER"; + if (dt == DisplayType.Binary) + return "BLOB"; + if (dt == DisplayType.TextLong) + return "CLOB"; + if (dt == DisplayType.YesNo) + return "CHAR(1)"; + if (dt == DisplayType.List) + return "NVARCHAR2(" + getFieldLength() + ")"; + if (dt == DisplayType.Button) + return "CHAR(" + getFieldLength() + ")"; + else if (!DisplayType.isText(dt)) + log.severe("Unhandled Data Type = " + dt); + + return "NVARCHAR2(" + getFieldLength() + ")"; + } // getSQLDataType + */ + + /** + * Get Table Constraint + * @param tableName table name + * @return table constraint + */ + public String getConstraint(String tableName) + { + if (isKey()) { + String constraintName; + if (tableName.length() > 26) + // Oracle restricts object names to 30 characters + constraintName = tableName.substring(0, 26) + "_Key"; + else + constraintName = tableName + "_Key"; + return "CONSTRAINT " + constraintName + " PRIMARY KEY (" + getColumnName() + ")"; + } + /** + if (getAD_Reference_ID() == DisplayType.TableDir + || getAD_Reference_ID() == DisplayType.Search) + return "CONSTRAINT " ADTable_ADTableTrl + + " FOREIGN KEY (" + getColumnName() + ") REFERENCES " + + AD_Table(AD_Table_ID) ON DELETE CASCADE + **/ + + return ""; + } // getConstraint + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer ("MColumn["); + sb.append (get_ID()).append ("-").append (getColumnName()).append ("]"); + return sb.toString (); + } // toString + + /** Get IsAllowLogging . + * Determines, if a column must be recorded into the change log + */ + public boolean IsAllowLogging() { + return super.IsAllowLogging(); + } + + + //begin vpj-cd e-evolution + /** + * get Column ID + * @param String windowName + * @param String columnName + * @return int retValue + */ + public static int getColumn_ID(String TableName,String columnName) { + int m_table_id = MTable.getTable_ID(TableName); + if (m_table_id == 0) + return 0; + + int retValue = 0; + String SQL = "SELECT AD_Column_ID FROM AD_Column WHERE AD_Table_ID = ? AND columnname = ?"; + try + { + PreparedStatement pstmt = DB.prepareStatement(SQL, null); + pstmt.setInt(1, m_table_id); + pstmt.setString(2, columnName); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + retValue = rs.getInt(1); + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + s_log.log(Level.SEVERE, SQL, e); + retValue = -1; + } + return retValue; + } + //end vpj-cd e-evolution + + /** + * Get Table Id for a column + * @param ctx context + * @param AD_Column_ID id + * @param trxName transaction + * @return MColumn + */ + public static int getTable_ID(Properties ctx, int AD_Column_ID, String trxName) + { + String sqlStmt = "SELECT AD_Table_ID FROM AD_Column WHERE AD_Column_ID=?"; + return DB.getSQLValue(trxName, sqlStmt, AD_Column_ID); + } + + +} // MColumn diff --git a/base/src/org/compiere/model/MSession.java b/base/src/org/compiere/model/MSession.java index 165749aa14..88cbd7fb8c 100644 --- a/base/src/org/compiere/model/MSession.java +++ b/base/src/org/compiere/model/MSession.java @@ -1,316 +1,319 @@ -/****************************************************************************** - * Product: Adempiere ERP & CRM Smart Business Solution * - * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * - * This program is free software; you can redistribute it and/or modify it * - * under the terms version 2 of the GNU General Public License as published * - * by the Free Software Foundation. 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. * - * For the text or an alternative of this public license, you may reach us * - * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * - * or via info@compiere.org or http://www.compiere.org/license.html * - *****************************************************************************/ -package org.compiere.model; - -import java.net.*; -import java.sql.*; -import java.util.*; -import java.util.logging.*; - -import org.compiere.Adempiere; -import org.compiere.util.*; - -/** - * Session Model. - * Maintained in AMenu. - * - * @author Jorg Janke - * @version $Id: MSession.java,v 1.3 2006/07/30 00:58:05 jjanke Exp $ - * - * @author Teo Sarca, SC ARHIPAC SERVICE SRL - *
  • BF [ 1810182 ] Session lost after cache reset - *
  • BF [ 1892156 ] MSession is not really cached - */ -public class MSession extends X_AD_Session -{ - /** - * Get existing or create local session - * @param ctx context - * @param createNew create if not found - * @return session session - */ - public static MSession get (Properties ctx, boolean createNew) - { - int AD_Session_ID = Env.getContextAsInt(ctx, "#AD_Session_ID"); - MSession session = null; - if (AD_Session_ID > 0) - session = (MSession)s_sessions.get(new Integer(AD_Session_ID)); - // Try to load - if (session == null && AD_Session_ID > 0) - { - session = new MSession(ctx, AD_Session_ID, null); - if (session.get_ID() != AD_Session_ID) { - Env.setContext (ctx, "#AD_Session_ID", AD_Session_ID); - } - s_sessions.put(AD_Session_ID, session); - } - // Create New - if (session == null && createNew) - { - session = new MSession (ctx, null); // local session - session.save(); - AD_Session_ID = session.getAD_Session_ID(); - Env.setContext (ctx, "#AD_Session_ID", AD_Session_ID); - s_sessions.put (new Integer(AD_Session_ID), session); - } - return session; - } // get - - /** - * Get existing or create remote session - * @param ctx context - * @param Remote_Addr remote address - * @param Remote_Host remote host - * @param WebSession web session - * @return session - */ - public static MSession get (Properties ctx, String Remote_Addr, String Remote_Host, String WebSession) - { - int AD_Session_ID = Env.getContextAsInt(ctx, "#AD_Session_ID"); - MSession session = null; - if (AD_Session_ID > 0) - session = (MSession)s_sessions.get(new Integer(AD_Session_ID)); - if (session == null) - { - session = new MSession (ctx, Remote_Addr, Remote_Host, WebSession, null); // remote session - session.save(); - AD_Session_ID = session.getAD_Session_ID(); - Env.setContext(ctx, "#AD_Session_ID", AD_Session_ID); - s_sessions.put(new Integer(AD_Session_ID), session); - } - return session; - } // get - - /** Sessions */ - private static CCache s_sessions = Ini.isClient() - ? new CCache("AD_Session_ID", 1, 0) // one client session - : new CCache("AD_Session_ID", 30, 0); // no time-out - - - /************************************************************************** - * Standard Constructor - * @param ctx context - * @param AD_Session_ID id - * @param trxName transaction - */ - public MSession (Properties ctx, int AD_Session_ID, String trxName) - { - super(ctx, AD_Session_ID, trxName); - if (AD_Session_ID == 0) - { - setProcessed (false); - } - } // MSession - - /** - * Load Costructor - * @param ctx context - * @param rs result set - * @param trxName transaction - */ - public MSession(Properties ctx, ResultSet rs, String trxName) - { - super(ctx, rs, trxName); - } // MSession - - /** - * New (remote) Constructor - * @param ctx context - * @param Remote_Addr remote address - * @param Remote_Host remote host - * @param WebSession web session - * @param trxName transaction - */ - public MSession (Properties ctx, String Remote_Addr, String Remote_Host, String WebSession, String trxName) - { - this (ctx, 0, trxName); - if (Remote_Addr != null) - setRemote_Addr(Remote_Addr); - if (Remote_Host != null) - setRemote_Host(Remote_Host); - if (WebSession != null) - setWebSession(WebSession); - setDescription(Adempiere.MAIN_VERSION + "_" - + Adempiere.DATE_VERSION + " " - + Adempiere.getImplementationVersion()); - setAD_Role_ID(Env.getContextAsInt(ctx, "#AD_Role_ID")); - setLoginDate(Env.getContextAsDate(ctx, "#Date")); - } // MSession - - /** - * New (local) Constructor - * @param ctx context - * @param trxName transaction - */ - public MSession (Properties ctx, String trxName) - { - this (ctx, 0, trxName); - try - { - InetAddress lh = InetAddress.getLocalHost(); - setRemote_Addr(lh.getHostAddress()); - setRemote_Host(lh.getHostName()); - setDescription(Adempiere.MAIN_VERSION + "_" - + Adempiere.DATE_VERSION + " " - + Adempiere.getImplementationVersion()); - setAD_Role_ID(Env.getContextAsInt(ctx, "#AD_Role_ID")); - setLoginDate(Env.getContextAsDate(ctx, "#Date")); - } - catch (UnknownHostException e) - { - log.log(Level.SEVERE, "No Local Host", e); - } - } // MSession - - /** Web Store Session */ - private boolean m_webStoreSession = false; - - /** - * Is it a Web Store Session - * @return Returns true if Web Store Session. - */ - public boolean isWebStoreSession () - { - return m_webStoreSession; - } // isWebStoreSession - - /** - * Set Web Store Session - * @param webStoreSession The webStoreSession to set. - */ - public void setWebStoreSession (boolean webStoreSession) - { - m_webStoreSession = webStoreSession; - } // setWebStoreSession - - /** - * String Representation - * @return info - */ - public String toString() - { - StringBuffer sb = new StringBuffer("MSession[") - .append(getAD_Session_ID()) - .append(",AD_User_ID=").append(getCreatedBy()) - .append(",").append(getCreated()) - .append(",Remote=").append(getRemote_Addr()); - String s = getRemote_Host(); - if (s != null && s.length() > 0) - sb.append(",").append(s); - if (m_webStoreSession) - sb.append(",WebStoreSession"); - sb.append("]"); - return sb.toString(); - } // toString - - /** - * Session Logout - */ - public void logout() - { - setProcessed(true); - save(); - s_sessions.remove(new Integer(getAD_Session_ID())); - log.info(TimeUtil.formatElapsed(getCreated(), getUpdated())); - } // logout - - /** - * Preserved for backward compatibility - *@deprecated - */ - public MChangeLog changeLog ( - String TrxName, int AD_ChangeLog_ID, - int AD_Table_ID, int AD_Column_ID, int Record_ID, - int AD_Client_ID, int AD_Org_ID, - Object OldValue, Object NewValue) - { - return changeLog(TrxName, AD_ChangeLog_ID, AD_Table_ID, AD_Column_ID, - Record_ID, AD_Client_ID, AD_Org_ID, OldValue, NewValue, - (String) null); - } // changeLog - - /** - * Create Change Log only if table is logged - * @param TrxName transaction name - * @param AD_ChangeLog_ID 0 for new change log - * @param AD_Table_ID table - * @param AD_Column_ID column - * @param Record_ID record - * @param AD_Client_ID client - * @param AD_Org_ID org - * @param OldValue old - * @param NewValue new - * @return saved change log or null - */ - public MChangeLog changeLog ( - String TrxName, int AD_ChangeLog_ID, - int AD_Table_ID, int AD_Column_ID, int Record_ID, - int AD_Client_ID, int AD_Org_ID, - Object OldValue, Object NewValue, String event) - { - // Null handling - if (OldValue == null && NewValue == null) - return null; - // Equal Value - if (OldValue != null && NewValue != null && OldValue.equals(NewValue)) - return null; - - // No Log - if (AD_Column_ID == 6652 - || AD_Column_ID == 6653) // AD_Process.Statistics_ - return null; - - // Role Logging - MRole role = MRole.getDefault(getCtx(), false); - // Do we need to log - if (m_webStoreSession // log if WebStore - || MChangeLog.isLogged(AD_Table_ID) // im/explicit log - || (role != null && role.isChangeLog()))// Role Logging - ; - else - return null; - // - log.finest("AD_ChangeLog_ID=" + AD_ChangeLog_ID - + ", AD_Session_ID=" + getAD_Session_ID() - + ", AD_Table_ID=" + AD_Table_ID + ", AD_Column_ID=" + AD_Column_ID - + ": " + OldValue + " -> " + NewValue); - boolean success = false; - - try - { - MChangeLog cl = new MChangeLog(getCtx(), - AD_ChangeLog_ID, TrxName, getAD_Session_ID(), - AD_Table_ID, AD_Column_ID, Record_ID, AD_Client_ID, AD_Org_ID, - OldValue, NewValue, event); - if (cl.save()) - return cl; - } - catch (Exception e) - { - log.log(Level.SEVERE, "AD_ChangeLog_ID=" + AD_ChangeLog_ID - + ", AD_Session_ID=" + getAD_Session_ID() - + ", AD_Table_ID=" + AD_Table_ID + ", AD_Column_ID=" + AD_Column_ID, e); - return null; - } - log.log(Level.SEVERE, "AD_ChangeLog_ID=" + AD_ChangeLog_ID - + ", AD_Session_ID=" + getAD_Session_ID() - + ", AD_Table_ID=" + AD_Table_ID + ", AD_Column_ID=" + AD_Column_ID); - return null; - } // changeLog - -} // MSession - +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.sql.ResultSet; +import java.util.Properties; +import java.util.logging.Level; + +import org.compiere.Adempiere; +import org.compiere.util.CCache; +import org.compiere.util.Env; +import org.compiere.util.Ini; +import org.compiere.util.TimeUtil; + +/** + * Session Model. + * Maintained in AMenu. + * + * @author Jorg Janke + * @version $Id: MSession.java,v 1.3 2006/07/30 00:58:05 jjanke Exp $ + * + * @author Teo Sarca, SC ARHIPAC SERVICE SRL + *
  • BF [ 1810182 ] Session lost after cache reset + *
  • BF [ 1892156 ] MSession is not really cached + */ +public class MSession extends X_AD_Session +{ + /** + * + */ + private static final long serialVersionUID = 480745219310430126L; + + + /** + * Get existing or create local session + * @param ctx context + * @param createNew create if not found + * @return session session + */ + public static MSession get (Properties ctx, boolean createNew) + { + int AD_Session_ID = Env.getContextAsInt(ctx, "#AD_Session_ID"); + MSession session = null; + if (AD_Session_ID > 0) + session = (MSession)s_sessions.get(new Integer(AD_Session_ID)); + // Try to load + if (session == null && AD_Session_ID > 0) + { + session = new MSession(ctx, AD_Session_ID, null); + if (session.get_ID() != AD_Session_ID) { + Env.setContext (ctx, "#AD_Session_ID", AD_Session_ID); + } + s_sessions.put(AD_Session_ID, session); + } + // Create New + if (session == null && createNew) + { + session = new MSession (ctx, null); // local session + session.save(); + AD_Session_ID = session.getAD_Session_ID(); + Env.setContext (ctx, "#AD_Session_ID", AD_Session_ID); + s_sessions.put (new Integer(AD_Session_ID), session); + } + return session; + } // get + + /** + * Get existing or create remote session + * @param ctx context + * @param Remote_Addr remote address + * @param Remote_Host remote host + * @param WebSession web session + * @return session + */ + public static MSession get (Properties ctx, String Remote_Addr, String Remote_Host, String WebSession) + { + int AD_Session_ID = Env.getContextAsInt(ctx, "#AD_Session_ID"); + MSession session = null; + if (AD_Session_ID > 0) + session = (MSession)s_sessions.get(new Integer(AD_Session_ID)); + if (session == null) + { + session = new MSession (ctx, Remote_Addr, Remote_Host, WebSession, null); // remote session + session.save(); + AD_Session_ID = session.getAD_Session_ID(); + Env.setContext(ctx, "#AD_Session_ID", AD_Session_ID); + s_sessions.put(new Integer(AD_Session_ID), session); + } + return session; + } // get + + /** Sessions */ + private static CCache s_sessions = Ini.isClient() + ? new CCache("AD_Session_ID", 1, 0) // one client session + : new CCache("AD_Session_ID", 30, 0); // no time-out + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param AD_Session_ID id + * @param trxName transaction + */ + public MSession (Properties ctx, int AD_Session_ID, String trxName) + { + super(ctx, AD_Session_ID, trxName); + if (AD_Session_ID == 0) + { + setProcessed (false); + } + } // MSession + + /** + * Load Costructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MSession(Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MSession + + /** + * New (remote) Constructor + * @param ctx context + * @param Remote_Addr remote address + * @param Remote_Host remote host + * @param WebSession web session + * @param trxName transaction + */ + public MSession (Properties ctx, String Remote_Addr, String Remote_Host, String WebSession, String trxName) + { + this (ctx, 0, trxName); + if (Remote_Addr != null) + setRemote_Addr(Remote_Addr); + if (Remote_Host != null) + setRemote_Host(Remote_Host); + if (WebSession != null) + setWebSession(WebSession); + setDescription(Adempiere.MAIN_VERSION + "_" + + Adempiere.DATE_VERSION + " " + + Adempiere.getImplementationVersion()); + setAD_Role_ID(Env.getContextAsInt(ctx, "#AD_Role_ID")); + setLoginDate(Env.getContextAsDate(ctx, "#Date")); + } // MSession + + /** + * New (local) Constructor + * @param ctx context + * @param trxName transaction + */ + public MSession (Properties ctx, String trxName) + { + this (ctx, 0, trxName); + try + { + InetAddress lh = InetAddress.getLocalHost(); + setRemote_Addr(lh.getHostAddress()); + setRemote_Host(lh.getHostName()); + setDescription(Adempiere.MAIN_VERSION + "_" + + Adempiere.DATE_VERSION + " " + + Adempiere.getImplementationVersion()); + setAD_Role_ID(Env.getContextAsInt(ctx, "#AD_Role_ID")); + setLoginDate(Env.getContextAsDate(ctx, "#Date")); + } + catch (UnknownHostException e) + { + log.log(Level.SEVERE, "No Local Host", e); + } + } // MSession + + /** Web Store Session */ + private boolean m_webStoreSession = false; + + /** + * Is it a Web Store Session + * @return Returns true if Web Store Session. + */ + public boolean isWebStoreSession () + { + return m_webStoreSession; + } // isWebStoreSession + + /** + * Set Web Store Session + * @param webStoreSession The webStoreSession to set. + */ + public void setWebStoreSession (boolean webStoreSession) + { + m_webStoreSession = webStoreSession; + } // setWebStoreSession + + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("MSession[") + .append(getAD_Session_ID()) + .append(",AD_User_ID=").append(getCreatedBy()) + .append(",").append(getCreated()) + .append(",Remote=").append(getRemote_Addr()); + String s = getRemote_Host(); + if (s != null && s.length() > 0) + sb.append(",").append(s); + if (m_webStoreSession) + sb.append(",WebStoreSession"); + sb.append("]"); + return sb.toString(); + } // toString + + /** + * Session Logout + */ + public void logout() + { + setProcessed(true); + save(); + s_sessions.remove(new Integer(getAD_Session_ID())); + log.info(TimeUtil.formatElapsed(getCreated(), getUpdated())); + } // logout + + /** + * Preserved for backward compatibility + *@deprecated + */ + public MChangeLog changeLog ( + String TrxName, int AD_ChangeLog_ID, + int AD_Table_ID, int AD_Column_ID, int Record_ID, + int AD_Client_ID, int AD_Org_ID, + Object OldValue, Object NewValue) + { + return changeLog(TrxName, AD_ChangeLog_ID, AD_Table_ID, AD_Column_ID, + Record_ID, AD_Client_ID, AD_Org_ID, OldValue, NewValue, + (String) null); + } // changeLog + + /** + * Create Change Log only if table is logged + * @param TrxName transaction name + * @param AD_ChangeLog_ID 0 for new change log + * @param AD_Table_ID table + * @param AD_Column_ID column + * @param Record_ID record + * @param AD_Client_ID client + * @param AD_Org_ID org + * @param OldValue old + * @param NewValue new + * @return saved change log or null + */ + public MChangeLog changeLog ( + String TrxName, int AD_ChangeLog_ID, + int AD_Table_ID, int AD_Column_ID, int Record_ID, + int AD_Client_ID, int AD_Org_ID, + Object OldValue, Object NewValue, String event) + { + // Null handling + if (OldValue == null && NewValue == null) + return null; + // Equal Value + if (OldValue != null && NewValue != null && OldValue.equals(NewValue)) + return null; + + // Role Logging + MRole role = MRole.getDefault(getCtx(), false); + // Do we need to log + if (m_webStoreSession // log if WebStore + || MChangeLog.isLogged(AD_Table_ID) // im/explicit log + || (role != null && role.isChangeLog()))// Role Logging + ; + else + return null; + // + log.finest("AD_ChangeLog_ID=" + AD_ChangeLog_ID + + ", AD_Session_ID=" + getAD_Session_ID() + + ", AD_Table_ID=" + AD_Table_ID + ", AD_Column_ID=" + AD_Column_ID + + ": " + OldValue + " -> " + NewValue); + try + { + MChangeLog cl = new MChangeLog(getCtx(), + AD_ChangeLog_ID, TrxName, getAD_Session_ID(), + AD_Table_ID, AD_Column_ID, Record_ID, AD_Client_ID, AD_Org_ID, + OldValue, NewValue, event); + if (cl.save()) + return cl; + } + catch (Exception e) + { + log.log(Level.SEVERE, "AD_ChangeLog_ID=" + AD_ChangeLog_ID + + ", AD_Session_ID=" + getAD_Session_ID() + + ", AD_Table_ID=" + AD_Table_ID + ", AD_Column_ID=" + AD_Column_ID, e); + return null; + } + log.log(Level.SEVERE, "AD_ChangeLog_ID=" + AD_ChangeLog_ID + + ", AD_Session_ID=" + getAD_Session_ID() + + ", AD_Table_ID=" + AD_Table_ID + ", AD_Column_ID=" + AD_Column_ID); + return null; + } // changeLog + +} // MSession + diff --git a/base/src/org/compiere/model/PO.java b/base/src/org/compiere/model/PO.java index 418e73d358..57136f6429 100644 --- a/base/src/org/compiere/model/PO.java +++ b/base/src/org/compiere/model/PO.java @@ -1,3736 +1,3744 @@ -/****************************************************************************** - * Product: Adempiere ERP & CRM Smart Business Solution * - * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * - * This program is free software; you can redistribute it and/or modify it * - * under the terms version 2 of the GNU General Public License as published * - * by the Free Software Foundation. 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. * - * For the text or an alternative of this public license, you may reach us * - * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * - * or via info@compiere.org or http://www.compiere.org/license.html * - *****************************************************************************/ -package org.compiere.model; - -import java.io.Serializable; -import java.io.StringWriter; -import java.math.BigDecimal; -import java.sql.Blob; -import java.sql.Clob; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Properties; -import java.util.logging.Level; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import org.adempiere.exceptions.AdempiereException; -import org.adempiere.exceptions.DBException; -import org.compiere.Adempiere; -import org.compiere.acct.Doc; -import org.compiere.util.CLogMgt; -import org.compiere.util.CLogger; -import org.compiere.util.CacheMgt; -import org.compiere.util.DB; -import org.compiere.util.DisplayType; -import org.compiere.util.Env; -import org.compiere.util.Evaluatee; -import org.compiere.util.Msg; -import org.compiere.util.SecureEngine; -import org.compiere.util.Trace; -import org.compiere.util.Trx; -import org.compiere.util.ValueNamePair; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * Persistent Object. - * Superclass for actual implementations - * - * @author Jorg Janke - * @version $Id: PO.java,v 1.12 2006/08/09 16:38:47 jjanke Exp $ - * - * @author Teo Sarca, SC ARHIPAC SERVICE SRL - *
  • FR [ 1675490 ] ModelValidator on modelChange after events - *
  • BF [ 1704828 ] PO.is_Changed() and PO.is_ValueChanged are not consistent - *
  • FR [ 1720995 ] Add PO.saveEx() and PO.deleteEx() methods - *
  • BF [ 1990856 ] PO.set_Value* : truncate string more than needed - */ -public abstract class PO - implements Serializable, Comparator, Evaluatee -{ - /** - * Set Document Value Workflow Manager - * @param docWFMgr mgr - */ - public static void setDocWorkflowMgr (DocWorkflowMgr docWFMgr) - { - s_docWFMgr = docWFMgr; - s_log.config (s_docWFMgr.toString()); - } // setDocWorkflowMgr - - /** Document Value Workflow Manager */ - private static DocWorkflowMgr s_docWFMgr = null; - - /** User Maintained Entity Type */ - static protected final String ENTITYTYPE_UserMaintained = "U"; - /** Dictionary Maintained Entity Type */ - static protected final String ENTITYTYPE_Dictionary = "D"; - - /************************************************************************** - * Create New Persisent Object - * @param ctx context - */ - public PO (Properties ctx) - { - this (ctx, 0, null, null); - } // PO - - /** - * Create & Load existing Persistent Object - * @param ID The unique ID of the object - * @param ctx context - * @param trxName transaction name - */ - public PO (Properties ctx, int ID, String trxName) - { - this (ctx, ID, trxName, null); - } // PO - - /** - * Create & Load existing Persistent Object. - * @param ctx context - * @param rs optional - load from current result set position (no navigation, not closed) - * if null, a new record is created. - * @param trxName transaction name - */ - public PO (Properties ctx, ResultSet rs, String trxName) - { - this (ctx, 0, trxName, rs); - } // PO - - /** - * Create & Load existing Persistent Object. - *
    -	 *  You load
    -	 * 		- an existing single key record with 	new PO (ctx, Record_ID)
    -	 * 			or									new PO (ctx, Record_ID, trxName)
    -	 * 			or									new PO (ctx, rs, get_TrxName())
    -	 * 		- a new single key record with			new PO (ctx, 0)
    -	 * 		- an existing multi key record with		new PO (ctx, rs, get_TrxName())
    -	 * 		- a new multi key record with			new PO (ctx, null)
    -	 *  The ID for new single key records is created automatically,
    -	 *  you need to set the IDs for multi-key records explicitly.
    -	 *	
    - * @param ctx context - * @param ID the ID if 0, the record defaults are applied - ignored if re exists - * @param trxName transaction name - * @param rs optional - load from current result set position (no navigation, not closed) - */ - public PO (Properties ctx, int ID, String trxName, ResultSet rs) - { - if (ctx == null) - throw new IllegalArgumentException ("No Context"); - p_ctx = ctx; - m_trxName = trxName; - - p_info = initPO(ctx); - if (p_info == null || p_info.getTableName() == null) - throw new IllegalArgumentException ("Invalid PO Info - " + p_info); - // - int size = p_info.getColumnCount(); - m_oldValues = new Object[size]; - m_newValues = new Object[size]; - - if (rs != null) - load(rs); // will not have virtual columns - else - load(ID, trxName); - } // PO - - /** - * Create New PO by Copying existing (key not copied). - * @param ctx context - * @param source souce object - * @param AD_Client_ID client - * @param AD_Org_ID org - */ - public PO (Properties ctx, PO source, int AD_Client_ID, int AD_Org_ID) - { - this (ctx, 0, null, null); // create new - // - if (source != null) - copyValues (source, this); - setAD_Client_ID(AD_Client_ID); - setAD_Org_ID(AD_Org_ID); - } // PO - - - /** Logger */ - protected transient CLogger log = CLogger.getCLogger (getClass()); - /** Static Logger */ - private static CLogger s_log = CLogger.getCLogger (PO.class); - - /** Context */ - protected Properties p_ctx; - /** Model Info */ - protected volatile POInfo p_info = null; - - /** Original Values */ - private Object[] m_oldValues = null; - /** New Valies */ - private Object[] m_newValues = null; - - /** Record_IDs */ - private Object[] m_IDs = new Object[] {I_ZERO}; - /** Key Columns */ - private String[] m_KeyColumns = null; - /** Create New for Multi Key */ - private boolean m_createNew = false; - /** Attachment with entriess */ - private MAttachment m_attachment = null; - /** Deleted ID */ - private int m_idOld = 0; - /** Custom Columns */ - private HashMap m_custom = null; - - /** Zero Integer */ - protected static final Integer I_ZERO = new Integer(0); - /** Accounting Columns */ - private ArrayList s_acctColumns = null; - - /** TODO - Trifon */ - private boolean m_isReplication = false; - - /** Access Level S__ 100 4 System info */ - public static final int ACCESSLEVEL_SYSTEM = 4; - /** Access Level _C_ 010 2 Client info */ - public static final int ACCESSLEVEL_CLIENT = 2; - /** Access Level __O 001 1 Organization info */ - public static final int ACCESSLEVEL_ORG = 1; - /** Access Level SCO 111 7 System shared info */ - public static final int ACCESSLEVEL_ALL = 7; - /** Access Level SC_ 110 6 System/Client info */ - public static final int ACCESSLEVEL_SYSTEMCLIENT = 6; - /** Access Level _CO 011 3 Client shared info */ - public static final int ACCESSLEVEL_CLIENTORG = 3; - - - /** - * Initialize and return PO_Info - * @param ctx context - * @return POInfo - */ - abstract protected POInfo initPO (Properties ctx); - - /** - * Get Table Access Level - * @return Access Level - */ - abstract protected int get_AccessLevel(); - - /** - * String representation - * @return String representation - */ - public String toString() - { - StringBuffer sb = new StringBuffer("PO[") - .append(get_WhereClause(true)).append("]"); - return sb.toString(); - } // toString - - /** - * Equals based on ID - * @param cmp comperator - * @return true if ID the same - */ - public boolean equals (Object cmp) - { - if (cmp == null) - return false; - if (!(cmp instanceof PO)) - return false; - if (cmp.getClass().equals(this.getClass())) - // if both ID's are zero they can't be compared by ID - if (((PO)cmp).get_ID() == 0 && get_ID() == 0) - return super.equals(cmp); - else - return ((PO)cmp).get_ID() == get_ID(); - return super.equals(cmp); - } // equals - - /** - * Compare based on DocumentNo, Value, Name, Description - * @param o1 Object 1 - * @param o2 Object 2 - * @return -1 if o1 < o2 - */ - public int compare (Object o1, Object o2) - { - if (o1 == null) - return -1; - else if (o2 == null) - return 1; - if (!(o1 instanceof PO)) - throw new ClassCastException ("Not PO -1- " + o1); - if (!(o2 instanceof PO)) - throw new ClassCastException ("Not PO -2- " + o2); - // same class - if (o1.getClass().equals(o2.getClass())) - { - int index = get_ColumnIndex("DocumentNo"); - if (index == -1) - index = get_ColumnIndex("Value"); - if (index == -1) - index = get_ColumnIndex("Name"); - if (index == -1) - index = get_ColumnIndex("Description"); - if (index != -1) - { - PO po1 = (PO)o1; - Object comp1 = po1.get_Value(index); - PO po2 = (PO)o2; - Object comp2 = po2.get_Value(index); - if (comp1 == null) - return -1; - else if (comp2 == null) - return 1; - return comp1.toString().compareTo(comp2.toString()); - } - } - return o1.toString().compareTo(o2.toString()); - } // compare - - /** - * Get TableName. - * @return table name - */ - public String get_TableName() - { - return p_info.getTableName(); - } // get_TableName - - /** - * Get Key Columns. - * @return table name - */ - public String[] get_KeyColumns() - { - return m_KeyColumns; - } // get_KeyColumns - - /** - * Get Table ID. - * @return table id - */ - public int get_Table_ID() - { - return p_info.getAD_Table_ID(); - } // get_TableID - - /** - * Return Single Key Record ID - * @return ID or 0 - */ - public int get_ID() - { - Object oo = m_IDs[0]; - if (oo != null && oo instanceof Integer) - return ((Integer)oo).intValue(); - return 0; - } // getID - - /** - * Return Deleted Single Key Record ID - * @return ID or 0 - */ - public int get_IDOld() - { - return m_idOld; - } // getID - - /** - * Get Context - * @return context - */ - public Properties getCtx() - { - return p_ctx; - } // getCtx - - /** - * Get Logger - * @return logger - */ - public CLogger get_Logger() - { - return log; - } // getLogger - - /************************************************************************** - * Get Value - * @param index index - * @return value - */ - public final Object get_Value (int index) - { - if (index < 0 || index >= get_ColumnCount()) - { - log.log(Level.WARNING, "Index invalid - " + index); - return null; - } - if (m_newValues[index] != null) - { - if (m_newValues[index].equals(Null.NULL)) - return null; - return m_newValues[index]; - } - return m_oldValues[index]; - } // get_Value - - /** - * Get Value as int - * @param index index - * @return int value or 0 - */ - protected int get_ValueAsInt (int index) - { - Object value = get_Value(index); - if (value == null) - return 0; - if (value instanceof Integer) - return ((Integer)value).intValue(); - try - { - return Integer.parseInt(value.toString()); - } - catch (NumberFormatException ex) - { - log.warning(p_info.getColumnName(index) + " - " + ex.getMessage()); - return 0; - } - } // get_ValueAsInt - - /** - * Get Value - * @param columnName column name - * @return value or null - */ - public final Object get_Value (String columnName) - { - int index = get_ColumnIndex(columnName); - if (index < 0) - { - log.log(Level.WARNING, "Column not found - " + columnName); - Trace.printStack(); - return null; - } - return get_Value (index); - } // get_Value - - /** - * Get Encrypted Value - * @param columnName column name - * @return value or null - */ - protected final Object get_ValueE (String columnName) - { - return get_Value (columnName); - } // get_ValueE - - /** - * Get Column Value - * @param variableName name - * @return value or "" - */ - public String get_ValueAsString (String variableName) - { - Object value = get_Value (variableName); - if (value == null) - return ""; - return value.toString(); - } // get_ValueAsString - - /** - * Get Value of Column - * @param AD_Column_ID column - * @return value or null - */ - public final Object get_ValueOfColumn (int AD_Column_ID) - { - int index = p_info.getColumnIndex(AD_Column_ID); - if (index < 0) - { - log.log(Level.WARNING, "Not found - AD_Column_ID=" + AD_Column_ID); - return null; - } - return get_Value (index); - } // get_ValueOfColumn - - /** - * Get Old Value - * @param index index - * @return value - */ - public final Object get_ValueOld (int index) - { - if (index < 0 || index >= get_ColumnCount()) - { - log.log(Level.WARNING, "Index invalid - " + index); - return null; - } - return m_oldValues[index]; - } // get_ValueOld - - /** - * Get Old Value - * @param columnName column name - * @return value or null - */ - public final Object get_ValueOld (String columnName) - { - int index = get_ColumnIndex(columnName); - if (index < 0) - { - log.log(Level.WARNING, "Column not found - " + columnName); - return null; - } - return get_ValueOld (index); - } // get_ValueOld - - /** - * Get Old Value as int - * @param columnName column name - * @return int value or 0 - */ - protected int get_ValueOldAsInt (String columnName) - { - Object value = get_ValueOld(columnName); - if (value == null) - return 0; - if (value instanceof Integer) - return ((Integer)value).intValue(); - try - { - return Integer.parseInt(value.toString()); - } - catch (NumberFormatException ex) - { - log.warning(columnName + " - " + ex.getMessage()); - return 0; - } - } // get_ValueOldAsInt - - /** - * Is Value Changed - * @param index index - * @return true if changed - */ - public final boolean is_ValueChanged (int index) - { - if (index < 0 || index >= get_ColumnCount()) - { - log.log(Level.WARNING, "Index invalid - " + index); - return false; - } - if (m_newValues[index] == null) - return false; - return !m_newValues[index].equals(m_oldValues[index]); - } // is_ValueChanged - - /** - * Is Value Changed - * @param columnName column name - * @return true if changed - */ - public final boolean is_ValueChanged (String columnName) - { - int index = get_ColumnIndex(columnName); - if (index < 0) - { - log.log(Level.WARNING, "Column not found - " + columnName); - return false; - } - return is_ValueChanged (index); - } // is_ValueChanged - - /** - * Return new - old. - * - New Value if Old Valus is null - * - New Value - Old Value if Number - * - otherwise null - * @param index index - * @return new - old or null if not appropiate or not changed - */ - public final Object get_ValueDifference (int index) - { - if (index < 0 || index >= get_ColumnCount()) - { - log.log(Level.WARNING, "Index invalid - " + index); - return null; - } - Object nValue = m_newValues[index]; - // No new Value or NULL - if (nValue == null || nValue == Null.NULL) - return null; - // - Object oValue = m_oldValues[index]; - if (oValue == null || oValue == Null.NULL) - return nValue; - if (nValue instanceof BigDecimal) - { - BigDecimal obd = (BigDecimal)oValue; - return ((BigDecimal)nValue).subtract(obd); - } - else if (nValue instanceof Integer) - { - int result = ((Integer)nValue).intValue(); - result -= ((Integer)oValue).intValue(); - return new Integer(result); - } - // - log.warning("Invalid type - New=" + nValue); - return null; - } // get_ValueDifference - - /** - * Return new - old. - * - New Value if Old Valus is null - * - New Value - Old Value if Number - * - otherwise null - * @param columnName column name - * @return new - old or null if not appropiate or not changed - */ - public final Object get_ValueDifference (String columnName) - { - int index = get_ColumnIndex(columnName); - if (index < 0) - { - log.log(Level.WARNING, "Column not found - " + columnName); - return null; - } - return get_ValueDifference (index); - } // get_ValueDifference - - - /************************************************************************** - * Set Value - * @param ColumnName column name - * @param value value - * @return true if value set - */ - protected final boolean set_Value (String ColumnName, Object value) - { - if (value instanceof String && ColumnName.equals("WhereClause") - && value.toString().toUpperCase().indexOf("=NULL") != -1) - log.warning("Invalid Null Value - " + ColumnName + "=" + value); - - int index = get_ColumnIndex(ColumnName); - if (index < 0) - { - log.log(Level.SEVERE, "Column not found - " + ColumnName); - return false; - } - if (ColumnName.endsWith("_ID") && value instanceof String ) - { - log.severe("Invalid Data Type for " + ColumnName + "=" + value); - value = Integer.parseInt((String)value); - } - - return set_Value (index, value); - } // setValue - - /** - * Set Encrypted Value - * @param ColumnName column name - * @param value value - * @return true if value set - */ - protected final boolean set_ValueE (String ColumnName, Object value) - { - return set_Value (ColumnName, value); - } // setValueE - - /** - * Set Value if updateable and correct class. - * (and to NULL if not mandatory) - * @param index index - * @param value value - * @return true if value set - */ - protected final boolean set_Value (int index, Object value) - { - if (index < 0 || index >= get_ColumnCount()) - { - log.log(Level.WARNING, "Index invalid - " + index); - return false; - } - String ColumnName = p_info.getColumnName(index); - String colInfo = " - " + ColumnName; - // - if (p_info.isVirtualColumn(index)) - { - log.log(Level.WARNING, "Virtual Column" + colInfo); - return false; - } - // - // globalqss -- Bug 1618469 - is throwing not updateable even on new records - // if (!p_info.isColumnUpdateable(index)) - if ( ( ! p_info.isColumnUpdateable(index) ) && ( ! is_new() ) ) - { - colInfo += " - NewValue=" + value + " - OldValue=" + get_Value(index); - log.log(Level.WARNING, "Column not updateable" + colInfo); - return false; - } - // - if (value == null) - { - if (p_info.isColumnMandatory(index)) - { - log.log(Level.WARNING, "Cannot set mandatory column to null " + colInfo); - // Trace.printStack(); - return false; - } - m_newValues[index] = Null.NULL; // correct - log.finer(ColumnName + " = null"); - } - else - { - // matching class or generic object - if (value.getClass().equals(p_info.getColumnClass(index)) - || p_info.getColumnClass(index) == Object.class) - m_newValues[index] = value; // correct - // Integer can be set as BigDecimal - else if (value.getClass() == BigDecimal.class - && p_info.getColumnClass(index) == Integer.class) - m_newValues[index] = new Integer (((BigDecimal)value).intValue()); - // Set Boolean - else if (p_info.getColumnClass(index) == Boolean.class - && ("Y".equals(value) || "N".equals(value)) ) - m_newValues[index] = new Boolean("Y".equals(value)); - // added by vpj-cd - // To solve BUG [ 1618423 ] Set Project Type button in Project window throws warning - // generated because C_Project.C_Project_Type_ID is defined as button in dictionary - // although is ID (integer) in database - else if (value.getClass() == Integer.class - && p_info.getColumnClass(index) == String.class) - m_newValues[index] = value; - else if (value.getClass() == String.class - && p_info.getColumnClass(index) == Integer.class) - try - { - m_newValues[index] = new Integer((String)value); - } - catch (NumberFormatException e) - { - log.log(Level.SEVERE, ColumnName - + " - Class invalid: " + value.getClass().toString() - + ", Should be " + p_info.getColumnClass(index).toString() + ": " + value); - return false; - } - else - { - log.log(Level.SEVERE, ColumnName - + " - Class invalid: " + value.getClass().toString() - + ", Should be " + p_info.getColumnClass(index).toString() + ": " + value); - return false; - } - // Validate (Min/Max) - String error = p_info.validate(index, value); - if (error != null) - { - log.log(Level.WARNING, ColumnName + "=" + value + " - " + error); - return false; - } - // Length for String - if (p_info.getColumnClass(index) == String.class) - { - String stringValue = value.toString(); - int length = p_info.getFieldLength(index); - if (stringValue.length() > length && length > 0) - { - log.warning(ColumnName + " - Value too long - truncated to length=" + length); - m_newValues[index] = stringValue.substring(0,length); - } - } - if (CLogMgt.isLevelFinest()) - log.finest(ColumnName + " = " + m_newValues[index] + " (OldValue="+m_oldValues[index]+")"); - } - set_Keys (ColumnName, m_newValues[index]); - return true; - } // setValue - - /** - * Set Value w/o check (update, r/o, ..). - * Used when Column is R/O - * Required for key and parent values - * @param ColumnName column name - * @param value value - * @return true if value set - */ - protected final boolean set_ValueNoCheck (String ColumnName, Object value) - { - int index = get_ColumnIndex(ColumnName); - if (index < 0) - { - log.log(Level.SEVERE, "Column not found - " + ColumnName); - return false; - } - if (value == null) - m_newValues[index] = Null.NULL; // write direct - else - { - // matching class or generic object - if (value.getClass().equals(p_info.getColumnClass(index)) - || p_info.getColumnClass(index) == Object.class) - m_newValues[index] = value; // correct - // Integer can be set as BigDecimal - else if (value.getClass() == BigDecimal.class - && p_info.getColumnClass(index) == Integer.class) - m_newValues[index] = new Integer (((BigDecimal)value).intValue()); - // Set Boolean - else if (p_info.getColumnClass(index) == Boolean.class - && ("Y".equals(value) || "N".equals(value)) ) - m_newValues[index] = new Boolean("Y".equals(value)); - else if (p_info.getColumnClass(index) == Integer.class - && value.getClass() == String.class) - { - try - { - int intValue = Integer.parseInt((String)value); - m_newValues[index] = Integer.valueOf(intValue); - } - catch (Exception e) - { - log.warning (ColumnName - + " - Class invalid: " + value.getClass().toString() - + ", Should be " + p_info.getColumnClass(index).toString() + ": " + value); - m_newValues[index] = null; - } - } - else - { - log.warning (ColumnName - + " - Class invalid: " + value.getClass().toString() - + ", Should be " + p_info.getColumnClass(index).toString() + ": " + value); - m_newValues[index] = value; // correct - } - // Validate (Min/Max) - String error = p_info.validate(index, value); - if (error != null) - log.warning(ColumnName + "=" + value + " - " + error); - // length for String - if (p_info.getColumnClass(index) == String.class) - { - String stringValue = value.toString(); - int length = p_info.getFieldLength(index); - if (stringValue.length() > length && length > 0) - { - log.warning(ColumnName + " - Value too long - truncated to length=" + length); - m_newValues[index] = stringValue.substring(0,length); - } - } - } - log.finest(ColumnName + " = " + m_newValues[index] - + " (" + (m_newValues[index]==null ? "-" : m_newValues[index].getClass().getName()) + ")"); - set_Keys (ColumnName, m_newValues[index]); - return true; - } // set_ValueNoCheck - - /** - * Set Encrypted Value w/o check (update, r/o, ..). - * Used when Column is R/O - * Required for key and parent values - * @param ColumnName column name - * @param value value - * @return true if value set - */ - protected final boolean set_ValueNoCheckE (String ColumnName, Object value) - { - return set_ValueNoCheckE (ColumnName, value); - } // set_ValueNoCheckE - - /** - * Set value of Column - * @param columnName - * @param value - */ - public final void set_ValueOfColumn(String columnName, Object value) - { - int AD_Column_ID = p_info.getAD_Column_ID(columnName); - if (AD_Column_ID > 0) - { - set_ValueOfColumn(AD_Column_ID, value); - } - } - - /** - * Set Value of Column - * @param AD_Column_ID column - * @param value value - */ - public final void set_ValueOfColumn (int AD_Column_ID, Object value) - { - int index = p_info.getColumnIndex(AD_Column_ID); - if (index < 0) - log.log(Level.SEVERE, "Not found - AD_Column_ID=" + AD_Column_ID); - String ColumnName = p_info.getColumnName(index); - if (ColumnName.equals("IsApproved")) - set_ValueNoCheck(ColumnName, value); - else - set_Value (index, value); - } // setValueOfColumn - - - /** - * Set Custom Column - * @param columnName column - * @param value value - */ - public final void set_CustomColumn (String columnName, Object value) - { - // [ 1845793 ] PO.set_CustomColumn not updating correctly m_newValues - // this is for columns not in PO - verify and call proper method if exists - int poIndex = get_ColumnIndex(columnName); - if (poIndex > 0) { - // is not custom column - it exists in the PO - set_Value(columnName, value); - return; - } - if (m_custom == null) - m_custom = new HashMap(); - String valueString = "NULL"; - if (value == null) - ; - else if (value instanceof Number) - valueString = value.toString(); - else if (value instanceof Boolean) - valueString = ((Boolean)value).booleanValue() ? "'Y'" : "'N'"; - else if (value instanceof Timestamp) - valueString = DB.TO_DATE((Timestamp)value, false); - else // if (value instanceof String) - valueString = DB.TO_STRING(value.toString()); - // Save it - log.log(Level.INFO, columnName + "=" + valueString); - m_custom.put(columnName, valueString); - } // set_CustomColumn - - - /** - * Set (numeric) Key Value - * @param ColumnName column name - * @param value value - */ - private void set_Keys (String ColumnName, Object value) - { - // Update if KeyColumn - for (int i = 0; i < m_IDs.length; i++) - { - if (ColumnName.equals (m_KeyColumns[i])) - { - m_IDs[i] = value; - } - } // for all key columns - } // setKeys - - - /************************************************************************** - * Get Column Count - * @return column count - */ - protected int get_ColumnCount() - { - return p_info.getColumnCount(); - } // getColumnCount - - /** - * Get Column Name - * @param index index - * @return ColumnName - */ - protected String get_ColumnName (int index) - { - return p_info.getColumnName (index); - } // getColumnName - - /** - * Get Column Label - * @param index index - * @return Column Label - */ - protected String get_ColumnLabel (int index) - { - return p_info.getColumnLabel (index); - } // getColumnLabel - - /** - * Get Column Description - * @param index index - * @return column description - */ - protected String get_ColumnDescription (int index) - { - return p_info.getColumnDescription (index); - } // getColumnDescription - - /** - * Is Column Mandatory - * @param index index - * @return true if column mandatory - */ - protected boolean isColumnMandatory (int index) - { - return p_info.isColumnMandatory(index); - } // isColumnNandatory - - /** - * Is Column Updateable - * @param index index - * @return true if column updateable - */ - protected boolean isColumnUpdateable (int index) - { - return p_info.isColumnUpdateable(index); - } // isColumnUpdateable - - /** - * Set Column Updateable - * @param index index - * @param updateable column updateable - */ - protected void set_ColumnUpdateable (int index, boolean updateable) - { - p_info.setColumnUpdateable(index, updateable); - } // setColumnUpdateable - - /** - * Set all columns updateable - * @param updateable updateable - */ - protected void setUpdateable (boolean updateable) - { - p_info.setUpdateable (updateable); - } // setUpdateable - - /** - * Get Column DisplayType - * @param index index - * @return display type - */ - protected int get_ColumnDisplayType (int index) - { - return p_info.getColumnDisplayType(index); - } // getColumnDisplayType - - /** - * Get Lookup - * @param index index - * @return Lookup or null - */ - protected Lookup get_ColumnLookup(int index) - { - return p_info.getColumnLookup(index); - } // getColumnLookup - - /** - * Get Column Index - * @param columnName column name - * @return index of column with ColumnName or -1 if not found - */ - public final int get_ColumnIndex (String columnName) - { - return p_info.getColumnIndex(columnName); - } // getColumnIndex - - /** - * Get Display Value of value - * @param columnName columnName - * @param currentValue current value - * @return String value with "./." as null - */ - protected String get_DisplayValue(String columnName, boolean currentValue) - { - Object value = currentValue ? get_Value(columnName) : get_ValueOld(columnName); - if (value == null) - return "./."; - String retValue = value.toString(); - int index = get_ColumnIndex(columnName); - if (index < 0) - return retValue; - int dt = get_ColumnDisplayType(index); - if (DisplayType.isText(dt) || DisplayType.YesNo == dt) - return retValue; - // Lookup - Lookup lookup = get_ColumnLookup(index); - if (lookup != null) - return lookup.getDisplay(value); - // Other - return retValue; - } // get_DisplayValue - - - /** - * Copy old values of From to new values of To. - * Does not copy Keys - * @param from old, existing & unchanged PO - * @param to new, not saved PO - * @param AD_Client_ID client - * @param AD_Org_ID org - */ - protected static void copyValues (PO from, PO to, int AD_Client_ID, int AD_Org_ID) - { - copyValues (from, to); - to.setAD_Client_ID(AD_Client_ID); - to.setAD_Org_ID(AD_Org_ID); - } // copyValues - - /** - * Copy old values of From to new values of To. - * Does not copy Keys and AD_Client_ID/AD_Org_ID - * @param from old, existing & unchanged PO - * @param to new, not saved PO - */ - public static void copyValues (PO from, PO to) - { - s_log.fine("From ID=" + from.get_ID() + " - To ID=" + to.get_ID()); - // Different Classes - if (from.getClass() != to.getClass()) - { - for (int i1 = 0; i1 < from.m_oldValues.length; i1++) - { - if (from.p_info.isVirtualColumn(i1) - || from.p_info.isKey(i1)) // KeyColumn - continue; - String colName = from.p_info.getColumnName(i1); - // Ignore Standard Values - if (colName.startsWith("Created") - || colName.startsWith("Updated") - || colName.equals("IsActive") - || colName.equals("AD_Client_ID") - || colName.equals("AD_Org_ID") - || colName.equals("Processing") - ) - ; // ignore - else - { - for (int i2 = 0; i2 < to.m_oldValues.length; i2++) - { - if (to.p_info.getColumnName(i2).equals(colName)) - { - to.m_newValues[i2] = from.m_oldValues[i1]; - break; - } - } - } - } // from loop - } - else // same class - { - for (int i = 0; i < from.m_oldValues.length; i++) - { - if (from.p_info.isVirtualColumn(i) - || from.p_info.isKey(i)) // KeyColumn - continue; - String colName = from.p_info.getColumnName(i); - // Ignore Standard Values - if (colName.startsWith("Created") - || colName.startsWith("Updated") - || colName.equals("IsActive") - || colName.equals("AD_Client_ID") - || colName.equals("AD_Org_ID") - || colName.equals("Processing") - ) - ; // ignore - else - to.m_newValues[i] = from.m_oldValues[i]; - } - } // same class - } // copy - - - /************************************************************************** - * Load record with ID - * @param ID ID - * @param trxName transaction name - */ - protected void load (int ID, String trxName) - { - log.finest("ID=" + ID); - if (ID > 0) - { - m_IDs = new Object[] {new Integer(ID)}; - m_KeyColumns = new String[] {p_info.getTableName() + "_ID"}; - load(trxName); - } - else // new - { - loadDefaults(); - m_createNew = true; - setKeyInfo(); // sets m_IDs - loadComplete(true); - } - } // load - - - /** - * (re)Load record with m_ID[*] - * @param trxName transaction - * @return true if loaded - */ - public boolean load (String trxName) - { - m_trxName = trxName; - boolean success = true; - StringBuffer sql = new StringBuffer("SELECT "); - int size = get_ColumnCount(); - for (int i = 0; i < size; i++) - { - if (i != 0) - sql.append(","); - sql.append(p_info.getColumnSQL(i)); // Normal and Virtual Column - } - sql.append(" FROM ").append(p_info.getTableName()) - .append(" WHERE ") - .append(get_WhereClause(false)); - - // - // int index = -1; - if (CLogMgt.isLevelFinest()) - log.finest(get_WhereClause(true)); - PreparedStatement pstmt = null; - ResultSet rs = null; - try - { - pstmt = DB.prepareStatement(sql.toString(), m_trxName); // local trx only - for (int i = 0; i < m_IDs.length; i++) - { - Object oo = m_IDs[i]; - if (oo instanceof Integer) - pstmt.setInt(i+1, ((Integer)m_IDs[i]).intValue()); - else - pstmt.setString(i+1, m_IDs[i].toString()); - } - rs = pstmt.executeQuery(); - if (rs.next()) - { - success = load(rs); - } - else - { - log.log(Level.SEVERE, "NO Data found for " + get_WhereClause(true), new Exception()); - m_IDs = new Object[] {I_ZERO}; - success = false; - // throw new DBException("NO Data found for " + get_WhereClause(true)); - } - m_createNew = false; - // reset new values - m_newValues = new Object[size]; - } - catch (Exception e) - { - String msg = ""; - if (m_trxName != null) - msg = "[" + m_trxName + "] - "; - msg += get_WhereClause(true) - // + ", Index=" + index - // + ", Column=" + get_ColumnName(index) - // + ", " + p_info.toString(index) - + ", SQL=" + sql.toString(); - success = false; - m_IDs = new Object[] {I_ZERO}; - log.log(Level.SEVERE, msg, e); - // throw new DBException(e); - } - // Finish - finally { - DB.close(rs, pstmt); - rs = null; pstmt = null; - } - loadComplete(success); - return success; - } // load - - - /** - * Load from the current position of a ResultSet - * @param rs result set - * @return true if loaded - */ - protected boolean load (ResultSet rs) - { - int size = get_ColumnCount(); - boolean success = true; - int index = 0; - log.finest("(rs)"); - // load column values - for (index = 0; index < size; index++) - { - String columnName = p_info.getColumnName(index); - Class clazz = p_info.getColumnClass(index); - int dt = p_info.getColumnDisplayType(index); - try - { - if (clazz == Integer.class) - m_oldValues[index] = decrypt(index, new Integer(rs.getInt(columnName))); - else if (clazz == BigDecimal.class) - m_oldValues[index] = decrypt(index, rs.getBigDecimal(columnName)); - else if (clazz == Boolean.class) - m_oldValues[index] = new Boolean ("Y".equals(decrypt(index, rs.getString(columnName)))); - else if (clazz == Timestamp.class) - m_oldValues[index] = decrypt(index, rs.getTimestamp(columnName)); - else if (DisplayType.isLOB(dt)) - m_oldValues[index] = get_LOB (rs.getObject(columnName)); - else if (clazz == String.class) - m_oldValues[index] = decrypt(index, rs.getString(columnName)); - else - m_oldValues[index] = loadSpecial(rs, index); - // NULL - if (rs.wasNull() && m_oldValues[index] != null) - m_oldValues[index] = null; - // - if (CLogMgt.isLevelAll()) - log.finest(String.valueOf(index) + ": " + p_info.getColumnName(index) - + "(" + p_info.getColumnClass(index) + ") = " + m_oldValues[index]); - } - catch (SQLException e) - { - if (p_info.isVirtualColumn(index)) // if rs constructor used - log.log(Level.FINER, "Virtual Column not loaded: " + columnName); - else - { - log.log(Level.SEVERE, "(rs) - " + String.valueOf(index) - + ": " + p_info.getTableName() + "." + p_info.getColumnName(index) - + " (" + p_info.getColumnClass(index) + ") - " + e); - success = false; - } - } - } - m_createNew = false; - setKeyInfo(); - loadComplete(success); - return success; - } // load - - /** - * Load from HashMap - * @param hmIn hash map - * @return true if loaded - */ - protected boolean load (HashMap hmIn) - { - int size = get_ColumnCount(); - boolean success = true; - int index = 0; - log.finest("(hm)"); - // load column values - for (index = 0; index < size; index++) - { - String columnName = p_info.getColumnName(index); - String value = (String)hmIn.get(columnName); - if (value == null) - continue; - Class clazz = p_info.getColumnClass(index); - int dt = p_info.getColumnDisplayType(index); - try - { - if (clazz == Integer.class) - m_oldValues[index] = new Integer(value); - else if (clazz == BigDecimal.class) - m_oldValues[index] = new BigDecimal(value); - else if (clazz == Boolean.class) - m_oldValues[index] = new Boolean ("Y".equals(value)); - else if (clazz == Timestamp.class) - m_oldValues[index] = Timestamp.valueOf(value); - else if (DisplayType.isLOB(dt)) - m_oldValues[index] = null; // get_LOB (rs.getObject(columnName)); - else if (clazz == String.class) - m_oldValues[index] = value; - else - m_oldValues[index] = null; // loadSpecial(rs, index); - // - if (CLogMgt.isLevelAll()) - log.finest(String.valueOf(index) + ": " + p_info.getColumnName(index) - + "(" + p_info.getColumnClass(index) + ") = " + m_oldValues[index]); - } - catch (Exception e) - { - if (p_info.isVirtualColumn(index)) // if rs constructor used - log.log(Level.FINER, "Virtual Column not loaded: " + columnName); - else - { - log.log(Level.SEVERE, "(ht) - " + String.valueOf(index) - + ": " + p_info.getTableName() + "." + p_info.getColumnName(index) - + " (" + p_info.getColumnClass(index) + ") - " + e); - success = false; - } - } - } - m_createNew = false; - // Overwrite - setStandardDefaults(); - setKeyInfo(); - loadComplete(success); - return success; - } // load - - /** - * Create Hashmap with data as Strings - * @return HashMap - */ - protected HashMap get_HashMap() - { - HashMap hmOut = new HashMap(); - int size = get_ColumnCount(); - for (int i = 0; i < size; i++) - { - Object value = get_Value(i); - // Don't insert NULL values (allows Database defaults) - if (value == null - || p_info.isVirtualColumn(i)) - continue; - // Display Type - int dt = p_info.getColumnDisplayType(i); - // Based on class of definition, not class of value - Class c = p_info.getColumnClass(i); - String stringValue = null; - if (c == Object.class) - ; // saveNewSpecial (value, i)); - else if (value == null || value.equals (Null.NULL)) - ; - else if (value instanceof Integer || value instanceof BigDecimal) - stringValue = value.toString(); - else if (c == Boolean.class) - { - boolean bValue = false; - if (value instanceof Boolean) - bValue = ((Boolean)value).booleanValue(); - else - bValue = "Y".equals(value); - stringValue = bValue ? "Y" : "N"; - } - else if (value instanceof Timestamp) - stringValue = value.toString(); - else if (c == String.class) - stringValue = (String)value; - else if (DisplayType.isLOB(dt)) - ; - else - ; // saveNewSpecial (value, i)); - // - if (stringValue != null) - hmOut.put(p_info.getColumnName(i), stringValue); - } - // Custom Columns - if (m_custom != null) - { - Iterator it = m_custom.keySet().iterator(); - while (it.hasNext()) - { - String column = (String)it.next(); -// int index = p_info.getColumnIndex(column); - String value = (String)m_custom.get(column); - if (value != null) - hmOut.put(column, value); - } - m_custom = null; - } - return hmOut; - } // get_HashMap - - /** - * Load Special data (images, ..). - * To be extended by sub-classes - * @param rs result set - * @param index zero based index - * @return value value - * @throws SQLException - */ - protected Object loadSpecial (ResultSet rs, int index) throws SQLException - { - log.finest("(NOP) - " + p_info.getColumnName(index)); - return null; - } // loadSpecial - - /** - * Load is complete - * @param success success - * To be extended by sub-classes - */ - protected void loadComplete (boolean success) - { - } // loadComplete - - - /** - * Load Defaults - */ - protected void loadDefaults() - { - setStandardDefaults(); - // - /** @todo defaults from Field */ - // MField.getDefault(p_info.getDefaultLogic(i)); - } // loadDefaults - - /** - * Set Default values. - * Client, Org, Created/Updated, *By, IsActive - */ - protected void setStandardDefaults() - { - int size = get_ColumnCount(); - for (int i = 0; i < size; i++) - { - if (p_info.isVirtualColumn(i)) - continue; - String colName = p_info.getColumnName(i); - // Set Standard Values - if (colName.endsWith("tedBy")) - m_newValues[i] = new Integer (Env.getContextAsInt(p_ctx, "#AD_User_ID")); - else if (colName.equals("Created") || colName.equals("Updated")) - m_newValues[i] = new Timestamp (System.currentTimeMillis()); - else if (colName.equals(p_info.getTableName() + "_ID")) // KeyColumn - m_newValues[i] = I_ZERO; - else if (colName.equals("IsActive")) - m_newValues[i] = new Boolean(true); - else if (colName.equals("AD_Client_ID")) - m_newValues[i] = new Integer(Env.getAD_Client_ID(p_ctx)); - else if (colName.equals("AD_Org_ID")) - m_newValues[i] = new Integer(Env.getAD_Org_ID(p_ctx)); - else if (colName.equals("Processed")) - m_newValues[i] = new Boolean(false); - else if (colName.equals("Processing")) - m_newValues[i] = new Boolean(false); - else if (colName.equals("Posted")) - m_newValues[i] = new Boolean(false); - } - } // setDefaults - - /** - * Set Key Info (IDs and KeyColumns). - */ - private void setKeyInfo() - { - // Search for Primary Key - for (int i = 0; i < p_info.getColumnCount(); i++) - { - if (p_info.isKey(i)) - { - String ColumnName = p_info.getColumnName(i); - m_KeyColumns = new String[] {ColumnName}; - if (p_info.getColumnName(i).endsWith("_ID")) - { - Integer ii = (Integer)get_Value(i); - if (ii == null) - m_IDs = new Object[] {I_ZERO}; - else - m_IDs = new Object[] {ii}; - log.finest("(PK) " + ColumnName + "=" + ii); - } - else - { - Object oo = get_Value(i); - if (oo == null) - m_IDs = new Object[] {null}; - else - m_IDs = new Object[] {oo}; - log.finest("(PK) " + ColumnName + "=" + oo); - } - return; - } - } // primary key search - - // Search for Parents - ArrayList columnNames = new ArrayList(); - for (int i = 0; i < p_info.getColumnCount(); i++) - { - if (p_info.isColumnParent(i)) - columnNames.add(p_info.getColumnName(i)); - } - // Set FKs - int size = columnNames.size(); - if (size == 0) - throw new IllegalStateException("No PK nor FK - " + p_info.getTableName()); - m_IDs = new Object[size]; - m_KeyColumns = new String[size]; - for (int i = 0; i < size; i++) - { - m_KeyColumns[i] = (String)columnNames.get(i); - if (m_KeyColumns[i].endsWith("_ID")) - { - Integer ii = null; - try - { - ii = (Integer)get_Value(m_KeyColumns[i]); - } - catch (Exception e) - { - log.log(Level.SEVERE, "", e); - } - if (ii != null) - m_IDs[i] = ii; - } - else - m_IDs[i] = get_Value(m_KeyColumns[i]); - log.finest("(FK) " + m_KeyColumns[i] + "=" + m_IDs[i]); - } - } // setKeyInfo - - - /************************************************************************** - * Are all mandatory Fields filled (i.e. can we save)?. - * Stops at first null mandatory field - * @return true if all mandatory fields are ok - */ - protected boolean isMandatoryOK() - { - int size = get_ColumnCount(); - for (int i = 0; i < size; i++) - { - if (p_info.isColumnMandatory(i)) - { - if (p_info.isVirtualColumn(i)) - continue; - if (get_Value(i) == null || get_Value(i).equals(Null.NULL)) - { - log.info(p_info.getColumnName(i)); - return false; - } - } - } - return true; - } // isMandatoryOK - - - /************************************************************************** - * Set AD_Client - * @param AD_Client_ID client - */ - final protected void setAD_Client_ID (int AD_Client_ID) - { - set_ValueNoCheck ("AD_Client_ID", new Integer(AD_Client_ID)); - } // setAD_Client_ID - - /** - * Get AD_Client - * @return AD_Client_ID - */ - public final int getAD_Client_ID() - { - Integer ii = (Integer)get_Value("AD_Client_ID"); - if (ii == null) - return 0; - return ii.intValue(); - } // getAD_Client_ID - - /** - * Set AD_Org - * @param AD_Org_ID org - */ - final public void setAD_Org_ID (int AD_Org_ID) - { - set_ValueNoCheck ("AD_Org_ID", new Integer(AD_Org_ID)); - } // setAD_Org_ID - - /** - * Get AD_Org - * @return AD_Org_ID - */ - public int getAD_Org_ID() - { - Integer ii = (Integer)get_Value("AD_Org_ID"); - if (ii == null) - return 0; - return ii.intValue(); - } // getAD_Org_ID - - /** - * Overwrite Client Org if different - * @param AD_Client_ID client - * @param AD_Org_ID org - */ - protected void setClientOrg (int AD_Client_ID, int AD_Org_ID) - { - if (AD_Client_ID != getAD_Client_ID()) - setAD_Client_ID(AD_Client_ID); - if (AD_Org_ID != getAD_Org_ID()) - setAD_Org_ID(AD_Org_ID); - } // setClientOrg - - /** - * Overwrite Client Org if different - * @param po persistent object - */ - protected void setClientOrg (PO po) - { - setClientOrg(po.getAD_Client_ID(), po.getAD_Org_ID()); - } // setClientOrg - - /** - * Set Active - * @param active active - */ - public final void setIsActive (boolean active) - { - set_Value("IsActive", new Boolean(active)); - } // setActive - - /** - * Is Active - * @return is active - */ - public final boolean isActive() - { - Boolean bb = (Boolean)get_Value("IsActive"); - if (bb != null) - return bb.booleanValue(); - return false; - } // isActive - - /** - * Get Created - * @return created - */ - final public Timestamp getCreated() - { - return (Timestamp)get_Value("Created"); - } // getCreated - - /** - * Get Updated - * @return updated - */ - final public Timestamp getUpdated() - { - return (Timestamp)get_Value("Updated"); - } // getUpdated - - /** - * Get CreatedBy - * @return AD_User_ID - */ - final public int getCreatedBy() - { - Integer ii = (Integer)get_Value("CreatedBy"); - if (ii == null) - return 0; - return ii.intValue(); - } // getCreateddBy - - /** - * Get UpdatedBy - * @return AD_User_ID - */ - final public int getUpdatedBy() - { - Integer ii = (Integer)get_Value("UpdatedBy"); - if (ii == null) - return 0; - return ii.intValue(); - } // getUpdatedBy - - /** - * Set UpdatedBy - * @param AD_User_ID user - */ - final protected void setUpdatedBy (int AD_User_ID) - { - set_ValueNoCheck ("UpdatedBy", new Integer(AD_User_ID)); - } // setAD_User_ID - - /** - * Get Translation of column - * @param columnName - * @param AD_Language - * @return translation or null if not found - */ - protected String get_Translation (String columnName, String AD_Language) - { - if (columnName == null || AD_Language == null - || m_IDs.length > 1 || m_IDs[0].equals(I_ZERO) - || !(m_IDs[0] instanceof Integer)) - { - log.severe ("Invalid Argument: ColumnName" + columnName - + ", AD_Language=" + AD_Language - + ", ID.length=" + m_IDs.length + ", ID=" + m_IDs[0]); - return null; - } - int ID = ((Integer)m_IDs[0]).intValue(); - String retValue = null; - StringBuffer sql = new StringBuffer ("SELECT ").append(columnName) - .append(" FROM ").append(p_info.getTableName()).append("_Trl WHERE ") - .append(m_KeyColumns[0]).append("=?") - .append(" AND AD_Language=?"); - PreparedStatement pstmt = null; - ResultSet rs = null; - try - { - pstmt = DB.prepareStatement (sql.toString(), get_TrxName()); - pstmt.setInt (1, ID); - pstmt.setString (2, AD_Language); - rs = pstmt.executeQuery (); - if (rs.next ()) - retValue = rs.getString(1); - } - catch (Exception e) - { - log.log(Level.SEVERE, sql.toString(), e); - } - finally { - DB.close(rs, pstmt); - rs = null; pstmt = null; - } - return retValue; - } // get_Translation - - /** - * Is new record - * @return true if new - */ - public boolean is_new() - { - if (m_createNew) - return true; - // - for (int i = 0; i < m_IDs.length; i++) - { - if (m_IDs[i].equals(I_ZERO)) - continue; - return false; // one value is non-zero - } - return true; - } // is_new - - /* - * Classes which override save() method: - * org.compiere.process.DocActionTemplate - * org.compiere.model.MClient - * org.compiere.model.MClientInfo - * org.compiere.model.MSystem - */ - /************************************************************************** - * Update Value or create new record. - * To reload call load() - not updated - * @return true if saved - */ - public boolean save() - { - CLogger.resetLast(); - boolean newRecord = is_new(); // save locally as load resets - if (!newRecord && !is_Changed()) - { - log.fine("Nothing changed - " + p_info.getTableName()); - return true; - } - - // Organization Check - if (getAD_Org_ID() == 0 - && (get_AccessLevel() == ACCESSLEVEL_ORG - || (get_AccessLevel() == ACCESSLEVEL_CLIENTORG - && MClientShare.isOrgLevelOnly(getAD_Client_ID(), get_Table_ID())))) - { - log.saveError("FillMandatory", Msg.getElement(getCtx(), "AD_Org_ID")); - return false; - } - // Should be Org 0 - if (getAD_Org_ID() != 0) - { - boolean reset = get_AccessLevel() == ACCESSLEVEL_SYSTEM; - if (!reset && MClientShare.isClientLevelOnly(getAD_Client_ID(), get_Table_ID())) - { - reset = get_AccessLevel() == ACCESSLEVEL_CLIENT - || get_AccessLevel() == ACCESSLEVEL_SYSTEMCLIENT - || get_AccessLevel() == ACCESSLEVEL_CLIENTORG; - } - if (reset) - { - log.warning("Set Org to 0"); - setAD_Org_ID(0); - } - } - - Trx localTrx = null; - if (m_trxName == null) { - m_trxName = Trx.createTrxName("POSave"); - localTrx = Trx.get(m_trxName, true); - } - - // Before Save - try - { - if (!beforeSave(newRecord)) - { - log.warning("beforeSave failed - " + toString()); - if (localTrx != null) { - localTrx.rollback(); - localTrx.close(); - m_trxName = null; - } - return false; - } - } - catch (Exception e) - { - log.log(Level.WARNING, "beforeSave - " + toString(), e); - log.saveError("Error", e.toString(), false); - if (localTrx != null) { - localTrx.rollback(); - localTrx.close(); - m_trxName = null; - } - return false; - } - - try { - // Call ModelValidators TYPE_NEW/TYPE_CHANGE - String errorMsg = ModelValidationEngine.get().fireModelChange - (this, newRecord ? ModelValidator.TYPE_NEW : ModelValidator.TYPE_CHANGE); - if (errorMsg != null) - { - log.warning("Validation failed - " + errorMsg); - log.saveError("Error", errorMsg); - if (localTrx != null) { - localTrx.rollback(); - m_trxName = null; - } - return false; - } - // Save - if (newRecord) - { - boolean b = saveNew(); - if (b) - { - if (localTrx != null) - return localTrx.commit(); - else - return b; - } - else - { - if (localTrx != null) - localTrx.rollback(); - return b; - } - } - else - { - boolean b = saveUpdate(); - if (b) - { - if (localTrx != null) - return localTrx.commit(); - else - return b; - } - else - { - if (localTrx != null) - localTrx.rollback(); - return b; - } - } - } finally { - if (localTrx != null) - { - localTrx.close(); - m_trxName = null; - } - } - } // save - - /** - * Update Value or create new record. - * @throws AdempiereException - * @see #save() - */ - public void saveEx() throws AdempiereException - { - if (!save()) { - String msg = null; - ValueNamePair err = CLogger.retrieveError(); - if (err != null) - msg = err.getName(); - if (msg == null || msg.length() == 0) - msg = "SaveError"; - throw new AdempiereException(msg); - } - } - - /** - * Finish Save Process - * @param newRecord new - * @param success success - * @return true if saved - */ - private boolean saveFinish (boolean newRecord, boolean success) - { - // Translations - if (success) - { - if (newRecord) - insertTranslations(); - else - updateTranslations(); - } - // - try - { - success = afterSave (newRecord, success); - } - catch (Exception e) - { - log.log(Level.WARNING, "afterSave", e); - log.saveError("Error", e.toString(), false); - success = false; - // throw new DBException(e); - } - // Call ModelValidators TYPE_AFTER_NEW/TYPE_AFTER_CHANGE - teo_sarca [ 1675490 ] - if (success) { - String errorMsg = ModelValidationEngine.get().fireModelChange - (this, newRecord ? - (isReplication() ? ModelValidator.TYPE_AFTER_NEW_REPLICATION : ModelValidator.TYPE_AFTER_NEW) - : - (isReplication() ? ModelValidator.TYPE_AFTER_CHANGE_REPLICATION : ModelValidator.TYPE_AFTER_CHANGE) - ); - setReplication(false); - if (errorMsg != null) { - log.saveError("Error", errorMsg); - success = false; - } - } - // OK - if (success) - { - if (s_docWFMgr == null) - { - try - { - Class.forName("org.compiere.wf.DocWorkflowManager"); - } - catch (Exception e) - { - } - } - if (s_docWFMgr != null) - s_docWFMgr.process (this, p_info.getAD_Table_ID()); - - // Copy to Old values - int size = p_info.getColumnCount(); - for (int i = 0; i < size; i++) - { - if (m_newValues[i] != null) - { - if (m_newValues[i] == Null.NULL) - m_oldValues[i] = null; - else - m_oldValues[i] = m_newValues[i]; - } - } - m_newValues = new Object[size]; - } - m_createNew = false; - if (!newRecord) - CacheMgt.get().reset(p_info.getTableName()); - return success; - } // saveFinish - - /** - * Update Value or create new record. - * To reload call load() - not updated - * @param trxName transaction - * @return true if saved - */ - public boolean save (String trxName) - { - set_TrxName(trxName); - return save(); - } // save - - public boolean saveReplica (boolean isFromReplication) - { - setReplication(isFromReplication); - return save(); - } - - /** - * Update Value or create new record. - * @param trxName transaction - * @throws AdempiereException - * @see #saveEx(String) - */ - public void saveEx(String trxName) throws AdempiereException - { - set_TrxName(trxName); - saveEx(); - } - - /** - * Is there a Change to be saved? - * @return true if record changed - */ - public boolean is_Changed() - { - int size = get_ColumnCount(); - for (int i = 0; i < size; i++) - { - // Test if the column has changed - teo_sarca [ 1704828 ] - if (is_ValueChanged(i)) - return true; - } - if (m_custom != null && m_custom.size() > 0) - return true; // there are custom columns modified - return false; - } // is_Change - - /** - * Called before Save for Pre-Save Operation - * @param newRecord new record - * @return true if record can be saved - */ - protected boolean beforeSave(boolean newRecord) - { - /** Prevents saving - log.saveError("Error", Msg.parseTranslation(getCtx(), "@C_Currency_ID@ = @C_Currency_ID@")); - log.saveError("FillMandatory", Msg.getElement(getCtx(), "PriceEntered")); - /** Issues message - log.saveWarning(AD_Message, message); - log.saveInfo (AD_Message, message); - **/ - return true; - } // beforeSave - - /** - * Called after Save for Post-Save Operation - * @param newRecord new record - * @param success true if save operation was success - * @return if save was a success - */ - protected boolean afterSave (boolean newRecord, boolean success) - { - return success; - } // afterSave - - /** - * Update Record directly - * @return true if updated - */ - protected boolean saveUpdate() - { - String where = get_WhereClause(true); - // - boolean changes = false; - StringBuffer sql = new StringBuffer ("UPDATE "); - sql.append(p_info.getTableName()).append( " SET "); - boolean updated = false; - boolean updatedBy = false; - lobReset(); - - // Change Log - MSession session = MSession.get (p_ctx, false); - if (session == null) - log.fine("No Session found"); - int AD_ChangeLog_ID = 0; - - int size = get_ColumnCount(); - for (int i = 0; i < size; i++) - { - Object value = m_newValues[i]; - if (value == null - || p_info.isVirtualColumn(i)) - continue; - // we have a change - Class c = p_info.getColumnClass(i); - int dt = p_info.getColumnDisplayType(i); - String columnName = p_info.getColumnName(i); - // - // updated/by - if (columnName.equals("UpdatedBy")) - { - if (updatedBy) // explicit - continue; - updatedBy = true; - } - else if (columnName.equals("Updated")) - { - if (updated) - continue; - updated = true; - } - if (DisplayType.isLOB(dt)) - { - lobAdd (value, i, dt); - // If no changes set UpdatedBy explicitly to ensure commit of lob - if (!changes && !updatedBy) - { - int AD_User_ID = Env.getContextAsInt(p_ctx, "#AD_User_ID"); - set_ValueNoCheck("UpdatedBy", new Integer(AD_User_ID)); - sql.append("UpdatedBy=").append(AD_User_ID); - changes = true; - updatedBy = true; - } - continue; - } - // Update Document No - if (columnName.equals("DocumentNo")) - { - String strValue = (String)value; - if (strValue.startsWith("<") && strValue.endsWith(">")) - { - value = null; - int AD_Client_ID = getAD_Client_ID(); - int index = p_info.getColumnIndex("C_DocTypeTarget_ID"); - if (index == -1) - index = p_info.getColumnIndex("C_DocType_ID"); - if (index != -1) // get based on Doc Type (might return null) - value = DB.getDocumentNo(get_ValueAsInt(index), m_trxName, false, this); - if (value == null) // not overwritten by DocType and not manually entered - value = DB.getDocumentNo(AD_Client_ID, p_info.getTableName(), m_trxName, this); - } - else - log.warning("DocumentNo updated: " + m_oldValues[i] + " -> " + value); - } - - if (changes) - sql.append(", "); - changes = true; - sql.append(columnName).append("="); - - // values - if (value == Null.NULL) - sql.append("NULL"); - else if (value instanceof Integer || value instanceof BigDecimal) - sql.append(encrypt(i,value)); - else if (c == Boolean.class) - { - boolean bValue = false; - if (value instanceof Boolean) - bValue = ((Boolean)value).booleanValue(); - else - bValue = "Y".equals(value); - sql.append(encrypt(i,bValue ? "'Y'" : "'N'")); - } - else if (value instanceof Timestamp) - sql.append(DB.TO_DATE((Timestamp)encrypt(i,value),p_info.getColumnDisplayType(i) == DisplayType.Date)); - else { - if (value.toString().length() == 0) { - // [ 1722057 ] Encrypted columns throw error if saved as null - // don't encrypt NULL - sql.append(DB.TO_STRING(value.toString())); - } else { - sql.append(encrypt(i,DB.TO_STRING(value.toString()))); - } - } - - // Change Log - Only - if (session != null - && m_IDs.length == 1 - && !p_info.isEncrypted(i) // not encrypted - && !p_info.isVirtualColumn(i) // no virtual column - && !"Password".equals(columnName) - ) - { - Object oldV = m_oldValues[i]; - Object newV = value; - if (oldV != null && oldV == Null.NULL) - oldV = null; - if (newV != null && newV == Null.NULL) - newV = null; - // change log on update - MChangeLog cLog = session.changeLog ( - m_trxName, AD_ChangeLog_ID, - p_info.getAD_Table_ID(), p_info.getColumn(i).AD_Column_ID, - get_ID(), getAD_Client_ID(), getAD_Org_ID(), oldV, newV, MChangeLog.EVENTCHANGELOG_Update); - if (cLog != null) - AD_ChangeLog_ID = cLog.getAD_ChangeLog_ID(); - } - } // for all fields - - // Custom Columns (cannot be logged as no column) - if (m_custom != null) - { - Iterator it = m_custom.keySet().iterator(); - while (it.hasNext()) - { - if (changes) - sql.append(", "); - changes = true; - // - String column = (String)it.next(); - String value = (String)m_custom.get(column); - int index = p_info.getColumnIndex(column); - sql.append(column).append("=").append(encrypt(index,value)); - } - m_custom = null; - } - - // Something changed - if (changes) - { - if (m_trxName == null) - log.fine(p_info.getTableName() + "." + where); - else - log.fine("[" + m_trxName + "] - " + p_info.getTableName() + "." + where); - if (!updated) // Updated not explicitly set - { - Timestamp now = new Timestamp(System.currentTimeMillis()); - set_ValueNoCheck("Updated", now); - sql.append(",Updated=").append(DB.TO_DATE(now, false)); - } - if (!updatedBy) // UpdatedBy not explicitly set - { - int AD_User_ID = Env.getContextAsInt(p_ctx, "#AD_User_ID"); - set_ValueNoCheck("UpdatedBy", new Integer(AD_User_ID)); - sql.append(",UpdatedBy=").append(AD_User_ID); - } - sql.append(" WHERE ").append(where); - /** @todo status locking goes here */ - - log.finest(sql.toString()); - int no = DB.executeUpdate(sql.toString(), m_trxName); - boolean ok = no == 1; - if (ok) - ok = lobSave(); - else - { - if (m_trxName == null) - log.log(Level.WARNING, "#" + no - + " - " + p_info.getTableName() + "." + where); - else - log.log(Level.WARNING, "#" + no - + " - [" + m_trxName + "] - " + p_info.getTableName() + "." + where); - } - return saveFinish (false, ok); - } - - // nothing changed, so OK - return saveFinish (false, true); - } // saveUpdate - - /** - * Create New Record - * @return true if new record inserted - */ - private boolean saveNew() - { - // Set ID for single key - Multi-Key values need explicitly be set previously - if (m_IDs.length == 1 && p_info.hasKeyColumn() - && m_KeyColumns[0].endsWith("_ID")) // AD_Language, EntityType - { - int no = saveNew_getID(); - if (no <= 0) - no = DB.getNextID(getAD_Client_ID(), p_info.getTableName(), m_trxName); - if (no <= 0) - { - log.severe("No NextID (" + no + ")"); - return saveFinish (true, false); - } - m_IDs[0] = new Integer(no); - set_ValueNoCheck(m_KeyColumns[0], m_IDs[0]); - } - if (m_trxName == null) - log.fine(p_info.getTableName() + " - " + get_WhereClause(true)); - else - log.fine("[" + m_trxName + "] - " + p_info.getTableName() + " - " + get_WhereClause(true)); - - // Set new DocumentNo - String columnName = "DocumentNo"; - int index = p_info.getColumnIndex(columnName); - if (index != -1) - { - String value = (String)get_Value(index); - if (value != null && value.startsWith("<") && value.endsWith(">")) - value = null; - if (value == null || value.length() == 0) - { - int dt = p_info.getColumnIndex("C_DocTypeTarget_ID"); - if (dt == -1) - dt = p_info.getColumnIndex("C_DocType_ID"); - if (dt != -1) // get based on Doc Type (might return null) - value = DB.getDocumentNo(get_ValueAsInt(dt), m_trxName, false, this); - if (value == null) // not overwritten by DocType and not manually entered - value = DB.getDocumentNo(getAD_Client_ID(), p_info.getTableName(), m_trxName, this); - set_ValueNoCheck(columnName, value); - } - } - // Set empty Value - columnName = "Value"; - index = p_info.getColumnIndex(columnName); - if (index != -1) - { - String value = (String)get_Value(index); - if (value == null || value.length() == 0) - { - value = DB.getDocumentNo (getAD_Client_ID(), p_info.getTableName(), m_trxName, this); - set_ValueNoCheck(columnName, value); - } - } - - lobReset(); - - // Change Log - MSession session = MSession.get (p_ctx, false); - if (session == null) - log.fine("No Session found"); - int AD_ChangeLog_ID = 0; - - // SQL - StringBuffer sqlInsert = new StringBuffer("INSERT INTO "); - sqlInsert.append(p_info.getTableName()).append(" ("); - StringBuffer sqlValues = new StringBuffer(") VALUES ("); - int size = get_ColumnCount(); - boolean doComma = false; - for (int i = 0; i < size; i++) - { - Object value = get_Value(i); - // Don't insert NULL values (allows Database defaults) - if (value == null - || p_info.isVirtualColumn(i)) - continue; - - // Display Type - int dt = p_info.getColumnDisplayType(i); - if (DisplayType.isLOB(dt)) - { - lobAdd (value, i, dt); - continue; - } - - // ** add column ** - if (doComma) - { - sqlInsert.append(","); - sqlValues.append(","); - } - else - doComma = true; - sqlInsert.append(p_info.getColumnName(i)); - // - // Based on class of definition, not class of value - Class c = p_info.getColumnClass(i); - try - { - if (c == Object.class) // may have need to deal with null values differently - sqlValues.append (saveNewSpecial (value, i)); - else if (value == null || value.equals (Null.NULL)) - sqlValues.append ("NULL"); - else if (value instanceof Integer || value instanceof BigDecimal) - sqlValues.append (encrypt(i,value)); - else if (c == Boolean.class) - { - boolean bValue = false; - if (value instanceof Boolean) - bValue = ((Boolean)value).booleanValue(); - else - bValue = "Y".equals(value); - sqlValues.append (encrypt(i,bValue ? "'Y'" : "'N'")); - } - else if (value instanceof Timestamp) - sqlValues.append (DB.TO_DATE ((Timestamp)encrypt(i,value), p_info.getColumnDisplayType (i) == DisplayType.Date)); - else if (c == String.class) - sqlValues.append (encrypt(i,DB.TO_STRING ((String)value))); - else if (DisplayType.isLOB(dt)) - sqlValues.append("null"); // no db dependent stuff here - else - sqlValues.append (saveNewSpecial (value, i)); - } - catch (Exception e) - { - String msg = ""; - if (m_trxName != null) - msg = "[" + m_trxName + "] - "; - msg += p_info.toString(i) - + " - Value=" + value - + "(" + (value==null ? "null" : value.getClass().getName()) + ")"; - log.log(Level.SEVERE, msg, e); - throw new DBException(e); // fini - } - - // Change Log - Only - String insertLog = MSysConfig.getValue("SYSTEM_INSERT_CHANGELOG", "Y", getAD_Client_ID()); - if ( session != null - && m_IDs.length == 1 - && !p_info.isEncrypted(i) // not encrypted - && !p_info.isVirtualColumn(i) // no virtual column - && !"Password".equals(columnName) - && (insertLog.equalsIgnoreCase("Y") - || (insertLog.equalsIgnoreCase("K") && p_info.getColumn(i).IsKey)) - ) - { - // change log on new - MChangeLog cLog = session.changeLog ( - m_trxName, AD_ChangeLog_ID, - p_info.getAD_Table_ID(), p_info.getColumn(i).AD_Column_ID, - get_ID(), getAD_Client_ID(), getAD_Org_ID(), null, value, MChangeLog.EVENTCHANGELOG_Insert); - if (cLog != null) - AD_ChangeLog_ID = cLog.getAD_ChangeLog_ID(); - } - - } - // Custom Columns - if (m_custom != null) - { - Iterator it = m_custom.keySet().iterator(); - while (it.hasNext()) - { - String column = (String)it.next(); - index = p_info.getColumnIndex(column); - String value = (String)m_custom.get(column); - if (doComma) - { - sqlInsert.append(","); - sqlValues.append(","); - } - else - doComma = true; - sqlInsert.append(column); - //jz for ad_issue, some value may include ' in a string??? - sqlValues.append(encrypt(index, value)); - } - m_custom = null; - } - sqlInsert.append(sqlValues) - .append(")"); - // - int no = DB.executeUpdate(sqlInsert.toString(), m_trxName); - boolean ok = no == 1; - if (ok) - { - ok = lobSave(); - if (!load(m_trxName)) // re-read Info - { - if (m_trxName == null) - log.log(Level.SEVERE, "reloading"); - else - log.log(Level.SEVERE, "[" + m_trxName + "] - reloading"); - ok = false;; - } - } - else - { - String msg = "Not inserted - "; - if (CLogMgt.isLevelFiner()) - msg += sqlInsert.toString(); - else - msg += get_TableName(); - if (m_trxName == null) - log.log(Level.WARNING, msg); - else - log.log(Level.WARNING, "[" + m_trxName + "]" + msg); - } - return saveFinish (true, ok); - } // saveNew - - /** - * Get ID for new record during save. - * You can overwite this to explicitly set the ID - * @return ID to be used or 0 for fedault logic - */ - protected int saveNew_getID() - { - return 0; - } // saveNew_getID - - - /** - * Create Single/Multi Key Where Clause - * @param withValues if true uses actual values otherwise ? - * @return where clause - */ - public String get_WhereClause (boolean withValues) - { - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < m_IDs.length; i++) - { - if (i != 0) - sb.append(" AND "); - sb.append(m_KeyColumns[i]).append("="); - if (withValues) - { - if (m_KeyColumns[i].endsWith("_ID")) - sb.append(m_IDs[i]); - else - sb.append("'").append(m_IDs[i]).append("'"); - } - else - sb.append("?"); - } - return sb.toString(); - } // getWhereClause - - - /** - * Save Special Data. - * To be extended by sub-classes - * @param value value - * @param index index - * @return SQL code for INSERT VALUES clause - */ - protected String saveNewSpecial (Object value, int index) - { - String colName = p_info.getColumnName(index); - String colClass = p_info.getColumnClass(index).toString(); - String colValue = value == null ? "null" : value.getClass().toString(); -// int dt = p_info.getColumnDisplayType(index); - - log.log(Level.SEVERE, "Unknown class for column " + colName - + " (" + colClass + ") - Value=" + colValue); - - if (value == null) - return "NULL"; - return value.toString(); - } // saveNewSpecial - - /** - * Encrypt data. - * Not: LOB, special values/Obkects - * @param index index - * @param xx data - * @return xx - */ - private Object encrypt (int index, Object xx) - { - if (xx == null) - return null; - if (index != -1 && p_info.isEncrypted(index)) - return SecureEngine.encrypt(xx); - return xx; - } // encrypt - - /** - * Decrypt data - * @param index index - * @param yy data - * @return yy - */ - private Object decrypt (int index, Object yy) - { - if (yy == null) - return null; - if (index != -1 && p_info.isEncrypted(index)) - return SecureEngine.decrypt(yy); - return yy; - } // decrypt - - /************************************************************************** - * Delete Current Record - * @param force delete also processed records - * @return true if deleted - */ - public boolean delete (boolean force) - { - CLogger.resetLast(); - if (is_new()) - return true; - - int AD_Table_ID = p_info.getAD_Table_ID(); - int Record_ID = get_ID(); - - if (!force) - { - int iProcessed = get_ColumnIndex("Processed"); - if (iProcessed != -1) - { - Boolean processed = (Boolean)get_Value(iProcessed); - if (processed != null && processed.booleanValue()) - { - log.warning("Record processed"); // CannotDeleteTrx - log.saveError("Processed", "Processed", false); - return false; - } - } // processed - } // force - - Trx localTrx = null; - boolean success = false; - try - { - - String localTrxName = m_trxName; - if (localTrxName == null) - { - localTrxName = Trx.createTrxName("POdel"); - localTrx = Trx.get(localTrxName, true); - m_trxName = localTrxName; - } - - try - { - if (!beforeDelete()) - { - log.warning("beforeDelete failed"); - return false; - } - } - catch (Exception e) - { - log.log(Level.WARNING, "beforeDelete", e); - log.saveError("Error", e.toString(), false); - // throw new DBException(e); - return false; - } - // Delete Restrict AD_Table_ID/Record_ID (Requests, ..) - String errorMsg = PO_Record.exists(AD_Table_ID, Record_ID, m_trxName); - if (errorMsg != null) - { - log.saveError("CannotDelete", errorMsg); - return false; - } - // Call ModelValidators TYPE_DELETE - errorMsg = ModelValidationEngine.get().fireModelChange - (this, isReplication() ? ModelValidator.TYPE_BEFORE_DELETE_REPLICATION : ModelValidator.TYPE_DELETE); - setReplication(false); // @Trifon - if (errorMsg != null) - { - log.saveError("Error", errorMsg); - return false; - } - - // - deleteTranslations(localTrxName); - // Delete Cascade AD_Table_ID/Record_ID (Attachments, ..) - PO_Record.deleteCascade(AD_Table_ID, Record_ID, localTrxName); - - // The Delete Statement - StringBuffer sql = new StringBuffer ("DELETE FROM ") //jz why no FROM?? - .append(p_info.getTableName()) - .append(" WHERE ") - .append(get_WhereClause(true)); - int no = DB.executeUpdate(sql.toString(), localTrxName); - success = no == 1; - - // Save ID - m_idOld = get_ID(); - // - if (!success) - { - log.warning("Not deleted"); - if (localTrx != null) - localTrx.rollback(); - } - else - { - if (success) - { - // Change Log - MSession session = MSession.get (p_ctx, false); - if (session == null) - log.fine("No Session found"); - else if (m_IDs.length == 1) - { - int AD_ChangeLog_ID = 0; - int size = get_ColumnCount(); - for (int i = 0; i < size; i++) - { - Object value = m_oldValues[i]; - if (value != null - && !p_info.isEncrypted(i) // not encrypted - && !p_info.isVirtualColumn(i) // no virtual column - && !"Password".equals(p_info.getColumnName(i)) - ) - { - // change log on delete - MChangeLog cLog = session.changeLog ( - m_trxName != null ? m_trxName : localTrxName, AD_ChangeLog_ID, - AD_Table_ID, p_info.getColumn(i).AD_Column_ID, - Record_ID, getAD_Client_ID(), getAD_Org_ID(), value, null, MChangeLog.EVENTCHANGELOG_Delete); - if (cLog != null) - AD_ChangeLog_ID = cLog.getAD_ChangeLog_ID(); - } - } // for all fields - } - - // Housekeeping - m_IDs[0] = I_ZERO; - if (m_trxName == null) - log.fine("complete"); - else - log.fine("[" + m_trxName + "] - complete"); - m_attachment = null; - } - else - { - log.warning("Not deleted"); - } - } - - try - { - success = afterDelete (success); - } - catch (Exception e) - { - log.log(Level.WARNING, "afterDelete", e); - log.saveError("Error", e.toString(), false); - success = false; - // throw new DBException(e); - } - - // Call ModelValidators TYPE_AFTER_DELETE - teo_sarca [ 1675490 ] - if (success) { - errorMsg = ModelValidationEngine.get().fireModelChange(this, ModelValidator.TYPE_AFTER_DELETE); - if (errorMsg != null) { - log.saveError("Error", errorMsg); - success = false; - } - } - - if (!success) - { - if (localTrx != null) - localTrx.rollback(); - } - else - { - if (localTrx != null) - { - try { - localTrx.commit(true); - } catch (SQLException e) { - log.saveError("Error", e); - success = false; - } - } - } - - // Reset - if (success) - { - m_idOld = 0; - int size = p_info.getColumnCount(); - m_oldValues = new Object[size]; - m_newValues = new Object[size]; - CacheMgt.get().reset(p_info.getTableName()); - } - } - finally - { - if (localTrx != null) - { - localTrx.close(); - m_trxName = null; - } - } - // log.info("" + success); - return success; - } // delete - - /** - * Delete Current Record - * @param force delete also processed records - * @throws AdempiereException - * @see #delete(boolean) - */ - public void deleteEx(boolean force) throws AdempiereException - { - if (!delete(force)) { - String msg = null; - ValueNamePair err = CLogger.retrieveError(); - if (err != null) - msg = err.getName(); - if (msg == null || msg.length() == 0) - msg = "DeleteError"; - throw new AdempiereException(msg); - } - } - - /** - * Delete Current Record - * @param force delete also processed records - * @param trxName transaction - * @return true if deleted - */ - public boolean delete (boolean force, String trxName) - { - set_TrxName(trxName); - return delete (force); - } // delete - - /** - * Delete Current Record - * @param force delete also processed records - * @param trxName transaction - * @throws AdempiereException - * @see {@link #deleteEx(boolean)} - */ - public void deleteEx(boolean force, String trxName) throws AdempiereException - { - set_TrxName(trxName); - deleteEx(force); - } - - /** - * Executed before Delete operation. - * @return true if record can be deleted - */ - protected boolean beforeDelete () - { - // log.saveError("Error", Msg.getMsg(getCtx(), "CannotDelete")); - return true; - } // beforeDelete - - /** - * Executed after Delete operation. - * @param success true if record deleted - * @return true if delete is a success - */ - protected boolean afterDelete (boolean success) - { - return success; - } // afterDelete - - - /** - * Insert (missing) Translation Records - * @return false if error (true if no translation or success) - */ - private boolean insertTranslations() - { - // Not a translation table - if (m_IDs.length > 1 - || m_IDs[0].equals(I_ZERO) - || !p_info.isTranslated() - || !(m_IDs[0] instanceof Integer)) - return true; - // - StringBuffer iColumns = new StringBuffer(); - StringBuffer sColumns = new StringBuffer(); - for (int i = 0; i < p_info.getColumnCount(); i++) - { - if (p_info.isColumnTranslated(i)) - { - iColumns.append(p_info.getColumnName(i)) - .append(","); - sColumns.append("t.") - .append(p_info.getColumnName(i)) - .append(","); - } - } - if (iColumns.length() == 0) - return true; - - String tableName = p_info.getTableName(); - String keyColumn = m_KeyColumns[0]; - StringBuffer sql = new StringBuffer ("INSERT INTO ") - .append(tableName).append("_Trl (AD_Language,") - .append(keyColumn).append(", ") - .append(iColumns) - .append(" IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy) ") - .append("SELECT l.AD_Language,t.") - .append(keyColumn).append(", ") - .append(sColumns) - .append(" 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy ") - .append("FROM AD_Language l, ").append(tableName).append(" t ") - .append("WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.") - .append(keyColumn).append("=").append(get_ID()) - /*jz since derby bug, rewrite the sql - .append(" AND NOT EXISTS (SELECT * FROM ").append(tableName) - .append("_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.") - .append(keyColumn).append("=t.").append(keyColumn).append(")"); - */ - .append(" AND EXISTS (SELECT * FROM ").append(tableName) - .append("_Trl tt WHERE tt.AD_Language!=l.AD_Language OR tt.") - .append(keyColumn).append("!=t.").append(keyColumn).append(")"); - int no = DB.executeUpdate(sql.toString(), m_trxName); - log.fine("#" + no); - return no > 0; - } // insertTranslations - - /** - * Update Translations. - * @return false if error (true if no translation or success) - */ - private boolean updateTranslations() - { - // Not a translation table - if (m_IDs.length > 1 - || m_IDs[0].equals(I_ZERO) - || !p_info.isTranslated() - || !(m_IDs[0] instanceof Integer)) - return true; - // - boolean trlColumnChanged = false; - for (int i = 0; i < p_info.getColumnCount(); i++) - { - if (p_info.isColumnTranslated(i) - && is_ValueChanged(p_info.getColumnName(i))) - { - trlColumnChanged = true; - break; - } - } - if (!trlColumnChanged) - return true; - // - MClient client = MClient.get(getCtx()); - // - String tableName = p_info.getTableName(); - String keyColumn = m_KeyColumns[0]; - StringBuffer sql = new StringBuffer ("UPDATE ") - .append(tableName).append("_Trl SET "); - // - if (client.isAutoUpdateTrl(tableName)) - { - for (int i = 0; i < p_info.getColumnCount(); i++) - { - if (p_info.isColumnTranslated(i)) - { - String columnName = p_info.getColumnName(i); - sql.append(columnName).append("="); - Object value = get_Value(columnName); - if (value == null) - sql.append("NULL"); - else if (value instanceof String) - sql.append(DB.TO_STRING((String)value)); - else if (value instanceof Boolean) - sql.append(((Boolean)value).booleanValue() ? "'Y'" : "'N'"); - else if (value instanceof Timestamp) - sql.append(DB.TO_DATE((Timestamp)value)); - else - sql.append(value.toString()); - sql.append(","); - } - } - sql.append("IsTranslated='Y'"); - } - else - sql.append("IsTranslated='N'"); - // - sql.append(" WHERE ") - .append(keyColumn).append("=").append(get_ID()); - int no = DB.executeUpdate(sql.toString(), m_trxName); - log.fine("#" + no); - return no >= 0; - } // updateTranslations - - /** - * Delete Translation Records - * @param trxName transaction - * @return false if error (true if no translation or success) - */ - private boolean deleteTranslations(String trxName) - { - // Not a translation table - if (m_IDs.length > 1 - || m_IDs[0].equals(I_ZERO) - || !p_info.isTranslated() - || !(m_IDs[0] instanceof Integer)) - return true; - // - String tableName = p_info.getTableName(); - String keyColumn = m_KeyColumns[0]; - StringBuffer sql = new StringBuffer ("DELETE FROM ") - .append(tableName).append("_Trl WHERE ") - .append(keyColumn).append("=").append(get_ID()); - int no = DB.executeUpdate(sql.toString(), trxName); - log.fine("#" + no); - return no >= 0; - } // deleteTranslations - - /** - * Insert Accounting Records - * @param acctTable accounting sub table - * @param acctBaseTable acct table to get data from - * @param whereClause optional where clause with alisa "p" for acctBaseTable - * @return true if records inserted - */ - protected boolean insert_Accounting (String acctTable, - String acctBaseTable, String whereClause) - { - if (s_acctColumns == null // cannot cache C_BP_*_Acct as there are 3 - || acctTable.startsWith("C_BP_")) - { - s_acctColumns = new ArrayList(); - String sql = "SELECT c.ColumnName " - + "FROM AD_Column c INNER JOIN AD_Table t ON (c.AD_Table_ID=t.AD_Table_ID) " - + "WHERE t.TableName=? AND c.IsActive='Y' AND c.AD_Reference_ID=25 ORDER BY 1"; - PreparedStatement pstmt = null; - ResultSet rs = null; - try - { - pstmt = DB.prepareStatement (sql, null); - pstmt.setString (1, acctTable); - rs = pstmt.executeQuery (); - while (rs.next ()) - s_acctColumns.add (rs.getString(1)); - } - catch (Exception e) - { - log.log(Level.SEVERE, acctTable, e); - } - finally { - DB.close(rs, pstmt); - rs = null; pstmt = null; - } - if (s_acctColumns.size() == 0) - { - log.severe ("No Columns for " + acctTable); - return false; - } - } - - // Create SQL Statement - INSERT - StringBuffer sb = new StringBuffer("INSERT INTO ") - .append(acctTable) - .append(" (").append(get_TableName()) - .append("_ID, C_AcctSchema_ID, AD_Client_ID,AD_Org_ID,IsActive, Created,CreatedBy,Updated,UpdatedBy "); - for (int i = 0; i < s_acctColumns.size(); i++) - sb.append(",").append(s_acctColumns.get(i)); - // .. SELECT - sb.append(") SELECT ").append(get_ID()) - .append(", p.C_AcctSchema_ID, p.AD_Client_ID,0,'Y', SysDate,") - .append(getUpdatedBy()).append(",SysDate,").append(getUpdatedBy()); - for (int i = 0; i < s_acctColumns.size(); i++) - sb.append(",p.").append(s_acctColumns.get(i)); - // .. FROM - sb.append(" FROM ").append(acctBaseTable) - .append(" p WHERE p.AD_Client_ID=").append(getAD_Client_ID()); - if (whereClause != null && whereClause.length() > 0) - sb.append (" AND ").append(whereClause); - sb.append(" AND NOT EXISTS (SELECT * FROM ").append(acctTable) - .append(" e WHERE e.C_AcctSchema_ID=p.C_AcctSchema_ID AND e.") - .append(get_TableName()).append("_ID=").append(get_ID()).append(")"); - // - int no = DB.executeUpdate(sb.toString(), get_TrxName()); - if (no > 0) - log.fine("#" + no); - else - log.warning("#" + no - + " - Table=" + acctTable + " from " + acctBaseTable); - return no > 0; - } // insert_Accounting - - /** - * Delete Accounting records. - * NOP - done by database constraints - * @param acctTable accounting sub table - * @return true - */ - protected boolean delete_Accounting(String acctTable) - { - return true; - } // delete_Accounting - - - /** - * Insert id data into Tree - * @param treeType MTree TREETYPE_* - * @return true if inserted - */ - protected boolean insert_Tree (String treeType) - { - return insert_Tree (treeType, 0); - } // insert_Tree - - /** - * Insert id data into Tree - * @param treeType MTree TREETYPE_* - * @param C_Element_ID element for accounting element values - * @return true if inserted - */ - protected boolean insert_Tree (String treeType, int C_Element_ID) - { - StringBuffer sb = new StringBuffer ("INSERT INTO ") - .append(MTree_Base.getNodeTableName(treeType)) - .append(" (AD_Client_ID,AD_Org_ID, IsActive,Created,CreatedBy,Updated,UpdatedBy, " - + "AD_Tree_ID, Node_ID, Parent_ID, SeqNo) " - + "SELECT t.AD_Client_ID,0, 'Y', SysDate, 0, SysDate, 0," - + "t.AD_Tree_ID, ").append(get_ID()).append(", 0, 999 " - + "FROM AD_Tree t " - + "WHERE t.AD_Client_ID=").append(getAD_Client_ID()).append(" AND t.IsActive='Y'"); - // Account Element Value handling - if (C_Element_ID != 0) - sb.append(" AND EXISTS (SELECT * FROM C_Element ae WHERE ae.C_Element_ID=") - .append(C_Element_ID).append(" AND t.AD_Tree_ID=ae.AD_Tree_ID)"); - else // std trees - sb.append(" AND t.IsAllNodes='Y' AND t.TreeType='").append(treeType).append("'"); - // Duplicate Check - sb.append(" AND NOT EXISTS (SELECT * FROM " + MTree_Base.getNodeTableName(treeType) + " e " - + "WHERE e.AD_Tree_ID=t.AD_Tree_ID AND Node_ID=").append(get_ID()).append(")"); - int no = DB.executeUpdate(sb.toString(), get_TrxName()); - if (no > 0) - log.fine("#" + no + " - TreeType=" + treeType); - else - log.warning("#" + no + " - TreeType=" + treeType); - return no > 0; - } // insert_Tree - - /** - * Delete ID Tree Nodes - * @param treeType MTree TREETYPE_* - * @return true if deleted - */ - protected boolean delete_Tree (String treeType) - { - int id = get_ID(); - if (id == 0) - id = get_IDOld(); - StringBuffer sb = new StringBuffer ("DELETE FROM ") - .append(MTree_Base.getNodeTableName(treeType)) - .append(" n WHERE Node_ID=").append(id) - .append(" AND EXISTS (SELECT * FROM AD_Tree t " - + "WHERE t.AD_Tree_ID=n.AD_Tree_ID AND t.TreeType='") - .append(treeType).append("')"); - int no = DB.executeUpdate(sb.toString(), get_TrxName()); - if (no > 0) - log.fine("#" + no + " - TreeType=" + treeType); - else - log.warning("#" + no + " - TreeType=" + treeType); - return no > 0; - } // delete_Tree - - /************************************************************************** - * Lock it. - * @return true if locked - */ - public boolean lock() - { - int index = get_ProcessingIndex(); - if (index != -1) - { - m_newValues[index] = Boolean.TRUE; // direct - String sql = "UPDATE " + p_info.getTableName() - + " SET Processing='Y' WHERE (Processing='N' OR Processing IS NULL) AND " - + get_WhereClause(true); - boolean success = DB.executeUpdate(sql, null) == 1; // outside trx - if (success) - log.fine("success"); - else - log.log(Level.WARNING, "failed"); - return success; - } - return false; - } // lock - - /** - * Get the Column Processing index - * @return index or -1 - */ - private int get_ProcessingIndex() - { - return p_info.getColumnIndex("Processing"); - } // getProcessingIndex - - /** - * UnLock it - * @param trxName transaction - * @return true if unlocked (false only if unlock fails) - */ - public boolean unlock (String trxName) - { - // log.warning(trxName); - int index = get_ProcessingIndex(); - if (index != -1) - { - m_newValues[index] = Boolean.FALSE; // direct - String sql = "UPDATE " + p_info.getTableName() - + " SET Processing='N' WHERE " + get_WhereClause(true); - boolean success = DB.executeUpdate(sql, trxName) == 1; - if (success) - log.fine("success" + (trxName == null ? "" : "[" + trxName + "]")); - else - log.log(Level.WARNING, "failed" + (trxName == null ? "" : " [" + trxName + "]")); - return success; - } - return true; - } // unlock - - /** Optional Transaction */ - private String m_trxName = null; - - /** - * Set Trx - * @param trxName transaction - */ - public void set_TrxName (String trxName) - { - m_trxName = trxName; - } // setTrx - - /** - * Get Trx - * @return transaction - */ - public String get_TrxName() - { - return m_trxName; - } // getTrx - - - /************************************************************************** - * Get Attachments. - * An attachment may have multiple entries - * @return Attachment or null - */ - public MAttachment getAttachment () - { - return getAttachment(false); - } // getAttachment - - /** - * Get Attachments - * @param requery requery - * @return Attachment or null - */ - public MAttachment getAttachment (boolean requery) - { - if (m_attachment == null || requery) - m_attachment = MAttachment.get (getCtx(), p_info.getAD_Table_ID(), get_ID()); - return m_attachment; - } // getAttachment - - /** - * Create/return Attachment for PO. - * If not exist, create new - * @return attachment - */ - public MAttachment createAttachment() - { - getAttachment (false); - if (m_attachment == null) - m_attachment = new MAttachment (getCtx(), p_info.getAD_Table_ID(), get_ID(), null); - return m_attachment; - } // createAttachment - - - /** - * Do we have a Attachment of type - * @param extension extension e.g. .pdf - * @return true if there is a attachment of type - */ - public boolean isAttachment (String extension) - { - getAttachment (false); - if (m_attachment == null) - return false; - for (int i = 0; i < m_attachment.getEntryCount(); i++) - { - if (m_attachment.getEntryName(i).endsWith(extension)) - { - log.fine("#" + i + ": " + m_attachment.getEntryName(i)); - return true; - } - } - return false; - } // isAttachment - - /** - * Get Attachment Data of type - * @param extension extension e.g. .pdf - * @return data or null - */ - public byte[] getAttachmentData (String extension) - { - getAttachment(false); - if (m_attachment == null) - return null; - for (int i = 0; i < m_attachment.getEntryCount(); i++) - { - if (m_attachment.getEntryName(i).endsWith(extension)) - { - log.fine("#" + i + ": " + m_attachment.getEntryName(i)); - return m_attachment.getEntryData(i); - } - } - return null; - } // getAttachmentData - - /** - * Do we have a PDF Attachment - * @return true if there is a PDF attachment - */ - public boolean isPdfAttachment() - { - return isAttachment(".pdf"); - } // isPdfAttachment - - /** - * Get PDF Attachment Data - * @return data or null - */ - public byte[] getPdfAttachment() - { - return getAttachmentData(".pdf"); - } // getPDFAttachment - - - /************************************************************************** - * Dump Record - */ - public void dump () - { - if (CLogMgt.isLevelFinest()) - { - log.finer(get_WhereClause (true)); - for (int i = 0; i < get_ColumnCount (); i++) - dump (i); - } - } // dump - - /** - * Dump column - * @param index index - */ - public void dump (int index) - { - StringBuffer sb = new StringBuffer(" ").append(index); - if (index < 0 || index >= get_ColumnCount()) - { - log.finest(sb.append(": invalid").toString()); - return; - } - sb.append(": ").append(get_ColumnName(index)) - .append(" = ").append(m_oldValues[index]) - .append(" (").append(m_newValues[index]).append(")"); - log.finest(sb.toString()); - } // dump - - - /************************************************************************* - * Get All IDs of Table. - * Used for listing all Entities - * - int[] IDs = PO.getAllIDs ("AD_PrintFont", null); - for (int i = 0; i < IDs.length; i++) - { - pf = new MPrintFont(Env.getCtx(), IDs[i]); - System.out.println(IDs[i] + " = " + pf.getFont()); - } - * - * @param TableName table name (key column with _ID) - * @param WhereClause optional where clause - * @return array of IDs or null - * @param trxName transaction - */ - public static int[] getAllIDs (String TableName, String WhereClause, String trxName) - { - ArrayList list = new ArrayList(); - StringBuffer sql = new StringBuffer("SELECT "); - sql.append(TableName).append("_ID FROM ").append(TableName); - if (WhereClause != null && WhereClause.length() > 0) - sql.append(" WHERE ").append(WhereClause); - PreparedStatement pstmt = null; - ResultSet rs = null; - try - { - pstmt = DB.prepareStatement(sql.toString(), trxName); - rs = pstmt.executeQuery(); - while (rs.next()) - list.add(new Integer(rs.getInt(1))); - } - catch (SQLException e) - { - s_log.log(Level.SEVERE, sql.toString(), e); - return null; - } - finally { - DB.close(rs, pstmt); - rs = null; pstmt = null; - } - // Convert to array - int[] retValue = new int[list.size()]; - for (int i = 0; i < retValue.length; i++) - retValue[i] = ((Integer)list.get(i)).intValue(); - return retValue; - } // getAllIDs - - - /** - * Get Find parameter. - * Convert to upper case and add % at the end - * @param query in string - * @return out string - */ - protected static String getFindParameter (String query) - { - if (query == null) - return null; - if (query.length() == 0 || query.equals("%")) - return null; - if (!query.endsWith("%")) - query += "%"; - return query.toUpperCase(); - } // getFindParameter - - - /************************************************************************** - * Load LOB - * @param value LOB - * @return object - */ - private Object get_LOB (Object value) - { - log.fine("Value=" + value); - if (value == null) - return null; - // - Object retValue = null; - - long length = -99; - try - { - //[ 1643996 ] Chat not working in postgres port - if (value instanceof String || - value instanceof byte[]) - retValue = value; - else if (value instanceof Clob) // returns String - { - Clob clob = (Clob)value; - length = clob.length(); - retValue = clob.getSubString(1, (int)length); - } - else if (value instanceof Blob) // returns byte[] - { - Blob blob = (Blob)value; - length = blob.length(); - int index = 1; // correct - if (blob.getClass().getName().equals("oracle.jdbc.rowset.OracleSerialBlob")) - index = 0; // Oracle Bug Invalid Arguments - // at oracle.jdbc.rowset.OracleSerialBlob.getBytes(OracleSerialBlob.java:130) - retValue = blob.getBytes(index, (int)length); - } - else - log.log(Level.SEVERE, "Unknown: " + value); - } - catch (Exception e) - { - log.log(Level.SEVERE, "Length=" + length, e); - } - return retValue; - } // getLOB - - /** LOB Info */ - private ArrayList m_lobInfo = null; - - /** - * Reset LOB info - */ - private void lobReset() - { - m_lobInfo = null; - } // resetLOB - - /** - * Prepare LOB save - * @param value value - * @param index index - * @param displayType display type - */ - private void lobAdd (Object value, int index, int displayType) - { - log.finest("Value=" + value); - PO_LOB lob = new PO_LOB (p_info.getTableName(), get_ColumnName(index), - get_WhereClause(true), displayType, value); - if (m_lobInfo == null) - m_lobInfo = new ArrayList(); - m_lobInfo.add(lob); - } // lobAdd - - /** - * Save LOB - * @return true if saved or ok - */ - private boolean lobSave () - { - if (m_lobInfo == null) - return true; - boolean retValue = true; - for (int i = 0; i < m_lobInfo.size(); i++) - { - PO_LOB lob = (PO_LOB)m_lobInfo.get(i); - if (!lob.save(get_TrxName())) - { - retValue = false; - break; - } - } // for all LOBs - lobReset(); - return retValue; - } // saveLOB - - /** - * Get Object xml representation as string - * @param xml optional string buffer - * @return updated/new string buffer header is only added once - */ - public StringBuffer get_xmlString (StringBuffer xml) - { - if (xml == null) - xml = new StringBuffer(); - else - xml.append(Env.NL); - // - try - { - StringWriter writer = new StringWriter(); - StreamResult result = new StreamResult(writer); - DOMSource source = new DOMSource(get_xmlDocument(xml.length()!=0)); - TransformerFactory tFactory = TransformerFactory.newInstance(); - Transformer transformer = tFactory.newTransformer(); - transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes"); - transformer.transform (source, result); - StringBuffer newXML = writer.getBuffer(); - // - if (xml.length() != 0) - { // // - int tagIndex = newXML.indexOf("?>"); - if (tagIndex != -1) - xml.append(newXML.substring(tagIndex+2)); - else - xml.append(newXML); - } - else - xml.append(newXML); - } - catch (Exception e) - { - log.log(Level.SEVERE, "", e); - } - return xml; - } // get_xmlString - - /** Table ID Attribute */ - protected final static String XML_ATTRIBUTE_AD_Table_ID = "AD_Table_ID"; - /** Record ID Attribute */ - protected final static String XML_ATTRIBUTE_Record_ID = "Record_ID"; - - /** - * Get XML Document representation - * @param noComment do not add comment - * @return XML document - */ - public Document get_xmlDocument(boolean noComment) - { - Document document = null; - try - { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - document = builder.newDocument(); - if (!noComment) - document.appendChild(document.createComment(Adempiere.getSummaryAscii())); - } - catch (Exception e) - { - log.log(Level.SEVERE, "", e); - } - // Root - Element root = document.createElement(get_TableName()); - root.setAttribute(XML_ATTRIBUTE_AD_Table_ID, String.valueOf(get_Table_ID())); - root.setAttribute(XML_ATTRIBUTE_Record_ID, String.valueOf(get_ID())); - document.appendChild(root); - // Columns - int size = get_ColumnCount(); - for (int i = 0; i < size; i++) - { - if (p_info.isVirtualColumn(i)) - continue; - - Element col = document.createElement(p_info.getColumnName(i)); - // - Object value = get_Value(i); - // Display Type - int dt = p_info.getColumnDisplayType(i); - // Based on class of definition, not class of value - Class c = p_info.getColumnClass(i); - if (value == null || value.equals (Null.NULL)) - ; - else if (c == Object.class) - col.appendChild(document.createCDATASection(value.toString())); - else if (value instanceof Integer || value instanceof BigDecimal) - col.appendChild(document.createTextNode(value.toString())); - else if (c == Boolean.class) - { - boolean bValue = false; - if (value instanceof Boolean) - bValue = ((Boolean)value).booleanValue(); - else - bValue = "Y".equals(value); - col.appendChild(document.createTextNode(bValue ? "Y" : "N")); - } - else if (value instanceof Timestamp) - col.appendChild(document.createTextNode(value.toString())); - else if (c == String.class) - col.appendChild(document.createCDATASection((String)value)); - else if (DisplayType.isLOB(dt)) - col.appendChild(document.createCDATASection(value.toString())); - else - col.appendChild(document.createCDATASection(value.toString())); - // - root.appendChild(col); - } - // Custom Columns - if (m_custom != null) - { - Iterator it = m_custom.keySet().iterator(); - while (it.hasNext()) - { - String columnName = (String)it.next(); -// int index = p_info.getColumnIndex(columnName); - String value = (String)m_custom.get(columnName); - // - Element col = document.createElement(columnName); - if (value != null) - col.appendChild(document.createTextNode(value)); - root.appendChild(col); - } - m_custom = null; - } - return document; - } // getDocument - - /* Doc - To be used on ModelValidator to get the corresponding Doc from the PO */ - private Doc m_doc; - - /** - * Set the accounting document associated to the PO - for use in POST ModelValidator - * @param doc Document - */ - public void setDoc(Doc doc) { - m_doc = doc; - } - - public void setReplication(boolean isFromReplication) - { - m_isReplication = isFromReplication; - } - - public boolean isReplication() - { - return m_isReplication; - } - - /** - * Set the accounting document associated to the PO - for use in POST ModelValidator - * @return Doc Document - */ - public Doc getDoc() { - return m_doc; - } - - /** - * PO.setTrxName - set given trxName to an array of POs - * As suggested by teo in [ 1854603 ] - */ - public static void set_TrxName(PO[] lines, String trxName) { - for (PO line : lines) - line.set_TrxName(trxName); - } - -} // PO +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.Serializable; +import java.io.StringWriter; +import java.math.BigDecimal; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Properties; +import java.util.logging.Level; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.adempiere.exceptions.AdempiereException; +import org.adempiere.exceptions.DBException; +import org.compiere.Adempiere; +import org.compiere.acct.Doc; +import org.compiere.util.CLogMgt; +import org.compiere.util.CLogger; +import org.compiere.util.CacheMgt; +import org.compiere.util.DB; +import org.compiere.util.DisplayType; +import org.compiere.util.Env; +import org.compiere.util.Evaluatee; +import org.compiere.util.Msg; +import org.compiere.util.SecureEngine; +import org.compiere.util.Trace; +import org.compiere.util.Trx; +import org.compiere.util.ValueNamePair; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Persistent Object. + * Superclass for actual implementations + * + * @author Jorg Janke + * @version $Id: PO.java,v 1.12 2006/08/09 16:38:47 jjanke Exp $ + * + * @author Teo Sarca, SC ARHIPAC SERVICE SRL + *
  • FR [ 1675490 ] ModelValidator on modelChange after events + *
  • BF [ 1704828 ] PO.is_Changed() and PO.is_ValueChanged are not consistent + *
  • FR [ 1720995 ] Add PO.saveEx() and PO.deleteEx() methods + *
  • BF [ 1990856 ] PO.set_Value* : truncate string more than needed + */ +public abstract class PO + implements Serializable, Comparator, Evaluatee +{ + /** + * + */ + private static final long serialVersionUID = -7147383015345754638L; + + /** + * Set Document Value Workflow Manager + * @param docWFMgr mgr + */ + public static void setDocWorkflowMgr (DocWorkflowMgr docWFMgr) + { + s_docWFMgr = docWFMgr; + s_log.config (s_docWFMgr.toString()); + } // setDocWorkflowMgr + + /** Document Value Workflow Manager */ + private static DocWorkflowMgr s_docWFMgr = null; + + /** User Maintained Entity Type */ + static protected final String ENTITYTYPE_UserMaintained = "U"; + /** Dictionary Maintained Entity Type */ + static protected final String ENTITYTYPE_Dictionary = "D"; + + /************************************************************************** + * Create New Persisent Object + * @param ctx context + */ + public PO (Properties ctx) + { + this (ctx, 0, null, null); + } // PO + + /** + * Create & Load existing Persistent Object + * @param ID The unique ID of the object + * @param ctx context + * @param trxName transaction name + */ + public PO (Properties ctx, int ID, String trxName) + { + this (ctx, ID, trxName, null); + } // PO + + /** + * Create & Load existing Persistent Object. + * @param ctx context + * @param rs optional - load from current result set position (no navigation, not closed) + * if null, a new record is created. + * @param trxName transaction name + */ + public PO (Properties ctx, ResultSet rs, String trxName) + { + this (ctx, 0, trxName, rs); + } // PO + + /** + * Create & Load existing Persistent Object. + *
    +	 *  You load
    +	 * 		- an existing single key record with 	new PO (ctx, Record_ID)
    +	 * 			or									new PO (ctx, Record_ID, trxName)
    +	 * 			or									new PO (ctx, rs, get_TrxName())
    +	 * 		- a new single key record with			new PO (ctx, 0)
    +	 * 		- an existing multi key record with		new PO (ctx, rs, get_TrxName())
    +	 * 		- a new multi key record with			new PO (ctx, null)
    +	 *  The ID for new single key records is created automatically,
    +	 *  you need to set the IDs for multi-key records explicitly.
    +	 *	
    + * @param ctx context + * @param ID the ID if 0, the record defaults are applied - ignored if re exists + * @param trxName transaction name + * @param rs optional - load from current result set position (no navigation, not closed) + */ + public PO (Properties ctx, int ID, String trxName, ResultSet rs) + { + if (ctx == null) + throw new IllegalArgumentException ("No Context"); + p_ctx = ctx; + m_trxName = trxName; + + p_info = initPO(ctx); + if (p_info == null || p_info.getTableName() == null) + throw new IllegalArgumentException ("Invalid PO Info - " + p_info); + // + int size = p_info.getColumnCount(); + m_oldValues = new Object[size]; + m_newValues = new Object[size]; + + if (rs != null) + load(rs); // will not have virtual columns + else + load(ID, trxName); + } // PO + + /** + * Create New PO by Copying existing (key not copied). + * @param ctx context + * @param source souce object + * @param AD_Client_ID client + * @param AD_Org_ID org + */ + public PO (Properties ctx, PO source, int AD_Client_ID, int AD_Org_ID) + { + this (ctx, 0, null, null); // create new + // + if (source != null) + copyValues (source, this); + setAD_Client_ID(AD_Client_ID); + setAD_Org_ID(AD_Org_ID); + } // PO + + + /** Logger */ + protected transient CLogger log = CLogger.getCLogger (getClass()); + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (PO.class); + + /** Context */ + protected Properties p_ctx; + /** Model Info */ + protected volatile POInfo p_info = null; + + /** Original Values */ + private Object[] m_oldValues = null; + /** New Valies */ + private Object[] m_newValues = null; + + /** Record_IDs */ + private Object[] m_IDs = new Object[] {I_ZERO}; + /** Key Columns */ + private String[] m_KeyColumns = null; + /** Create New for Multi Key */ + private boolean m_createNew = false; + /** Attachment with entriess */ + private MAttachment m_attachment = null; + /** Deleted ID */ + private int m_idOld = 0; + /** Custom Columns */ + private HashMap m_custom = null; + + /** Zero Integer */ + protected static final Integer I_ZERO = new Integer(0); + /** Accounting Columns */ + private ArrayList s_acctColumns = null; + + /** TODO - Trifon */ + private boolean m_isReplication = false; + + /** Access Level S__ 100 4 System info */ + public static final int ACCESSLEVEL_SYSTEM = 4; + /** Access Level _C_ 010 2 Client info */ + public static final int ACCESSLEVEL_CLIENT = 2; + /** Access Level __O 001 1 Organization info */ + public static final int ACCESSLEVEL_ORG = 1; + /** Access Level SCO 111 7 System shared info */ + public static final int ACCESSLEVEL_ALL = 7; + /** Access Level SC_ 110 6 System/Client info */ + public static final int ACCESSLEVEL_SYSTEMCLIENT = 6; + /** Access Level _CO 011 3 Client shared info */ + public static final int ACCESSLEVEL_CLIENTORG = 3; + + + /** + * Initialize and return PO_Info + * @param ctx context + * @return POInfo + */ + abstract protected POInfo initPO (Properties ctx); + + /** + * Get Table Access Level + * @return Access Level + */ + abstract protected int get_AccessLevel(); + + /** + * String representation + * @return String representation + */ + public String toString() + { + StringBuffer sb = new StringBuffer("PO[") + .append(get_WhereClause(true)).append("]"); + return sb.toString(); + } // toString + + /** + * Equals based on ID + * @param cmp comperator + * @return true if ID the same + */ + public boolean equals (Object cmp) + { + if (cmp == null) + return false; + if (!(cmp instanceof PO)) + return false; + if (cmp.getClass().equals(this.getClass())) + // if both ID's are zero they can't be compared by ID + if (((PO)cmp).get_ID() == 0 && get_ID() == 0) + return super.equals(cmp); + else + return ((PO)cmp).get_ID() == get_ID(); + return super.equals(cmp); + } // equals + + /** + * Compare based on DocumentNo, Value, Name, Description + * @param o1 Object 1 + * @param o2 Object 2 + * @return -1 if o1 < o2 + */ + public int compare (Object o1, Object o2) + { + if (o1 == null) + return -1; + else if (o2 == null) + return 1; + if (!(o1 instanceof PO)) + throw new ClassCastException ("Not PO -1- " + o1); + if (!(o2 instanceof PO)) + throw new ClassCastException ("Not PO -2- " + o2); + // same class + if (o1.getClass().equals(o2.getClass())) + { + int index = get_ColumnIndex("DocumentNo"); + if (index == -1) + index = get_ColumnIndex("Value"); + if (index == -1) + index = get_ColumnIndex("Name"); + if (index == -1) + index = get_ColumnIndex("Description"); + if (index != -1) + { + PO po1 = (PO)o1; + Object comp1 = po1.get_Value(index); + PO po2 = (PO)o2; + Object comp2 = po2.get_Value(index); + if (comp1 == null) + return -1; + else if (comp2 == null) + return 1; + return comp1.toString().compareTo(comp2.toString()); + } + } + return o1.toString().compareTo(o2.toString()); + } // compare + + /** + * Get TableName. + * @return table name + */ + public String get_TableName() + { + return p_info.getTableName(); + } // get_TableName + + /** + * Get Key Columns. + * @return table name + */ + public String[] get_KeyColumns() + { + return m_KeyColumns; + } // get_KeyColumns + + /** + * Get Table ID. + * @return table id + */ + public int get_Table_ID() + { + return p_info.getAD_Table_ID(); + } // get_TableID + + /** + * Return Single Key Record ID + * @return ID or 0 + */ + public int get_ID() + { + Object oo = m_IDs[0]; + if (oo != null && oo instanceof Integer) + return ((Integer)oo).intValue(); + return 0; + } // getID + + /** + * Return Deleted Single Key Record ID + * @return ID or 0 + */ + public int get_IDOld() + { + return m_idOld; + } // getID + + /** + * Get Context + * @return context + */ + public Properties getCtx() + { + return p_ctx; + } // getCtx + + /** + * Get Logger + * @return logger + */ + public CLogger get_Logger() + { + return log; + } // getLogger + + /************************************************************************** + * Get Value + * @param index index + * @return value + */ + public final Object get_Value (int index) + { + if (index < 0 || index >= get_ColumnCount()) + { + log.log(Level.WARNING, "Index invalid - " + index); + return null; + } + if (m_newValues[index] != null) + { + if (m_newValues[index].equals(Null.NULL)) + return null; + return m_newValues[index]; + } + return m_oldValues[index]; + } // get_Value + + /** + * Get Value as int + * @param index index + * @return int value or 0 + */ + protected int get_ValueAsInt (int index) + { + Object value = get_Value(index); + if (value == null) + return 0; + if (value instanceof Integer) + return ((Integer)value).intValue(); + try + { + return Integer.parseInt(value.toString()); + } + catch (NumberFormatException ex) + { + log.warning(p_info.getColumnName(index) + " - " + ex.getMessage()); + return 0; + } + } // get_ValueAsInt + + /** + * Get Value + * @param columnName column name + * @return value or null + */ + public final Object get_Value (String columnName) + { + int index = get_ColumnIndex(columnName); + if (index < 0) + { + log.log(Level.WARNING, "Column not found - " + columnName); + Trace.printStack(); + return null; + } + return get_Value (index); + } // get_Value + + /** + * Get Encrypted Value + * @param columnName column name + * @return value or null + */ + protected final Object get_ValueE (String columnName) + { + return get_Value (columnName); + } // get_ValueE + + /** + * Get Column Value + * @param variableName name + * @return value or "" + */ + public String get_ValueAsString (String variableName) + { + Object value = get_Value (variableName); + if (value == null) + return ""; + return value.toString(); + } // get_ValueAsString + + /** + * Get Value of Column + * @param AD_Column_ID column + * @return value or null + */ + public final Object get_ValueOfColumn (int AD_Column_ID) + { + int index = p_info.getColumnIndex(AD_Column_ID); + if (index < 0) + { + log.log(Level.WARNING, "Not found - AD_Column_ID=" + AD_Column_ID); + return null; + } + return get_Value (index); + } // get_ValueOfColumn + + /** + * Get Old Value + * @param index index + * @return value + */ + public final Object get_ValueOld (int index) + { + if (index < 0 || index >= get_ColumnCount()) + { + log.log(Level.WARNING, "Index invalid - " + index); + return null; + } + return m_oldValues[index]; + } // get_ValueOld + + /** + * Get Old Value + * @param columnName column name + * @return value or null + */ + public final Object get_ValueOld (String columnName) + { + int index = get_ColumnIndex(columnName); + if (index < 0) + { + log.log(Level.WARNING, "Column not found - " + columnName); + return null; + } + return get_ValueOld (index); + } // get_ValueOld + + /** + * Get Old Value as int + * @param columnName column name + * @return int value or 0 + */ + protected int get_ValueOldAsInt (String columnName) + { + Object value = get_ValueOld(columnName); + if (value == null) + return 0; + if (value instanceof Integer) + return ((Integer)value).intValue(); + try + { + return Integer.parseInt(value.toString()); + } + catch (NumberFormatException ex) + { + log.warning(columnName + " - " + ex.getMessage()); + return 0; + } + } // get_ValueOldAsInt + + /** + * Is Value Changed + * @param index index + * @return true if changed + */ + public final boolean is_ValueChanged (int index) + { + if (index < 0 || index >= get_ColumnCount()) + { + log.log(Level.WARNING, "Index invalid - " + index); + return false; + } + if (m_newValues[index] == null) + return false; + return !m_newValues[index].equals(m_oldValues[index]); + } // is_ValueChanged + + /** + * Is Value Changed + * @param columnName column name + * @return true if changed + */ + public final boolean is_ValueChanged (String columnName) + { + int index = get_ColumnIndex(columnName); + if (index < 0) + { + log.log(Level.WARNING, "Column not found - " + columnName); + return false; + } + return is_ValueChanged (index); + } // is_ValueChanged + + /** + * Return new - old. + * - New Value if Old Valus is null + * - New Value - Old Value if Number + * - otherwise null + * @param index index + * @return new - old or null if not appropiate or not changed + */ + public final Object get_ValueDifference (int index) + { + if (index < 0 || index >= get_ColumnCount()) + { + log.log(Level.WARNING, "Index invalid - " + index); + return null; + } + Object nValue = m_newValues[index]; + // No new Value or NULL + if (nValue == null || nValue == Null.NULL) + return null; + // + Object oValue = m_oldValues[index]; + if (oValue == null || oValue == Null.NULL) + return nValue; + if (nValue instanceof BigDecimal) + { + BigDecimal obd = (BigDecimal)oValue; + return ((BigDecimal)nValue).subtract(obd); + } + else if (nValue instanceof Integer) + { + int result = ((Integer)nValue).intValue(); + result -= ((Integer)oValue).intValue(); + return new Integer(result); + } + // + log.warning("Invalid type - New=" + nValue); + return null; + } // get_ValueDifference + + /** + * Return new - old. + * - New Value if Old Valus is null + * - New Value - Old Value if Number + * - otherwise null + * @param columnName column name + * @return new - old or null if not appropiate or not changed + */ + public final Object get_ValueDifference (String columnName) + { + int index = get_ColumnIndex(columnName); + if (index < 0) + { + log.log(Level.WARNING, "Column not found - " + columnName); + return null; + } + return get_ValueDifference (index); + } // get_ValueDifference + + + /************************************************************************** + * Set Value + * @param ColumnName column name + * @param value value + * @return true if value set + */ + protected final boolean set_Value (String ColumnName, Object value) + { + if (value instanceof String && ColumnName.equals("WhereClause") + && value.toString().toUpperCase().indexOf("=NULL") != -1) + log.warning("Invalid Null Value - " + ColumnName + "=" + value); + + int index = get_ColumnIndex(ColumnName); + if (index < 0) + { + log.log(Level.SEVERE, "Column not found - " + ColumnName); + return false; + } + if (ColumnName.endsWith("_ID") && value instanceof String ) + { + log.severe("Invalid Data Type for " + ColumnName + "=" + value); + value = Integer.parseInt((String)value); + } + + return set_Value (index, value); + } // setValue + + /** + * Set Encrypted Value + * @param ColumnName column name + * @param value value + * @return true if value set + */ + protected final boolean set_ValueE (String ColumnName, Object value) + { + return set_Value (ColumnName, value); + } // setValueE + + /** + * Set Value if updateable and correct class. + * (and to NULL if not mandatory) + * @param index index + * @param value value + * @return true if value set + */ + protected final boolean set_Value (int index, Object value) + { + if (index < 0 || index >= get_ColumnCount()) + { + log.log(Level.WARNING, "Index invalid - " + index); + return false; + } + String ColumnName = p_info.getColumnName(index); + String colInfo = " - " + ColumnName; + // + if (p_info.isVirtualColumn(index)) + { + log.log(Level.WARNING, "Virtual Column" + colInfo); + return false; + } + // + // globalqss -- Bug 1618469 - is throwing not updateable even on new records + // if (!p_info.isColumnUpdateable(index)) + if ( ( ! p_info.isColumnUpdateable(index) ) && ( ! is_new() ) ) + { + colInfo += " - NewValue=" + value + " - OldValue=" + get_Value(index); + log.log(Level.WARNING, "Column not updateable" + colInfo); + return false; + } + // + if (value == null) + { + if (p_info.isColumnMandatory(index)) + { + log.log(Level.WARNING, "Cannot set mandatory column to null " + colInfo); + // Trace.printStack(); + return false; + } + m_newValues[index] = Null.NULL; // correct + log.finer(ColumnName + " = null"); + } + else + { + // matching class or generic object + if (value.getClass().equals(p_info.getColumnClass(index)) + || p_info.getColumnClass(index) == Object.class) + m_newValues[index] = value; // correct + // Integer can be set as BigDecimal + else if (value.getClass() == BigDecimal.class + && p_info.getColumnClass(index) == Integer.class) + m_newValues[index] = new Integer (((BigDecimal)value).intValue()); + // Set Boolean + else if (p_info.getColumnClass(index) == Boolean.class + && ("Y".equals(value) || "N".equals(value)) ) + m_newValues[index] = new Boolean("Y".equals(value)); + // added by vpj-cd + // To solve BUG [ 1618423 ] Set Project Type button in Project window throws warning + // generated because C_Project.C_Project_Type_ID is defined as button in dictionary + // although is ID (integer) in database + else if (value.getClass() == Integer.class + && p_info.getColumnClass(index) == String.class) + m_newValues[index] = value; + else if (value.getClass() == String.class + && p_info.getColumnClass(index) == Integer.class) + try + { + m_newValues[index] = new Integer((String)value); + } + catch (NumberFormatException e) + { + log.log(Level.SEVERE, ColumnName + + " - Class invalid: " + value.getClass().toString() + + ", Should be " + p_info.getColumnClass(index).toString() + ": " + value); + return false; + } + else + { + log.log(Level.SEVERE, ColumnName + + " - Class invalid: " + value.getClass().toString() + + ", Should be " + p_info.getColumnClass(index).toString() + ": " + value); + return false; + } + // Validate (Min/Max) + String error = p_info.validate(index, value); + if (error != null) + { + log.log(Level.WARNING, ColumnName + "=" + value + " - " + error); + return false; + } + // Length for String + if (p_info.getColumnClass(index) == String.class) + { + String stringValue = value.toString(); + int length = p_info.getFieldLength(index); + if (stringValue.length() > length && length > 0) + { + log.warning(ColumnName + " - Value too long - truncated to length=" + length); + m_newValues[index] = stringValue.substring(0,length); + } + } + if (CLogMgt.isLevelFinest()) + log.finest(ColumnName + " = " + m_newValues[index] + " (OldValue="+m_oldValues[index]+")"); + } + set_Keys (ColumnName, m_newValues[index]); + return true; + } // setValue + + /** + * Set Value w/o check (update, r/o, ..). + * Used when Column is R/O + * Required for key and parent values + * @param ColumnName column name + * @param value value + * @return true if value set + */ + protected final boolean set_ValueNoCheck (String ColumnName, Object value) + { + int index = get_ColumnIndex(ColumnName); + if (index < 0) + { + log.log(Level.SEVERE, "Column not found - " + ColumnName); + return false; + } + if (value == null) + m_newValues[index] = Null.NULL; // write direct + else + { + // matching class or generic object + if (value.getClass().equals(p_info.getColumnClass(index)) + || p_info.getColumnClass(index) == Object.class) + m_newValues[index] = value; // correct + // Integer can be set as BigDecimal + else if (value.getClass() == BigDecimal.class + && p_info.getColumnClass(index) == Integer.class) + m_newValues[index] = new Integer (((BigDecimal)value).intValue()); + // Set Boolean + else if (p_info.getColumnClass(index) == Boolean.class + && ("Y".equals(value) || "N".equals(value)) ) + m_newValues[index] = new Boolean("Y".equals(value)); + else if (p_info.getColumnClass(index) == Integer.class + && value.getClass() == String.class) + { + try + { + int intValue = Integer.parseInt((String)value); + m_newValues[index] = Integer.valueOf(intValue); + } + catch (Exception e) + { + log.warning (ColumnName + + " - Class invalid: " + value.getClass().toString() + + ", Should be " + p_info.getColumnClass(index).toString() + ": " + value); + m_newValues[index] = null; + } + } + else + { + log.warning (ColumnName + + " - Class invalid: " + value.getClass().toString() + + ", Should be " + p_info.getColumnClass(index).toString() + ": " + value); + m_newValues[index] = value; // correct + } + // Validate (Min/Max) + String error = p_info.validate(index, value); + if (error != null) + log.warning(ColumnName + "=" + value + " - " + error); + // length for String + if (p_info.getColumnClass(index) == String.class) + { + String stringValue = value.toString(); + int length = p_info.getFieldLength(index); + if (stringValue.length() > length && length > 0) + { + log.warning(ColumnName + " - Value too long - truncated to length=" + length); + m_newValues[index] = stringValue.substring(0,length); + } + } + } + log.finest(ColumnName + " = " + m_newValues[index] + + " (" + (m_newValues[index]==null ? "-" : m_newValues[index].getClass().getName()) + ")"); + set_Keys (ColumnName, m_newValues[index]); + return true; + } // set_ValueNoCheck + + /** + * Set Encrypted Value w/o check (update, r/o, ..). + * Used when Column is R/O + * Required for key and parent values + * @param ColumnName column name + * @param value value + * @return true if value set + */ + protected final boolean set_ValueNoCheckE (String ColumnName, Object value) + { + return set_ValueNoCheckE (ColumnName, value); + } // set_ValueNoCheckE + + /** + * Set value of Column + * @param columnName + * @param value + */ + public final void set_ValueOfColumn(String columnName, Object value) + { + int AD_Column_ID = p_info.getAD_Column_ID(columnName); + if (AD_Column_ID > 0) + { + set_ValueOfColumn(AD_Column_ID, value); + } + } + + /** + * Set Value of Column + * @param AD_Column_ID column + * @param value value + */ + public final void set_ValueOfColumn (int AD_Column_ID, Object value) + { + int index = p_info.getColumnIndex(AD_Column_ID); + if (index < 0) + log.log(Level.SEVERE, "Not found - AD_Column_ID=" + AD_Column_ID); + String ColumnName = p_info.getColumnName(index); + if (ColumnName.equals("IsApproved")) + set_ValueNoCheck(ColumnName, value); + else + set_Value (index, value); + } // setValueOfColumn + + + /** + * Set Custom Column + * @param columnName column + * @param value value + */ + public final void set_CustomColumn (String columnName, Object value) + { + // [ 1845793 ] PO.set_CustomColumn not updating correctly m_newValues + // this is for columns not in PO - verify and call proper method if exists + int poIndex = get_ColumnIndex(columnName); + if (poIndex > 0) { + // is not custom column - it exists in the PO + set_Value(columnName, value); + return; + } + if (m_custom == null) + m_custom = new HashMap(); + String valueString = "NULL"; + if (value == null) + ; + else if (value instanceof Number) + valueString = value.toString(); + else if (value instanceof Boolean) + valueString = ((Boolean)value).booleanValue() ? "'Y'" : "'N'"; + else if (value instanceof Timestamp) + valueString = DB.TO_DATE((Timestamp)value, false); + else // if (value instanceof String) + valueString = DB.TO_STRING(value.toString()); + // Save it + log.log(Level.INFO, columnName + "=" + valueString); + m_custom.put(columnName, valueString); + } // set_CustomColumn + + + /** + * Set (numeric) Key Value + * @param ColumnName column name + * @param value value + */ + private void set_Keys (String ColumnName, Object value) + { + // Update if KeyColumn + for (int i = 0; i < m_IDs.length; i++) + { + if (ColumnName.equals (m_KeyColumns[i])) + { + m_IDs[i] = value; + } + } // for all key columns + } // setKeys + + + /************************************************************************** + * Get Column Count + * @return column count + */ + protected int get_ColumnCount() + { + return p_info.getColumnCount(); + } // getColumnCount + + /** + * Get Column Name + * @param index index + * @return ColumnName + */ + protected String get_ColumnName (int index) + { + return p_info.getColumnName (index); + } // getColumnName + + /** + * Get Column Label + * @param index index + * @return Column Label + */ + protected String get_ColumnLabel (int index) + { + return p_info.getColumnLabel (index); + } // getColumnLabel + + /** + * Get Column Description + * @param index index + * @return column description + */ + protected String get_ColumnDescription (int index) + { + return p_info.getColumnDescription (index); + } // getColumnDescription + + /** + * Is Column Mandatory + * @param index index + * @return true if column mandatory + */ + protected boolean isColumnMandatory (int index) + { + return p_info.isColumnMandatory(index); + } // isColumnNandatory + + /** + * Is Column Updateable + * @param index index + * @return true if column updateable + */ + protected boolean isColumnUpdateable (int index) + { + return p_info.isColumnUpdateable(index); + } // isColumnUpdateable + + /** + * Set Column Updateable + * @param index index + * @param updateable column updateable + */ + protected void set_ColumnUpdateable (int index, boolean updateable) + { + p_info.setColumnUpdateable(index, updateable); + } // setColumnUpdateable + + /** + * Set all columns updateable + * @param updateable updateable + */ + protected void setUpdateable (boolean updateable) + { + p_info.setUpdateable (updateable); + } // setUpdateable + + /** + * Get Column DisplayType + * @param index index + * @return display type + */ + protected int get_ColumnDisplayType (int index) + { + return p_info.getColumnDisplayType(index); + } // getColumnDisplayType + + /** + * Get Lookup + * @param index index + * @return Lookup or null + */ + protected Lookup get_ColumnLookup(int index) + { + return p_info.getColumnLookup(index); + } // getColumnLookup + + /** + * Get Column Index + * @param columnName column name + * @return index of column with ColumnName or -1 if not found + */ + public final int get_ColumnIndex (String columnName) + { + return p_info.getColumnIndex(columnName); + } // getColumnIndex + + /** + * Get Display Value of value + * @param columnName columnName + * @param currentValue current value + * @return String value with "./." as null + */ + protected String get_DisplayValue(String columnName, boolean currentValue) + { + Object value = currentValue ? get_Value(columnName) : get_ValueOld(columnName); + if (value == null) + return "./."; + String retValue = value.toString(); + int index = get_ColumnIndex(columnName); + if (index < 0) + return retValue; + int dt = get_ColumnDisplayType(index); + if (DisplayType.isText(dt) || DisplayType.YesNo == dt) + return retValue; + // Lookup + Lookup lookup = get_ColumnLookup(index); + if (lookup != null) + return lookup.getDisplay(value); + // Other + return retValue; + } // get_DisplayValue + + + /** + * Copy old values of From to new values of To. + * Does not copy Keys + * @param from old, existing & unchanged PO + * @param to new, not saved PO + * @param AD_Client_ID client + * @param AD_Org_ID org + */ + protected static void copyValues (PO from, PO to, int AD_Client_ID, int AD_Org_ID) + { + copyValues (from, to); + to.setAD_Client_ID(AD_Client_ID); + to.setAD_Org_ID(AD_Org_ID); + } // copyValues + + /** + * Copy old values of From to new values of To. + * Does not copy Keys and AD_Client_ID/AD_Org_ID + * @param from old, existing & unchanged PO + * @param to new, not saved PO + */ + public static void copyValues (PO from, PO to) + { + s_log.fine("From ID=" + from.get_ID() + " - To ID=" + to.get_ID()); + // Different Classes + if (from.getClass() != to.getClass()) + { + for (int i1 = 0; i1 < from.m_oldValues.length; i1++) + { + if (from.p_info.isVirtualColumn(i1) + || from.p_info.isKey(i1)) // KeyColumn + continue; + String colName = from.p_info.getColumnName(i1); + // Ignore Standard Values + if (colName.startsWith("Created") + || colName.startsWith("Updated") + || colName.equals("IsActive") + || colName.equals("AD_Client_ID") + || colName.equals("AD_Org_ID") + || colName.equals("Processing") + ) + ; // ignore + else + { + for (int i2 = 0; i2 < to.m_oldValues.length; i2++) + { + if (to.p_info.getColumnName(i2).equals(colName)) + { + to.m_newValues[i2] = from.m_oldValues[i1]; + break; + } + } + } + } // from loop + } + else // same class + { + for (int i = 0; i < from.m_oldValues.length; i++) + { + if (from.p_info.isVirtualColumn(i) + || from.p_info.isKey(i)) // KeyColumn + continue; + String colName = from.p_info.getColumnName(i); + // Ignore Standard Values + if (colName.startsWith("Created") + || colName.startsWith("Updated") + || colName.equals("IsActive") + || colName.equals("AD_Client_ID") + || colName.equals("AD_Org_ID") + || colName.equals("Processing") + ) + ; // ignore + else + to.m_newValues[i] = from.m_oldValues[i]; + } + } // same class + } // copy + + + /************************************************************************** + * Load record with ID + * @param ID ID + * @param trxName transaction name + */ + protected void load (int ID, String trxName) + { + log.finest("ID=" + ID); + if (ID > 0) + { + m_IDs = new Object[] {new Integer(ID)}; + m_KeyColumns = new String[] {p_info.getTableName() + "_ID"}; + load(trxName); + } + else // new + { + loadDefaults(); + m_createNew = true; + setKeyInfo(); // sets m_IDs + loadComplete(true); + } + } // load + + + /** + * (re)Load record with m_ID[*] + * @param trxName transaction + * @return true if loaded + */ + public boolean load (String trxName) + { + m_trxName = trxName; + boolean success = true; + StringBuffer sql = new StringBuffer("SELECT "); + int size = get_ColumnCount(); + for (int i = 0; i < size; i++) + { + if (i != 0) + sql.append(","); + sql.append(p_info.getColumnSQL(i)); // Normal and Virtual Column + } + sql.append(" FROM ").append(p_info.getTableName()) + .append(" WHERE ") + .append(get_WhereClause(false)); + + // + // int index = -1; + if (CLogMgt.isLevelFinest()) + log.finest(get_WhereClause(true)); + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement(sql.toString(), m_trxName); // local trx only + for (int i = 0; i < m_IDs.length; i++) + { + Object oo = m_IDs[i]; + if (oo instanceof Integer) + pstmt.setInt(i+1, ((Integer)m_IDs[i]).intValue()); + else + pstmt.setString(i+1, m_IDs[i].toString()); + } + rs = pstmt.executeQuery(); + if (rs.next()) + { + success = load(rs); + } + else + { + log.log(Level.SEVERE, "NO Data found for " + get_WhereClause(true), new Exception()); + m_IDs = new Object[] {I_ZERO}; + success = false; + // throw new DBException("NO Data found for " + get_WhereClause(true)); + } + m_createNew = false; + // reset new values + m_newValues = new Object[size]; + } + catch (Exception e) + { + String msg = ""; + if (m_trxName != null) + msg = "[" + m_trxName + "] - "; + msg += get_WhereClause(true) + // + ", Index=" + index + // + ", Column=" + get_ColumnName(index) + // + ", " + p_info.toString(index) + + ", SQL=" + sql.toString(); + success = false; + m_IDs = new Object[] {I_ZERO}; + log.log(Level.SEVERE, msg, e); + // throw new DBException(e); + } + // Finish + finally { + DB.close(rs, pstmt); + rs = null; pstmt = null; + } + loadComplete(success); + return success; + } // load + + + /** + * Load from the current position of a ResultSet + * @param rs result set + * @return true if loaded + */ + protected boolean load (ResultSet rs) + { + int size = get_ColumnCount(); + boolean success = true; + int index = 0; + log.finest("(rs)"); + // load column values + for (index = 0; index < size; index++) + { + String columnName = p_info.getColumnName(index); + Class clazz = p_info.getColumnClass(index); + int dt = p_info.getColumnDisplayType(index); + try + { + if (clazz == Integer.class) + m_oldValues[index] = decrypt(index, new Integer(rs.getInt(columnName))); + else if (clazz == BigDecimal.class) + m_oldValues[index] = decrypt(index, rs.getBigDecimal(columnName)); + else if (clazz == Boolean.class) + m_oldValues[index] = new Boolean ("Y".equals(decrypt(index, rs.getString(columnName)))); + else if (clazz == Timestamp.class) + m_oldValues[index] = decrypt(index, rs.getTimestamp(columnName)); + else if (DisplayType.isLOB(dt)) + m_oldValues[index] = get_LOB (rs.getObject(columnName)); + else if (clazz == String.class) + m_oldValues[index] = decrypt(index, rs.getString(columnName)); + else + m_oldValues[index] = loadSpecial(rs, index); + // NULL + if (rs.wasNull() && m_oldValues[index] != null) + m_oldValues[index] = null; + // + if (CLogMgt.isLevelAll()) + log.finest(String.valueOf(index) + ": " + p_info.getColumnName(index) + + "(" + p_info.getColumnClass(index) + ") = " + m_oldValues[index]); + } + catch (SQLException e) + { + if (p_info.isVirtualColumn(index)) // if rs constructor used + log.log(Level.FINER, "Virtual Column not loaded: " + columnName); + else + { + log.log(Level.SEVERE, "(rs) - " + String.valueOf(index) + + ": " + p_info.getTableName() + "." + p_info.getColumnName(index) + + " (" + p_info.getColumnClass(index) + ") - " + e); + success = false; + } + } + } + m_createNew = false; + setKeyInfo(); + loadComplete(success); + return success; + } // load + + /** + * Load from HashMap + * @param hmIn hash map + * @return true if loaded + */ + protected boolean load (HashMap hmIn) + { + int size = get_ColumnCount(); + boolean success = true; + int index = 0; + log.finest("(hm)"); + // load column values + for (index = 0; index < size; index++) + { + String columnName = p_info.getColumnName(index); + String value = (String)hmIn.get(columnName); + if (value == null) + continue; + Class clazz = p_info.getColumnClass(index); + int dt = p_info.getColumnDisplayType(index); + try + { + if (clazz == Integer.class) + m_oldValues[index] = new Integer(value); + else if (clazz == BigDecimal.class) + m_oldValues[index] = new BigDecimal(value); + else if (clazz == Boolean.class) + m_oldValues[index] = new Boolean ("Y".equals(value)); + else if (clazz == Timestamp.class) + m_oldValues[index] = Timestamp.valueOf(value); + else if (DisplayType.isLOB(dt)) + m_oldValues[index] = null; // get_LOB (rs.getObject(columnName)); + else if (clazz == String.class) + m_oldValues[index] = value; + else + m_oldValues[index] = null; // loadSpecial(rs, index); + // + if (CLogMgt.isLevelAll()) + log.finest(String.valueOf(index) + ": " + p_info.getColumnName(index) + + "(" + p_info.getColumnClass(index) + ") = " + m_oldValues[index]); + } + catch (Exception e) + { + if (p_info.isVirtualColumn(index)) // if rs constructor used + log.log(Level.FINER, "Virtual Column not loaded: " + columnName); + else + { + log.log(Level.SEVERE, "(ht) - " + String.valueOf(index) + + ": " + p_info.getTableName() + "." + p_info.getColumnName(index) + + " (" + p_info.getColumnClass(index) + ") - " + e); + success = false; + } + } + } + m_createNew = false; + // Overwrite + setStandardDefaults(); + setKeyInfo(); + loadComplete(success); + return success; + } // load + + /** + * Create Hashmap with data as Strings + * @return HashMap + */ + protected HashMap get_HashMap() + { + HashMap hmOut = new HashMap(); + int size = get_ColumnCount(); + for (int i = 0; i < size; i++) + { + Object value = get_Value(i); + // Don't insert NULL values (allows Database defaults) + if (value == null + || p_info.isVirtualColumn(i)) + continue; + // Display Type + int dt = p_info.getColumnDisplayType(i); + // Based on class of definition, not class of value + Class c = p_info.getColumnClass(i); + String stringValue = null; + if (c == Object.class) + ; // saveNewSpecial (value, i)); + else if (value == null || value.equals (Null.NULL)) + ; + else if (value instanceof Integer || value instanceof BigDecimal) + stringValue = value.toString(); + else if (c == Boolean.class) + { + boolean bValue = false; + if (value instanceof Boolean) + bValue = ((Boolean)value).booleanValue(); + else + bValue = "Y".equals(value); + stringValue = bValue ? "Y" : "N"; + } + else if (value instanceof Timestamp) + stringValue = value.toString(); + else if (c == String.class) + stringValue = (String)value; + else if (DisplayType.isLOB(dt)) + ; + else + ; // saveNewSpecial (value, i)); + // + if (stringValue != null) + hmOut.put(p_info.getColumnName(i), stringValue); + } + // Custom Columns + if (m_custom != null) + { + Iterator it = m_custom.keySet().iterator(); + while (it.hasNext()) + { + String column = (String)it.next(); +// int index = p_info.getColumnIndex(column); + String value = (String)m_custom.get(column); + if (value != null) + hmOut.put(column, value); + } + m_custom = null; + } + return hmOut; + } // get_HashMap + + /** + * Load Special data (images, ..). + * To be extended by sub-classes + * @param rs result set + * @param index zero based index + * @return value value + * @throws SQLException + */ + protected Object loadSpecial (ResultSet rs, int index) throws SQLException + { + log.finest("(NOP) - " + p_info.getColumnName(index)); + return null; + } // loadSpecial + + /** + * Load is complete + * @param success success + * To be extended by sub-classes + */ + protected void loadComplete (boolean success) + { + } // loadComplete + + + /** + * Load Defaults + */ + protected void loadDefaults() + { + setStandardDefaults(); + // + /** @todo defaults from Field */ + // MField.getDefault(p_info.getDefaultLogic(i)); + } // loadDefaults + + /** + * Set Default values. + * Client, Org, Created/Updated, *By, IsActive + */ + protected void setStandardDefaults() + { + int size = get_ColumnCount(); + for (int i = 0; i < size; i++) + { + if (p_info.isVirtualColumn(i)) + continue; + String colName = p_info.getColumnName(i); + // Set Standard Values + if (colName.endsWith("tedBy")) + m_newValues[i] = new Integer (Env.getContextAsInt(p_ctx, "#AD_User_ID")); + else if (colName.equals("Created") || colName.equals("Updated")) + m_newValues[i] = new Timestamp (System.currentTimeMillis()); + else if (colName.equals(p_info.getTableName() + "_ID")) // KeyColumn + m_newValues[i] = I_ZERO; + else if (colName.equals("IsActive")) + m_newValues[i] = new Boolean(true); + else if (colName.equals("AD_Client_ID")) + m_newValues[i] = new Integer(Env.getAD_Client_ID(p_ctx)); + else if (colName.equals("AD_Org_ID")) + m_newValues[i] = new Integer(Env.getAD_Org_ID(p_ctx)); + else if (colName.equals("Processed")) + m_newValues[i] = new Boolean(false); + else if (colName.equals("Processing")) + m_newValues[i] = new Boolean(false); + else if (colName.equals("Posted")) + m_newValues[i] = new Boolean(false); + } + } // setDefaults + + /** + * Set Key Info (IDs and KeyColumns). + */ + private void setKeyInfo() + { + // Search for Primary Key + for (int i = 0; i < p_info.getColumnCount(); i++) + { + if (p_info.isKey(i)) + { + String ColumnName = p_info.getColumnName(i); + m_KeyColumns = new String[] {ColumnName}; + if (p_info.getColumnName(i).endsWith("_ID")) + { + Integer ii = (Integer)get_Value(i); + if (ii == null) + m_IDs = new Object[] {I_ZERO}; + else + m_IDs = new Object[] {ii}; + log.finest("(PK) " + ColumnName + "=" + ii); + } + else + { + Object oo = get_Value(i); + if (oo == null) + m_IDs = new Object[] {null}; + else + m_IDs = new Object[] {oo}; + log.finest("(PK) " + ColumnName + "=" + oo); + } + return; + } + } // primary key search + + // Search for Parents + ArrayList columnNames = new ArrayList(); + for (int i = 0; i < p_info.getColumnCount(); i++) + { + if (p_info.isColumnParent(i)) + columnNames.add(p_info.getColumnName(i)); + } + // Set FKs + int size = columnNames.size(); + if (size == 0) + throw new IllegalStateException("No PK nor FK - " + p_info.getTableName()); + m_IDs = new Object[size]; + m_KeyColumns = new String[size]; + for (int i = 0; i < size; i++) + { + m_KeyColumns[i] = (String)columnNames.get(i); + if (m_KeyColumns[i].endsWith("_ID")) + { + Integer ii = null; + try + { + ii = (Integer)get_Value(m_KeyColumns[i]); + } + catch (Exception e) + { + log.log(Level.SEVERE, "", e); + } + if (ii != null) + m_IDs[i] = ii; + } + else + m_IDs[i] = get_Value(m_KeyColumns[i]); + log.finest("(FK) " + m_KeyColumns[i] + "=" + m_IDs[i]); + } + } // setKeyInfo + + + /************************************************************************** + * Are all mandatory Fields filled (i.e. can we save)?. + * Stops at first null mandatory field + * @return true if all mandatory fields are ok + */ + protected boolean isMandatoryOK() + { + int size = get_ColumnCount(); + for (int i = 0; i < size; i++) + { + if (p_info.isColumnMandatory(i)) + { + if (p_info.isVirtualColumn(i)) + continue; + if (get_Value(i) == null || get_Value(i).equals(Null.NULL)) + { + log.info(p_info.getColumnName(i)); + return false; + } + } + } + return true; + } // isMandatoryOK + + + /************************************************************************** + * Set AD_Client + * @param AD_Client_ID client + */ + final protected void setAD_Client_ID (int AD_Client_ID) + { + set_ValueNoCheck ("AD_Client_ID", new Integer(AD_Client_ID)); + } // setAD_Client_ID + + /** + * Get AD_Client + * @return AD_Client_ID + */ + public final int getAD_Client_ID() + { + Integer ii = (Integer)get_Value("AD_Client_ID"); + if (ii == null) + return 0; + return ii.intValue(); + } // getAD_Client_ID + + /** + * Set AD_Org + * @param AD_Org_ID org + */ + final public void setAD_Org_ID (int AD_Org_ID) + { + set_ValueNoCheck ("AD_Org_ID", new Integer(AD_Org_ID)); + } // setAD_Org_ID + + /** + * Get AD_Org + * @return AD_Org_ID + */ + public int getAD_Org_ID() + { + Integer ii = (Integer)get_Value("AD_Org_ID"); + if (ii == null) + return 0; + return ii.intValue(); + } // getAD_Org_ID + + /** + * Overwrite Client Org if different + * @param AD_Client_ID client + * @param AD_Org_ID org + */ + protected void setClientOrg (int AD_Client_ID, int AD_Org_ID) + { + if (AD_Client_ID != getAD_Client_ID()) + setAD_Client_ID(AD_Client_ID); + if (AD_Org_ID != getAD_Org_ID()) + setAD_Org_ID(AD_Org_ID); + } // setClientOrg + + /** + * Overwrite Client Org if different + * @param po persistent object + */ + protected void setClientOrg (PO po) + { + setClientOrg(po.getAD_Client_ID(), po.getAD_Org_ID()); + } // setClientOrg + + /** + * Set Active + * @param active active + */ + public final void setIsActive (boolean active) + { + set_Value("IsActive", new Boolean(active)); + } // setActive + + /** + * Is Active + * @return is active + */ + public final boolean isActive() + { + Boolean bb = (Boolean)get_Value("IsActive"); + if (bb != null) + return bb.booleanValue(); + return false; + } // isActive + + /** + * Get Created + * @return created + */ + final public Timestamp getCreated() + { + return (Timestamp)get_Value("Created"); + } // getCreated + + /** + * Get Updated + * @return updated + */ + final public Timestamp getUpdated() + { + return (Timestamp)get_Value("Updated"); + } // getUpdated + + /** + * Get CreatedBy + * @return AD_User_ID + */ + final public int getCreatedBy() + { + Integer ii = (Integer)get_Value("CreatedBy"); + if (ii == null) + return 0; + return ii.intValue(); + } // getCreateddBy + + /** + * Get UpdatedBy + * @return AD_User_ID + */ + final public int getUpdatedBy() + { + Integer ii = (Integer)get_Value("UpdatedBy"); + if (ii == null) + return 0; + return ii.intValue(); + } // getUpdatedBy + + /** + * Set UpdatedBy + * @param AD_User_ID user + */ + final protected void setUpdatedBy (int AD_User_ID) + { + set_ValueNoCheck ("UpdatedBy", new Integer(AD_User_ID)); + } // setAD_User_ID + + /** + * Get Translation of column + * @param columnName + * @param AD_Language + * @return translation or null if not found + */ + protected String get_Translation (String columnName, String AD_Language) + { + if (columnName == null || AD_Language == null + || m_IDs.length > 1 || m_IDs[0].equals(I_ZERO) + || !(m_IDs[0] instanceof Integer)) + { + log.severe ("Invalid Argument: ColumnName" + columnName + + ", AD_Language=" + AD_Language + + ", ID.length=" + m_IDs.length + ", ID=" + m_IDs[0]); + return null; + } + int ID = ((Integer)m_IDs[0]).intValue(); + String retValue = null; + StringBuffer sql = new StringBuffer ("SELECT ").append(columnName) + .append(" FROM ").append(p_info.getTableName()).append("_Trl WHERE ") + .append(m_KeyColumns[0]).append("=?") + .append(" AND AD_Language=?"); + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement (sql.toString(), get_TrxName()); + pstmt.setInt (1, ID); + pstmt.setString (2, AD_Language); + rs = pstmt.executeQuery (); + if (rs.next ()) + retValue = rs.getString(1); + } + catch (Exception e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + finally { + DB.close(rs, pstmt); + rs = null; pstmt = null; + } + return retValue; + } // get_Translation + + /** + * Is new record + * @return true if new + */ + public boolean is_new() + { + if (m_createNew) + return true; + // + for (int i = 0; i < m_IDs.length; i++) + { + if (m_IDs[i].equals(I_ZERO)) + continue; + return false; // one value is non-zero + } + return true; + } // is_new + + /* + * Classes which override save() method: + * org.compiere.process.DocActionTemplate + * org.compiere.model.MClient + * org.compiere.model.MClientInfo + * org.compiere.model.MSystem + */ + /************************************************************************** + * Update Value or create new record. + * To reload call load() - not updated + * @return true if saved + */ + public boolean save() + { + CLogger.resetLast(); + boolean newRecord = is_new(); // save locally as load resets + if (!newRecord && !is_Changed()) + { + log.fine("Nothing changed - " + p_info.getTableName()); + return true; + } + + // Organization Check + if (getAD_Org_ID() == 0 + && (get_AccessLevel() == ACCESSLEVEL_ORG + || (get_AccessLevel() == ACCESSLEVEL_CLIENTORG + && MClientShare.isOrgLevelOnly(getAD_Client_ID(), get_Table_ID())))) + { + log.saveError("FillMandatory", Msg.getElement(getCtx(), "AD_Org_ID")); + return false; + } + // Should be Org 0 + if (getAD_Org_ID() != 0) + { + boolean reset = get_AccessLevel() == ACCESSLEVEL_SYSTEM; + if (!reset && MClientShare.isClientLevelOnly(getAD_Client_ID(), get_Table_ID())) + { + reset = get_AccessLevel() == ACCESSLEVEL_CLIENT + || get_AccessLevel() == ACCESSLEVEL_SYSTEMCLIENT + || get_AccessLevel() == ACCESSLEVEL_CLIENTORG; + } + if (reset) + { + log.warning("Set Org to 0"); + setAD_Org_ID(0); + } + } + + Trx localTrx = null; + if (m_trxName == null) { + m_trxName = Trx.createTrxName("POSave"); + localTrx = Trx.get(m_trxName, true); + } + + // Before Save + try + { + if (!beforeSave(newRecord)) + { + log.warning("beforeSave failed - " + toString()); + if (localTrx != null) { + localTrx.rollback(); + localTrx.close(); + m_trxName = null; + } + return false; + } + } + catch (Exception e) + { + log.log(Level.WARNING, "beforeSave - " + toString(), e); + log.saveError("Error", e.toString(), false); + if (localTrx != null) { + localTrx.rollback(); + localTrx.close(); + m_trxName = null; + } + return false; + } + + try { + // Call ModelValidators TYPE_NEW/TYPE_CHANGE + String errorMsg = ModelValidationEngine.get().fireModelChange + (this, newRecord ? ModelValidator.TYPE_NEW : ModelValidator.TYPE_CHANGE); + if (errorMsg != null) + { + log.warning("Validation failed - " + errorMsg); + log.saveError("Error", errorMsg); + if (localTrx != null) { + localTrx.rollback(); + m_trxName = null; + } + return false; + } + // Save + if (newRecord) + { + boolean b = saveNew(); + if (b) + { + if (localTrx != null) + return localTrx.commit(); + else + return b; + } + else + { + if (localTrx != null) + localTrx.rollback(); + return b; + } + } + else + { + boolean b = saveUpdate(); + if (b) + { + if (localTrx != null) + return localTrx.commit(); + else + return b; + } + else + { + if (localTrx != null) + localTrx.rollback(); + return b; + } + } + } finally { + if (localTrx != null) + { + localTrx.close(); + m_trxName = null; + } + } + } // save + + /** + * Update Value or create new record. + * @throws AdempiereException + * @see #save() + */ + public void saveEx() throws AdempiereException + { + if (!save()) { + String msg = null; + ValueNamePair err = CLogger.retrieveError(); + if (err != null) + msg = err.getName(); + if (msg == null || msg.length() == 0) + msg = "SaveError"; + throw new AdempiereException(msg); + } + } + + /** + * Finish Save Process + * @param newRecord new + * @param success success + * @return true if saved + */ + private boolean saveFinish (boolean newRecord, boolean success) + { + // Translations + if (success) + { + if (newRecord) + insertTranslations(); + else + updateTranslations(); + } + // + try + { + success = afterSave (newRecord, success); + } + catch (Exception e) + { + log.log(Level.WARNING, "afterSave", e); + log.saveError("Error", e.toString(), false); + success = false; + // throw new DBException(e); + } + // Call ModelValidators TYPE_AFTER_NEW/TYPE_AFTER_CHANGE - teo_sarca [ 1675490 ] + if (success) { + String errorMsg = ModelValidationEngine.get().fireModelChange + (this, newRecord ? + (isReplication() ? ModelValidator.TYPE_AFTER_NEW_REPLICATION : ModelValidator.TYPE_AFTER_NEW) + : + (isReplication() ? ModelValidator.TYPE_AFTER_CHANGE_REPLICATION : ModelValidator.TYPE_AFTER_CHANGE) + ); + setReplication(false); + if (errorMsg != null) { + log.saveError("Error", errorMsg); + success = false; + } + } + // OK + if (success) + { + if (s_docWFMgr == null) + { + try + { + Class.forName("org.compiere.wf.DocWorkflowManager"); + } + catch (Exception e) + { + } + } + if (s_docWFMgr != null) + s_docWFMgr.process (this, p_info.getAD_Table_ID()); + + // Copy to Old values + int size = p_info.getColumnCount(); + for (int i = 0; i < size; i++) + { + if (m_newValues[i] != null) + { + if (m_newValues[i] == Null.NULL) + m_oldValues[i] = null; + else + m_oldValues[i] = m_newValues[i]; + } + } + m_newValues = new Object[size]; + } + m_createNew = false; + if (!newRecord) + CacheMgt.get().reset(p_info.getTableName()); + return success; + } // saveFinish + + /** + * Update Value or create new record. + * To reload call load() - not updated + * @param trxName transaction + * @return true if saved + */ + public boolean save (String trxName) + { + set_TrxName(trxName); + return save(); + } // save + + public boolean saveReplica (boolean isFromReplication) + { + setReplication(isFromReplication); + return save(); + } + + /** + * Update Value or create new record. + * @param trxName transaction + * @throws AdempiereException + * @see #saveEx(String) + */ + public void saveEx(String trxName) throws AdempiereException + { + set_TrxName(trxName); + saveEx(); + } + + /** + * Is there a Change to be saved? + * @return true if record changed + */ + public boolean is_Changed() + { + int size = get_ColumnCount(); + for (int i = 0; i < size; i++) + { + // Test if the column has changed - teo_sarca [ 1704828 ] + if (is_ValueChanged(i)) + return true; + } + if (m_custom != null && m_custom.size() > 0) + return true; // there are custom columns modified + return false; + } // is_Change + + /** + * Called before Save for Pre-Save Operation + * @param newRecord new record + * @return true if record can be saved + */ + protected boolean beforeSave(boolean newRecord) + { + /** Prevents saving + log.saveError("Error", Msg.parseTranslation(getCtx(), "@C_Currency_ID@ = @C_Currency_ID@")); + log.saveError("FillMandatory", Msg.getElement(getCtx(), "PriceEntered")); + /** Issues message + log.saveWarning(AD_Message, message); + log.saveInfo (AD_Message, message); + **/ + return true; + } // beforeSave + + /** + * Called after Save for Post-Save Operation + * @param newRecord new record + * @param success true if save operation was success + * @return if save was a success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + return success; + } // afterSave + + /** + * Update Record directly + * @return true if updated + */ + protected boolean saveUpdate() + { + String where = get_WhereClause(true); + // + boolean changes = false; + StringBuffer sql = new StringBuffer ("UPDATE "); + sql.append(p_info.getTableName()).append( " SET "); + boolean updated = false; + boolean updatedBy = false; + lobReset(); + + // Change Log + MSession session = MSession.get (p_ctx, false); + if (session == null) + log.fine("No Session found"); + int AD_ChangeLog_ID = 0; + + int size = get_ColumnCount(); + for (int i = 0; i < size; i++) + { + Object value = m_newValues[i]; + if (value == null + || p_info.isVirtualColumn(i)) + continue; + // we have a change + Class c = p_info.getColumnClass(i); + int dt = p_info.getColumnDisplayType(i); + String columnName = p_info.getColumnName(i); + // + // updated/by + if (columnName.equals("UpdatedBy")) + { + if (updatedBy) // explicit + continue; + updatedBy = true; + } + else if (columnName.equals("Updated")) + { + if (updated) + continue; + updated = true; + } + if (DisplayType.isLOB(dt)) + { + lobAdd (value, i, dt); + // If no changes set UpdatedBy explicitly to ensure commit of lob + if (!changes && !updatedBy) + { + int AD_User_ID = Env.getContextAsInt(p_ctx, "#AD_User_ID"); + set_ValueNoCheck("UpdatedBy", new Integer(AD_User_ID)); + sql.append("UpdatedBy=").append(AD_User_ID); + changes = true; + updatedBy = true; + } + continue; + } + // Update Document No + if (columnName.equals("DocumentNo")) + { + String strValue = (String)value; + if (strValue.startsWith("<") && strValue.endsWith(">")) + { + value = null; + int AD_Client_ID = getAD_Client_ID(); + int index = p_info.getColumnIndex("C_DocTypeTarget_ID"); + if (index == -1) + index = p_info.getColumnIndex("C_DocType_ID"); + if (index != -1) // get based on Doc Type (might return null) + value = DB.getDocumentNo(get_ValueAsInt(index), m_trxName, false, this); + if (value == null) // not overwritten by DocType and not manually entered + value = DB.getDocumentNo(AD_Client_ID, p_info.getTableName(), m_trxName, this); + } + else + log.warning("DocumentNo updated: " + m_oldValues[i] + " -> " + value); + } + + if (changes) + sql.append(", "); + changes = true; + sql.append(columnName).append("="); + + // values + if (value == Null.NULL) + sql.append("NULL"); + else if (value instanceof Integer || value instanceof BigDecimal) + sql.append(encrypt(i,value)); + else if (c == Boolean.class) + { + boolean bValue = false; + if (value instanceof Boolean) + bValue = ((Boolean)value).booleanValue(); + else + bValue = "Y".equals(value); + sql.append(encrypt(i,bValue ? "'Y'" : "'N'")); + } + else if (value instanceof Timestamp) + sql.append(DB.TO_DATE((Timestamp)encrypt(i,value),p_info.getColumnDisplayType(i) == DisplayType.Date)); + else { + if (value.toString().length() == 0) { + // [ 1722057 ] Encrypted columns throw error if saved as null + // don't encrypt NULL + sql.append(DB.TO_STRING(value.toString())); + } else { + sql.append(encrypt(i,DB.TO_STRING(value.toString()))); + } + } + + // Change Log - Only + if (session != null + && m_IDs.length == 1 + && p_info.isAllowLogging(i) // logging allowed + && !p_info.isEncrypted(i) // not encrypted + && !p_info.isVirtualColumn(i) // no virtual column + && !"Password".equals(columnName) + ) + { + Object oldV = m_oldValues[i]; + Object newV = value; + if (oldV != null && oldV == Null.NULL) + oldV = null; + if (newV != null && newV == Null.NULL) + newV = null; + // change log on update + MChangeLog cLog = session.changeLog ( + m_trxName, AD_ChangeLog_ID, + p_info.getAD_Table_ID(), p_info.getColumn(i).AD_Column_ID, + get_ID(), getAD_Client_ID(), getAD_Org_ID(), oldV, newV, MChangeLog.EVENTCHANGELOG_Update); + if (cLog != null) + AD_ChangeLog_ID = cLog.getAD_ChangeLog_ID(); + } + } // for all fields + + // Custom Columns (cannot be logged as no column) + if (m_custom != null) + { + Iterator it = m_custom.keySet().iterator(); + while (it.hasNext()) + { + if (changes) + sql.append(", "); + changes = true; + // + String column = (String)it.next(); + String value = (String)m_custom.get(column); + int index = p_info.getColumnIndex(column); + sql.append(column).append("=").append(encrypt(index,value)); + } + m_custom = null; + } + + // Something changed + if (changes) + { + if (m_trxName == null) + log.fine(p_info.getTableName() + "." + where); + else + log.fine("[" + m_trxName + "] - " + p_info.getTableName() + "." + where); + if (!updated) // Updated not explicitly set + { + Timestamp now = new Timestamp(System.currentTimeMillis()); + set_ValueNoCheck("Updated", now); + sql.append(",Updated=").append(DB.TO_DATE(now, false)); + } + if (!updatedBy) // UpdatedBy not explicitly set + { + int AD_User_ID = Env.getContextAsInt(p_ctx, "#AD_User_ID"); + set_ValueNoCheck("UpdatedBy", new Integer(AD_User_ID)); + sql.append(",UpdatedBy=").append(AD_User_ID); + } + sql.append(" WHERE ").append(where); + /** @todo status locking goes here */ + + log.finest(sql.toString()); + int no = DB.executeUpdate(sql.toString(), m_trxName); + boolean ok = no == 1; + if (ok) + ok = lobSave(); + else + { + if (m_trxName == null) + log.log(Level.WARNING, "#" + no + + " - " + p_info.getTableName() + "." + where); + else + log.log(Level.WARNING, "#" + no + + " - [" + m_trxName + "] - " + p_info.getTableName() + "." + where); + } + return saveFinish (false, ok); + } + + // nothing changed, so OK + return saveFinish (false, true); + } // saveUpdate + + /** + * Create New Record + * @return true if new record inserted + */ + private boolean saveNew() + { + // Set ID for single key - Multi-Key values need explicitly be set previously + if (m_IDs.length == 1 && p_info.hasKeyColumn() + && m_KeyColumns[0].endsWith("_ID")) // AD_Language, EntityType + { + int no = saveNew_getID(); + if (no <= 0) + no = DB.getNextID(getAD_Client_ID(), p_info.getTableName(), m_trxName); + if (no <= 0) + { + log.severe("No NextID (" + no + ")"); + return saveFinish (true, false); + } + m_IDs[0] = new Integer(no); + set_ValueNoCheck(m_KeyColumns[0], m_IDs[0]); + } + if (m_trxName == null) + log.fine(p_info.getTableName() + " - " + get_WhereClause(true)); + else + log.fine("[" + m_trxName + "] - " + p_info.getTableName() + " - " + get_WhereClause(true)); + + // Set new DocumentNo + String columnName = "DocumentNo"; + int index = p_info.getColumnIndex(columnName); + if (index != -1) + { + String value = (String)get_Value(index); + if (value != null && value.startsWith("<") && value.endsWith(">")) + value = null; + if (value == null || value.length() == 0) + { + int dt = p_info.getColumnIndex("C_DocTypeTarget_ID"); + if (dt == -1) + dt = p_info.getColumnIndex("C_DocType_ID"); + if (dt != -1) // get based on Doc Type (might return null) + value = DB.getDocumentNo(get_ValueAsInt(dt), m_trxName, false, this); + if (value == null) // not overwritten by DocType and not manually entered + value = DB.getDocumentNo(getAD_Client_ID(), p_info.getTableName(), m_trxName, this); + set_ValueNoCheck(columnName, value); + } + } + // Set empty Value + columnName = "Value"; + index = p_info.getColumnIndex(columnName); + if (index != -1) + { + String value = (String)get_Value(index); + if (value == null || value.length() == 0) + { + value = DB.getDocumentNo (getAD_Client_ID(), p_info.getTableName(), m_trxName, this); + set_ValueNoCheck(columnName, value); + } + } + + lobReset(); + + // Change Log + MSession session = MSession.get (p_ctx, false); + if (session == null) + log.fine("No Session found"); + int AD_ChangeLog_ID = 0; + + // SQL + StringBuffer sqlInsert = new StringBuffer("INSERT INTO "); + sqlInsert.append(p_info.getTableName()).append(" ("); + StringBuffer sqlValues = new StringBuffer(") VALUES ("); + int size = get_ColumnCount(); + boolean doComma = false; + for (int i = 0; i < size; i++) + { + Object value = get_Value(i); + // Don't insert NULL values (allows Database defaults) + if (value == null + || p_info.isVirtualColumn(i)) + continue; + + // Display Type + int dt = p_info.getColumnDisplayType(i); + if (DisplayType.isLOB(dt)) + { + lobAdd (value, i, dt); + continue; + } + + // ** add column ** + if (doComma) + { + sqlInsert.append(","); + sqlValues.append(","); + } + else + doComma = true; + sqlInsert.append(p_info.getColumnName(i)); + // + // Based on class of definition, not class of value + Class c = p_info.getColumnClass(i); + try + { + if (c == Object.class) // may have need to deal with null values differently + sqlValues.append (saveNewSpecial (value, i)); + else if (value == null || value.equals (Null.NULL)) + sqlValues.append ("NULL"); + else if (value instanceof Integer || value instanceof BigDecimal) + sqlValues.append (encrypt(i,value)); + else if (c == Boolean.class) + { + boolean bValue = false; + if (value instanceof Boolean) + bValue = ((Boolean)value).booleanValue(); + else + bValue = "Y".equals(value); + sqlValues.append (encrypt(i,bValue ? "'Y'" : "'N'")); + } + else if (value instanceof Timestamp) + sqlValues.append (DB.TO_DATE ((Timestamp)encrypt(i,value), p_info.getColumnDisplayType (i) == DisplayType.Date)); + else if (c == String.class) + sqlValues.append (encrypt(i,DB.TO_STRING ((String)value))); + else if (DisplayType.isLOB(dt)) + sqlValues.append("null"); // no db dependent stuff here + else + sqlValues.append (saveNewSpecial (value, i)); + } + catch (Exception e) + { + String msg = ""; + if (m_trxName != null) + msg = "[" + m_trxName + "] - "; + msg += p_info.toString(i) + + " - Value=" + value + + "(" + (value==null ? "null" : value.getClass().getName()) + ")"; + log.log(Level.SEVERE, msg, e); + throw new DBException(e); // fini + } + + // Change Log - Only + String insertLog = MSysConfig.getValue("SYSTEM_INSERT_CHANGELOG", "Y", getAD_Client_ID()); + if ( session != null + && m_IDs.length == 1 + && p_info.isAllowLogging(i) // logging allowed + && !p_info.isEncrypted(i) // not encrypted + && !p_info.isVirtualColumn(i) // no virtual column + && !"Password".equals(columnName) + && (insertLog.equalsIgnoreCase("Y") + || (insertLog.equalsIgnoreCase("K") && p_info.getColumn(i).IsKey)) + ) + { + // change log on new + MChangeLog cLog = session.changeLog ( + m_trxName, AD_ChangeLog_ID, + p_info.getAD_Table_ID(), p_info.getColumn(i).AD_Column_ID, + get_ID(), getAD_Client_ID(), getAD_Org_ID(), null, value, MChangeLog.EVENTCHANGELOG_Insert); + if (cLog != null) + AD_ChangeLog_ID = cLog.getAD_ChangeLog_ID(); + } + + } + // Custom Columns + if (m_custom != null) + { + Iterator it = m_custom.keySet().iterator(); + while (it.hasNext()) + { + String column = (String)it.next(); + index = p_info.getColumnIndex(column); + String value = (String)m_custom.get(column); + if (doComma) + { + sqlInsert.append(","); + sqlValues.append(","); + } + else + doComma = true; + sqlInsert.append(column); + //jz for ad_issue, some value may include ' in a string??? + sqlValues.append(encrypt(index, value)); + } + m_custom = null; + } + sqlInsert.append(sqlValues) + .append(")"); + // + int no = DB.executeUpdate(sqlInsert.toString(), m_trxName); + boolean ok = no == 1; + if (ok) + { + ok = lobSave(); + if (!load(m_trxName)) // re-read Info + { + if (m_trxName == null) + log.log(Level.SEVERE, "reloading"); + else + log.log(Level.SEVERE, "[" + m_trxName + "] - reloading"); + ok = false;; + } + } + else + { + String msg = "Not inserted - "; + if (CLogMgt.isLevelFiner()) + msg += sqlInsert.toString(); + else + msg += get_TableName(); + if (m_trxName == null) + log.log(Level.WARNING, msg); + else + log.log(Level.WARNING, "[" + m_trxName + "]" + msg); + } + return saveFinish (true, ok); + } // saveNew + + /** + * Get ID for new record during save. + * You can overwite this to explicitly set the ID + * @return ID to be used or 0 for fedault logic + */ + protected int saveNew_getID() + { + return 0; + } // saveNew_getID + + + /** + * Create Single/Multi Key Where Clause + * @param withValues if true uses actual values otherwise ? + * @return where clause + */ + public String get_WhereClause (boolean withValues) + { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < m_IDs.length; i++) + { + if (i != 0) + sb.append(" AND "); + sb.append(m_KeyColumns[i]).append("="); + if (withValues) + { + if (m_KeyColumns[i].endsWith("_ID")) + sb.append(m_IDs[i]); + else + sb.append("'").append(m_IDs[i]).append("'"); + } + else + sb.append("?"); + } + return sb.toString(); + } // getWhereClause + + + /** + * Save Special Data. + * To be extended by sub-classes + * @param value value + * @param index index + * @return SQL code for INSERT VALUES clause + */ + protected String saveNewSpecial (Object value, int index) + { + String colName = p_info.getColumnName(index); + String colClass = p_info.getColumnClass(index).toString(); + String colValue = value == null ? "null" : value.getClass().toString(); +// int dt = p_info.getColumnDisplayType(index); + + log.log(Level.SEVERE, "Unknown class for column " + colName + + " (" + colClass + ") - Value=" + colValue); + + if (value == null) + return "NULL"; + return value.toString(); + } // saveNewSpecial + + /** + * Encrypt data. + * Not: LOB, special values/Obkects + * @param index index + * @param xx data + * @return xx + */ + private Object encrypt (int index, Object xx) + { + if (xx == null) + return null; + if (index != -1 && p_info.isEncrypted(index)) + return SecureEngine.encrypt(xx); + return xx; + } // encrypt + + /** + * Decrypt data + * @param index index + * @param yy data + * @return yy + */ + private Object decrypt (int index, Object yy) + { + if (yy == null) + return null; + if (index != -1 && p_info.isEncrypted(index)) + return SecureEngine.decrypt(yy); + return yy; + } // decrypt + + /************************************************************************** + * Delete Current Record + * @param force delete also processed records + * @return true if deleted + */ + public boolean delete (boolean force) + { + CLogger.resetLast(); + if (is_new()) + return true; + + int AD_Table_ID = p_info.getAD_Table_ID(); + int Record_ID = get_ID(); + + if (!force) + { + int iProcessed = get_ColumnIndex("Processed"); + if (iProcessed != -1) + { + Boolean processed = (Boolean)get_Value(iProcessed); + if (processed != null && processed.booleanValue()) + { + log.warning("Record processed"); // CannotDeleteTrx + log.saveError("Processed", "Processed", false); + return false; + } + } // processed + } // force + + Trx localTrx = null; + boolean success = false; + try + { + + String localTrxName = m_trxName; + if (localTrxName == null) + { + localTrxName = Trx.createTrxName("POdel"); + localTrx = Trx.get(localTrxName, true); + m_trxName = localTrxName; + } + + try + { + if (!beforeDelete()) + { + log.warning("beforeDelete failed"); + return false; + } + } + catch (Exception e) + { + log.log(Level.WARNING, "beforeDelete", e); + log.saveError("Error", e.toString(), false); + // throw new DBException(e); + return false; + } + // Delete Restrict AD_Table_ID/Record_ID (Requests, ..) + String errorMsg = PO_Record.exists(AD_Table_ID, Record_ID, m_trxName); + if (errorMsg != null) + { + log.saveError("CannotDelete", errorMsg); + return false; + } + // Call ModelValidators TYPE_DELETE + errorMsg = ModelValidationEngine.get().fireModelChange + (this, isReplication() ? ModelValidator.TYPE_BEFORE_DELETE_REPLICATION : ModelValidator.TYPE_DELETE); + setReplication(false); // @Trifon + if (errorMsg != null) + { + log.saveError("Error", errorMsg); + return false; + } + + // + deleteTranslations(localTrxName); + // Delete Cascade AD_Table_ID/Record_ID (Attachments, ..) + PO_Record.deleteCascade(AD_Table_ID, Record_ID, localTrxName); + + // The Delete Statement + StringBuffer sql = new StringBuffer ("DELETE FROM ") //jz why no FROM?? + .append(p_info.getTableName()) + .append(" WHERE ") + .append(get_WhereClause(true)); + int no = DB.executeUpdate(sql.toString(), localTrxName); + success = no == 1; + + // Save ID + m_idOld = get_ID(); + // + if (!success) + { + log.warning("Not deleted"); + if (localTrx != null) + localTrx.rollback(); + } + else + { + if (success) + { + // Change Log + MSession session = MSession.get (p_ctx, false); + if (session == null) + log.fine("No Session found"); + else if (m_IDs.length == 1) + { + int AD_ChangeLog_ID = 0; + int size = get_ColumnCount(); + for (int i = 0; i < size; i++) + { + Object value = m_oldValues[i]; + if (value != null + && p_info.isAllowLogging(i) // logging allowed + && !p_info.isEncrypted(i) // not encrypted + && !p_info.isVirtualColumn(i) // no virtual column + && !"Password".equals(p_info.getColumnName(i)) + ) + { + // change log on delete + MChangeLog cLog = session.changeLog ( + m_trxName != null ? m_trxName : localTrxName, AD_ChangeLog_ID, + AD_Table_ID, p_info.getColumn(i).AD_Column_ID, + Record_ID, getAD_Client_ID(), getAD_Org_ID(), value, null, MChangeLog.EVENTCHANGELOG_Delete); + if (cLog != null) + AD_ChangeLog_ID = cLog.getAD_ChangeLog_ID(); + } + } // for all fields + } + + // Housekeeping + m_IDs[0] = I_ZERO; + if (m_trxName == null) + log.fine("complete"); + else + log.fine("[" + m_trxName + "] - complete"); + m_attachment = null; + } + else + { + log.warning("Not deleted"); + } + } + + try + { + success = afterDelete (success); + } + catch (Exception e) + { + log.log(Level.WARNING, "afterDelete", e); + log.saveError("Error", e.toString(), false); + success = false; + // throw new DBException(e); + } + + // Call ModelValidators TYPE_AFTER_DELETE - teo_sarca [ 1675490 ] + if (success) { + errorMsg = ModelValidationEngine.get().fireModelChange(this, ModelValidator.TYPE_AFTER_DELETE); + if (errorMsg != null) { + log.saveError("Error", errorMsg); + success = false; + } + } + + if (!success) + { + if (localTrx != null) + localTrx.rollback(); + } + else + { + if (localTrx != null) + { + try { + localTrx.commit(true); + } catch (SQLException e) { + log.saveError("Error", e); + success = false; + } + } + } + + // Reset + if (success) + { + m_idOld = 0; + int size = p_info.getColumnCount(); + m_oldValues = new Object[size]; + m_newValues = new Object[size]; + CacheMgt.get().reset(p_info.getTableName()); + } + } + finally + { + if (localTrx != null) + { + localTrx.close(); + m_trxName = null; + } + } + // log.info("" + success); + return success; + } // delete + + /** + * Delete Current Record + * @param force delete also processed records + * @throws AdempiereException + * @see #delete(boolean) + */ + public void deleteEx(boolean force) throws AdempiereException + { + if (!delete(force)) { + String msg = null; + ValueNamePair err = CLogger.retrieveError(); + if (err != null) + msg = err.getName(); + if (msg == null || msg.length() == 0) + msg = "DeleteError"; + throw new AdempiereException(msg); + } + } + + /** + * Delete Current Record + * @param force delete also processed records + * @param trxName transaction + * @return true if deleted + */ + public boolean delete (boolean force, String trxName) + { + set_TrxName(trxName); + return delete (force); + } // delete + + /** + * Delete Current Record + * @param force delete also processed records + * @param trxName transaction + * @throws AdempiereException + * @see {@link #deleteEx(boolean)} + */ + public void deleteEx(boolean force, String trxName) throws AdempiereException + { + set_TrxName(trxName); + deleteEx(force); + } + + /** + * Executed before Delete operation. + * @return true if record can be deleted + */ + protected boolean beforeDelete () + { + // log.saveError("Error", Msg.getMsg(getCtx(), "CannotDelete")); + return true; + } // beforeDelete + + /** + * Executed after Delete operation. + * @param success true if record deleted + * @return true if delete is a success + */ + protected boolean afterDelete (boolean success) + { + return success; + } // afterDelete + + + /** + * Insert (missing) Translation Records + * @return false if error (true if no translation or success) + */ + private boolean insertTranslations() + { + // Not a translation table + if (m_IDs.length > 1 + || m_IDs[0].equals(I_ZERO) + || !p_info.isTranslated() + || !(m_IDs[0] instanceof Integer)) + return true; + // + StringBuffer iColumns = new StringBuffer(); + StringBuffer sColumns = new StringBuffer(); + for (int i = 0; i < p_info.getColumnCount(); i++) + { + if (p_info.isColumnTranslated(i)) + { + iColumns.append(p_info.getColumnName(i)) + .append(","); + sColumns.append("t.") + .append(p_info.getColumnName(i)) + .append(","); + } + } + if (iColumns.length() == 0) + return true; + + String tableName = p_info.getTableName(); + String keyColumn = m_KeyColumns[0]; + StringBuffer sql = new StringBuffer ("INSERT INTO ") + .append(tableName).append("_Trl (AD_Language,") + .append(keyColumn).append(", ") + .append(iColumns) + .append(" IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy) ") + .append("SELECT l.AD_Language,t.") + .append(keyColumn).append(", ") + .append(sColumns) + .append(" 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy ") + .append("FROM AD_Language l, ").append(tableName).append(" t ") + .append("WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.") + .append(keyColumn).append("=").append(get_ID()) + /*jz since derby bug, rewrite the sql + .append(" AND NOT EXISTS (SELECT * FROM ").append(tableName) + .append("_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.") + .append(keyColumn).append("=t.").append(keyColumn).append(")"); + */ + .append(" AND EXISTS (SELECT * FROM ").append(tableName) + .append("_Trl tt WHERE tt.AD_Language!=l.AD_Language OR tt.") + .append(keyColumn).append("!=t.").append(keyColumn).append(")"); + int no = DB.executeUpdate(sql.toString(), m_trxName); + log.fine("#" + no); + return no > 0; + } // insertTranslations + + /** + * Update Translations. + * @return false if error (true if no translation or success) + */ + private boolean updateTranslations() + { + // Not a translation table + if (m_IDs.length > 1 + || m_IDs[0].equals(I_ZERO) + || !p_info.isTranslated() + || !(m_IDs[0] instanceof Integer)) + return true; + // + boolean trlColumnChanged = false; + for (int i = 0; i < p_info.getColumnCount(); i++) + { + if (p_info.isColumnTranslated(i) + && is_ValueChanged(p_info.getColumnName(i))) + { + trlColumnChanged = true; + break; + } + } + if (!trlColumnChanged) + return true; + // + MClient client = MClient.get(getCtx()); + // + String tableName = p_info.getTableName(); + String keyColumn = m_KeyColumns[0]; + StringBuffer sql = new StringBuffer ("UPDATE ") + .append(tableName).append("_Trl SET "); + // + if (client.isAutoUpdateTrl(tableName)) + { + for (int i = 0; i < p_info.getColumnCount(); i++) + { + if (p_info.isColumnTranslated(i)) + { + String columnName = p_info.getColumnName(i); + sql.append(columnName).append("="); + Object value = get_Value(columnName); + if (value == null) + sql.append("NULL"); + else if (value instanceof String) + sql.append(DB.TO_STRING((String)value)); + else if (value instanceof Boolean) + sql.append(((Boolean)value).booleanValue() ? "'Y'" : "'N'"); + else if (value instanceof Timestamp) + sql.append(DB.TO_DATE((Timestamp)value)); + else + sql.append(value.toString()); + sql.append(","); + } + } + sql.append("IsTranslated='Y'"); + } + else + sql.append("IsTranslated='N'"); + // + sql.append(" WHERE ") + .append(keyColumn).append("=").append(get_ID()); + int no = DB.executeUpdate(sql.toString(), m_trxName); + log.fine("#" + no); + return no >= 0; + } // updateTranslations + + /** + * Delete Translation Records + * @param trxName transaction + * @return false if error (true if no translation or success) + */ + private boolean deleteTranslations(String trxName) + { + // Not a translation table + if (m_IDs.length > 1 + || m_IDs[0].equals(I_ZERO) + || !p_info.isTranslated() + || !(m_IDs[0] instanceof Integer)) + return true; + // + String tableName = p_info.getTableName(); + String keyColumn = m_KeyColumns[0]; + StringBuffer sql = new StringBuffer ("DELETE FROM ") + .append(tableName).append("_Trl WHERE ") + .append(keyColumn).append("=").append(get_ID()); + int no = DB.executeUpdate(sql.toString(), trxName); + log.fine("#" + no); + return no >= 0; + } // deleteTranslations + + /** + * Insert Accounting Records + * @param acctTable accounting sub table + * @param acctBaseTable acct table to get data from + * @param whereClause optional where clause with alisa "p" for acctBaseTable + * @return true if records inserted + */ + protected boolean insert_Accounting (String acctTable, + String acctBaseTable, String whereClause) + { + if (s_acctColumns == null // cannot cache C_BP_*_Acct as there are 3 + || acctTable.startsWith("C_BP_")) + { + s_acctColumns = new ArrayList(); + String sql = "SELECT c.ColumnName " + + "FROM AD_Column c INNER JOIN AD_Table t ON (c.AD_Table_ID=t.AD_Table_ID) " + + "WHERE t.TableName=? AND c.IsActive='Y' AND c.AD_Reference_ID=25 ORDER BY 1"; + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setString (1, acctTable); + rs = pstmt.executeQuery (); + while (rs.next ()) + s_acctColumns.add (rs.getString(1)); + } + catch (Exception e) + { + log.log(Level.SEVERE, acctTable, e); + } + finally { + DB.close(rs, pstmt); + rs = null; pstmt = null; + } + if (s_acctColumns.size() == 0) + { + log.severe ("No Columns for " + acctTable); + return false; + } + } + + // Create SQL Statement - INSERT + StringBuffer sb = new StringBuffer("INSERT INTO ") + .append(acctTable) + .append(" (").append(get_TableName()) + .append("_ID, C_AcctSchema_ID, AD_Client_ID,AD_Org_ID,IsActive, Created,CreatedBy,Updated,UpdatedBy "); + for (int i = 0; i < s_acctColumns.size(); i++) + sb.append(",").append(s_acctColumns.get(i)); + // .. SELECT + sb.append(") SELECT ").append(get_ID()) + .append(", p.C_AcctSchema_ID, p.AD_Client_ID,0,'Y', SysDate,") + .append(getUpdatedBy()).append(",SysDate,").append(getUpdatedBy()); + for (int i = 0; i < s_acctColumns.size(); i++) + sb.append(",p.").append(s_acctColumns.get(i)); + // .. FROM + sb.append(" FROM ").append(acctBaseTable) + .append(" p WHERE p.AD_Client_ID=").append(getAD_Client_ID()); + if (whereClause != null && whereClause.length() > 0) + sb.append (" AND ").append(whereClause); + sb.append(" AND NOT EXISTS (SELECT * FROM ").append(acctTable) + .append(" e WHERE e.C_AcctSchema_ID=p.C_AcctSchema_ID AND e.") + .append(get_TableName()).append("_ID=").append(get_ID()).append(")"); + // + int no = DB.executeUpdate(sb.toString(), get_TrxName()); + if (no > 0) + log.fine("#" + no); + else + log.warning("#" + no + + " - Table=" + acctTable + " from " + acctBaseTable); + return no > 0; + } // insert_Accounting + + /** + * Delete Accounting records. + * NOP - done by database constraints + * @param acctTable accounting sub table + * @return true + */ + protected boolean delete_Accounting(String acctTable) + { + return true; + } // delete_Accounting + + + /** + * Insert id data into Tree + * @param treeType MTree TREETYPE_* + * @return true if inserted + */ + protected boolean insert_Tree (String treeType) + { + return insert_Tree (treeType, 0); + } // insert_Tree + + /** + * Insert id data into Tree + * @param treeType MTree TREETYPE_* + * @param C_Element_ID element for accounting element values + * @return true if inserted + */ + protected boolean insert_Tree (String treeType, int C_Element_ID) + { + StringBuffer sb = new StringBuffer ("INSERT INTO ") + .append(MTree_Base.getNodeTableName(treeType)) + .append(" (AD_Client_ID,AD_Org_ID, IsActive,Created,CreatedBy,Updated,UpdatedBy, " + + "AD_Tree_ID, Node_ID, Parent_ID, SeqNo) " + + "SELECT t.AD_Client_ID,0, 'Y', SysDate, 0, SysDate, 0," + + "t.AD_Tree_ID, ").append(get_ID()).append(", 0, 999 " + + "FROM AD_Tree t " + + "WHERE t.AD_Client_ID=").append(getAD_Client_ID()).append(" AND t.IsActive='Y'"); + // Account Element Value handling + if (C_Element_ID != 0) + sb.append(" AND EXISTS (SELECT * FROM C_Element ae WHERE ae.C_Element_ID=") + .append(C_Element_ID).append(" AND t.AD_Tree_ID=ae.AD_Tree_ID)"); + else // std trees + sb.append(" AND t.IsAllNodes='Y' AND t.TreeType='").append(treeType).append("'"); + // Duplicate Check + sb.append(" AND NOT EXISTS (SELECT * FROM " + MTree_Base.getNodeTableName(treeType) + " e " + + "WHERE e.AD_Tree_ID=t.AD_Tree_ID AND Node_ID=").append(get_ID()).append(")"); + int no = DB.executeUpdate(sb.toString(), get_TrxName()); + if (no > 0) + log.fine("#" + no + " - TreeType=" + treeType); + else + log.warning("#" + no + " - TreeType=" + treeType); + return no > 0; + } // insert_Tree + + /** + * Delete ID Tree Nodes + * @param treeType MTree TREETYPE_* + * @return true if deleted + */ + protected boolean delete_Tree (String treeType) + { + int id = get_ID(); + if (id == 0) + id = get_IDOld(); + StringBuffer sb = new StringBuffer ("DELETE FROM ") + .append(MTree_Base.getNodeTableName(treeType)) + .append(" n WHERE Node_ID=").append(id) + .append(" AND EXISTS (SELECT * FROM AD_Tree t " + + "WHERE t.AD_Tree_ID=n.AD_Tree_ID AND t.TreeType='") + .append(treeType).append("')"); + int no = DB.executeUpdate(sb.toString(), get_TrxName()); + if (no > 0) + log.fine("#" + no + " - TreeType=" + treeType); + else + log.warning("#" + no + " - TreeType=" + treeType); + return no > 0; + } // delete_Tree + + /************************************************************************** + * Lock it. + * @return true if locked + */ + public boolean lock() + { + int index = get_ProcessingIndex(); + if (index != -1) + { + m_newValues[index] = Boolean.TRUE; // direct + String sql = "UPDATE " + p_info.getTableName() + + " SET Processing='Y' WHERE (Processing='N' OR Processing IS NULL) AND " + + get_WhereClause(true); + boolean success = DB.executeUpdate(sql, null) == 1; // outside trx + if (success) + log.fine("success"); + else + log.log(Level.WARNING, "failed"); + return success; + } + return false; + } // lock + + /** + * Get the Column Processing index + * @return index or -1 + */ + private int get_ProcessingIndex() + { + return p_info.getColumnIndex("Processing"); + } // getProcessingIndex + + /** + * UnLock it + * @param trxName transaction + * @return true if unlocked (false only if unlock fails) + */ + public boolean unlock (String trxName) + { + // log.warning(trxName); + int index = get_ProcessingIndex(); + if (index != -1) + { + m_newValues[index] = Boolean.FALSE; // direct + String sql = "UPDATE " + p_info.getTableName() + + " SET Processing='N' WHERE " + get_WhereClause(true); + boolean success = DB.executeUpdate(sql, trxName) == 1; + if (success) + log.fine("success" + (trxName == null ? "" : "[" + trxName + "]")); + else + log.log(Level.WARNING, "failed" + (trxName == null ? "" : " [" + trxName + "]")); + return success; + } + return true; + } // unlock + + /** Optional Transaction */ + private String m_trxName = null; + + /** + * Set Trx + * @param trxName transaction + */ + public void set_TrxName (String trxName) + { + m_trxName = trxName; + } // setTrx + + /** + * Get Trx + * @return transaction + */ + public String get_TrxName() + { + return m_trxName; + } // getTrx + + + /************************************************************************** + * Get Attachments. + * An attachment may have multiple entries + * @return Attachment or null + */ + public MAttachment getAttachment () + { + return getAttachment(false); + } // getAttachment + + /** + * Get Attachments + * @param requery requery + * @return Attachment or null + */ + public MAttachment getAttachment (boolean requery) + { + if (m_attachment == null || requery) + m_attachment = MAttachment.get (getCtx(), p_info.getAD_Table_ID(), get_ID()); + return m_attachment; + } // getAttachment + + /** + * Create/return Attachment for PO. + * If not exist, create new + * @return attachment + */ + public MAttachment createAttachment() + { + getAttachment (false); + if (m_attachment == null) + m_attachment = new MAttachment (getCtx(), p_info.getAD_Table_ID(), get_ID(), null); + return m_attachment; + } // createAttachment + + + /** + * Do we have a Attachment of type + * @param extension extension e.g. .pdf + * @return true if there is a attachment of type + */ + public boolean isAttachment (String extension) + { + getAttachment (false); + if (m_attachment == null) + return false; + for (int i = 0; i < m_attachment.getEntryCount(); i++) + { + if (m_attachment.getEntryName(i).endsWith(extension)) + { + log.fine("#" + i + ": " + m_attachment.getEntryName(i)); + return true; + } + } + return false; + } // isAttachment + + /** + * Get Attachment Data of type + * @param extension extension e.g. .pdf + * @return data or null + */ + public byte[] getAttachmentData (String extension) + { + getAttachment(false); + if (m_attachment == null) + return null; + for (int i = 0; i < m_attachment.getEntryCount(); i++) + { + if (m_attachment.getEntryName(i).endsWith(extension)) + { + log.fine("#" + i + ": " + m_attachment.getEntryName(i)); + return m_attachment.getEntryData(i); + } + } + return null; + } // getAttachmentData + + /** + * Do we have a PDF Attachment + * @return true if there is a PDF attachment + */ + public boolean isPdfAttachment() + { + return isAttachment(".pdf"); + } // isPdfAttachment + + /** + * Get PDF Attachment Data + * @return data or null + */ + public byte[] getPdfAttachment() + { + return getAttachmentData(".pdf"); + } // getPDFAttachment + + + /************************************************************************** + * Dump Record + */ + public void dump () + { + if (CLogMgt.isLevelFinest()) + { + log.finer(get_WhereClause (true)); + for (int i = 0; i < get_ColumnCount (); i++) + dump (i); + } + } // dump + + /** + * Dump column + * @param index index + */ + public void dump (int index) + { + StringBuffer sb = new StringBuffer(" ").append(index); + if (index < 0 || index >= get_ColumnCount()) + { + log.finest(sb.append(": invalid").toString()); + return; + } + sb.append(": ").append(get_ColumnName(index)) + .append(" = ").append(m_oldValues[index]) + .append(" (").append(m_newValues[index]).append(")"); + log.finest(sb.toString()); + } // dump + + + /************************************************************************* + * Get All IDs of Table. + * Used for listing all Entities + * + int[] IDs = PO.getAllIDs ("AD_PrintFont", null); + for (int i = 0; i < IDs.length; i++) + { + pf = new MPrintFont(Env.getCtx(), IDs[i]); + System.out.println(IDs[i] + " = " + pf.getFont()); + } + * + * @param TableName table name (key column with _ID) + * @param WhereClause optional where clause + * @return array of IDs or null + * @param trxName transaction + */ + public static int[] getAllIDs (String TableName, String WhereClause, String trxName) + { + ArrayList list = new ArrayList(); + StringBuffer sql = new StringBuffer("SELECT "); + sql.append(TableName).append("_ID FROM ").append(TableName); + if (WhereClause != null && WhereClause.length() > 0) + sql.append(" WHERE ").append(WhereClause); + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement(sql.toString(), trxName); + rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new Integer(rs.getInt(1))); + } + catch (SQLException e) + { + s_log.log(Level.SEVERE, sql.toString(), e); + return null; + } + finally { + DB.close(rs, pstmt); + rs = null; pstmt = null; + } + // Convert to array + int[] retValue = new int[list.size()]; + for (int i = 0; i < retValue.length; i++) + retValue[i] = ((Integer)list.get(i)).intValue(); + return retValue; + } // getAllIDs + + + /** + * Get Find parameter. + * Convert to upper case and add % at the end + * @param query in string + * @return out string + */ + protected static String getFindParameter (String query) + { + if (query == null) + return null; + if (query.length() == 0 || query.equals("%")) + return null; + if (!query.endsWith("%")) + query += "%"; + return query.toUpperCase(); + } // getFindParameter + + + /************************************************************************** + * Load LOB + * @param value LOB + * @return object + */ + private Object get_LOB (Object value) + { + log.fine("Value=" + value); + if (value == null) + return null; + // + Object retValue = null; + + long length = -99; + try + { + //[ 1643996 ] Chat not working in postgres port + if (value instanceof String || + value instanceof byte[]) + retValue = value; + else if (value instanceof Clob) // returns String + { + Clob clob = (Clob)value; + length = clob.length(); + retValue = clob.getSubString(1, (int)length); + } + else if (value instanceof Blob) // returns byte[] + { + Blob blob = (Blob)value; + length = blob.length(); + int index = 1; // correct + if (blob.getClass().getName().equals("oracle.jdbc.rowset.OracleSerialBlob")) + index = 0; // Oracle Bug Invalid Arguments + // at oracle.jdbc.rowset.OracleSerialBlob.getBytes(OracleSerialBlob.java:130) + retValue = blob.getBytes(index, (int)length); + } + else + log.log(Level.SEVERE, "Unknown: " + value); + } + catch (Exception e) + { + log.log(Level.SEVERE, "Length=" + length, e); + } + return retValue; + } // getLOB + + /** LOB Info */ + private ArrayList m_lobInfo = null; + + /** + * Reset LOB info + */ + private void lobReset() + { + m_lobInfo = null; + } // resetLOB + + /** + * Prepare LOB save + * @param value value + * @param index index + * @param displayType display type + */ + private void lobAdd (Object value, int index, int displayType) + { + log.finest("Value=" + value); + PO_LOB lob = new PO_LOB (p_info.getTableName(), get_ColumnName(index), + get_WhereClause(true), displayType, value); + if (m_lobInfo == null) + m_lobInfo = new ArrayList(); + m_lobInfo.add(lob); + } // lobAdd + + /** + * Save LOB + * @return true if saved or ok + */ + private boolean lobSave () + { + if (m_lobInfo == null) + return true; + boolean retValue = true; + for (int i = 0; i < m_lobInfo.size(); i++) + { + PO_LOB lob = (PO_LOB)m_lobInfo.get(i); + if (!lob.save(get_TrxName())) + { + retValue = false; + break; + } + } // for all LOBs + lobReset(); + return retValue; + } // saveLOB + + /** + * Get Object xml representation as string + * @param xml optional string buffer + * @return updated/new string buffer header is only added once + */ + public StringBuffer get_xmlString (StringBuffer xml) + { + if (xml == null) + xml = new StringBuffer(); + else + xml.append(Env.NL); + // + try + { + StringWriter writer = new StringWriter(); + StreamResult result = new StreamResult(writer); + DOMSource source = new DOMSource(get_xmlDocument(xml.length()!=0)); + TransformerFactory tFactory = TransformerFactory.newInstance(); + Transformer transformer = tFactory.newTransformer(); + transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes"); + transformer.transform (source, result); + StringBuffer newXML = writer.getBuffer(); + // + if (xml.length() != 0) + { // // + int tagIndex = newXML.indexOf("?>"); + if (tagIndex != -1) + xml.append(newXML.substring(tagIndex+2)); + else + xml.append(newXML); + } + else + xml.append(newXML); + } + catch (Exception e) + { + log.log(Level.SEVERE, "", e); + } + return xml; + } // get_xmlString + + /** Table ID Attribute */ + protected final static String XML_ATTRIBUTE_AD_Table_ID = "AD_Table_ID"; + /** Record ID Attribute */ + protected final static String XML_ATTRIBUTE_Record_ID = "Record_ID"; + + /** + * Get XML Document representation + * @param noComment do not add comment + * @return XML document + */ + public Document get_xmlDocument(boolean noComment) + { + Document document = null; + try + { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + document = builder.newDocument(); + if (!noComment) + document.appendChild(document.createComment(Adempiere.getSummaryAscii())); + } + catch (Exception e) + { + log.log(Level.SEVERE, "", e); + } + // Root + Element root = document.createElement(get_TableName()); + root.setAttribute(XML_ATTRIBUTE_AD_Table_ID, String.valueOf(get_Table_ID())); + root.setAttribute(XML_ATTRIBUTE_Record_ID, String.valueOf(get_ID())); + document.appendChild(root); + // Columns + int size = get_ColumnCount(); + for (int i = 0; i < size; i++) + { + if (p_info.isVirtualColumn(i)) + continue; + + Element col = document.createElement(p_info.getColumnName(i)); + // + Object value = get_Value(i); + // Display Type + int dt = p_info.getColumnDisplayType(i); + // Based on class of definition, not class of value + Class c = p_info.getColumnClass(i); + if (value == null || value.equals (Null.NULL)) + ; + else if (c == Object.class) + col.appendChild(document.createCDATASection(value.toString())); + else if (value instanceof Integer || value instanceof BigDecimal) + col.appendChild(document.createTextNode(value.toString())); + else if (c == Boolean.class) + { + boolean bValue = false; + if (value instanceof Boolean) + bValue = ((Boolean)value).booleanValue(); + else + bValue = "Y".equals(value); + col.appendChild(document.createTextNode(bValue ? "Y" : "N")); + } + else if (value instanceof Timestamp) + col.appendChild(document.createTextNode(value.toString())); + else if (c == String.class) + col.appendChild(document.createCDATASection((String)value)); + else if (DisplayType.isLOB(dt)) + col.appendChild(document.createCDATASection(value.toString())); + else + col.appendChild(document.createCDATASection(value.toString())); + // + root.appendChild(col); + } + // Custom Columns + if (m_custom != null) + { + Iterator it = m_custom.keySet().iterator(); + while (it.hasNext()) + { + String columnName = (String)it.next(); +// int index = p_info.getColumnIndex(columnName); + String value = (String)m_custom.get(columnName); + // + Element col = document.createElement(columnName); + if (value != null) + col.appendChild(document.createTextNode(value)); + root.appendChild(col); + } + m_custom = null; + } + return document; + } // getDocument + + /* Doc - To be used on ModelValidator to get the corresponding Doc from the PO */ + private Doc m_doc; + + /** + * Set the accounting document associated to the PO - for use in POST ModelValidator + * @param doc Document + */ + public void setDoc(Doc doc) { + m_doc = doc; + } + + public void setReplication(boolean isFromReplication) + { + m_isReplication = isFromReplication; + } + + public boolean isReplication() + { + return m_isReplication; + } + + /** + * Set the accounting document associated to the PO - for use in POST ModelValidator + * @return Doc Document + */ + public Doc getDoc() { + return m_doc; + } + + /** + * PO.setTrxName - set given trxName to an array of POs + * As suggested by teo in [ 1854603 ] + */ + public static void set_TrxName(PO[] lines, String trxName) { + for (PO line : lines) + line.set_TrxName(trxName); + } + +} // PO diff --git a/base/src/org/compiere/model/POInfo.java b/base/src/org/compiere/model/POInfo.java index 4b89be1cea..f1185d9a2c 100644 --- a/base/src/org/compiere/model/POInfo.java +++ b/base/src/org/compiere/model/POInfo.java @@ -1,697 +1,713 @@ -/****************************************************************************** - * Product: Adempiere ERP & CRM Smart Business Solution * - * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * - * This program is free software; you can redistribute it and/or modify it * - * under the terms version 2 of the GNU General Public License as published * - * by the Free Software Foundation. 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. * - * For the text or an alternative of this public license, you may reach us * - * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * - * or via info@compiere.org or http://www.compiere.org/license.html * - *****************************************************************************/ -package org.compiere.model; - -import java.io.Serializable; -import java.math.BigDecimal; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Properties; -import java.util.logging.Level; - -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; - -/** - * Persistet Object Info. - * Provides structural information - * - * @author Jorg Janke - * @version $Id: POInfo.java,v 1.2 2006/07/30 00:58:37 jjanke Exp $ - */ -public class POInfo implements Serializable -{ - /** Used by Remote FinReport */ - static final long serialVersionUID = -5976719579744948419L; - - /** - * POInfo Factory - * @param ctx context - * @param AD_Table_ID AD_Table_ID - * @return POInfo - */ - public static POInfo getPOInfo (Properties ctx, int AD_Table_ID) - { - return getPOInfo(ctx, AD_Table_ID, null); - } - - /** - * POInfo Factory - * @param ctx context - * @param AD_Table_ID AD_Table_ID - * @param trxName Transaction name - * @return POInfo - */ - public static POInfo getPOInfo (Properties ctx, int AD_Table_ID, String trxName) - { - Integer key = new Integer(AD_Table_ID); - POInfo retValue = (POInfo)s_cache.get(key); - if (retValue == null) - { - retValue = new POInfo(ctx, AD_Table_ID, false, trxName); - if (retValue.getColumnCount() == 0) - // May be run before Language verification - retValue = new POInfo(ctx, AD_Table_ID, true, trxName); - else - s_cache.put(key, retValue); - } - return retValue; - } // getPOInfo - - /** Cache of POInfo */ - private static CCache s_cache = new CCache("POInfo", 200); - - /************************************************************************** - * Create Persistent Info - * @param ctx context - * @param AD_Table_ID AD_ Table_ID - * @param baseLanguageOnly get in base language - */ - private POInfo (Properties ctx, int AD_Table_ID, boolean baseLanguageOnly) - { - this(ctx, AD_Table_ID, baseLanguageOnly, null); - } - - /************************************************************************** - * Create Persistent Info - * @param ctx context - * @param AD_Table_ID AD_ Table_ID - * @param baseLanguageOnly get in base language - * @param trxName transaction name - */ - private POInfo (Properties ctx, int AD_Table_ID, boolean baseLanguageOnly, String trxName) - { - m_ctx = ctx; - m_AD_Table_ID = AD_Table_ID; - boolean baseLanguage = baseLanguageOnly ? true : Env.isBaseLanguage(m_ctx, "AD_Table"); - loadInfo (baseLanguage, trxName); - } // PInfo - - /** Context */ - private Properties m_ctx = null; - /** Table_ID */ - private int m_AD_Table_ID = 0; - /** Table Name */ - private String m_TableName = null; - /** Access Level */ - private String m_AccessLevel = MTable.ACCESSLEVEL_Organization; - /** Columns */ - private POInfoColumn[] m_columns = null; - /** Table has Key Column */ - private boolean m_hasKeyColumn = false; - - - /** - * Load Table/Column Info - * @param baseLanguage in English - * @param trxName - */ - private void loadInfo (boolean baseLanguage, String trxName) - { - ArrayList list = new ArrayList(15); - StringBuffer sql = new StringBuffer(); - sql.append("SELECT t.TableName, c.ColumnName,c.AD_Reference_ID," // 1..3 - + "c.IsMandatory,c.IsUpdateable,c.DefaultValue," // 4..6 - + "e.Name,e.Description, c.AD_Column_ID, " // 7..9 - + "c.IsKey,c.IsParent, " // 10..11 - + "c.AD_Reference_Value_ID, vr.Code, " // 12..13 - + "c.FieldLength, c.ValueMin, c.ValueMax, c.IsTranslated, " // 14..17 - + "t.AccessLevel, c.ColumnSQL, c.IsEncrypted "); // 18..20 - sql.append("FROM AD_Table t" - + " INNER JOIN AD_Column c ON (t.AD_Table_ID=c.AD_Table_ID)" - + " LEFT OUTER JOIN AD_Val_Rule vr ON (c.AD_Val_Rule_ID=vr.AD_Val_Rule_ID)" - + " INNER JOIN AD_Element"); - if (!baseLanguage) - sql.append("_Trl"); - sql.append(" e " - + " ON (c.AD_Element_ID=e.AD_Element_ID) " - + "WHERE t.AD_Table_ID=?" - + " AND c.IsActive='Y'"); - if (!baseLanguage) - sql.append(" AND e.AD_Language='").append(Env.getAD_Language(m_ctx)).append("'"); - // - PreparedStatement pstmt = null; - ResultSet rs = null; - try - { - pstmt = DB.prepareStatement(sql.toString(), trxName); - pstmt.setInt(1, m_AD_Table_ID); - rs = pstmt.executeQuery(); - while (rs.next()) - { - if (m_TableName == null) - m_TableName = rs.getString(1); - String ColumnName = rs.getString(2); - int AD_Reference_ID = rs.getInt(3); - boolean IsMandatory = "Y".equals(rs.getString(4)); - boolean IsUpdateable = "Y".equals(rs.getString(5)); - String DefaultLogic = rs.getString(6); - String Name = rs.getString(7); - String Description = rs.getString(8); - int AD_Column_ID = rs.getInt(9); - boolean IsKey = "Y".equals(rs.getString(10)); - if (IsKey) - m_hasKeyColumn = true; - boolean IsParent = "Y".equals(rs.getString(11)); - int AD_Reference_Value_ID = rs.getInt(12); - String ValidationCode = rs.getString(13); - int FieldLength = rs.getInt(14); - String ValueMin = rs.getString(15); - String ValueMax = rs.getString(16); - boolean IsTranslated = "Y".equals(rs.getString(17)); - // - m_AccessLevel = rs.getString(18); - String ColumnSQL = rs.getString(19); - boolean IsEncrypted = "Y".equals(rs.getString(20)); - - POInfoColumn col = new POInfoColumn ( - AD_Column_ID, ColumnName, ColumnSQL, AD_Reference_ID, - IsMandatory, IsUpdateable, - DefaultLogic, Name, Description, - IsKey, IsParent, - AD_Reference_Value_ID, ValidationCode, - FieldLength, ValueMin, ValueMax, - IsTranslated, IsEncrypted); - list.add(col); - } - } - catch (SQLException e) - { - CLogger.get().log(Level.SEVERE, sql.toString(), e); - } - finally { - DB.close(rs, pstmt); - rs = null; pstmt = null; - } - // convert to array - m_columns = new POInfoColumn[list.size()]; - list.toArray(m_columns); - } // loadInfo - - /** - * String representation - * @return String Representation - */ - public String toString() - { - return "POInfo[" + getTableName() + ",AD_Table_ID=" + getAD_Table_ID() + "]"; - } // toString - - /** - * String representation for index - * @param index column index - * @return String Representation - */ - public String toString (int index) - { - if (index < 0 || index >= m_columns.length) - return "POInfo[" + getTableName() + "-(InvalidColumnIndex=" + index + ")]"; - return "POInfo[" + getTableName() + "-" + m_columns[index].toString() + "]"; - } // toString - - /** - * Get Table Name - * @return Table Name - */ - public String getTableName() - { - return m_TableName; - } // getTableName - - /** - * Get AD_Table_ID - * @return AD_Table_ID - */ - public int getAD_Table_ID() - { - return m_AD_Table_ID; - } // getAD_Table_ID - - /** - * Table has a Key Column - * @return true if has a key column - */ - public boolean hasKeyColumn() - { - return m_hasKeyColumn; - } // hasKeyColumn - - /** - * Get Table Access Level - * @return Table.ACCESS.. - */ - public String getAccessLevel() - { - return m_AccessLevel; - } // getAccessLevel - - /************************************************************************** - * Get ColumnCount - * @return column count - */ - public int getColumnCount() - { - return m_columns.length; - } // getColumnCount - - /** - * Get Column Index - * @param ColumnName column name - * @return index of column with ColumnName or -1 if not found - */ - public int getColumnIndex (String ColumnName) - { - for (int i = 0; i < m_columns.length; i++) - { - if (ColumnName.equalsIgnoreCase(m_columns[i].ColumnName)) // teo_sarca : modified to compare ignoring case [ 1619179 ] - return i; - } - return -1; - } // getColumnIndex - - /** - * Get Column Index - * @param AD_Column_ID column - * @return index of column with ColumnName or -1 if not found - */ - public int getColumnIndex (int AD_Column_ID) - { - for (int i = 0; i < m_columns.length; i++) - { - if (AD_Column_ID == m_columns[i].AD_Column_ID) - return i; - } - return -1; - } // getColumnIndex - - /** - * @param columnName - * @return AD_Column_ID if found, -1 if not found - */ - public int getAD_Column_ID(String columnName) - { - for (int i = 0; i < m_columns.length; i++) - { - if (m_columns[i].ColumnName.equals(columnName)) - return m_columns[i].AD_Column_ID; - } - return -1; - } - - /** - * Get Column - * @param index index - * @return column - */ - protected POInfoColumn getColumn (int index) - { - if (index < 0 || index >= m_columns.length) - return null; - return m_columns[index]; - } // getColumn - - /** - * Get Column Name - * @param index index - * @return ColumnName column name - */ - public String getColumnName (int index) - { - if (index < 0 || index >= m_columns.length) - return null; - return m_columns[index].ColumnName; - } // getColumnName - - /** - * Get Column SQL or Column Name - * @param index index - * @return ColumnSQL column sql or name - */ - public String getColumnSQL (int index) - { - if (index < 0 || index >= m_columns.length) - return null; - if (m_columns[index].ColumnSQL != null && m_columns[index].ColumnSQL.length() > 0) - return m_columns[index].ColumnSQL + " AS " + m_columns[index].ColumnName; - return m_columns[index].ColumnName; - } // getColumnSQL - - /** - * Is Column Virtal? - * @param index index - * @return true if column is virtual - */ - public boolean isVirtualColumn (int index) - { - if (index < 0 || index >= m_columns.length) - return true; - return m_columns[index].ColumnSQL != null - && m_columns[index].ColumnSQL.length() > 0; - } // isVirtualColumn - - /** - * Get Column Label - * @param index index - * @return column label - */ - public String getColumnLabel (int index) - { - if (index < 0 || index >= m_columns.length) - return null; - return m_columns[index].ColumnLabel; - } // getColumnLabel - - /** - * Get Column Description - * @param index index - * @return column description - */ - public String getColumnDescription (int index) - { - if (index < 0 || index >= m_columns.length) - return null; - return m_columns[index].ColumnDescription; - } // getColumnDescription - - /** - * Get Column Class - * @param index index - * @return Class - */ - public Class getColumnClass (int index) - { - if (index < 0 || index >= m_columns.length) - return null; - return m_columns[index].ColumnClass; - } // getColumnClass - - /** - * Get Column Display Type - * @param index index - * @return DisplayType - */ - public int getColumnDisplayType (int index) - { - if (index < 0 || index >= m_columns.length) - return DisplayType.String; - return m_columns[index].DisplayType; - } // getColumnDisplayType - - /** - * Get Column Default Logic - * @param index index - * @return Default Logic - */ - public String getDefaultLogic (int index) - { - if (index < 0 || index >= m_columns.length) - return null; - return m_columns[index].DefaultLogic; - } // getDefaultLogic - - /** - * Is Column Mandatory - * @param index index - * @return true if column mandatory - */ - public boolean isColumnMandatory (int index) - { - if (index < 0 || index >= m_columns.length) - return false; - return m_columns[index].IsMandatory; - } // isMandatory - - /** - * Is Column Updateable - * @param index index - * @return true if column updateable - */ - public boolean isColumnUpdateable (int index) - { - if (index < 0 || index >= m_columns.length) - return false; - return m_columns[index].IsUpdateable; - } // isUpdateable - - /** - * Set Column Updateable - * @param index index - * @param updateable column updateable - */ - public void setColumnUpdateable (int index, boolean updateable) - { - if (index < 0 || index >= m_columns.length) - return; - m_columns[index].IsUpdateable = updateable; - } // setColumnUpdateable - - /** - * Set all columns updateable - * @param updateable updateable - */ - public void setUpdateable (boolean updateable) - { - for (int i = 0; i < m_columns.length; i++) - m_columns[i].IsUpdateable = updateable; - } // setUpdateable - - /** - * Is Lookup Column - * @param index index - * @return true if it is a lookup column - */ - public boolean isColumnLookup (int index) - { - if (index < 0 || index >= m_columns.length) - return false; - return DisplayType.isLookup(m_columns[index].DisplayType); - } // isColumnLookup - - /** - * Get Lookup - * @param index index - * @return Lookup - */ - public Lookup getColumnLookup (int index) - { - if (!isColumnLookup(index)) - return null; - // - int WindowNo = 0; - // List, Table, TableDir - Lookup lookup = null; - try - { - lookup = MLookupFactory.get (m_ctx, WindowNo, - m_columns[index].AD_Column_ID, m_columns[index].DisplayType, - Env.getLanguage(m_ctx), m_columns[index].ColumnName, - m_columns[index].AD_Reference_Value_ID, - m_columns[index].IsParent, m_columns[index].ValidationCode); - } - catch (Exception e) - { - lookup = null; // cannot create Lookup - } - return lookup; - /** @todo other lookup types */ - } // getColumnLookup - - /** - * Is Column Key - * @param index index - * @return true if column is the key - */ - public boolean isKey (int index) - { - if (index < 0 || index >= m_columns.length) - return false; - return m_columns[index].IsKey; - } // isKey - - /** - * Is Column Parent - * @param index index - * @return true if column is a Parent - */ - public boolean isColumnParent (int index) - { - if (index < 0 || index >= m_columns.length) - return false; - return m_columns[index].IsParent; - } // isColumnParent - - /** - * Is Column Translated - * @param index index - * @return true if column is translated - */ - public boolean isColumnTranslated (int index) - { - if (index < 0 || index >= m_columns.length) - return false; - return m_columns[index].IsTranslated; - } // isColumnTranslated - - /** - * Is Table Translated - * @return true if table is translated - */ - public boolean isTranslated () - { - for (int i = 0; i < m_columns.length; i++) - { - if (m_columns[i].IsTranslated) - return true; - } - return false; - } // isTranslated - - /** - * Is Column (data) Encrypted - * @param index index - * @return true if column is encrypted - */ - public boolean isEncrypted (int index) - { - if (index < 0 || index >= m_columns.length) - return false; - return m_columns[index].IsEncrypted; - } // isEncrypted - - /** - * Get Column FieldLength - * @param index index - * @return field length - */ - public int getFieldLength (int index) - { - if (index < 0 || index >= m_columns.length) - return 0; - return m_columns[index].FieldLength; - } // getFieldLength - - /** - * Validate Content - * @param index index - * @param value new Value - * @return null if all valid otherwise error message - */ - public String validate (int index, Object value) - { - if (index < 0 || index >= m_columns.length) - return "RangeError"; - // Mandatory (i.e. not null - if (m_columns[index].IsMandatory && value == null) - { - return "IsMandatory"; - } - if (value == null) - return null; - - // Length ignored - - // - if (m_columns[index].ValueMin != null) - { - BigDecimal value_BD = null; - try - { - if (m_columns[index].ValueMin_BD != null) - value_BD = new BigDecimal(value.toString()); - } - catch (Exception ex){} - // Both are Numeric - if (m_columns[index].ValueMin_BD != null && value_BD != null) - { // error: 1 - 0 => 1 - OK: 1 - 1 => 0 & 1 - 10 => -1 - int comp = m_columns[index].ValueMin_BD.compareTo(value_BD); - if (comp > 0) - { - return "MinValue=" + m_columns[index].ValueMin_BD - + "(" + m_columns[index].ValueMin + ")" - + " - compared with Numeric Value=" + value_BD + "(" + value + ")" - + " - results in " + comp; - } - } - else // String - { - int comp = m_columns[index].ValueMin.compareTo(value.toString()); - if (comp > 0) - { - return "MinValue=" + m_columns[index].ValueMin - + " - compared with String Value=" + value - + " - results in " + comp; - } - } - } - if (m_columns[index].ValueMax != null) - { - BigDecimal value_BD = null; - try - { - if (m_columns[index].ValueMax_BD != null) - value_BD = new BigDecimal(value.toString()); - } - catch (Exception ex){} - // Both are Numeric - if (m_columns[index].ValueMax_BD != null && value_BD != null) - { // error 12 - 20 => -1 - OK: 12 - 12 => 0 & 12 - 10 => 1 - int comp = m_columns[index].ValueMax_BD.compareTo(value_BD); - if (comp < 0) - { - return "MaxValue=" + m_columns[index].ValueMax_BD + "(" + m_columns[index].ValueMax + ")" - + " - compared with Numeric Value=" + value_BD + "(" + value + ")" - + " - results in " + comp; - } - } - else // String - { - int comp = m_columns[index].ValueMax.compareTo(value.toString()); - if (comp < 0) - { - return "MaxValue=" + m_columns[index].ValueMax - + " - compared with String Value=" + value - + " - results in " + comp; - } - } - } - return null; - } // validate - - /** - * Build select clause - * @return stringbuffer - */ - public StringBuffer buildSelect() - { - StringBuffer sql = new StringBuffer("SELECT "); - int size = getColumnCount(); - for (int i = 0; i < size; i++) - { - if (i != 0) - sql.append(","); - sql.append(getColumnSQL(i)); // Normal and Virtual Column - } - sql.append(" FROM ").append(getTableName()); - return sql; - } - -} // POInfo +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Properties; +import java.util.logging.Level; + +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; + +/** + * Persistet Object Info. + * Provides structural information + * + * @author Jorg Janke + * @version $Id: POInfo.java,v 1.2 2006/07/30 00:58:37 jjanke Exp $ + */ +public class POInfo implements Serializable +{ + /** Used by Remote FinReport */ + static final long serialVersionUID = -5976719579744948419L; + + /** + * POInfo Factory + * @param ctx context + * @param AD_Table_ID AD_Table_ID + * @return POInfo + */ + public static POInfo getPOInfo (Properties ctx, int AD_Table_ID) + { + return getPOInfo(ctx, AD_Table_ID, null); + } + + /** + * POInfo Factory + * @param ctx context + * @param AD_Table_ID AD_Table_ID + * @param trxName Transaction name + * @return POInfo + */ + public static POInfo getPOInfo (Properties ctx, int AD_Table_ID, String trxName) + { + Integer key = new Integer(AD_Table_ID); + POInfo retValue = (POInfo)s_cache.get(key); + if (retValue == null) + { + retValue = new POInfo(ctx, AD_Table_ID, false, trxName); + if (retValue.getColumnCount() == 0) + // May be run before Language verification + retValue = new POInfo(ctx, AD_Table_ID, true, trxName); + else + s_cache.put(key, retValue); + } + return retValue; + } // getPOInfo + + /** Cache of POInfo */ + private static CCache s_cache = new CCache("POInfo", 200); + + /************************************************************************** + * Create Persistent Info + * @param ctx context + * @param AD_Table_ID AD_ Table_ID + * @param baseLanguageOnly get in base language + */ + private POInfo (Properties ctx, int AD_Table_ID, boolean baseLanguageOnly) + { + this(ctx, AD_Table_ID, baseLanguageOnly, null); + } + + /************************************************************************** + * Create Persistent Info + * @param ctx context + * @param AD_Table_ID AD_ Table_ID + * @param baseLanguageOnly get in base language + * @param trxName transaction name + */ + private POInfo (Properties ctx, int AD_Table_ID, boolean baseLanguageOnly, String trxName) + { + m_ctx = ctx; + m_AD_Table_ID = AD_Table_ID; + boolean baseLanguage = baseLanguageOnly ? true : Env.isBaseLanguage(m_ctx, "AD_Table"); + loadInfo (baseLanguage, trxName); + } // PInfo + + /** Context */ + private Properties m_ctx = null; + /** Table_ID */ + private int m_AD_Table_ID = 0; + /** Table Name */ + private String m_TableName = null; + /** Access Level */ + private String m_AccessLevel = MTable.ACCESSLEVEL_Organization; + /** Columns */ + private POInfoColumn[] m_columns = null; + /** Table has Key Column */ + private boolean m_hasKeyColumn = false; + + + /** + * Load Table/Column Info + * @param baseLanguage in English + * @param trxName + */ + private void loadInfo (boolean baseLanguage, String trxName) + { + ArrayList list = new ArrayList(15); + StringBuffer sql = new StringBuffer(); + sql.append("SELECT t.TableName, c.ColumnName,c.AD_Reference_ID," // 1..3 + + "c.IsMandatory,c.IsUpdateable,c.DefaultValue," // 4..6 + + "e.Name,e.Description, c.AD_Column_ID, " // 7..9 + + "c.IsKey,c.IsParent, " // 10..11 + + "c.AD_Reference_Value_ID, vr.Code, " // 12..13 + + "c.FieldLength, c.ValueMin, c.ValueMax, c.IsTranslated, " // 14..17 + + "t.AccessLevel, c.ColumnSQL, c.IsEncrypted, " // 18..20 + + "c.IsAllowLogging "); // 21 + sql.append("FROM AD_Table t" + + " INNER JOIN AD_Column c ON (t.AD_Table_ID=c.AD_Table_ID)" + + " LEFT OUTER JOIN AD_Val_Rule vr ON (c.AD_Val_Rule_ID=vr.AD_Val_Rule_ID)" + + " INNER JOIN AD_Element"); + if (!baseLanguage) + sql.append("_Trl"); + sql.append(" e " + + " ON (c.AD_Element_ID=e.AD_Element_ID) " + + "WHERE t.AD_Table_ID=?" + + " AND c.IsActive='Y'"); + if (!baseLanguage) + sql.append(" AND e.AD_Language='").append(Env.getAD_Language(m_ctx)).append("'"); + // + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement(sql.toString(), trxName); + pstmt.setInt(1, m_AD_Table_ID); + rs = pstmt.executeQuery(); + while (rs.next()) + { + if (m_TableName == null) + m_TableName = rs.getString(1); + String ColumnName = rs.getString(2); + int AD_Reference_ID = rs.getInt(3); + boolean IsMandatory = "Y".equals(rs.getString(4)); + boolean IsUpdateable = "Y".equals(rs.getString(5)); + String DefaultLogic = rs.getString(6); + String Name = rs.getString(7); + String Description = rs.getString(8); + int AD_Column_ID = rs.getInt(9); + boolean IsKey = "Y".equals(rs.getString(10)); + if (IsKey) + m_hasKeyColumn = true; + boolean IsParent = "Y".equals(rs.getString(11)); + int AD_Reference_Value_ID = rs.getInt(12); + String ValidationCode = rs.getString(13); + int FieldLength = rs.getInt(14); + String ValueMin = rs.getString(15); + String ValueMax = rs.getString(16); + boolean IsTranslated = "Y".equals(rs.getString(17)); + // + m_AccessLevel = rs.getString(18); + String ColumnSQL = rs.getString(19); + boolean IsEncrypted = "Y".equals(rs.getString(20)); + boolean IsAllowLogging = "Y".equals(rs.getString(21)); + + POInfoColumn col = new POInfoColumn ( + AD_Column_ID, ColumnName, ColumnSQL, AD_Reference_ID, + IsMandatory, IsUpdateable, + DefaultLogic, Name, Description, + IsKey, IsParent, + AD_Reference_Value_ID, ValidationCode, + FieldLength, ValueMin, ValueMax, + IsTranslated, IsEncrypted, + IsAllowLogging); + list.add(col); + } + } + catch (SQLException e) + { + CLogger.get().log(Level.SEVERE, sql.toString(), e); + } + finally { + DB.close(rs, pstmt); + rs = null; pstmt = null; + } + // convert to array + m_columns = new POInfoColumn[list.size()]; + list.toArray(m_columns); + } // loadInfo + + /** + * String representation + * @return String Representation + */ + public String toString() + { + return "POInfo[" + getTableName() + ",AD_Table_ID=" + getAD_Table_ID() + "]"; + } // toString + + /** + * String representation for index + * @param index column index + * @return String Representation + */ + public String toString (int index) + { + if (index < 0 || index >= m_columns.length) + return "POInfo[" + getTableName() + "-(InvalidColumnIndex=" + index + ")]"; + return "POInfo[" + getTableName() + "-" + m_columns[index].toString() + "]"; + } // toString + + /** + * Get Table Name + * @return Table Name + */ + public String getTableName() + { + return m_TableName; + } // getTableName + + /** + * Get AD_Table_ID + * @return AD_Table_ID + */ + public int getAD_Table_ID() + { + return m_AD_Table_ID; + } // getAD_Table_ID + + /** + * Table has a Key Column + * @return true if has a key column + */ + public boolean hasKeyColumn() + { + return m_hasKeyColumn; + } // hasKeyColumn + + /** + * Get Table Access Level + * @return Table.ACCESS.. + */ + public String getAccessLevel() + { + return m_AccessLevel; + } // getAccessLevel + + /************************************************************************** + * Get ColumnCount + * @return column count + */ + public int getColumnCount() + { + return m_columns.length; + } // getColumnCount + + /** + * Get Column Index + * @param ColumnName column name + * @return index of column with ColumnName or -1 if not found + */ + public int getColumnIndex (String ColumnName) + { + for (int i = 0; i < m_columns.length; i++) + { + if (ColumnName.equalsIgnoreCase(m_columns[i].ColumnName)) // teo_sarca : modified to compare ignoring case [ 1619179 ] + return i; + } + return -1; + } // getColumnIndex + + /** + * Get Column Index + * @param AD_Column_ID column + * @return index of column with ColumnName or -1 if not found + */ + public int getColumnIndex (int AD_Column_ID) + { + for (int i = 0; i < m_columns.length; i++) + { + if (AD_Column_ID == m_columns[i].AD_Column_ID) + return i; + } + return -1; + } // getColumnIndex + + /** + * @param columnName + * @return AD_Column_ID if found, -1 if not found + */ + public int getAD_Column_ID(String columnName) + { + for (int i = 0; i < m_columns.length; i++) + { + if (m_columns[i].ColumnName.equals(columnName)) + return m_columns[i].AD_Column_ID; + } + return -1; + } + + /** + * Get Column + * @param index index + * @return column + */ + protected POInfoColumn getColumn (int index) + { + if (index < 0 || index >= m_columns.length) + return null; + return m_columns[index]; + } // getColumn + + /** + * Get Column Name + * @param index index + * @return ColumnName column name + */ + public String getColumnName (int index) + { + if (index < 0 || index >= m_columns.length) + return null; + return m_columns[index].ColumnName; + } // getColumnName + + /** + * Get Column SQL or Column Name + * @param index index + * @return ColumnSQL column sql or name + */ + public String getColumnSQL (int index) + { + if (index < 0 || index >= m_columns.length) + return null; + if (m_columns[index].ColumnSQL != null && m_columns[index].ColumnSQL.length() > 0) + return m_columns[index].ColumnSQL + " AS " + m_columns[index].ColumnName; + return m_columns[index].ColumnName; + } // getColumnSQL + + /** + * Is Column Virtal? + * @param index index + * @return true if column is virtual + */ + public boolean isVirtualColumn (int index) + { + if (index < 0 || index >= m_columns.length) + return true; + return m_columns[index].ColumnSQL != null + && m_columns[index].ColumnSQL.length() > 0; + } // isVirtualColumn + + /** + * Get Column Label + * @param index index + * @return column label + */ + public String getColumnLabel (int index) + { + if (index < 0 || index >= m_columns.length) + return null; + return m_columns[index].ColumnLabel; + } // getColumnLabel + + /** + * Get Column Description + * @param index index + * @return column description + */ + public String getColumnDescription (int index) + { + if (index < 0 || index >= m_columns.length) + return null; + return m_columns[index].ColumnDescription; + } // getColumnDescription + + /** + * Get Column Class + * @param index index + * @return Class + */ + public Class getColumnClass (int index) + { + if (index < 0 || index >= m_columns.length) + return null; + return m_columns[index].ColumnClass; + } // getColumnClass + + /** + * Get Column Display Type + * @param index index + * @return DisplayType + */ + public int getColumnDisplayType (int index) + { + if (index < 0 || index >= m_columns.length) + return DisplayType.String; + return m_columns[index].DisplayType; + } // getColumnDisplayType + + /** + * Get Column Default Logic + * @param index index + * @return Default Logic + */ + public String getDefaultLogic (int index) + { + if (index < 0 || index >= m_columns.length) + return null; + return m_columns[index].DefaultLogic; + } // getDefaultLogic + + /** + * Is Column Mandatory + * @param index index + * @return true if column mandatory + */ + public boolean isColumnMandatory (int index) + { + if (index < 0 || index >= m_columns.length) + return false; + return m_columns[index].IsMandatory; + } // isMandatory + + /** + * Is Column Updateable + * @param index index + * @return true if column updateable + */ + public boolean isColumnUpdateable (int index) + { + if (index < 0 || index >= m_columns.length) + return false; + return m_columns[index].IsUpdateable; + } // isUpdateable + + /** + * Set Column Updateable + * @param index index + * @param updateable column updateable + */ + public void setColumnUpdateable (int index, boolean updateable) + { + if (index < 0 || index >= m_columns.length) + return; + m_columns[index].IsUpdateable = updateable; + } // setColumnUpdateable + + /** + * Set all columns updateable + * @param updateable updateable + */ + public void setUpdateable (boolean updateable) + { + for (int i = 0; i < m_columns.length; i++) + m_columns[i].IsUpdateable = updateable; + } // setUpdateable + + /** + * Is Lookup Column + * @param index index + * @return true if it is a lookup column + */ + public boolean isColumnLookup (int index) + { + if (index < 0 || index >= m_columns.length) + return false; + return DisplayType.isLookup(m_columns[index].DisplayType); + } // isColumnLookup + + /** + * Get Lookup + * @param index index + * @return Lookup + */ + public Lookup getColumnLookup (int index) + { + if (!isColumnLookup(index)) + return null; + // + int WindowNo = 0; + // List, Table, TableDir + Lookup lookup = null; + try + { + lookup = MLookupFactory.get (m_ctx, WindowNo, + m_columns[index].AD_Column_ID, m_columns[index].DisplayType, + Env.getLanguage(m_ctx), m_columns[index].ColumnName, + m_columns[index].AD_Reference_Value_ID, + m_columns[index].IsParent, m_columns[index].ValidationCode); + } + catch (Exception e) + { + lookup = null; // cannot create Lookup + } + return lookup; + /** @todo other lookup types */ + } // getColumnLookup + + /** + * Is Column Key + * @param index index + * @return true if column is the key + */ + public boolean isKey (int index) + { + if (index < 0 || index >= m_columns.length) + return false; + return m_columns[index].IsKey; + } // isKey + + /** + * Is Column Parent + * @param index index + * @return true if column is a Parent + */ + public boolean isColumnParent (int index) + { + if (index < 0 || index >= m_columns.length) + return false; + return m_columns[index].IsParent; + } // isColumnParent + + /** + * Is Column Translated + * @param index index + * @return true if column is translated + */ + public boolean isColumnTranslated (int index) + { + if (index < 0 || index >= m_columns.length) + return false; + return m_columns[index].IsTranslated; + } // isColumnTranslated + + /** + * Is Table Translated + * @return true if table is translated + */ + public boolean isTranslated () + { + for (int i = 0; i < m_columns.length; i++) + { + if (m_columns[i].IsTranslated) + return true; + } + return false; + } // isTranslated + + /** + * Is Column (data) Encrypted + * @param index index + * @return true if column is encrypted + */ + public boolean isEncrypted (int index) + { + if (index < 0 || index >= m_columns.length) + return false; + return m_columns[index].IsEncrypted; + } // isEncrypted + + /** + * Is allowed logging on this column + * + * @param index + * index + * @return true if column is allowed to be logged + */ + public boolean isAllowLogging(int index) { + if (index < 0 || index >= m_columns.length) + return false; + return m_columns[index].IsAllowLogging; + } // isAllowLogging + + /** + * Get Column FieldLength + * @param index index + * @return field length + */ + public int getFieldLength (int index) + { + if (index < 0 || index >= m_columns.length) + return 0; + return m_columns[index].FieldLength; + } // getFieldLength + + /** + * Validate Content + * @param index index + * @param value new Value + * @return null if all valid otherwise error message + */ + public String validate (int index, Object value) + { + if (index < 0 || index >= m_columns.length) + return "RangeError"; + // Mandatory (i.e. not null + if (m_columns[index].IsMandatory && value == null) + { + return "IsMandatory"; + } + if (value == null) + return null; + + // Length ignored + + // + if (m_columns[index].ValueMin != null) + { + BigDecimal value_BD = null; + try + { + if (m_columns[index].ValueMin_BD != null) + value_BD = new BigDecimal(value.toString()); + } + catch (Exception ex){} + // Both are Numeric + if (m_columns[index].ValueMin_BD != null && value_BD != null) + { // error: 1 - 0 => 1 - OK: 1 - 1 => 0 & 1 - 10 => -1 + int comp = m_columns[index].ValueMin_BD.compareTo(value_BD); + if (comp > 0) + { + return "MinValue=" + m_columns[index].ValueMin_BD + + "(" + m_columns[index].ValueMin + ")" + + " - compared with Numeric Value=" + value_BD + "(" + value + ")" + + " - results in " + comp; + } + } + else // String + { + int comp = m_columns[index].ValueMin.compareTo(value.toString()); + if (comp > 0) + { + return "MinValue=" + m_columns[index].ValueMin + + " - compared with String Value=" + value + + " - results in " + comp; + } + } + } + if (m_columns[index].ValueMax != null) + { + BigDecimal value_BD = null; + try + { + if (m_columns[index].ValueMax_BD != null) + value_BD = new BigDecimal(value.toString()); + } + catch (Exception ex){} + // Both are Numeric + if (m_columns[index].ValueMax_BD != null && value_BD != null) + { // error 12 - 20 => -1 - OK: 12 - 12 => 0 & 12 - 10 => 1 + int comp = m_columns[index].ValueMax_BD.compareTo(value_BD); + if (comp < 0) + { + return "MaxValue=" + m_columns[index].ValueMax_BD + "(" + m_columns[index].ValueMax + ")" + + " - compared with Numeric Value=" + value_BD + "(" + value + ")" + + " - results in " + comp; + } + } + else // String + { + int comp = m_columns[index].ValueMax.compareTo(value.toString()); + if (comp < 0) + { + return "MaxValue=" + m_columns[index].ValueMax + + " - compared with String Value=" + value + + " - results in " + comp; + } + } + } + return null; + } // validate + + /** + * Build select clause + * @return stringbuffer + */ + public StringBuffer buildSelect() + { + StringBuffer sql = new StringBuffer("SELECT "); + int size = getColumnCount(); + for (int i = 0; i < size; i++) + { + if (i != 0) + sql.append(","); + sql.append(getColumnSQL(i)); // Normal and Virtual Column + } + sql.append(" FROM ").append(getTableName()); + return sql; + } + +} // POInfo diff --git a/base/src/org/compiere/model/POInfoColumn.java b/base/src/org/compiere/model/POInfoColumn.java index cdb4e22130..814f277f22 100644 --- a/base/src/org/compiere/model/POInfoColumn.java +++ b/base/src/org/compiere/model/POInfoColumn.java @@ -1,181 +1,186 @@ -/****************************************************************************** - * Product: Adempiere ERP & CRM Smart Business Solution * - * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * - * This program is free software; you can redistribute it and/or modify it * - * under the terms version 2 of the GNU General Public License as published * - * by the Free Software Foundation. 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. * - * For the text or an alternative of this public license, you may reach us * - * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * - * or via info@compiere.org or http://www.compiere.org/license.html * - *****************************************************************************/ -package org.compiere.model; - -import java.io.*; -import java.math.*; -import java.util.logging.*; -import org.compiere.util.*; - -/** - * PO Info Column Info Value Object - * - * @author Jorg Janke - * @version $Id: POInfoColumn.java,v 1.3 2006/07/30 00:58:04 jjanke Exp $ - */ -public class POInfoColumn implements Serializable -{ - /** Used by Remote FinReport */ - static final long serialVersionUID = -3983585608504631958L; - - /** - * Constructor - * @param ad_Column_ID Column ID - * @param columnName Dolumn name - * @param columnSQL virtual column - * @param displayType Display Type - * @param isMandatory Mandatory - * @param isUpdateable Updateable - * @param defaultLogic Default Logic - * @param columnLabel Column Label - * @param columnDescription Column Description - * @param isKey true if key - * @param isParent true if parent - * @param ad_Reference_Value_ID reference value - * @param validationCode sql validation code - * @param fieldLength Field Length - * @param valueMin minimal value - * @param valueMax maximal value - * @param isTranslated translated - * @param isEncrypted encrypted - */ - public POInfoColumn (int ad_Column_ID, String columnName, String columnSQL, int displayType, - boolean isMandatory, boolean isUpdateable, String defaultLogic, - String columnLabel, String columnDescription, - boolean isKey, boolean isParent, - int ad_Reference_Value_ID, String validationCode, - int fieldLength, String valueMin, String valueMax, - boolean isTranslated, boolean isEncrypted) - { - AD_Column_ID = ad_Column_ID; - ColumnName = columnName; - ColumnSQL = columnSQL; - DisplayType = displayType; - if (columnName.equals("AD_Language") || columnName.equals("EntityType")) - { - DisplayType = org.compiere.util.DisplayType.String; - ColumnClass = String.class; - } - else if (columnName.equals("Posted") - || columnName.equals("Processed") - || columnName.equals("Processing")) - { - ColumnClass = Boolean.class; - } - else if (columnName.equals("Record_ID")) - { - DisplayType = org.compiere.util.DisplayType.ID; - ColumnClass = Integer.class; - } - else - ColumnClass = org.compiere.util.DisplayType.getClass(displayType, true); - IsMandatory = isMandatory; - IsUpdateable = isUpdateable; - DefaultLogic = defaultLogic; - ColumnLabel = columnLabel; - ColumnDescription = columnDescription; - IsKey = isKey; - IsParent = isParent; - // - AD_Reference_Value_ID = ad_Reference_Value_ID; - ValidationCode = validationCode; - // - FieldLength = fieldLength; - ValueMin = valueMin; - try - { - if (valueMin != null && valueMin.length() > 0) - ValueMin_BD = new BigDecimal(valueMin); - } - catch (Exception ex) - { - CLogger.get().log(Level.SEVERE, "ValueMin=" + valueMin, ex); - } - ValueMax = valueMax; - try - { - if (valueMax != null && valueMax.length() > 0) - ValueMax_BD = new BigDecimal(valueMax); - } - catch (Exception ex) - { - CLogger.get().log(Level.SEVERE, "ValueMax=" + valueMax, ex); - } - IsTranslated = isTranslated; - IsEncrypted = isEncrypted; - } // Column - - /** Column ID */ - public int AD_Column_ID; - /** Column Name */ - public String ColumnName; - /** Virtual Column */ - public String ColumnSQL; - /** Display Type */ - public int DisplayType; - /** Data Type */ - public Class ColumnClass; - /** Mandatory */ - public boolean IsMandatory; - /** Default Value */ - public String DefaultLogic; - /** Updateable */ - public boolean IsUpdateable; - /** Label */ - public String ColumnLabel; - /** Description */ - public String ColumnDescription; - /** PK */ - public boolean IsKey; - /** FK to Parent */ - public boolean IsParent; - /** Translated */ - public boolean IsTranslated; - /** Encryoted */ - public boolean IsEncrypted; - - /** Reference Value */ - public int AD_Reference_Value_ID; - /** Validation */ - public String ValidationCode; - - /** Field Length */ - public int FieldLength; - /** Min Value */ - public String ValueMin; - /** Max Value */ - public String ValueMax; - /** Min Value */ - public BigDecimal ValueMin_BD = null; - /** Max Value */ - public BigDecimal ValueMax_BD = null; - - /** - * String representation - * @return info - */ - public String toString() - { - StringBuffer sb = new StringBuffer("POInfo.Column["); - sb.append(ColumnName).append(",ID=").append(AD_Column_ID) - .append(",DisplayType=").append(DisplayType) - .append(",ColumnClass=").append(ColumnClass); - sb.append("]"); - return sb.toString(); - } // toString - -} // POInfoColumn +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.logging.Level; + +import org.compiere.util.CLogger; + +/** + * PO Info Column Info Value Object + * + * @author Jorg Janke + * @version $Id: POInfoColumn.java,v 1.3 2006/07/30 00:58:04 jjanke Exp $ + */ +public class POInfoColumn implements Serializable +{ + /** Used by Remote FinReport */ + static final long serialVersionUID = -3983585608504631958L; + + /** + * Constructor + * @param ad_Column_ID Column ID + * @param columnName Column name + * @param columnSQL virtual column + * @param displayType Display Type + * @param isMandatory Mandatory + * @param isUpdateable Updateable + * @param defaultLogic Default Logic + * @param columnLabel Column Label + * @param columnDescription Column Description + * @param isKey true if key + * @param isParent true if parent + * @param ad_Reference_Value_ID reference value + * @param validationCode sql validation code + * @param fieldLength Field Length + * @param valueMin minimal value + * @param valueMax maximal value + * @param isTranslated translated + * @param isEncrypted encrypted + * @param isAllowLogging allow logging + */ + public POInfoColumn (int ad_Column_ID, String columnName, String columnSQL, int displayType, + boolean isMandatory, boolean isUpdateable, String defaultLogic, + String columnLabel, String columnDescription, + boolean isKey, boolean isParent, + int ad_Reference_Value_ID, String validationCode, + int fieldLength, String valueMin, String valueMax, + boolean isTranslated, boolean isEncrypted, boolean isAllowLogging) + { + AD_Column_ID = ad_Column_ID; + ColumnName = columnName; + ColumnSQL = columnSQL; + DisplayType = displayType; + if (columnName.equals("AD_Language") || columnName.equals("EntityType")) + { + DisplayType = org.compiere.util.DisplayType.String; + ColumnClass = String.class; + } + else if (columnName.equals("Posted") + || columnName.equals("Processed") + || columnName.equals("Processing")) + { + ColumnClass = Boolean.class; + } + else if (columnName.equals("Record_ID")) + { + DisplayType = org.compiere.util.DisplayType.ID; + ColumnClass = Integer.class; + } + else + ColumnClass = org.compiere.util.DisplayType.getClass(displayType, true); + IsMandatory = isMandatory; + IsUpdateable = isUpdateable; + DefaultLogic = defaultLogic; + ColumnLabel = columnLabel; + ColumnDescription = columnDescription; + IsKey = isKey; + IsParent = isParent; + // + AD_Reference_Value_ID = ad_Reference_Value_ID; + ValidationCode = validationCode; + // + FieldLength = fieldLength; + ValueMin = valueMin; + try + { + if (valueMin != null && valueMin.length() > 0) + ValueMin_BD = new BigDecimal(valueMin); + } + catch (Exception ex) + { + CLogger.get().log(Level.SEVERE, "ValueMin=" + valueMin, ex); + } + ValueMax = valueMax; + try + { + if (valueMax != null && valueMax.length() > 0) + ValueMax_BD = new BigDecimal(valueMax); + } + catch (Exception ex) + { + CLogger.get().log(Level.SEVERE, "ValueMax=" + valueMax, ex); + } + IsTranslated = isTranslated; + IsEncrypted = isEncrypted; + IsAllowLogging = isAllowLogging; + } // Column + + /** Column ID */ + public int AD_Column_ID; + /** Column Name */ + public String ColumnName; + /** Virtual Column */ + public String ColumnSQL; + /** Display Type */ + public int DisplayType; + /** Data Type */ + public Class ColumnClass; + /** Mandatory */ + public boolean IsMandatory; + /** Default Value */ + public String DefaultLogic; + /** Updateable */ + public boolean IsUpdateable; + /** Label */ + public String ColumnLabel; + /** Description */ + public String ColumnDescription; + /** PK */ + public boolean IsKey; + /** FK to Parent */ + public boolean IsParent; + /** Translated */ + public boolean IsTranslated; + /** Encrypted */ + public boolean IsEncrypted; + /** Allow Logging */ + public boolean IsAllowLogging; + + /** Reference Value */ + public int AD_Reference_Value_ID; + /** Validation */ + public String ValidationCode; + + /** Field Length */ + public int FieldLength; + /** Min Value */ + public String ValueMin; + /** Max Value */ + public String ValueMax; + /** Min Value */ + public BigDecimal ValueMin_BD = null; + /** Max Value */ + public BigDecimal ValueMax_BD = null; + + /** + * String representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("POInfo.Column["); + sb.append(ColumnName).append(",ID=").append(AD_Column_ID) + .append(",DisplayType=").append(DisplayType) + .append(",ColumnClass=").append(ColumnClass); + sb.append("]"); + return sb.toString(); + } // toString + +} // POInfoColumn diff --git a/base/src/org/compiere/model/X_AD_Column.java b/base/src/org/compiere/model/X_AD_Column.java index 43196a1f44..dc760dc2bc 100644 --- a/base/src/org/compiere/model/X_AD_Column.java +++ b/base/src/org/compiere/model/X_AD_Column.java @@ -958,4 +958,20 @@ public class X_AD_Column extends PO implements I_AD_Column, I_Persistent return Env.ZERO; return bd; } -} \ No newline at end of file + + /** Get IsAllowLogging . + * Determines, if a column must be recorded into the change log + */ + public boolean IsAllowLogging() { + Object oo = get_Value(COLUMNNAME_isAllowLogging); + if (oo != null) + { + if (oo instanceof Boolean) + return ((Boolean)oo).booleanValue(); + return "Y".equals(oo); + } + return false; + } +} + + \ No newline at end of file diff --git a/migration/351a-trunk/240_FR1810133.sql b/migration/351a-trunk/240_FR1810133.sql new file mode 100644 index 0000000000..45f88c6ee2 --- /dev/null +++ b/migration/351a-trunk/240_FR1810133.sql @@ -0,0 +1,29 @@ +-- Jul 23, 2008 4:50:40 PM COT +-- [ 1810133 ] Add logging policy on column level +INSERT INTO AD_Element (AD_Client_ID,AD_Element_ID,AD_Org_ID,ColumnName,Created,CreatedBy,Description,EntityType,IsActive,Name,PrintName,Updated,UpdatedBy) VALUES (0,53669,0,'IsAllowLogging',TO_DATE('2008-07-23 16:50:36','YYYY-MM-DD HH24:MI:SS'),100,'Determine if a column must be recorded into the change log','U','Y','IsAllowLogging','IsAllowLogging',TO_DATE('2008-07-23 16:50:36','YYYY-MM-DD HH24:MI:SS'),100) +; + +INSERT INTO AD_Element_Trl (AD_Language,AD_Element_ID, Description,Help,Name,PO_Description,PO_Help,PO_Name,PO_PrintName,PrintName, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy) SELECT l.AD_Language,t.AD_Element_ID, t.Description,t.Help,t.Name,t.PO_Description,t.PO_Help,t.PO_Name,t.PO_PrintName,t.PrintName, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy FROM AD_Language l, AD_Element t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Element_ID=53669 AND EXISTS (SELECT * FROM AD_Element_Trl tt WHERE tt.AD_Language!=l.AD_Language OR tt.AD_Element_ID!=t.AD_Element_ID) +; + +UPDATE AD_Element_Trl SET IsTranslated='Y',Name='RegistrarEnLog',PrintName='Registrar en Log de Cambios',Description='Determina si una columna debe ser registrada en el log de cambios',Updated=TO_DATE('2008-07-23 16:53:04','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Element_ID=53669 AND AD_Language='es_MX' +; + +INSERT INTO AD_Column (AD_Client_ID,AD_Column_ID,AD_Element_ID,AD_Org_ID,AD_Reference_ID,AD_Table_ID,ColumnName,Created,CreatedBy,DefaultValue,Description,EntityType,FieldLength,IsActive,IsAlwaysUpdateable,IsEncrypted,IsIdentifier,IsKey,IsMandatory,IsParent,IsSelectionColumn,IsSyncDatabase,IsTranslated,IsUpdateable,Name,SeqNo,Updated,UpdatedBy,Version) VALUES (0,56187,53669,0,20,101,'IsAllowLogging',TO_DATE('2008-07-23 16:55:42','YYYY-MM-DD HH24:MI:SS'),100,'Y','Determine if a column must be recorded into the change log','D',1,'Y','N','N','N','N','N','N','N','N','N','Y','IsAllowLogging',0,TO_DATE('2008-07-23 16:55:42','YYYY-MM-DD HH24:MI:SS'),100,0) +; + +INSERT INTO AD_Column_Trl (AD_Language,AD_Column_ID, Name, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy) SELECT l.AD_Language,t.AD_Column_ID, t.Name, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy FROM AD_Language l, AD_Column t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Column_ID=56187 AND EXISTS (SELECT * FROM AD_Column_Trl tt WHERE tt.AD_Language!=l.AD_Language OR tt.AD_Column_ID!=t.AD_Column_ID) +; + +ALTER TABLE AD_Column ADD IsAllowLogging CHAR(1) DEFAULT 'Y' CHECK (IsAllowLogging IN ('Y','N')) +; + +INSERT INTO AD_Field (AD_Client_ID,AD_Column_ID,AD_Field_ID,AD_Org_ID,AD_Tab_ID,Created,CreatedBy,Description,DisplayLength,EntityType,IsActive,IsCentrallyMaintained,IsDisplayed,IsEncrypted,IsFieldOnly,IsHeading,IsReadOnly,IsSameLine,Name,SeqNo,SortNo,Updated,UpdatedBy) VALUES (0,56187,56317,0,101,TO_DATE('2008-07-23 16:57:53','YYYY-MM-DD HH24:MI:SS'),100,'Determine if a column must be recorded into the change log',0,'D','Y','Y','Y','N','N','N','N','N','IsAllowLogging',370,0,TO_DATE('2008-07-23 16:57:53','YYYY-MM-DD HH24:MI:SS'),100) +; + +INSERT INTO AD_Field_Trl (AD_Language,AD_Field_ID, Description,Help,Name, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy) SELECT l.AD_Language,t.AD_Field_ID, t.Description,t.Help,t.Name, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy FROM AD_Language l, AD_Field t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Field_ID=56317 AND EXISTS (SELECT * FROM AD_Field_Trl tt WHERE tt.AD_Language!=l.AD_Language OR tt.AD_Field_ID!=t.AD_Field_ID) +; + + +UPDATE AD_Column SET IsAllowLogging = 'N' WHERE AD_Column_ID IN (6652, 6653) +; diff --git a/migration/351a-trunk/postgresql/240_FR1810133.sql b/migration/351a-trunk/postgresql/240_FR1810133.sql new file mode 100644 index 0000000000..86bcce2809 --- /dev/null +++ b/migration/351a-trunk/postgresql/240_FR1810133.sql @@ -0,0 +1,29 @@ +-- Jul 23, 2008 4:50:40 PM COT +-- [ 1810133 ] Add logging policy on column level +INSERT INTO AD_Element (AD_Client_ID,AD_Element_ID,AD_Org_ID,ColumnName,Created,CreatedBy,Description,EntityType,IsActive,Name,PrintName,Updated,UpdatedBy) VALUES (0,53669,0,'IsAllowLogging',TO_TIMESTAMP('2008-07-23 16:50:36','YYYY-MM-DD HH24:MI:SS'),100,'Determine if a column must be recorded into the change log','U','Y','IsAllowLogging','IsAllowLogging',TO_TIMESTAMP('2008-07-23 16:50:36','YYYY-MM-DD HH24:MI:SS'),100) +; + +INSERT INTO AD_Element_Trl (AD_Language,AD_Element_ID, Description,Help,Name,PO_Description,PO_Help,PO_Name,PO_PrintName,PrintName, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy) SELECT l.AD_Language,t.AD_Element_ID, t.Description,t.Help,t.Name,t.PO_Description,t.PO_Help,t.PO_Name,t.PO_PrintName,t.PrintName, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy FROM AD_Language l, AD_Element t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Element_ID=53669 AND EXISTS (SELECT * FROM AD_Element_Trl tt WHERE tt.AD_Language!=l.AD_Language OR tt.AD_Element_ID!=t.AD_Element_ID) +; + +UPDATE AD_Element_Trl SET IsTranslated='Y',Name='RegistrarEnLog',PrintName='Registrar en Log de Cambios',Description='Determina si una columna debe ser registrada en el log de cambios',Updated=TO_TIMESTAMP('2008-07-23 16:53:04','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Element_ID=53669 AND AD_Language='es_MX' +; + +INSERT INTO AD_Column (AD_Client_ID,AD_Column_ID,AD_Element_ID,AD_Org_ID,AD_Reference_ID,AD_Table_ID,ColumnName,Created,CreatedBy,DefaultValue,Description,EntityType,FieldLength,IsActive,IsAlwaysUpdateable,IsEncrypted,IsIdentifier,IsKey,IsMandatory,IsParent,IsSelectionColumn,IsSyncDatabase,IsTranslated,IsUpdateable,Name,SeqNo,Updated,UpdatedBy,Version) VALUES (0,56187,53669,0,20,101,'IsAllowLogging',TO_TIMESTAMP('2008-07-23 16:55:42','YYYY-MM-DD HH24:MI:SS'),100,'Y','Determine if a column must be recorded into the change log','D',1,'Y','N','N','N','N','N','N','N','N','N','Y','IsAllowLogging',0,TO_TIMESTAMP('2008-07-23 16:55:42','YYYY-MM-DD HH24:MI:SS'),100,0) +; + +INSERT INTO AD_Column_Trl (AD_Language,AD_Column_ID, Name, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy) SELECT l.AD_Language,t.AD_Column_ID, t.Name, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy FROM AD_Language l, AD_Column t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Column_ID=56187 AND EXISTS (SELECT * FROM AD_Column_Trl tt WHERE tt.AD_Language!=l.AD_Language OR tt.AD_Column_ID!=t.AD_Column_ID) +; + +ALTER TABLE AD_Column ADD COLUMN IsAllowLogging CHAR(1) DEFAULT 'Y' CHECK (IsAllowLogging IN ('Y','N')) +; + +INSERT INTO AD_Field (AD_Client_ID,AD_Column_ID,AD_Field_ID,AD_Org_ID,AD_Tab_ID,Created,CreatedBy,Description,DisplayLength,EntityType,IsActive,IsCentrallyMaintained,IsDisplayed,IsEncrypted,IsFieldOnly,IsHeading,IsReadOnly,IsSameLine,Name,SeqNo,SortNo,Updated,UpdatedBy) VALUES (0,56187,56317,0,101,TO_TIMESTAMP('2008-07-23 16:57:53','YYYY-MM-DD HH24:MI:SS'),100,'Determine if a column must be recorded into the change log',0,'D','Y','Y','Y','N','N','N','N','N','IsAllowLogging',370,0,TO_TIMESTAMP('2008-07-23 16:57:53','YYYY-MM-DD HH24:MI:SS'),100) +; + +INSERT INTO AD_Field_Trl (AD_Language,AD_Field_ID, Description,Help,Name, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy) SELECT l.AD_Language,t.AD_Field_ID, t.Description,t.Help,t.Name, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy FROM AD_Language l, AD_Field t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Field_ID=56317 AND EXISTS (SELECT * FROM AD_Field_Trl tt WHERE tt.AD_Language!=l.AD_Language OR tt.AD_Field_ID!=t.AD_Field_ID) +; + + +UPDATE AD_Column SET IsAllowLogging = 'N' WHERE AD_Column_ID IN (6652, 6653) +;