📄 mlookup.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.io.*;
import java.sql.*;
import java.util.*;
import java.util.logging.*;
import org.compiere.util.*;
/**
* An intelligent MutableComboBoxModel, which determines what can be cached.
* <pre>
* Validated - SQL is final / not dynamic
* AllLoaded - All Records are loaded
*
* Get Info about Lookup
* - SQL
* - KeyColumn
* - Zoom Target
* </pre>
* @author Jorg Janke
* @version $Id: MLookup.java,v 1.40 2006/01/19 01:51:20 jjanke Exp $
*/
public final class MLookup extends Lookup implements Serializable
{
/**
* MLookup Constructor
* @param info info
* @param TabNo tab no
*/
public MLookup (MLookupInfo info, int TabNo)
{
super(info.DisplayType, info.WindowNo);
m_info = info;
log.fine(m_info.KeyColumn);
// load into local lookup, if already cached
if (MLookupCache.loadFromCache (m_info, m_lookup))
return;
// Don't load Search or CreatedBy/UpdatedBy
if (m_info.DisplayType == DisplayType.Search
|| m_info.IsCreadedUpdatedBy)
return;
// Don't load Parents/Keys
if (m_info.IsParent || m_info.IsKey)
{
m_hasInactive = true; // creates focus listener for dynamic loading
return; // required when parent needs to be selected (e.g. price from product)
}
//
m_loader = new MLoader();
// if (TabNo != 0)
// m_loader.setPriority(Thread.NORM_PRIORITY - 1);
m_loader.start();
// m_loader.run(); // test sync call
} // MLookup
/** Inactive Marker Start */
public static final String INACTIVE_S = "~";
/** Inactive Marker End */
public static final String INACTIVE_E = "~";
/** Number of max rows to load */
private static final int MAX_ROWS = 1000; // i.e. Drop Down has max 500 items
/** Indicator for Null */
private static Integer MINUS_ONE = new Integer(-1);
/** The Lookup Info Value Object */
private MLookupInfo m_info = null;
/** Storage of data Key-NamePair */
private volatile LinkedHashMap<Object,Object> m_lookup = new LinkedHashMap<Object,Object>();
/** The Data Loader */
private MLoader m_loader;
//
/** All Data loaded */
private boolean m_allLoaded = false;
/** Inactive records exists */
private boolean m_hasInactive = false;
/* Refreshing - disable cashing */
private boolean m_refreshing = false;
/** Next Read for Parent */
private long m_nextRead = 0;
/**
* Dispose
*/
public void dispose()
{
if (m_info != null)
log.fine(m_info.KeyColumn + ": dispose");
if (m_loader != null && m_loader.isAlive())
m_loader.interrupt();
m_loader = null;
//
if (m_lookup != null)
m_lookup.clear();
m_lookup = null;
if (m_lookupDirect != null)
m_lookupDirect.clear();
m_lookupDirect = null;
//
m_info = null;
//
super.dispose();
} // dispose
/**
* Wait until async Load Complete
*/
public void loadComplete()
{
if (m_loader != null && m_loader.isAlive())
{
try
{
m_loader.join();
m_loader = null;
}
catch (InterruptedException ie)
{
log.log(Level.SEVERE, m_info.KeyColumn + ": Interrupted", ie);
}
}
} // loadComplete
/**
* Get value (name) for key.
* If not found return null;
* @param key key (Integer for Keys or String for Lists)
* @return value
*/
public NamePair get (Object key)
{
if (key == null || MINUS_ONE.equals(key)) // indicator for null
return null;
if (m_info.IsParent && m_nextRead < System.currentTimeMillis())
{
m_lookup.clear();
if (m_lookupDirect != null)
m_lookupDirect.clear();
m_nextRead = System.currentTimeMillis() + 500; // 1/2 sec
}
// try cache
NamePair retValue = (NamePair)m_lookup.get(key);
if (retValue != null)
return retValue;
// Not found and waiting for loader
if (m_loader != null && m_loader.isAlive())
{
log.finer((m_info.KeyColumn==null ? "ID="+m_info.Column_ID : m_info.KeyColumn) + ": waiting for Loader");
loadComplete();
// is most current
retValue = (NamePair)m_lookup.get(key);
if (retValue != null)
return retValue;
}
// Always check for parents - not if we SQL was validated and completely loaded
if (!m_info.IsParent && m_info.IsValidated && m_allLoaded)
{
log.finer(m_info.KeyColumn + ": <NULL> - " + key // + "(" + key.getClass()
+ "; Size=" + m_lookup.size());
// log.finest( m_lookup.keySet().toString(), "ContainsKey = " + m_lookup.containsKey(key));
// also for new values and inactive ones
return getDirect(key, false, true); // cache locally
}
log.finest (m_info.KeyColumn + ": " + key
+ "; Size=" + m_lookup.size() + "; Validated=" + m_info.IsValidated
+ "; All Loaded=" + m_allLoaded + "; HasInactive=" + m_hasInactive);
// never loaded
if (!m_allLoaded
&& m_lookup.size() == 0
&& !m_info.IsCreadedUpdatedBy
&& !m_info.IsParent
&& m_info.DisplayType != DisplayType.Search)
{
m_loader = new MLoader();
m_loader.run(); // sync!
retValue = (NamePair)m_lookup.get(key);
if (retValue != null)
return retValue;
}
// Try to get it directly
boolean cacheLocal = m_info.IsValidated ;
return getDirect(key, false, cacheLocal); // do NOT cache
} // get
/**
* Get Display value (name).
* If not found return key embedded in inactive signs.
* @param key key
* @return value
*/
public String getDisplay (Object key)
{
if (key == null)
return "";
//
Object display = get (key);
if (display == null)
return "<" + key.toString() + ">";
return display.toString();
} // getDisplay
/**
* The Lookup contains the key
* @param key key
* @return true if key is known
*/
public boolean containsKey (Object key)
{
return m_lookup.containsKey(key);
} // containsKey
/**
* @return a string representation of the object.
*/
public String toString()
{
return "MLookup[" + m_info.KeyColumn + ",Column_ID=" + m_info.Column_ID
+ ",Size=" + m_lookup.size() + ",Validated=" + isValidated()
+ "-" + getValidation()
+ "]";
} // toString
/**
* Indicates whether some other object is "equal to" this one.
* @param obj the reference object with which to compare.
* @return <code>true</code> if this object is the same as the obj
* argument; <code>false</code> otherwise.
*/
public boolean equals(Object obj)
{
if (obj instanceof MLookup)
{
MLookup ll = (MLookup)obj;
if (ll.m_info.Column_ID == this.m_info.Column_ID)
return true;
}
return false;
} // equals
/**
* Return Size
* @return size
*/
public int size()
{
return m_lookup.size();
} // size
/**
* Is it all loaded
* @return true, if all loaded
*/
public boolean isAllLoaded()
{
return m_allLoaded;
} // isAllLoaded
/**
* Is the List fully Validated
* @return true, if validated
*/
public boolean isValidated()
{
if (m_info == null)
return false;
return m_info.IsValidated;
} // isValidated
/**
* Get Validation SQL
* @return Validation SQL
*/
public String getValidation()
{
return m_info.ValidationCode;
} // getValidation
/**
* Get Reference Value
* @return Reference Value
*/
public int getAD_Reference_Value_ID()
{
return m_info.AD_Reference_Value_ID;
} // getAD_Reference_Value_ID
/**
* Has inactive elements in list
* @return true, if list contains inactive values
*/
public boolean hasInactive()
{
return m_hasInactive;
} // hasInactive
/**
* Return info as ArrayList containing Value/KeyNamePair
* @param onlyValidated only validated
* @param loadParent get Data even for parent lookups
* @return List
*/
private ArrayList<Object> getData (boolean onlyValidated, boolean loadParent)
{
if (m_loader != null && m_loader.isAlive())
{
log.fine((m_info.KeyColumn==null ? "ID="+m_info.Column_ID : m_info.KeyColumn) + ": getData - waiting for Loader");
loadComplete();
}
// Never Loaded (correctly)
if (!m_allLoaded || m_lookup.size() == 0)
refresh (loadParent);
// already validation included
if (m_info.IsValidated)
return new ArrayList<Object>(m_lookup.values());
if (!m_info.IsValidated && onlyValidated)
{
refresh (loadParent);
log.fine(m_info.KeyColumn + ": getData Validated - #" + m_lookup.size());
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -