⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mtab.java

📁 大家共享愉快, 共享愉快, 共享愉快, 共享愉快,共享愉快
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/******************************************************************************
 * 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 + -