📄 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 Smart Business Solution. The Initial
* Developer of the Original Code is Jorg Janke. Portions created by Jorg Janke
* are Copyright (C) 1999-2005 Jorg Janke.
* All parts are Copyright (C) 1999-2005 ComPiere, Inc. All Rights Reserved.
* Contributor(s): ______________________________________.
*****************************************************************************/
package org.compiere.model;
import java.beans.*;
import java.io.*;
import java.sql.*;
import java.text.*;
import java.util.*;
import java.util.logging.*;
import javax.swing.event.*;
import org.compiere.util.*;
/**
* Tab Model.
* - a combination of AD_Tab (the display attributes) and AD_Table information.
* <p>
* The Tab owns also it's Table model
* and listens to data changes to update the Field values.
*
* <p>
* The Tab maintains the bound property: CurrentRow
*
* <pre>
* Event Hierarchies:
* - dataChanged (from MTable)
* - setCurrentRow
* - Update all Field Values
*
* - setValue
* - Update Field Value
* - Callout
* </pre>
* @author Jorg Janke
* @version $Id: MTab.java,v 1.101 2006/01/28 01:28:28 jjanke Exp $
*/
public final class MTab implements DataStatusListener, Evaluatee, Serializable
{
/**
* Create Tab (Model) from Value Object.
* <p>
* 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.AD_Table_ID, 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<Integer,Integer> m_Attachment = null;
/** Locks */
private ArrayList<Integer> m_Lock = 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";
/** A list of event listeners for this component. */
protected EventListenerList m_listenerList = new EventListenerList();
/** Current Data Status Event */
private DataStatusEvent m_DataStatusEvent = null;
/** Query */
private MQuery m_query = new MQuery();
private String m_oldQuery = "0=9";
private String m_linkValue = "999999";
/** Order By Array if SortNo 1..3 */
private String[] m_OrderBys = new String[3];
/** List of Key Parents */
private ArrayList<String> m_parents = new ArrayList<String>(2);
/** Map of ColumnName of source field (key) and the dependant field (value) */
private MultiMap<String,MField> m_depOnField = new MultiMap<String,MField>();
/** Async Loader */
private Loader m_loader = null;
/** Async Loading complete */
private volatile boolean m_loadComplete = false;
/** Is Tab Included in other Tab */
private boolean m_included = false;
/** Logger */
protected CLogger log = CLogger.getCLogger(getClass());
/**************************************************************************
* 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.config ("");
while (m_loader.isAlive())
{
try
{
Thread.sleep(100); // 1/10 sec
}
catch (Exception e)
{
log.log(Level.SEVERE, "", e);
}
}
log.config ("fini");
} // waitLoadComplete
/**
* Initialize Tab with record from AD_Tab_v
* @param async async
* @return true, if correctly initialized (ignored)
*/
protected boolean initTab (boolean async)
{
log.fine("#" + m_vo.TabNo + " - Async=" + async + " - Where=" + m_vo.WhereClause);
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.fine("#" + m_vo.TabNo + " - Async=" + async + " - fini");
m_loadComplete = true;
return true;
} // initTab
/**
* Dispose - clean up resources
*/
protected void dispose()
{
log.fine("#" + 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.fine("#" + m_vo.TabNo);
if (m_vo.Fields == null)
return false;
// 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())
m_keyColumnName = columnName;
// Parent Column(s)
if (field.isParentColumn())
m_parents.add(columnName);
// Order By
int sortNo = field.getSortNo();
if (sortNo == 0)
;
else if (Math.abs(sortNo) == 1)
{
m_OrderBys[0] = columnName;
if (sortNo < 0)
m_OrderBys[0] += " DESC";
}
else if (Math.abs(sortNo) == 2)
{
m_OrderBys[1] = columnName;
if (sortNo < 0)
m_OrderBys[1] += " DESC";
}
else if (Math.abs(sortNo) == 3)
{
m_OrderBys[2] = columnName;
if (sortNo < 0)
m_OrderBys[2] += " DESC";
}
// Add field
m_mTable.addField(field);
// List of ColumnNames, this field is dependent on
ArrayList<String> 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.
* <B>Do not directly communicate with the table model,
* but through the methods of this class</B>
* @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 hasDependants (String columnName)
{
// m_depOnField.printToLog();
return m_depOnField.containsKey(columnName);
} // isDependentOn
/**
* Get dependents fields of columnName
* @param columnName column name
* @return ArrayList with MFields dependent on columnName
*/
public ArrayList getDependantList (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()
{
if (m_query != null)
return m_query.isActive();
return false;
} // isQueryActive
/**
* Is Query New Record
* @return true if query active
*/
public boolean isQueryNewRecord()
{
if (m_query != null)
return m_query.isNewRecordQuery();
return false;
} // isQueryNewRecord
/**
* 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.
* <pre>
* Scenarios:
* - Never opened (full query)
* - query changed (full query)
* - Detail link value changed (full query)
* - otherwise (refreshAll)
* </pre>
* @param onlyCurrentRows only current rows (1 day)
*/
public void query (boolean onlyCurrentRows)
{
query (onlyCurrentRows, 0);
} // query
/**
* Assemble whereClause and query MTable and position to row 0.
* <pre>
* Scenarios:
* - Never opened (full query)
* - query changed (full query)
* - Detail link value changed (full query)
* - otherwise (refreshAll)
* </pre>
* @param onlyCurrentRows only current rows
* @param onlyCurrentDays if only current row, how many days back
*/
public void query (boolean onlyCurrentRows, int onlyCurrentDays)
{
log.fine("#" + m_vo.TabNo
+ " - Only Current Rows=" + onlyCurrentRows
+ ", Days=" + onlyCurrentDays + ", Detail=" + isDetail());
// 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);
if (m_vo.onlyCurrentDays > 0)
{
if (where.length() > 0)
where.append(" AND ");
where.append("Created >= ");
if (DB.isSybase())
where.append("dateadd(dd,-").append(m_vo.onlyCurrentDays).append(",getdate())");
else
where.append("SysDate-").append(m_vo.onlyCurrentDays);
}
// Detail Query
if (isDetail())
{
String lc = getLinkColumnName();
if (lc.equals(""))
log.severe ("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.severe ("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
*/
log.fine("#" + m_vo.TabNo + " - " + where);
if (m_mTable.isOpen())
{
if (refresh)
m_mTable.dataRefreshAll();
else
m_mTable.dataRequery(where.toString(), m_vo.onlyCurrentRows && !isDetail(), onlyCurrentDays);
}
else
{
m_mTable.setSelectWhereClause(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.fine("Ignored(More than 1 Restriction): " + query);
return query.getWhereClause();
}
String colName = query.getColumnName(0);
if (colName == null)
{
log.fine("Ignored(No Column): " + query);
return query.getWhereClause();
}
// a '(' in the name = function - don't try to resolve
if (colName.indexOf('(') != -1)
{
log.fine("Ignored(Function): " + colName);
return query.getWhereClause();
}
// OK - Query is valid
// Zooms to the same Window (Parents, ..)
String refColName = null;
if (colName.equals("R_RequestRelated_ID"))
refColName = "R_Request_ID";
else if (colName.startsWith("C_DocType"))
refColName = "C_DocType_ID";
if (refColName != null)
{
query.setColumnName(0, refColName);
if (getField(refColName) != null)
{
log.fine("Column " + colName + " replaced with synonym " + refColName);
return query.getWhereClause();
}
refColName = null;
}
// Simple Query.
if (getField(colName) != null)
{
log.fine("Field Found: " + colName);
return query.getWhereClause();
}
// Find Refernce Column e.g. BillTo_ID -> C_BPartner_Location_ID
String sql = "SELECT cc.ColumnName "
+ "FROM AD_Column c"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -