diff --git a/org.adempiere.base/src/org/compiere/model/MLookup.java b/org.adempiere.base/src/org/compiere/model/MLookup.java index 39608ab35a..b596f2ac26 100644 --- a/org.adempiere.base/src/org/compiere/model/MLookup.java +++ b/org.adempiere.base/src/org/compiere/model/MLookup.java @@ -121,8 +121,10 @@ public final class MLookup extends Lookup implements Serializable /** Inactive records exists */ private boolean m_hasInactive = false; - /* Refreshing - disable cashing */ + /* Refreshing */ private boolean m_refreshing = false; + /* Refresh cache(if exists) */ + private boolean m_refreshCache = false; /** Next Read for Parent */ private long m_nextRead = 0; @@ -552,23 +554,17 @@ public final class MLookup extends Lookup implements Serializable CCache vnpCache = null; if (isNumber) { - knpCache = s_directKeyNamePairCache.get(cacheKey); - if (knpCache != null) - { - KeyNamePair knp = knpCache.get(Integer.parseInt(key.toString())); - if (knp != null) - return knp; - } + knpCache = getDirectKeyNamePairCache(m_info, cacheKey); + KeyNamePair knp = knpCache.get(Integer.parseInt(key.toString())); + if (knp != null) + return knp; } else { - vnpCache = s_directValueNamePairCache.get(cacheKey); - if (vnpCache != null) - { - ValueNamePair vnp = vnpCache.get(key.toString()); - if (vnp != null) - return vnp; - } + vnpCache = getDirectValueNamePairCache(m_info, cacheKey); + ValueNamePair vnp = vnpCache.get(key.toString()); + if (vnp != null) + return vnp; } PreparedStatement pstmt = null; ResultSet rs = null; @@ -596,16 +592,7 @@ public final class MLookup extends Lookup implements Serializable if (saveInCache) // save if m_lookup.put(Integer.valueOf(keyValue), p); directValue = p; - if (knpCache != null) - { - knpCache.put(p.getKey(), p); - } - else - { - knpCache = new CCache(null, "MLookup.DirectKeyNamePairCache", 100, 60, false, MAX_NAMEPAIR_CACHE_SIZE); - knpCache.put(p.getKey(), p); - s_directKeyNamePairCache.put(cacheKey, knpCache); - } + knpCache.put(p.getKey(), p); } else { @@ -614,16 +601,7 @@ public final class MLookup extends Lookup implements Serializable if (saveInCache) // save if m_lookup.put(value, p); directValue = p; - if (vnpCache != null) - { - vnpCache.put(p.getValue(), p); - } - else - { - vnpCache = new CCache(null, "MLookup.DirectValueNamePairCache", 100, 60, false, MAX_NAMEPAIR_CACHE_SIZE); - vnpCache.put(p.getValue(), p); - s_directValueNamePairCache.put(cacheKey, vnpCache); - } + vnpCache.put(p.getValue(), p); } if (rs.next()) log.log(Level.SEVERE, m_info.KeyColumn + ": Not unique (first returned) for " @@ -682,110 +660,93 @@ public final class MLookup extends Lookup implements Serializable { KeyNamePair knp = null; int id = Integer.parseInt(key.toString()); - knpCache = s_directKeyNamePairCache.get(cacheKey); - if (knpCache != null) + knpCache = getDirectKeyNamePairCache(m_info, cacheKey); + knp = knpCache.get(id); + if (knp == null) { - knp = knpCache.get(id); - } - if (knp == null) knp = new KeyNamePair(id, null); - list.add(knp); - notInCaches.put(id, i); + notInCaches.put(id, i); + } + list.add(knp); } else { ValueNamePair vnp = null; - vnpCache = s_directValueNamePairCache.get(cacheKey); - if (vnpCache != null) - { - vnp = vnpCache.get(key.toString()); - } + vnpCache = getDirectValueNamePairCache(m_info, cacheKey); + vnp = vnpCache.get(key.toString()); if (vnp == null) + { vnp = new ValueNamePair(key.toString(), null); - list.add(vnp); - notInCaches.put(key.toString(), i); + notInCaches.put(key.toString(), i); + } + list.add(vnp); } } - StringBuilder builder = new StringBuilder(); - for(int i = 0; i < notInCaches.size(); i++) + if (notInCaches.size() > 0) { - if (builder.length() > 0) - builder.append(" UNION ALL "); - builder.append(m_info.QueryDirect); - } - - try (PreparedStatement pstmt = DB.prepareStatement(builder.toString(), null)) - { - Set keySet = notInCaches.keySet(); - int i = 0; - for(Object id : keySet) + StringBuilder builder = new StringBuilder(); + for(int i = 0; i < notInCaches.size(); i++) { - i++; - if (id instanceof Integer) - { - pstmt.setInt(i, (int) id); - } - else - { - pstmt.setString(i, id.toString()); - } + if (builder.length() > 0) + builder.append(" UNION ALL "); + builder.append(m_info.QueryDirect); } - ResultSet rs = pstmt.executeQuery(); - while (rs.next()) + + try (PreparedStatement pstmt = DB.prepareStatement(builder.toString(), null)) { - StringBuilder name = new StringBuilder().append(rs.getString(3)); - boolean isActive = rs.getString(4).equals("Y"); - if (!isActive) + Set keySet = notInCaches.keySet(); + int i = 0; + for(Object id : keySet) { - name.insert(0, INACTIVE_S).append(INACTIVE_E); - } - if (isNumber) - { - int keyValue = rs.getInt(1); - KeyNamePair p = new KeyNamePair(keyValue, name.toString()); - if (knpCache != null) + i++; + if (id instanceof Integer) { - knpCache.put(p.getKey(), p); + pstmt.setInt(i, (int) id); } else { - knpCache = new CCache(null, "MLookup.DirectKeyNamePairCache", 100, 60, false, MAX_NAMEPAIR_CACHE_SIZE); - knpCache.put(p.getKey(), p); - s_directKeyNamePairCache.put(cacheKey, knpCache); + pstmt.setString(i, id.toString()); } - Integer idx = notInCaches.get(p.getKey()); - if (idx != null) - list.set(idx.intValue(), p); } - else + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { - String value = rs.getString(2); - ValueNamePair p = new ValueNamePair(value, name.toString()); - if (vnpCache != null) + StringBuilder name = new StringBuilder().append(rs.getString(3)); + boolean isActive = rs.getString(4).equals("Y"); + if (!isActive) { - vnpCache.put(p.getValue(), p); + name.insert(0, INACTIVE_S).append(INACTIVE_E); + } + if (isNumber) + { + int keyValue = rs.getInt(1); + KeyNamePair p = new KeyNamePair(keyValue, name.toString()); + knpCache.put(p.getKey(), p); + Integer idx = notInCaches.get(p.getKey()); + if (idx != null) + list.set(idx.intValue(), p); } else { - vnpCache = new CCache(null, "MLookup.DirectValueNamePairCache", 100, 60, false, MAX_NAMEPAIR_CACHE_SIZE); + String value = rs.getString(2); + ValueNamePair p = new ValueNamePair(value, name.toString()); vnpCache.put(p.getValue(), p); - s_directValueNamePairCache.put(cacheKey, vnpCache); + Integer idx = notInCaches.get(p.getValue()); + if (idx != null) + list.set(idx.intValue(), p); } - Integer idx = notInCaches.get(p.getValue()); - if (idx != null) - list.set(idx.intValue(), p); } + } catch (SQLException e) { + log.log(Level.SEVERE, e.getMessage(), e); + } + + for(int i = list.size()-1; i >= 0; i--) + { + NamePair np = list.get(i); + if (np.getName() == null) + list.remove(i); } - } catch (SQLException e) { - log.log(Level.SEVERE, e.getMessage(), e); - } - - for(int i = list.size()-1; i >= 0; i--) - { - NamePair np = list.get(i); - if (np.getName() == null) - list.remove(i); } return list.toArray(new NamePair[0]); @@ -854,6 +815,20 @@ public final class MLookup extends Lookup implements Serializable return refresh(true); } // refresh + public int refreshItemsAndCache() + { + if (m_refreshing) return 0; + m_refreshCache = true; + try + { + return refresh(); + } + finally + { + m_refreshCache = false; + } + } + /** * Refresh & return number of items read * @param loadParent get data of parent lookups @@ -874,11 +849,17 @@ public final class MLookup extends Lookup implements Serializable } m_refreshing = true; - //force refresh - m_lookup.clear(); - fillComboBox(isMandatory(), true, true, false, isShortList()); // idempiere 90 - m_refreshing = false; - return m_lookup.size(); + try + { + //force refresh + m_lookup.clear(); + fillComboBox(isMandatory(), true, true, false, isShortList()); // idempiere 90 + return m_lookup.size(); + } + finally + { + m_refreshing = false; + } } // refresh /** @@ -934,12 +915,70 @@ public final class MLookup extends Lookup implements Serializable return m_info; } - private final static CCache> s_keyNamePairCache = new CCache>(null, "MLookup.KeyNamePairCache", 100, 60, false, 500); - private final static CCache> s_valueNamePairCache = new CCache>(null, "MLookup.ValueNamePairCache", 100, 60, false, 500); + + + private final static CCache>> s_keyNamePairCache = new CCache>>(null, "MLookup.KeyNamePairCache", 100, 60, false, 500); + private final static CCache>> s_valueNamePairCache = new CCache>>(null, "MLookup.ValueNamePairCache", 100, 60, false, 500); private final static CCache> s_directKeyNamePairCache = new CCache>(null, "", 100, 60, false, 500); private final static CCache> s_directValueNamePairCache = new CCache>(null, "", 100, 60, false, 500); + private synchronized static List getKeyNamePairCache(MLookupInfo lookupInfo, String cacheKey) + { + CCache> knpCache = s_keyNamePairCache.get(lookupInfo.TableName); + if (knpCache == null) + { + knpCache = new CCache>(lookupInfo.TableName, lookupInfo.TableName + " KeyNamePair Cache", 100, 60, false, 500); + s_keyNamePairCache.put(lookupInfo.TableName, knpCache); + } + List list = knpCache.get(cacheKey); + if (list == null) + { + list = new ArrayList(); + knpCache.put(cacheKey, list); + } + return list; + } + + private synchronized static List getValueNamePairCache(MLookupInfo lookupInfo, String cacheKey) + { + CCache> vnpCache = s_valueNamePairCache.get(lookupInfo.TableName); + if (vnpCache == null) + { + vnpCache = new CCache>(lookupInfo.TableName, lookupInfo.TableName + " ValueNamePair Cache", 100, 60, false, 500); + s_valueNamePairCache.put(lookupInfo.TableName, vnpCache); + } + List list = vnpCache.get(cacheKey); + if (list == null) + { + list = new ArrayList(); + vnpCache.put(cacheKey, list); + } + return list; + } + + private synchronized static CCache getDirectKeyNamePairCache(MLookupInfo lookupInfo, String cacheKey) + { + CCache knpCache = s_directKeyNamePairCache.get(cacheKey); + if (knpCache == null) + { + knpCache = new CCache(lookupInfo.TableName, lookupInfo.TableName + " DirectKeyNamePairCache", 100, 60, false, MAX_NAMEPAIR_CACHE_SIZE); + s_directKeyNamePairCache.put(cacheKey, knpCache); + } + return knpCache; + } + + private synchronized static CCache getDirectValueNamePairCache(MLookupInfo lookupInfo, String cacheKey) + { + CCache vnpCache = s_directValueNamePairCache.get(cacheKey); + if (vnpCache == null) + { + vnpCache = new CCache(lookupInfo.TableName, lookupInfo.TableName + " DirectValueNamePairCache", 100, 60, false, MAX_NAMEPAIR_CACHE_SIZE); + s_directValueNamePairCache.put(cacheKey, vnpCache); + } + return vnpCache; + } + /************************************************************************** * MLookup Loader */ @@ -1034,36 +1073,42 @@ public final class MLookup extends Lookup implements Serializable List vnpCache = null; if (isNumber) { - knpCache = s_keyNamePairCache.get(cacheKey); - if (knpCache != null) + knpCache = getKeyNamePairCache(m_info, cacheKey); + if (knpCache.size() > 0) { - for(KeyNamePair knp : knpCache) + if (m_refreshCache) { - m_lookup.put(knp.getKey(), knp); + knpCache.clear(); + } + else + { + for(KeyNamePair knp : knpCache) + { + m_lookup.put(knp.getKey(), knp); + } + return; } - return; - } - else - { - knpCache = new ArrayList(); } } else { - vnpCache = s_valueNamePairCache.get(cacheKey); - if (vnpCache != null) + vnpCache = getValueNamePairCache(m_info, cacheKey); + if (vnpCache.size() > 0) { - for(ValueNamePair vnp : vnpCache) + if (m_refreshCache) { - m_lookup.put(vnp.getValue(), vnp); + vnpCache.clear(); + } + else + { + for(ValueNamePair vnp : vnpCache) + { + m_lookup.put(vnp.getValue(), vnp); + } + return; } - return; } - else - { - vnpCache = new ArrayList(); - } } m_hasInactive = false; @@ -1132,18 +1177,7 @@ public final class MLookup extends Lookup implements Serializable vnpCache.add(p); } // if (log.isLoggable(Level.FINE)) log.fine( m_info.KeyColumn + ": " + name); - } - - if (isNumber) - { - if (knpCache.size() <= MAX_NAMEPAIR_CACHE_SIZE) - s_keyNamePairCache.put(cacheKey, knpCache); - } - else - { - if (vnpCache.size() <= MAX_NAMEPAIR_CACHE_SIZE) - s_valueNamePairCache.put(cacheKey, vnpCache); - } + } } catch (SQLException e) { diff --git a/org.adempiere.base/src/org/compiere/model/MLookupInfo.java b/org.adempiere.base/src/org/compiere/model/MLookupInfo.java index d316136dfb..d2c08f27ec 100644 --- a/org.adempiere.base/src/org/compiere/model/MLookupInfo.java +++ b/org.adempiere.base/src/org/compiere/model/MLookupInfo.java @@ -26,6 +26,7 @@ import java.util.logging.Level; import org.compiere.util.CLogger; import org.compiere.util.DB; +import org.compiere.util.Util; /** * Info Class for Lookup SQL (ValueObject) @@ -234,7 +235,7 @@ public class MLookupInfo implements Serializable, Cloneable { MLookupInfo clone = (MLookupInfo)super.clone(); clone.parsedValidationCode = ""; - clone.IsValidated = false; + clone.IsValidated = Util.isEmpty(ValidationCode); clone.ctx = null; if (ZoomQuery != null) clone.ZoomQuery = ZoomQuery.clone(); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/InfoListSubModel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/InfoListSubModel.java index fab03cc3be..34f13b659e 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/InfoListSubModel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/InfoListSubModel.java @@ -31,6 +31,7 @@ import org.adempiere.webui.factory.InfoManager; import org.adempiere.webui.panel.InfoPanel; import org.compiere.model.GridField; import org.compiere.model.Lookup; +import org.compiere.model.MLookup; import org.compiere.util.NamePair; import org.compiere.util.Util; import org.compiere.util.ValueNamePair; @@ -51,6 +52,8 @@ public class InfoListSubModel implements ListSubModel { private String keyColumnName; private String whereClause; + private static final int AUTO_COMPLETE_QUERY_TIMEOUT = 1; //1 second + /** * * @param lookup @@ -86,6 +89,24 @@ public class InfoListSubModel implements ListSubModel { ListModelList model = new ListModelList<>(); if (value != null && !Util.isEmpty(value.toString(), true)) { String queryText = value.toString().trim(); + StringBuilder queryBuilder = new StringBuilder(queryText); + queryBuilder.append("?autocomplete={"); + queryBuilder.append("timeout:") + .append(AUTO_COMPLETE_QUERY_TIMEOUT) + .append(",") + .append("pagesize:") + .append(nRows); + if (lookup instanceof MLookup) { + MLookup mlookup = (MLookup) lookup; + List displayColumns = mlookup.getLookupInfo().lookupDisplayColumns; + if (displayColumns != null && displayColumns.size() > 0) { + queryBuilder.append(",") + .append("searchcolumn:") + .append(displayColumns.get(0)); + } + } + queryBuilder.append("}"); + queryText = queryBuilder.toString(); final InfoPanel ip = InfoManager.create(lookup, gridField, tableName, keyColumnName, queryText, false, getWhereClause()); if (ip != null && ip.loadedOK()) { diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WSearchEditor.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WSearchEditor.java index 53f904f3b7..04b22310f6 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WSearchEditor.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WSearchEditor.java @@ -21,7 +21,6 @@ import static org.compiere.model.SystemIDs.COLUMN_C_INVOICELINE_M_PRODUCT_ID; import static org.compiere.model.SystemIDs.COLUMN_C_INVOICE_C_BPARTNER_ID; import java.beans.PropertyChangeEvent; -import java.util.List; import java.util.Properties; import java.util.logging.Level; @@ -56,7 +55,6 @@ import org.compiere.model.X_AD_CtxHelp; import org.compiere.util.CLogger; import org.compiere.util.DisplayType; import org.compiere.util.Env; -import org.compiere.util.Util; import org.zkoss.zk.au.out.AuScript; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Executions; @@ -76,8 +74,7 @@ import org.zkoss.zk.ui.util.Clients; */ public class WSearchEditor extends WEditor implements ContextMenuListener, ValueChangeListener, IZoomableEditor { - private static final int MAX_AUTO_COMPLETE_ROWS = 50; - private static final int AUTO_COMPLETE_QUERY_TIMEOUT = 1; //1 second + private static final int MAX_AUTO_COMPLETE_ROWS = 50; private static final String[] LISTENER_EVENTS = {Events.ON_CLICK, Events.ON_CHANGE, Events.ON_OK}; public static final String ATTRIBUTE_IS_INFO_PANEL_OPEN = "ATTRIBUTE_IS_INFO_PANEL_OPEN"; private Lookup lookup; @@ -217,27 +214,7 @@ public class WSearchEditor extends WEditor implements ContextMenuListener, Value getComponent().getCombobox().addEventListener(Events.ON_CHANGING, (EventListener)(e) -> { if (!e.isChangingBySelectBack()) { listModel.setWhereClause(getWhereClause()); - String s = e.getValue(); - if (!Util.isEmpty(s, true)) { - StringBuilder query = new StringBuilder(s); - query.append("?autocomplete={"); - query.append("timeout:") - .append(AUTO_COMPLETE_QUERY_TIMEOUT) - .append(",") - .append("pagesize:") - .append(MAX_AUTO_COMPLETE_ROWS); - if (lookup instanceof MLookup) { - MLookup mlookup = (MLookup) lookup; - List displayColumns = mlookup.getLookupInfo().lookupDisplayColumns; - if (displayColumns != null && displayColumns.size() > 0) { - query.append(",") - .append("searchcolumn:") - .append(displayColumns.get(0)); - } - } - query.append("}"); - s = query.toString(); - } + String s = e.getValue(); getComponent().getCombobox().setModel(listModel.getSubModel(s, MAX_AUTO_COMPLETE_ROWS)); } }); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WTableDirEditor.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WTableDirEditor.java index 462e5b098d..8444cb36c8 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WTableDirEditor.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WTableDirEditor.java @@ -599,7 +599,12 @@ ContextMenuListener, IZoomableEditor Object curValue = getValue(); if (isReadWrite()) - lookup.refresh(); + { + if (lookup instanceof MLookup) + ((MLookup) lookup).refreshItemsAndCache(); + else + lookup.refresh(); + } else refreshList(); if (curValue != null)