www.pudn.com > code_source_compiere_erp_crm_logiciel_java.zip > MTab.java
/******************************************************************************
* The contents of this file are subject to the Compiere License Version 1.1
* ("License"); You may not use this file except in compliance with the License
* You may obtain a copy of the License at http://www.compiere.org/license.html
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
* The Original Code is Compiere ERP & CRM Business Solution
* The Initial Developer of the Original Code is Jorg Janke and ComPiere, Inc.
* Portions created by Jorg Janke are Copyright (C) 1999-2001 Jorg Janke, parts
* created by ComPiere are Copyright (C) ComPiere, Inc.; All Rights Reserved.
* Contributor(s): ______________________________________.
*****************************************************************************/
package org.compiere.model;
import java.sql.*;
import java.util.*;
import java.math.*;
import java.text.*;
import java.beans.*;
import java.io.*;
import org.compiere.util.ValueNamePair;
import org.compiere.util.*;
/**
* Tab Model.
* - a combination of AD_Tab (the display attributes) and AD_Table information.
*
* The Tab owns also it's Table model
* and listens to data changes to update the Field values.
*
*
* The Tab maintains the bound property: CurrentRow
*
*
* Event Hierarchies:
* - dataChanged (from MTable)
* - setCurrentRow
* - Update all Field Values
*
* - setValue
* - Update Field Value
* - Callout
*
* @author Jorg Janke
* @version $Id: MTab.java,v 1.41 2003/04/30 06:24:22 jjanke Exp $
*/
public final class MTab implements DataStatusListener, Serializable
{
/**
* Create Tab (Model) from Value Object.
*
* MTab provides a property listener for changed rows and a
* DataStatusListener for communicating changes of the underlying data
* @param vo Value Object
*/
public MTab(MTabVO vo)
{
m_vo = vo;
// Create MTable
m_mTable = new MTable (m_vo.ctx, m_vo.TableName, m_vo.WindowNo, m_vo.TabNo, true);
m_mTable.setReadOnly(m_vo.IsReadOnly || m_vo.IsView);
m_mTable.setDeleteable(m_vo.IsDeleteable);
// Load Tab
// if (vo.TabNo == 0)
initTab(false);
// else
// {
// m_loader = new Loader();
// m_loader.setPriority(Thread.MIN_PRIORITY);
// m_loader.start();
// }
// waitLoadCompete();
} // M_Tab
/** Value Object */
private MTabVO m_vo;
/** The Table Model for Query */
private MTable m_mTable = null;
private String m_keyColumnName = "";
private String m_linkColumnName = "";
private String m_extendedWhere;
/** Attachments */
private HashMap m_Attachment = null;
/** Current Row */
private int m_currentRow = -1;
/** Property Change */
private PropertyChangeSupport m_propertyChangeSupport = new PropertyChangeSupport(this);
/** Property Change Type */
public static final String PROPERTY = "CurrentRow";
private Vector m_dataStatusListeners = null;
private DataStatusEvent m_DataStatusEvent = null;
//
private MQuery m_query = new MQuery();
private String m_oldQuery = "0=9";
private String m_linkValue = "999999";
/** Order By Array if SortNo 1..2 */
private String[] m_OrderBys = new String[2];
/** List of Key Parents */
private ArrayList m_parents = new ArrayList(2);
/** Map of ColumnName of source field (key) and the dependent field (value) */
private MultiMap m_depOnField = new MultiMap();
/** Async Loader */
private Loader m_loader = null;
/** Async Loading complete */
private volatile boolean m_loadComplete = false;
/*************************************************************************/
/**
* Tab loader for Tabs > 0
*/
class Loader extends Thread
{
/**
* Async Loading of Tab > 0
*/
public void run()
{
initTab (true);
} // run
} // Loader
/**
* Wait until load is complete
*/
private void waitLoadCompete()
{
if (m_loadComplete)
return;
//
m_loader.setPriority(Thread.NORM_PRIORITY);
Log.trace(Log.l1_User, "MTab.waitLoadComplete");
while (m_loader.isAlive())
{
try
{
Thread.sleep(100); // 1/10 sec
}
catch (Exception e)
{
Log.error("MTab.waitLoadComplete", e);
}
}
Log.trace(Log.l1_User, "MTab.waitLoadComplete - fini");
} // waitLoadComplete
/**
* Initialize Tab with record from AD_Tab_v
* @param async async
* @return true, if correctly initialized (ignored)
*/
private boolean initTab (boolean async)
{
Log.trace(Log.l3_Util, "MTab.initTab #" + m_vo.TabNo + " - Async=" + async);
m_extendedWhere = m_vo.WhereClause;
// Get Field Data
if (!loadFields())
{
m_loadComplete = true;
return false;
}
// Order By
m_mTable.setOrderClause(getOrderByClause(m_vo.onlyCurrentRows));
if (async)
Log.trace(Log.l3_Util, "MTab.initTab #" + m_vo.TabNo + " - Async=" + async, "fini");
m_loadComplete = true;
return true;
} // initTab
/**
* Dispose - clean up resources
*/
protected void dispose()
{
Log.trace(Log.l3_Util, "MTab.dispose #" + m_vo.TabNo);
m_OrderBys = null;
//
m_parents.clear();
m_parents = null;
//
m_mTable.close (true); // also disposes Fields
m_mTable = null;
//
m_depOnField.clear();
m_depOnField = null;
if (m_Attachment != null)
m_Attachment.clear();
m_Attachment = null;
//
m_vo.Fields.clear();
m_vo.Fields = null;
m_vo = null;
} // dispose
/**
* Get Field data and add to MTable, if it's required or displayed.
* Reqiored fields are keys, parents, or standard Columns
* @return true if fields loaded
*/
private boolean loadFields()
{
Log.trace(Log.l3_Util, "MTab.loadFields #" + m_vo.TabNo);
if (m_vo.Fields == null)
return false;
// Add RowID if this is not a view
if (!m_vo.IsView)
{
MField rowID = new MField (MFieldVO.createRowID (m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, m_vo.AD_Window_ID));
m_mTable.addField(rowID);
}
// Add Fields
for (int f = 0; f < m_vo.Fields.size(); f++)
{
MFieldVO voF = (MFieldVO)m_vo.Fields.get(f);
// Add Fields to Table
if (voF != null)
{
MField field = new MField (voF);
String columnName = field.getColumnName();
// Record Info
if (field.isKey())
{
if (m_vo.IsView) // make it a RowID for selection & update
voF.initRowID();
m_keyColumnName = columnName;
}
// Parent Column(s)
if (field.isParent())
m_parents.add(columnName);
// Order By
if (field.getSortNo() == 1)
m_OrderBys[0] = columnName;
else if (field.getSortNo() == 2)
m_OrderBys[1] = columnName;
// Add field
m_mTable.addField(field);
// List of ColumnNames, this field is dependent on
ArrayList list = field.getDependentOn();
for (int i = 0; i < list.size(); i++)
m_depOnField.put(list.get(i), field); // ColumnName, Field
// Add fields all fields are dependent on
if (columnName.equals("IsActive") || columnName.equals("Processed"))
m_depOnField.put(columnName, null);
}
} // for all fields
// Add Standard Fields
if (m_mTable.getField("Created") == null)
{
MField created = new MField (MFieldVO.createStdField(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, m_vo.AD_Window_ID, false, true, true));
m_mTable.addField(created);
}
if (m_mTable.getField("CreatedBy") == null)
{
MField createdBy = new MField (MFieldVO.createStdField(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, m_vo.AD_Window_ID, false, true, false));
m_mTable.addField(createdBy);
}
if (m_mTable.getField("Updated") == null)
{
MField updated = new MField (MFieldVO.createStdField(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, m_vo.AD_Window_ID, false, false, true));
m_mTable.addField(updated);
}
if (m_mTable.getField("UpdatedBy") == null)
{
MField updatedBy = new MField (MFieldVO.createStdField(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, m_vo.AD_Window_ID, false, false, false));
m_mTable.addField(updatedBy);
}
return true;
} // loadFields
/**
* Get TableModel.
* Do not directly communicate with the table model,
* but through the methods of this class
* @return Table Model
*/
public MTable getTableModel()
{
return m_mTable;
} // getTableModel
/**
* Get Tab Icon
* @return Icon
*/
public javax.swing.Icon getIcon()
{
if (m_vo.AD_Image_ID == 0)
return null;
//
/** @todo Load Image */
return null;
} // getIcon
/*************************************************************************/
/**
* Has this field dependents ?
* @param columnName column name
* @return true if column has dependent
*/
public boolean isDependentOn (String columnName)
{
// m_depOnField.printToLog();
return m_depOnField.containsKey(columnName);
} // isDependentOn
/**
* Get dependent fields of columnName
* @param columnName column name
* @return ArrayList with MFields dependent on columnName
*/
public ArrayList getDependentFieldList (String columnName)
{
return m_depOnField.getValues(columnName);
} // getDependentFieldList
/*************************************************************************/
/**
* Set Query
* @param query query
*/
public void setQuery(MQuery query)
{
if (query == null)
m_query = new MQuery();
else
m_query = query;
} // setQuery
/**
* Get Query
* @return query
*/
public MQuery getQuery()
{
return m_query;
} // getQuery
/**
* Is Query Active
* @return true if query active
*/
public boolean isQueryActive()
{
return m_query.isActive();
} // isQueryActive
/**
* Enable Events - enable data events of tabs (add listeners)
*/
public void enableEvents()
{
// Setup Events
m_mTable.addDataStatusListener(this);
// m_mTable.addTableModelListener(this);
} // enableEvents
/**
* Assemble whereClause and query MTable and position to row 0.
*
* Scenarios:
* - Never opened (full query)
* - query changed (full query)
* - Detail link value changed (full query)
* - otherwise (refreshAll)
*
* @param onlyCurrentRows only current rows (1 day)
*/
public void query (boolean onlyCurrentRows)
{
query (onlyCurrentRows, 1);
} // query
/**
* Assemble whereClause and query MTable and position to row 0.
*
* Scenarios:
* - Never opened (full query)
* - query changed (full query)
* - Detail link value changed (full query)
* - otherwise (refreshAll)
*
* @param onlyCurrentRows only current rows
* @param onlyCurrentDays if only current row, how many days back
*/
public void query (boolean onlyCurrentRows, int onlyCurrentDays)
{
Log.trace(Log.l3_Util, "MTab.query #" + m_vo.TabNo);
// is it same query?
boolean refresh = m_oldQuery.equals(m_query.getWhereClause())
&& m_vo.onlyCurrentRows == onlyCurrentRows && m_vo.onlyCurrentDays == onlyCurrentDays;
m_oldQuery = m_query.getWhereClause();
m_vo.onlyCurrentRows = onlyCurrentRows;
m_vo.onlyCurrentDays = onlyCurrentDays;
/**
* Set Where Clause
*/
// Tab Where Clause
StringBuffer where = new StringBuffer(m_vo.WhereClause);
// Detail Query
if (isDetail())
{
String lc = getLinkColumnName();
if (lc.equals(""))
Log.error("MTab.query - no link column");
else
{
String value = Env.getContext(m_vo.ctx, m_vo.WindowNo, lc);
// Same link value?
if (refresh)
refresh = m_linkValue.equals(value);
m_linkValue = value;
// Check validity
if (value.length() == 0)
Log.error("MTab.query - no value for link column " + lc);
else
{
// we have column and value
if (where.length() != 0)
where.append(" AND ");
where.append(lc).append("=");
if (lc.endsWith("_ID"))
where.append(value);
else
where.append("'").append(value).append("'");
}
}
} // isDetail
m_extendedWhere = where.toString();
// Final Query
if (m_query.isActive())
{
String q = validateQuery(m_query);
if (q != null)
{
if (where.length() > 0 )
where.append(" AND ");
where.append(q);
}
}
/**
* Query
*/
if (m_mTable.isOpen())
{
if (refresh)
m_mTable.dataRefreshAll();
else
m_mTable.dataRequery(where.toString(), m_vo.onlyCurrentRows && !isDetail(), onlyCurrentDays);
}
else
{
m_mTable.setWhereClause(where.toString(), m_vo.onlyCurrentRows && !isDetail(), onlyCurrentDays);
m_mTable.open();
}
// Go to Record 0
setCurrentRow(0, true);
} // query
/**
* Validate Query.
* If query column is not a tab column create EXISTS query
* @param query query
* @return where clause
*/
private String validateQuery (MQuery query)
{
if (query == null || query.getRestrictionCount() == 0)
return null;
// Check: only one restriction
if (query.getRestrictionCount() != 1)
{
Log.trace(Log.l6_Database, "MTab.validateQuery - ignored: " + query);
return query.getWhereClause();
}
String colName = query.getColumnName(0);
// a '(' in the name = function - don't try to resolve
if (colName.indexOf('(') != -1)
{
Log.trace(Log.l6_Database, "MTab.validateQuery - ignored: " + colName);
return query.getWhereClause();
}
// Query is valid ?
if (getField(colName) != null)
return query.getWhereClause();
// Find Refernce Column e.g. BillTo_ID -> C_BPartner_Location_ID
String sql = "SELECT cc.ColumnName "
+ "FROM AD_Column c"
+ " INNER JOIN AD_Ref_Table r ON (c.AD_Reference_Value_ID=r.AD_Reference_ID)"
+ " INNER JOIN AD_Column cc ON (r.AD_Key=cc.AD_Column_ID) "
+ "WHERE c.AD_Reference_ID=18" // Table
+ " AND c.ColumnName=?";
String refColName = null;
try
{
PreparedStatement pstmt = DB.prepareStatement(sql);
pstmt.setString(1, colName);
ResultSet rs = pstmt.executeQuery();
if (rs.next())
refColName = rs.getString(1);
rs.close();
pstmt.close();
}
catch (SQLException e)
{
Log.error("MTab.validateQuery (ref) - Column=" + colName, e);
return query.getWhereClause();
}
// Reference Column found
if (refColName != null)
{
query.setColumnName(0, refColName);
if (getField(refColName) != null)
{
Log.trace(Log.l6_Database, "MTab.validateQuery - Column " + colName + " replaced with " + refColName);
return query.getWhereClause();
}
colName = refColName;
}
// Column NOT in Tab - create EXISTS subquery
String tableName = null;
String tabKeyColumn = getKeyColumnName();
// Column=SalesRep_ID, Key=AD_User_ID, Query=SalesRep_ID=101
sql = "SELECT t.TableName "
+ "FROM AD_Column c"
+ " INNER JOIN AD_Table t ON (c.AD_Table_ID=t.AD_Table_ID) "
+ "WHERE c.ColumnName=? AND IsKey='Y'" // #1 Link Column
+ " AND EXISTS (SELECT * FROM AD_Column cc"
+ " WHERE cc.AD_Table_ID=t.AD_Table_ID AND cc.ColumnName=?)"; // #2 Tab Key Column
try
{
PreparedStatement pstmt = DB.prepareStatement(sql);
pstmt.setString(1, colName);
pstmt.setString(2, tabKeyColumn);
ResultSet rs = pstmt.executeQuery();
if (rs.next())
tableName = rs.getString(1);
rs.close();
pstmt.close();
}
catch (SQLException e)
{
Log.error("MTab.validateQuery - Column=" + colName + ", Key=" + tabKeyColumn, e);
return null;
}
// Causes could be functions in query
// e.g. Column=UPPER(Name), Key=AD_Element_ID, Query=UPPER(AD_Element.Name) LIKE '%CUSTOMER%'
if (tableName == null)
{
Log.trace(Log.l3_Util, "MTab.validateQuery not successfull - Column=" + colName + ", Key=" + tabKeyColumn + ", Query=" + query);
return query.getWhereClause();
}
query.setTableName("xx");
StringBuffer result = new StringBuffer ("EXISTS (SELECT * FROM ")
.append(tableName).append(" xx WHERE ")
.append(query.getWhereClause(true))
.append(" AND xx.").append(tabKeyColumn).append("=")
.append(getTableName()).append(".").append(tabKeyColumn).append(")");
Log.trace(Log.l6_Database, "MTab.validateQuery", result);
return result.toString();
} // validateQuery
/**
* Refresh all data
*/
public void dataRefreshAll ()
{
Log.trace(Log.l3_Util, "MTab.dataRefreshAll #" + m_vo.TabNo);
/** @todo does not work with alpha key */
int keyNo = m_mTable.getKeyID(m_currentRow);
m_mTable.dataRefreshAll();
// Should use RowID - not working for tables with multiple keys
if (keyNo != -1)
{
if (keyNo != m_mTable.getKeyID(m_currentRow)) // something changed
{
int size = getRowCount();
for (int i = 0; i < size; i++)
{
if (keyNo == m_mTable.getKeyID(i))
{
m_currentRow = i;
break;
}
}
}
}
setCurrentRow(m_currentRow, true);
} // dataRefreshAll
/**
* Refresh current row data
*/
public void dataRefresh ()
{
dataRefresh (m_currentRow);
} // dataRefresh
/**
* Refresh row data
* @param row index
*/
public void dataRefresh (int row)
{
Log.trace(Log.l3_Util, "MTab.dataRefresh #" + m_vo.TabNo, "row=" + row);
m_mTable.dataRefresh(row);
setCurrentRow(row, true);
} // dataRefresh
/**
* Uncoditionally Save data
* @param manualCmd if true, no vetoable PropertyChange will be fired for save confirmation from MTable
* @return true if save complete (or nor required)
*/
public boolean dataSave(boolean manualCmd)
{
Log.trace(Log.l3_Util, "MTab.dataSave #" + m_vo.TabNo, "row=" + m_currentRow);
boolean retValue = (m_mTable.dataSave(manualCmd) == MTable.SAVE_OK);
if (manualCmd)
setCurrentRow(m_currentRow, false);
return retValue;
} // dataSave
/**
* Do we need to Save?
* @param rowChange row change
* @param onlyRealChange if true the value of a field was actually changed
* (e.g. for new records, which have not been changed) - default false
* @return true it needs to be saved
*/
public boolean needSave (boolean rowChange, boolean onlyRealChange)
{
if (rowChange)
{
return m_mTable.needSave(-2, onlyRealChange);
}
else
{
if (onlyRealChange)
return m_mTable.needSave();
else
return m_mTable.needSave(onlyRealChange);
}
} // isDataChanged
/**
* Ignore data changes
*/
public void dataIgnore()
{
Log.trace(Log.l3_Util, "MTab.dataIgnore #" + m_vo.TabNo);
m_mTable.dataIgnore();
setCurrentRow(m_currentRow, false); // re-load data
Log.trace(Log.l3_Util, "MTab.dataIgnore #" + m_vo.TabNo + "- fini");
} // dataIgnore
/**
* Create (copy) new Row
* and process Callouts
* @param copy copy
* @return true if copied/new
*/
public boolean dataNew (boolean copy)
{
Log.trace(Log.l3_Util, "MTab.dataNew #" + m_vo.TabNo);
boolean retValue = m_mTable.dataNew (m_currentRow, copy);
setCurrentRow(m_currentRow + 1, true);
// process all Callouts (no dependency check - assumed that settings are valid)
for (int i = 0; i < getFieldCount(); i++)
processCallout(getField(i));
// check validity of defaults
for (int i = 0; i < getFieldCount(); i++)
getField(i).validateValue();
m_mTable.setChanged(false);
return retValue;
} // dataNew
/**
* Delete current Row
* @return true if deleted
*/
public boolean dataDelete()
{
Log.trace(Log.l3_Util, "MTab.dataDelete #" + m_vo.TabNo, "row=" + m_currentRow);
boolean retValue = m_mTable.dataDelete(m_currentRow);
setCurrentRow(m_currentRow, true);
return retValue;
} // dataDelete
/**
* Get Name of Tab
* @return name
*/
public String getName()
{
return m_vo.Name;
} // getName
/**
* Get Description of Tab
* @return description
*/
public String getDescription()
{
return m_vo.Description;
} // getDescription
/**
* Get Help of Tab
* @return help
*/
public String getHelp()
{
return m_vo.Help;
} // getHelp
/**
* Get Tab Level
* @return tab level
*/
public int getTabLevel()
{
return m_vo.TabLevel;
} // getTabLevel
/**
* Get Commit Warning
* @return commit warning
*/
public String getCommitWarning()
{
return m_vo.CommitWarning;
} // getCommitWarning
/**
* Return Table Model
* @return MTable
*/
protected MTable getMTable()
{
return m_mTable;
} // getMTable
/**
* Return the name of the key column - may be ""
* @return key column name
*/
public String getKeyColumnName()
{
return m_keyColumnName;
} // getKeyColumnName
/**
* Return Name of link column
* @return link column name
*/
public String getLinkColumnName()
{
return m_linkColumnName;
} // getLinkColumnName
/**
* Set Name of link column.
* Set from MWindow.loadTabData
* Used in MTab.isCurreny, (.setCurrentRow) .query - APanel.cmd_report
* and MField.isEditable and .isDefault via context
* @param linkColumnName name of column - or sets name to AD_Column_ID, if exists
*/
public void setLinkColumnName (String linkColumnName)
{
if (linkColumnName != null)
m_linkColumnName = linkColumnName;
else
{
if (m_vo.AD_Column_ID == 0)
return;
// we have a link column identified (primary parent column)
else
{
String SQL = "SELECT ColumnName FROM AD_Column WHERE AD_Column_ID=?";
try
{
PreparedStatement pstmt = DB.prepareStatement(SQL);
pstmt.setInt(1, m_vo.AD_Column_ID); // Link Column
ResultSet rs = pstmt.executeQuery();
if (rs.next())
m_linkColumnName = rs.getString(1);
rs.close();
pstmt.close();
}
catch (SQLException e)
{
Log.error("MTab.setLinkColumn", e);
}
Log.trace(Log.l6_Database, "MTab.setLinkColumnName - " + m_vo.AD_Column_ID, m_linkColumnName);
}
}
Env.setContext(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "LinkColumnName", linkColumnName);
} // setLinkColumnName
/**
* Is the tab current?.
*
* Yes - Table must be open
* - Query String is the same
* - Not Detail
* - Old link column value is same as current one
*
* @return true if current
*/
public boolean isCurrent()
{
// Open?
if (!m_mTable.isOpen())
return false;
// Same Query
if (!m_oldQuery.equals(m_query.getWhereClause()))
return false;
// Detail?
if (!isDetail())
return true;
// Same link column value
String value = Env.getContext(m_vo.ctx, m_vo.WindowNo, getLinkColumnName());
return m_linkValue.equals(value);
} // isCurrent
/**
* Are Only Current Rows displayed
* @return true if no history
*/
public boolean isOnlyCurrentRows()
{
return m_vo.onlyCurrentRows;
} // isOnlyCurrentRows
/**
* Return Parent ArrayList
* @return parent column names
*/
public ArrayList getParentColumnNames()
{
return m_parents;
} // getParentColumnNames
/**
* Get Tree ID of this tab
* @return ID
*/
private int getTreeID()
{
Log.trace(Log.l5_DData, "MTab.getTreeID " + m_vo.TableName);
String SQL = "SELECT * FROM AD_ClientInfo WHERE AD_Client="
+ Env.getContext(m_vo.ctx, m_vo.WindowNo, "#AD_Client_ID")
+ " ORDER BY AD_Org DESC";
//
if (m_vo.TableName.equals("AD_Menu"))
return 10; // MM
else if (m_vo.TableName.equals("C_ElementValue"))
return 20; // EV
else if (m_vo.TableName.equals("M_Product"))
return 30; // PR
else if (m_vo.TableName.equals("C_BPartner"))
return 40; // BP
else if (m_vo.TableName.equals("AD_Org"))
return 50; // OO
else if (m_vo.TableName.equals("C_Project"))
return 60; // PJ
return 0;
} // getTreeID
/**
* Returns true if this is a detail record
* @return true if not parent tab
*/
public boolean isDetail()
{
// We have IsParent columns and/or a link column
if (m_parents.size() > 0 || m_vo.AD_Column_ID != 0)
return true;
return false;
} // isDetail
/**
* Is Printed (Document can be printed)
* @return true if printing
*/
public boolean isPrinted()
{
return m_vo.AD_Process_ID != 0;
} // isPrinted
/**
* Get WindowNo
* @return window no
*/
public int getWindowNo()
{
return m_vo.WindowNo;
} // getWindowNo
/**
* Get TabNo
* @return tab no
*/
public int getTabNo()
{
return m_vo.TabNo;
} // getTabNo
/**
* Get Process ID
* @return Process ID
*/
public int getAD_Process_ID()
{
return m_vo.AD_Process_ID;
} // getAD_Process_ID
/**
* Is High Volume?
* @return true if high volumen table
*/
public boolean isHighVolume()
{
return m_vo.IsHighVolume;
} // isHighVolume
/**
* Is Read Only?
* @return true if read only
*/
public boolean isReadOnly()
{
return m_vo.IsReadOnly;
} // isReadOnly
/**
* Is Single Row
* @return true if single row
*/
public boolean isSingleRow()
{
return m_vo.IsSingleRow;
} // isSingleRow;
/**
* Set Single Row.
* Temporary store of current value
* @param isSingleRow toggle
*/
public void setSingleRow (boolean isSingleRow)
{
m_vo.IsSingleRow = isSingleRow;
} // setSingleRow
/**
* Has Tree
* @return true if tree exists
*/
public boolean isTreeTab()
{
return m_vo.HasTree;
} // isTreeTab
/**
* Get Table ID
* @return Table ID
*/
public int getAD_Table_ID()
{
return m_vo.AD_Table_ID;
} // getAD_Table_ID
/**
* Get TableName
* @return Table Name
*/
public String getTableName()
{
return m_vo.TableName;
} // getTableName
/**
* Get Tab Where Clause
* @return where clause
*/
public String getWhereClause()
{
return m_vo.WhereClause;
} // getWhereClause
/**
* Is Sort Tab
* @return true if sort tab
*/
public boolean isSortTab()
{
return m_vo.IsSortTab;
} // isSortTab
/**
* Get Order column for sort tab
* @return AD_Column_ID
*/
public int getAD_ColumnSortOrder_ID()
{
return m_vo.AD_ColumnSortOrder_ID;
} // getAD_ColumnSortOrder_ID
/**
* Get Yes/No column for sort tab
* @return AD_Column_ID
*/
public int getAD_ColumnSortYesNo_ID()
{
return m_vo.AD_ColumnSortYesNo_ID;
} // getAD_ColumnSortYesNo_ID
/*************************************************************************/
/**
* Get extended Where Clause (parent link)
* @return parent link
*/
public String getWhereExtended()
{
return m_extendedWhere;
} // getWhereExtended
/**
* Get Order By Clause
* @param onlyCurrentRows only current rows
* @return Order By Clause
*/
private String getOrderByClause(boolean onlyCurrentRows)
{
// If there is no Tab Order By - use info from Fields
if (m_vo.OrderByClause.length() == 0 && m_OrderBys[0] != null)
{
m_vo.OrderByClause = m_OrderBys[0];
if (onlyCurrentRows && !isDetail()) // transaction order descending
m_vo.OrderByClause += " DESC";
if (m_OrderBys[1] != null)
m_vo.OrderByClause += "," + m_OrderBys[1];
}
return m_vo.OrderByClause;
} // getOrderByClause
/*************************************************************************/
/**
* Transaction support.
* Depending on Table returns transaction info
* @return info
*/
public String getTrxInfo()
{
// Order || Invoice
if (m_vo.TableName.startsWith("C_Order") || m_vo.TableName.startsWith("C_Invoice"))
{
int Record_ID;
boolean isOrder = m_vo.TableName.startsWith("C_Order");
//
StringBuffer sql = new StringBuffer("SELECT COUNT(*) AS Lines,c.ISO_Code,o.TotalLines,o.GrandTotal,"
+ "C_Base_Convert(o.GrandTotal,o.C_Currency_ID,o.AD_Client_ID,SysDate,o.AD_Org_ID) AS ConvAmt ");
if (isOrder)
{
Record_ID = Env.getContextAsInt(m_vo.ctx, m_vo.WindowNo, "C_Order_ID");
sql.append("FROM C_Order o, C_Currency c, C_OrderLine l "
+ "WHERE o.C_Currency_ID=c.C_Currency_ID"
+ " AND o.C_Order_ID=?"
+ " AND o.C_Order_ID=l.C_Order_ID ");
}
else
{
Record_ID = Env.getContextAsInt(m_vo.ctx, m_vo.WindowNo, "C_Invoice_ID");
sql.append("FROM C_Invoice o, C_Currency c, C_InvoiceLine l "
+ "WHERE o.C_Currency_ID=c.C_Currency_ID"
+ " AND o.C_Invoice_ID=?"
+ " AND o.C_Invoice_ID=l.C_Invoice_ID ");
}
sql.append("GROUP BY o.C_Currency_ID, c.ISO_Code, o.TotalLines, o.GrandTotal, o.AD_Client_ID, o.AD_Org_ID");
Log.trace(Log.l3_Util, "MTab.getTrxInfo " + m_vo.TableName + " - " + Record_ID);
MessageFormat mf = null;
try
{
mf = new MessageFormat(Msg.getMsg(Env.getAD_Language(m_vo.ctx), "OrderSummary"));
}
catch (Exception e)
{
Log.error("MTab.getTrxInfo - OrderSummary=" + Msg.getMsg(Env.getAD_Language(m_vo.ctx), "OrderSummary"), e);
}
if (mf == null)
return " ";
/**********************************************************************
* ** Message: OrderSummary **
* {0} Line(s) - {1,number,#,##0.00} - Toral: {2,number,#,##0.00} {3} = {4,number,#,##0.00}
*
* {0} - Number of lines
* {1} - Line toral
* {2} - Grand total (including tax, etc.)
* {3} - Currency
* (4) - Grand total converted to local currency
*/
Object[] arguments = new Object[5];
boolean filled = false;
//
try
{
PreparedStatement pstmt = DB.prepareStatement(sql.toString());
pstmt.setInt(1, Record_ID);
ResultSet rs = pstmt.executeQuery();
if (rs.next())
{
// {0} - Number of lines
Integer lines = new Integer(rs.getInt(1));
arguments[0] = lines;
// {1} - Line toral
Double lineTotal = new Double(rs.getDouble(3));
arguments[1] = lineTotal;
// {2} - Grand total (including tax, etc.)
Double grandTotal = new Double(rs.getDouble(4));
arguments[2] = grandTotal;
// {3} - Currency
String currency = rs.getString(2);
arguments[3] = currency;
// (4) - Grand total converted to Euro
Double grandEuro = new Double(rs.getDouble(5));
arguments[4] = grandEuro;
filled = true;
}
rs.close();
pstmt.close();
}
catch (SQLException e)
{
Log.error("MTab.getTrxInfo " + m_vo.TableName + "\nSQL=" + sql, e);
}
if (filled)
return mf.format (arguments);
return " ";
} // Order || Invoice
// Expense Report
else if (m_vo.TableName.startsWith("S_TimeExpense") && m_vo.TabNo == 0)
{
int Record_ID = Env.getContextAsInt(m_vo.ctx, m_vo.WindowNo, "S_TimeExpense_ID");
Log.trace(Log.l3_Util, "MTab.getTrxInfo " + m_vo.TableName + " - " + Record_ID);
MessageFormat mf = null;
try
{
mf = new MessageFormat(Msg.getMsg(Env.getAD_Language(m_vo.ctx), "ExpenseSummary"));
}
catch (Exception e)
{
Log.error("MTab.getTrxInfo - ExpenseSummary=" + Msg.getMsg(Env.getAD_Language(m_vo.ctx), "ExpenseSummary"), e);
}
if (mf == null)
return " ";
/**********************************************************************
* ** Message: ExpenseSummary **
* {0} Line(s) - Total: {1,number,#,##0.00} {2}
*
* {0} - Number of lines
* {1} - Toral
* {2} - Currency
*/
Object[] arguments = new Object[3];
boolean filled = false;
//
String SQL = "SELECT COUNT(*) AS Lines, SUM(ConvertedAmt*Qty) "
+ "FROM S_TimeExpenseLine "
+ "WHERE S_TimeExpense_ID=?";
//
try
{
PreparedStatement pstmt = DB.prepareStatement(SQL);
pstmt.setInt(1, Record_ID);
ResultSet rs = pstmt.executeQuery();
if (rs.next())
{
// {0} - Number of lines
Integer lines = new Integer(rs.getInt(1));
arguments[0] = lines;
// {1} - Line toral
Double total = new Double(rs.getDouble(2));
arguments[1] = total;
// {3} - Currency
arguments[2] = " ";
filled = true;
}
rs.close();
pstmt.close();
}
catch (SQLException e)
{
Log.error("MTab.getTrxInfo " + m_vo.TableName + "\nSQL=" + SQL, e);
}
if (filled)
return mf.format (arguments);
return " ";
} // S_TimeExpense
// Default - No Trx Info
return null;
} // getTrxInfo
/**
* Load Dependant Information
*/
private void loadDependentInfo()
{
/**
* Load Order Type from C_DocTypeTarget_ID
*/
if (m_vo.TableName.equals("C_Order"))
{
int C_DocTyp_ID = 0;
Integer target = (Integer)getValue("C_DocTypeTarget_ID");
if (target != null)
C_DocTyp_ID = target.intValue();
if (C_DocTyp_ID == 0)
return;
String sql = "SELECT DocSubTypeSO FROM C_DocType WHERE C_DocType_ID=?";
try
{
PreparedStatement pstmt = DB.prepareStatement(sql);
pstmt.setInt(1, C_DocTyp_ID);
ResultSet rs = pstmt.executeQuery();
if (rs.next())
Env.setContext(m_vo.ctx, m_vo.WindowNo, "OrderType", rs.getString(1));
rs.close();
pstmt.close();
}
catch (SQLException e)
{
Log.error("MTab.loadOrderType", e);
}
} // loadOrderInfo
} // loadDependentInfo
/*************************************************************************/
/**
* Load Attachments for this table
*/
public void loadAttachments()
{
Log.trace(Log.l3_Util, "MTab.loadAttachments #" + m_vo.TabNo);
if (!canHaveAttachment())
return;
String SQL = "SELECT AD_Attachment_ID, Record_ID FROM AD_Attachment "
+ "WHERE AD_Table_ID=?";
try
{
if (m_Attachment == null)
m_Attachment = new HashMap();
else
m_Attachment.clear();
PreparedStatement pstmt = DB.prepareStatement(SQL);
pstmt.setInt(1, m_vo.AD_Table_ID);
ResultSet rs = pstmt.executeQuery();
while (rs.next())
{
Integer key = new Integer(rs.getInt(2));
Integer value = new Integer(rs.getInt(1));
m_Attachment.put(key, value);
}
rs.close();
pstmt.close();
}
catch (SQLException e)
{
Log.error("MTab.loadAttachments", e);
}
Log.trace(Log.l4_Data, "Attachments=" + m_Attachment.size());
} // loadAttachment
/**
* Can this tab have Attachments?.
*
* It can have an attachment if it has a key column ending with _ID.
* The key column is empty, if there is no single identifying key.
* @return true if record can have attachment
*/
public boolean canHaveAttachment()
{
if (getKeyColumnName().endsWith("_ID"))
return true;
return false;
} // canHaveAttachment
/**
* Returns true, if current row has an Attachment
* @return true if record has attchment
*/
public boolean hasAttachment()
{
if (m_Attachment == null)
loadAttachments();
if (m_Attachment == null || m_Attachment.isEmpty())
return false;
//
Integer key = new Integer(m_mTable.getKeyID (m_currentRow));
return m_Attachment.containsKey(key);
} // hasAttachment
/**
* Get Attachment_ID.
* @return ID or 0, if not found
*/
public int getAD_AttachmentID()
{
if (m_Attachment == null)
loadAttachments();
if (m_Attachment.isEmpty())
return 0;
//
Integer key = new Integer(m_mTable.getKeyID (m_currentRow));
Integer value = (Integer)m_Attachment.get(key);
if (value == null)
return 0;
else
return value.intValue();
} // getAttachmentID
/*************************************************************************/
/**
* Data Status Listener from MTable.
* - get raw info and add current row information
* - update the current row
* - redistribute (fire) Data Status event
* @param e event
*/
public void dataStatusChanged (DataStatusEvent e)
{
Log.trace(Log.l3_Util, "MTab.dataStatusChanged #" + m_vo.TabNo, e.toString());
int oldCurrentRow = e.getCurrentRow();
m_DataStatusEvent = e; // save it
// when sorted set current row to 0
String msg = m_DataStatusEvent.getAD_Message();
if (msg != null && msg.equals("Sorted"))
setCurrentRow(0, true);
// set current row
m_DataStatusEvent.setCurrentRow(m_currentRow);
// Same row - update value
if (oldCurrentRow == m_currentRow)
{
MField field = m_mTable.getField(e.getChangedColumn());
Object value = m_mTable.getValueAt(m_currentRow, e.getChangedColumn());
field.setValue(value, m_mTable.isInserting());
}
else // Redistribute Info with current row info
fireDataStatusChanged(m_DataStatusEvent);
// Log.trace(Log.l3_Util, "MTab.dataStatusChanged #" + m_vo.TabNo + "- fini", e.toString());
} // dataStatusChanged
/**
* Inform Listeners and build WHO info
* @param e event
*/
private void fireDataStatusChanged (DataStatusEvent e)
{
Log.trace(Log.l4_Data, "MTab.fireDataStatusChanged", e.toString());
if (m_dataStatusListeners != null)
{
// WHO Info
if (e.getCurrentRow() >= 0)
{
e.Created = (Timestamp)getValue("Created");
e.CreatedBy = getValue("CreatedBy");
e.Updated = (Timestamp)getValue("Updated");
e.UpdatedBy = getValue("UpdatedBy");
// Info
StringBuffer info = new StringBuffer(getTableName());
// We have a key column
if (m_keyColumnName != null && m_keyColumnName.length() > 0)
{
info.append(" - ")
.append(m_keyColumnName).append("=").append(getValue(m_keyColumnName));
}
else // we have multiple parents
{
for (int i = 0; i < m_parents.size(); i++)
{
String keyCol = (String)m_parents.get(i);
info.append(" - ")
.append(keyCol).append("=").append(getValue(keyCol));
}
}
e.Info = info.toString();
}
e.setInserting(m_mTable.isInserting());
// Distribute/fire it
Vector listeners = m_dataStatusListeners;
int count = listeners.size();
for (int i = 0; i < count; i++)
((DataStatusListener) listeners.elementAt(i)).dataStatusChanged(e);
}
// Log.trace(Log.l4_Data, "MTab.fireDataStatusChanged - fini", e.toString());
} // fireDataStatusChanged
/**
* Create and fire Data Status Error Event
* @param AD_Message message
* @param info info
*/
protected void fireDataStatusEEvent(String AD_Message, String info)
{
m_mTable.fireDataStatusEEvent(AD_Message, info);
} // fireDataStatusEvent
/**
* Create and fire Data Status Error Event (from Error Log)
* @param errorLog log
*/
protected void fireDataStatusEEvent (ValueNamePair errorLog)
{
if (errorLog != null)
m_mTable.fireDataStatusEEvent(errorLog);
} // fireDataStatusEvent
/**
* Get Current Row
* @return current row
*/
public int getCurrentRow()
{
if (m_currentRow != verifyRow(m_currentRow))
setCurrentRow(m_mTable.getRowCount()-1, true);
return m_currentRow;
} // getCurrentRow
/**
* Get Current TableKey_ID
* @return ID
*/
public int getCurrentKeyID()
{
return m_mTable.getKeyID(m_currentRow);
} // getCurrentKeyID
/**
* Get Key ID of row
* @param row row number
* @return The Key ID of the row or -1 if not found
*/
public int getKeyID (int row)
{
return m_mTable.getKeyID (row);
} // getCurrentKeyID
/**
* Navigate absulute - goto Row - (zero based).
* - does nothing, if in current row
* - saves old row if required
* @param targetRow target row
* @return current row
*/
public int navigate (int targetRow)
{
// nothing to do
if (targetRow == m_currentRow)
return m_currentRow;
Log.trace(Log.l1_User, "MTab.navigate - Row=" + targetRow);
// Row range check
int newRow = verifyRow(targetRow);
// Check, if we have old uncommitted data
m_mTable.dataSave(newRow, false);
// new position
return setCurrentRow(newRow, true);
} // navigate
/**
* Navigate relatively - i.e. plus/minus from current position
* @param rowChange row change
* @return current row
*/
public int navigateRelative (int rowChange)
{
return navigate (m_currentRow + rowChange);
} // navigateRelative
/**
* Navigate to current now (reload)
* @return current row
*/
public int navigateCurrent()
{
Log.trace(Log.l1_User, "MTab.navigateCurrent");
return setCurrentRow(m_currentRow, true);
} // navigateCurrent
/**
* Row Range check
* @param targetRow target row
* @return checked row
*/
private int verifyRow (int targetRow)
{
int newRow = targetRow;
// Table Open?
if (!m_mTable.isOpen())
{
Log.error("MTab.verifyRow - Table not open");
return -1;
}
// Row Count
int rows = getRowCount();
if (rows == 0)
{
Log.trace(Log.l4_Data, "MTab.verifyRow", "No Rows");
return -1;
}
if (newRow >= rows)
{
newRow = rows-1;
Log.trace(Log.l4_Data, "MTab.verifyRow", "Set to max Row: " + newRow);
}
else if (newRow < 0)
{
newRow = 0;
Log.trace(Log.l4_Data, "MTab.verifyRow", "Set to first Row");
}
return newRow;
} // verifyRow
/**
* Set current row and load data into fields.
* If there is no row - load nulls
* @param newCurrentRow new current row
* @param fireEvents fire events
* @return current row
*/
private int setCurrentRow (int newCurrentRow, boolean fireEvents)
{
int oldCurrentRow = m_currentRow;
m_currentRow = verifyRow (newCurrentRow);
Log.trace(Log.l4_Data, "MTab.setCurrentRow = " + m_currentRow, "fire=" + fireEvents);
// Update Field Values
int size = m_mTable.getColumnCount();
for (int i = 0; i < size; i++)
{
MField mField = m_mTable.getField(i);
// get Value from Table
if (m_currentRow >= 0)
{
Object value = m_mTable.getValueAt(m_currentRow, i);
mField.setValue(value, m_mTable.isInserting());
}
else
{ // no rows - set to a reasonable value - not updateable
// Object value = null;
// if (mField.isKey() || mField.isParent() || mField.getColumnName().equals(m_linkColumnName))
// value = mField.getDefault();
mField.setValue();
}
}
loadDependentInfo();
if (!fireEvents) // prevents informing twice
return m_currentRow;
// inform VTable/.. -> rowChanged
m_propertyChangeSupport.firePropertyChange(PROPERTY, oldCurrentRow, m_currentRow);
// inform APanel/.. -> dataStatus with row updated
if (m_DataStatusEvent == null)
{
Log.trace(Log.l5_DData, "MTab.setCurrentRow - no existing data status event");
}
else
{
m_DataStatusEvent.setCurrentRow(m_currentRow);
String status = m_DataStatusEvent.getAD_Message();
if (status == null || status.length() == 0)
m_DataStatusEvent.setInfo("NavigateOrUpdate", null, false);
fireDataStatusChanged(m_DataStatusEvent);
}
return m_currentRow;
} // setCurrentRow
/*************************************************************************/
/**
* Get RowCount
* @return row count
*/
public int getRowCount()
{
int count = m_mTable.getRowCount();
// Wait a bit if currently loading
if (count == 0 && m_mTable.isLoading())
{
try
{
Thread.sleep(100); // .1 sec
}
catch (Exception e) {}
count = m_mTable.getRowCount();
}
return count;
} // getRowCount
/**
* Get Column/Field Count
* @return field count
*/
public int getFieldCount()
{
return m_mTable.getColumnCount();
} // getFieldCount
/**
* Get Field by index
* @param index index
* @return MField
*/
public MField getField (int index)
{
return m_mTable.getField(index);
} // getField
/**
* Get Field by DB column name
* @param columnName column name
* @return MField
*/
public MField getField (String columnName)
{
return m_mTable.getField(columnName);
} // getField
/**
* Set New Value & call Callout
* @param columnName database column name
* @param value value
* @return error message or ""
*/
public String setValue (String columnName, Object value)
{
if (columnName == null)
return "NoColumn";
return setValue(m_mTable.getField(columnName), value);
} // setValue
/**
* Set New Value & call Callout
* @param field field
* @param value value
* @return error message or ""
*/
public String setValue (MField field, Object value)
{
if (field == null)
return "NoField";
Log.trace(Log.l3_Util, "MTab.setValue - "
+ field.getColumnName() + "=" + value + " for row=" + m_currentRow);
int col = m_mTable.findColumn(field.getColumnName());
m_mTable.setValueAt(value, m_currentRow, col, false);
//
return processFieldChange (field);
} // setValue
/**
* Process Field Change - evaluate Dependencies and process Callouts.
*
* called from MTab.setValue or GridController.dataStatusChanged
* @param changedField changed field
* @return error message or ""
*/
public String processFieldChange (MField changedField)
{
processDependencies (changedField);
return processCallout (changedField);
} // processFieldChange
/**
* Evaluate Dependencies
* @param changedField changed field
*/
private void processDependencies (MField changedField)
{
String columnName = changedField.getColumnName();
// Log.trace(Log.l4_Data, "Changed Column", columnName);
// when column name is not in list of DependentOn fields - fini
if (!isDependentOn(columnName))
return;
// Get dependent MFields (may be because of display or dynamic lookup)
ArrayList list = getDependentFieldList(columnName);
for (int i = 0; i < list.size(); i++)
{
MField dependentField = (MField)list.get(i);
// Log.trace(Log.l5_DData, "Dependent Field", dependentField==null ? "null" : dependentField.getColumnName());
// if the field has a lookup
if (dependentField != null && dependentField.getLookup() instanceof MLookup)
{
MLookup mLookup = (MLookup)dependentField.getLookup();
// Log.trace(Log.l6_Database, "Lookup Validation", mLookup.getValidation());
// if the lookup is dynamic (i.e. contains this columnName as variable)
if (mLookup.getValidation().indexOf("@"+columnName+"@") != -1)
{
Log.trace(Log.l6_Database, "MTab.processDependencies",
columnName + " changed - " + dependentField.getColumnName() + " set to null");
// invalidate current selection
setValue(dependentField, null);
}
}
} // for all dependent fields
} // processDependencies
/**
* Process Callout(s).
*
* The Callout is in the string of
* "class.method;class.method;"
* If there is no class name, i.e. only a method name, the class is regarded
* as CalloutSystem.
* The class needs to comply with the Interface Callout.
*
* For a limited time, the old nptation of Sx_matheod / Ux_menthod is maintained.
*
* @param field field
* @return error message or ""
* @see org.compiere.model.Callout
*/
private String processCallout (MField field)
{
String callout = field.getCallout();
if (callout.length() == 0)
return "";
Object value = field.getValue();
Object oldValue = field.getOldValue();
Log.trace(Log.l3_Util, "MTab.processCallout - " + field.getColumnName() + "=" + value
+ " (" + callout + ") - old=" + oldValue);
StringTokenizer st = new StringTokenizer(callout, ";", false);
while (st.hasMoreTokens()) // for each callout
{
String cmd = st.nextToken().trim();
Callout call = null;
String method = null;
int methodStart = cmd.lastIndexOf(".");
try
{
if (methodStart == -1) // no class
{
// old version compatibility
if (cmd.charAt(0) == 'S' && cmd.charAt(2) == '_')
{
call = new CalloutSystem();
if (cmd.length() > 3)
method = cmd.substring(3);
}
else if (cmd.charAt(0) == 'U' && cmd.charAt(2) == '_')
{
Class cClass = Class.forName("com.compiere.custom.CalloutUser");
call = (Callout)cClass.newInstance();
if (cmd.length() > 3)
method = cmd.substring(3);
}
else
{
call = new CalloutSystem();
method = cmd;
}
}
else
{
Class cClass = Class.forName(cmd.substring(0,methodStart));
call = (Callout)cClass.newInstance();
method = cmd.substring(methodStart+1);
}
}
catch (Exception e)
{
Log.error("MTab.processCallout", e);
return "CalloutNameInvalid = " + cmd + " (" + e.toString() + ")";
}
String retValue = "";
if (call != null && method != null && !method.equals(""))
retValue = call.start(m_vo.ctx, method, m_vo.WindowNo, this, field, value, oldValue);
else
retValue = "CalloutNameInvalid = " + method;
if (!retValue.equals("")) // interrupt on first error
{
Log.error("MTab.processCallout - " + retValue);
return retValue;
}
} // for each callout
return "";
} // processCallout
/**
* Get Value of Field with columnName
* @param columnName column name
* @return value
*/
public Object getValue (String columnName)
{
if (columnName == null)
return null;
MField field = m_mTable.getField(columnName);
return getValue(field);
} // getValue
/**
* Get Value of Field
* @param field field
* @return value
*/
public Object getValue (MField field)
{
if (field == null)
return null;
return field.getValue();
} // getValue
/**
* Get Value of Field in row
* @param row row
* @param columnName column name
* @return value
*/
public Object getValue (int row, String columnName)
{
int col = m_mTable.findColumn(columnName);
if (col == -1)
return null;
return m_mTable.getValueAt(row, col);
} // getValue
/**
* toString
* @return String representation
*/
public String toString()
{
String retValue = "MTab #" + m_vo.TabNo;
if (m_vo != null)
retValue += " " + m_vo.Name + " (" + m_vo.AD_Tab_ID + ")";
return retValue;
} // toString
/*************************************************************************/
/**
* @param l listener
*/
public synchronized void removePropertyChangeListener(PropertyChangeListener l)
{
m_propertyChangeSupport.removePropertyChangeListener(l);
}
/**
* @param l listener
*/
public synchronized void addPropertyChangeListener(PropertyChangeListener l)
{
m_propertyChangeSupport.addPropertyChangeListener(l);
}
/**
* @param l listener
*/
public synchronized void removeDataStatusListener(DataStatusListener l)
{
if (m_dataStatusListeners != null && m_dataStatusListeners.contains(l))
{
Vector v = (Vector) m_dataStatusListeners.clone();
v.removeElement(l);
m_dataStatusListeners = v;
}
}
/**
* @param l listener
*/
public synchronized void addDataStatusListener(DataStatusListener l)
{
Vector v = m_dataStatusListeners == null ? new Vector(2) : (Vector) m_dataStatusListeners.clone();
if (!v.contains(l))
{
v.addElement(l);
m_dataStatusListeners = v;
}
}
} // M_Tab