/****************************************************************************** * 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 * * Contributor(s): Teo Sarca, (tentative) * *****************************************************************************/ package org.compiere.model; import java.lang.reflect.Proxy; import java.math.BigDecimal; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Collection; import java.util.Properties; import java.util.logging.Level; import org.adempiere.exceptions.AdempiereException; import org.adempiere.exceptions.DBException; import org.compiere.util.CLogger; import org.compiere.util.DB; import org.compiere.util.Env; import org.compiere.util.Language; import org.compiere.util.Util; public class SetGetUtil { /** Static logger */ private static CLogger s_log = CLogger.getCLogger(SetGetUtil.class); /** * Update columns from the result of the given query. *
If the query returns more than one row, only the first row will be used. *
This is a simplified version of {@link #updateColumns(SetGetModel[], String[], String, Object[], String)} * which calls: *
updateColumns(new SetGetModel[]{model}, columnNames, query, trxName);
*
* @param model
* @param columnNames
* column names; if null, all columns from given query are used;
* if a columnName from array is null it will be ignored
* @param sql sql query
* @param params sql parameters
* @param trxName
*
* @see #updateColumns(SetGetModel[], String[], String, Object[], String)
*/
public static void updateColumns(SetGetModel model, String[] columnNames, String sql, Object[] params, String trxName)
{
updateColumns(new SetGetModel[]{model}, columnNames, sql, params, trxName);
}
public static void updateColumns(SetGetModel model, String[] columnNames, String sql, String trxName)
{
updateColumns(new SetGetModel[]{model}, columnNames, sql, null, trxName);
}
/**
* Update columns from the result of the given query.
*
* @param models
* @param columnNames
* @param sql
* @param params
* @param trxName
*
* @see #updateColumns(SetGetModel[], String[], ResultSet)
*/
public static void updateColumns(SetGetModel[] models, String[] columnNames,
String sql, Object[] params,
String trxName)
{
PreparedStatement pstmt = null;
ResultSet rs = null;
try
{
pstmt = DB.prepareStatement(sql, trxName);
DB.setParameters(pstmt, params);
rs = pstmt.executeQuery();
updateColumns(models, columnNames, rs);
}
catch (SQLException e)
{
throw new DBException(e, sql);
}
finally
{
DB.close(rs, pstmt);
rs = null; pstmt = null;
}
} // updateColumns
/**
* Update columns from the result of the given query.
*
* @param models
* @param columnNames
* column names; if null, all columns from given query are used;
* if a columnName from array is null it will be ignored
* @param rs
* @throws SQLException
*/
public static void updateColumns(SetGetModel[] models, String[] columnNames, ResultSet rs)
throws SQLException
{
for (SetGetModel model : models)
{
if (s_log.isLoggable(Level.FINEST)) s_log.finest("Model: " + model);
if (rs.next())
{
if (columnNames == null)
{
columnNames = getColumnNames(rs);
}
for(String columnName : columnNames)
{
if (Util.isEmpty(columnName))
continue;
//
Object obj = null;
boolean ok = false;
obj = rs.getObject(columnName);
//
// Date Columns are returned as Date -> convert to java.sql.Timestamp
if (obj instanceof java.sql.Date)
{
obj = new java.sql.Timestamp(((java.sql.Date)obj).getTime());
}
//
// ID Columns (integer) are returned as BigDecimal -> convert to Integer
else if (obj instanceof BigDecimal && columnName.endsWith("_ID"))
{
obj = ((BigDecimal)obj).intValue();
}
//
ok = model.set_AttrValue(columnName, obj);
if (s_log.isLoggable(Level.FINEST)) s_log.finest("columnName=" + columnName + ", value=[" + obj + "][" + (obj != null ? obj.getClass().getName() : "null") + "], ok=" + ok);
}
}
else
{
if (s_log.isLoggable(Level.FINEST)) s_log.finest("@NoResult@");
break;
}
}
} // updateColumns
public static void updateColumns(SetGetModel model, String[] columnNames, ResultSet rs)
throws SQLException
{
updateColumns(new SetGetModel[]{model}, columnNames, rs);
}
/**
* Get Array of Column Names (String) for given ResultSet
* @param rs
* @return column names (upper case)
* @throws SQLException
*/
private static final String[] getColumnNames(ResultSet rs)
throws SQLException
{
if (rs == null)
{
return new String[0];
}
ResultSetMetaData rsmd = rs.getMetaData();
int no = rsmd.getColumnCount();
String[] columnNames = new String[no];
for (int i = 1; i <= no; i++)
{
columnNames[i - 1] = rsmd.getColumnName(i).toUpperCase();
}
//
return columnNames;
} // getColumnName
/**
* Copy from the fields to.
* The second object is not required to be in the same table.
* The following fields are not copied: AD_Client_ID, AD_Org_ID, Created% Updated% IsActive.
* If excludeFields includeFields and are null, then it will copy all the fields (which can be copied).
* @ param to destination object
* @ param object from source
* @ param includeFields name fields to be excluded; null will be interpreted as String [0];
* excludeFields includeFields and mutually exclusive, priority being includeFields;
* If includeFields excludeFields are null and then copy all fields
* @ param excludeFields name fields to be excluded, null will be interpreted as String [0]
* @return false if "to" or "from" is null, true otherwise
*/
public static boolean copyValues(PO to, PO from, String[] includeFields, String[] excludeFields)
{
int no = copyValues(to, from, includeFields, excludeFields, false);
return no >= 0;
}
/**
* Copy all values from "from" to "to"
* @return number of columns that were copied and were were also changed in object "from"
* @see #copyValues(PO, PO, String[], String[])
*/
public static int copyChangedValues(PO to, PO from)
{
return copyValues(to, from, null, null, true);
}
/**
*
* @param to
* @param from
* @param includeFields
* @param excludeFields
* @param trackOnlyChanges counts only the fields that were changed from
* (from.is_ValueChanged(int idx))
* @return -1 the error or the number of heads that have been copied;
* if trackOnlyChanges = true then copied and include only the columns that have changed and "from"
*/
private static int copyValues(PO to, PO from,
String[] includeFields, String[] excludeFields,
boolean trackOnlyChanges)
{
if (s_log.isLoggable(Level.FINEST))
{
s_log.finest("Entering: From=" + from+ " - To=" + to);
}
//
if (to == null || from == null)
{
if (s_log.isLoggable(Level.FINEST))
{
s_log.finest("Leaving: to == null || from == null");
Thread.dumpStack();
}
return -1;
}
//
if(includeFields != null)
{
excludeFields = null;
}
if (includeFields == null && excludeFields == null)
{
excludeFields = new String[]{"#"}; // dummy value
}
//
int copiedFields = 0;
for (int idx_from = 0; idx_from < from.get_ColumnCount(); idx_from++)
{
String colName = from.p_info.getColumnName(idx_from);
boolean isExcluded = false;
//
// Ignore Standard Values
if ("Created".equals(colName)
|| "CreatedBy".equals(colName)
|| "Updated".equals(colName)
|| "UpdatedBy".equals(colName)
|| "IsActive".equals(colName)
|| "AD_Client_ID".equals(colName)
|| "AD_Org_ID".equals(colName)
)
{
isExcluded = true;
}
//
// Include Policy
else if (includeFields != null)
{
isExcluded = true;
for(String incl : includeFields)
{
if (incl.equalsIgnoreCase(colName))
{
isExcluded = false;
break;
}
}
}
//
// Exclude Policy
else if (excludeFields != null)
{
for(String excl : excludeFields)
{
if (excl.equalsIgnoreCase(colName))
{
isExcluded = true;
break;
}
}
}
//-
if (isExcluded)
{
if (s_log.isLoggable(Level.FINEST)) s_log.finest("Field " + colName + " [SKIP:excluded]");
continue;
}
int idx_to = to.get_ColumnIndex(colName);
if (idx_to < 0)
{
if (s_log.isLoggable(Level.FINEST)) s_log.finest("Field " + colName + " [SKIP:idx_to < 0]");
continue;
}
if (to.p_info.isVirtualColumn(idx_to) || to.p_info.isKey(idx_to))
{ // KeyColumn
if (s_log.isLoggable(Level.FINEST)) s_log.finest("Field " + colName + " [SKIP:virtual or key]");
continue;
}
Object value = from.get_Value(idx_from);
to.set_Value(idx_to, value);
if (!trackOnlyChanges || from.is_ValueChanged(idx_from))
{
copiedFields++;
}
if (s_log.isLoggable(Level.FINEST)) s_log.finest("Field " + colName + "=[" + value + "], idx=" + idx_from + "->" + idx_to);
}
//
if (s_log.isLoggable(Level.FINEST)) s_log.finest("Leaving: to=" + to);
return copiedFields;
} // copyValues
/**
* Copy from the fields to the.
* The two objects do not need to be in the same table.
* @param to destination object
* @param from_tableName source object table
* @param from_id source object ID
* @param includeFields name fields to be excluded, null will be interpreted as String[0];
* @see #updateColumns(SetGetModel, String[], String, String)
*/
public static boolean copyValues(SetGetModel to, String from_tableName, int from_id, String[] includeFields)
{
if (to == null || from_tableName == null || from_id <= 0
|| includeFields == null || includeFields.length == 0)
{
return false;
}
StringBuilder sql = new StringBuilder();
for (String f : includeFields)
{
if (sql.length() > 0)
sql.append(",");
sql.append(f);
}
sql.insert(0, "SELECT ");
sql.append(" FROM ").append(from_tableName)
.append(" WHERE ").append(from_tableName).append("_ID=").append(from_id);
updateColumns(to, includeFields, sql.toString(), null);
return true;
}
/**
* Get Value as integer
* @param model
* @param name
* @return int value
*/
public static int get_AttrValueAsInt(SetGetModel model, String name)
{
Object o = model.get_AttrValue(name);
if (o instanceof Number)
return ((Number)o).intValue();
return 0;
} // get_AttrValueAsInt
/**
* Get Value as Timestamp
* @param model
* @param name
* @return Timestamp value
*/
public static Timestamp get_AttrValueAsDate(SetGetModel model, String name)
{
Object o = model.get_AttrValue(name);
if (o instanceof Timestamp)
return (Timestamp)o;
return null;
} // get_AttrValueAsDate
/**
* Get Value as BigDecimal
* @param model
* @param name
* @return BigDecimal or {@link BigDecimal#ZERO}
*/
public static BigDecimal get_AttrValueAsBigDecimal(SetGetModel model, String name)
{
Object o = model.get_AttrValue(name);
if (o instanceof BigDecimal)
return (BigDecimal)o;
return BigDecimal.ZERO;
} // get_AttrValueAsBigDecimal
/**
* Get Value as Boolean
* @param model
* @param name
* @return boolean value
*/
public static boolean get_AttrValueAsBoolean(SetGetModel model, String name)
{
Object o = model.get_AttrValue(name);
if (o != null) {
if (o instanceof Boolean)
return ((Boolean)o).booleanValue();
else
return "Y".equals(o);
}
return false;
}
/**
* Get Value as String
* @param model
* @param name
* @param valueIfNull value that will be returned if the value is null
* @return String value
*/
public static String get_AttrValueAsString(SetGetModel model, String name, String valueIfNull)
{
Object o = model.get_AttrValue(name);
if (o == null)
return valueIfNull;
return o.toString();
}
/**
* Set Attribute Value
* @param model
* @param name
* @param value
* @throws AdempiereException if it can not be set (error setting, attribute/column name not found).
*/
public static void set_AttrValueEx(SetGetModel model, String name, Object value)
{
if (!model.set_AttrValue(name, value))
throw new AdempiereException("Value not set "+name+"="+value);
}
/**
* @param model
* @param propertyNames
* @return true if ANY of given properties had changed
*/
public static boolean is_ValueChanged(SetGetModel model, String ... propertyNames)
{
for (String name : propertyNames)
{
if (model.is_AttrValueChanged(name))
{
return true;
}
}
return false;
}
/**
* Get TrxName for given object.
* @param o
* @return trxName or null
*/
public static String getTrxName(Object o)
{
if (o == null)
{
return null;
}
else if (o instanceof SetGetModel)
{
return ((SetGetModel)o).get_TrxName();
}
else if (o instanceof PO)
{
return ((PO)o).get_TrxName();
}
else
{
return null;
}
}
/**
* Check if given object was produced by used entry (i.e. created from a window)
* @param o object
* @return If object is instanceof PO then ...
* If object is null then false will be returned.
* Else true will be returned.
*/
public static boolean isUserEntry(Object o)
{
if (o == null)
{
return false;
}
else if (o instanceof PO)
{
return false; // TODO
}
else
{
return true;
}
}
/**
* Set model's Line#
* @param model
* @param parentColumnName parent column name; if null then it won't be used
* @param lineColumnName line column name; if null "Line" will be used
*/
public static void setLineNo(SetGetModel model, String parentColumnName, String lineColumnName)
{
if (lineColumnName == null)
{
lineColumnName = "Line";
}
int lineNo = get_AttrValueAsInt(model, lineColumnName);
if (lineNo != 0)
{
return;
}
//
String tableName = model.get_TableName();
String idColumnName = tableName+"_ID";
//
Collection