1 14 package org.compiere.model; 15 16 import java.sql.*; 17 import java.util.*; 18 import java.io.Serializable ; 19 20 import org.compiere.util.NamePair; 21 import org.compiere.util.KeyNamePair; 22 import org.compiere.util.ValueNamePair; 23 import org.compiere.util.DisplayType; 24 import org.compiere.util.DB; 25 import org.compiere.util.Env; 26 import org.compiere.util.Log; 27 28 42 public final class MLookup extends Lookup implements Serializable 43 { 44 49 public MLookup (MLookupInfo info, int TabNo) 50 { 51 super(); 52 m_info = info; 53 log.debug(m_info.KeyColumn); 54 55 if (MLookupCache.loadFromCache (m_info, m_lookup)) 57 return; 58 59 if (m_info.DisplayType == DisplayType.Search) 61 return; 62 if (m_info.IsParent) 64 { 65 m_hasInactive = true; return; } 68 m_loader = new Loader(); 70 m_loader.start(); 73 } 76 77 public static final String INACTIVE_S = "~"; 78 79 public static final String INACTIVE_E = "~"; 80 81 82 private MLookupInfo m_info = null; 83 84 85 private volatile LinkedHashMap m_lookup = new LinkedHashMap(); 86 87 private Loader m_loader; 88 89 private int m_maxRows = 1000000; 92 93 private boolean m_allLoaded = false; 94 95 private boolean m_hasInactive = false; 96 97 98 private boolean m_refreshing = false; 99 100 private static Integer s_minusOne = new Integer (-1); 101 102 105 public void dispose() 106 { 107 if (m_info != null) 108 log.debug(m_info.KeyColumn + ": dispose"); 109 if (m_loader != null) 110 { 111 while (m_loader.isAlive()) 112 m_loader.interrupt(); 113 } 114 m_loader = null; 115 if (m_lookup != null) 117 m_lookup.clear(); 118 m_lookup = null; 119 if (m_lookupDirect != null) 120 m_lookupDirect.clear(); 121 m_lookupDirect = null; 122 m_info = null; 124 super.dispose(); 126 } 128 131 public void loadComplete() 132 { 133 if (m_loader != null && m_loader.isAlive()) 134 { 135 try 136 { 137 m_loader.join(); 138 m_loader = null; 139 } 140 catch (InterruptedException ie) 141 { 142 log.error(m_info.KeyColumn + ": loadComplete - join interrupted", ie); 143 } 144 } 145 } 147 153 public NamePair get (Object key) 154 { 155 if (key == null || s_minusOne.equals(key)) return null; 157 158 NamePair retValue = (NamePair)m_lookup.get(key); 160 if (retValue != null) 161 return retValue; 162 163 if (m_loader != null && m_loader.isAlive()) 165 { 166 if (Log.isTraceLevel(7)) 167 log.debug ((m_info.KeyColumn==null ? "ID="+m_info.Column_ID : m_info.KeyColumn) + ": get - waiting for Loader"); 168 loadComplete(); 169 retValue = (NamePair)m_lookup.get(key); 171 if (retValue != null) 172 return retValue; 173 } 174 175 if (!m_info.IsParent && m_info.IsValidated && m_allLoaded) 177 { 178 if (Log.isTraceLevel(7)) 179 log.debug (m_info.KeyColumn + ": get <NULL> - " + key + "; Size=" + m_lookup.size()); 181 return getDirect(key, false, true); } 185 186 if (Log.isTraceLevel(7)) 187 log.debug (m_info.KeyColumn + ": get - " + key 188 + "; Size=" + m_lookup.size() + "; Validated=" + m_info.IsValidated 189 + "; All Loaded=" + m_allLoaded + "; HasInactive=" + m_hasInactive); 190 if (!m_allLoaded && m_lookup.size() == 0 && m_info.DisplayType != DisplayType.Search) 192 { 193 m_loader = new Loader(); 194 m_loader.run(); retValue = (NamePair)m_lookup.get(key); 196 if (retValue != null) 197 return retValue; 198 } 199 return getDirect(key, false, false); } 203 209 public String getDisplay (Object key) 210 { 211 if (key == null) 212 return ""; 213 Object display = get (key); 215 if (display == null) 216 return "<" + key.toString() + ">"; 217 return display.toString(); 218 } 220 225 public boolean containsKey (Object key) 226 { 227 return m_lookup.containsKey(key); 228 } 230 233 public String toString() 234 { 235 return "MLookup[" + m_info.KeyColumn + ",Column_ID=" + m_info.Column_ID 236 + ",Size=" + m_lookup.size() + ",Validated=" + isValidated() 237 + "-" + getValidation() 238 + "]"; 239 } 241 247 public boolean equals(Object obj) 248 { 249 if (obj instanceof MLookup) 250 { 251 MLookup ll = (MLookup)obj; 252 if (ll.m_info.Column_ID == this.m_info.Column_ID) 253 return true; 254 } 255 return false; 256 } 258 262 public int size() 263 { 264 return m_lookup.size(); 265 } 267 271 public boolean isAllLoaded() 272 { 273 return m_allLoaded; 274 } 276 280 public boolean isValidated() 281 { 282 return m_info.IsValidated; 283 } 285 289 public String getValidation() 290 { 291 return m_info.ValidationCode; 292 } 294 298 public int getAD_Reference_Value_ID() 299 { 300 return m_info.AD_Reference_Value_ID; 301 } 303 304 308 public boolean hasInactive() 309 { 310 return m_hasInactive; 311 } 313 319 private ArrayList getData (boolean onlyValidated, boolean loadParent) 320 { 321 if (m_loader != null && m_loader.isAlive()) 322 { 323 log.debug((m_info.KeyColumn==null ? "ID="+m_info.Column_ID : m_info.KeyColumn) + ": getData - waiting for Loader"); 324 loadComplete(); 325 } 326 327 if (!m_allLoaded || m_lookup.size() == 0) 329 refresh (loadParent); 330 331 if (m_info.IsValidated) 333 return new ArrayList(m_lookup.values()); 334 335 if (!m_info.IsValidated && onlyValidated) 336 { 337 refresh (loadParent); 338 log.debug(m_info.KeyColumn + ": getData Validated - #" + m_lookup.size()); 339 } 340 341 return new ArrayList(m_lookup.values()); 342 } 344 352 public ArrayList getData (boolean mandatory, boolean onlyValidated, boolean onlyActive, boolean temporary) 353 { 354 ArrayList list = getData (onlyValidated, temporary); 356 357 if (onlyActive && m_hasInactive) 359 { 360 for (int i = list.size(); i > 0; i--) 362 { 363 Object o = list.get(i-1); 364 if (o != null) 365 { 366 String s = o.toString(); 367 if (s.startsWith(INACTIVE_S) && s.endsWith(INACTIVE_E)) 368 list.remove(i-1); 369 } 370 } 371 } 372 373 if (!mandatory) 375 { 376 NamePair p = null; 377 if (m_info.KeyColumn != null && m_info.KeyColumn.endsWith("_ID")) 378 p = new KeyNamePair (-1, ""); 379 else 380 p = new ValueNamePair ("", ""); 381 list.add(0, p); 382 } 383 384 return list; 385 } 387 388 private HashMap m_lookupDirect = null; 389 390 private Object m_directNullKey = null; 391 392 399 public NamePair getDirect (Object key, boolean saveInCache, boolean cacheLocal) 400 { 401 if (Log.isTraceLevel(7)) 402 log.debug (m_info.KeyColumn + ": getDirect - " + key); 403 if (key == null || m_info.QueryDirect == null || m_info.QueryDirect.length() == 0) 405 return null; 406 if (key.equals(m_directNullKey)) 407 return null; 408 NamePair directValue = null; 410 if (m_lookupDirect != null) 411 { 412 directValue = (NamePair)m_lookupDirect.get(key); 413 if (directValue != null) 414 return directValue; 415 } 416 boolean isNumber = m_info.KeyColumn.endsWith("_ID"); 417 try 418 { 419 PreparedStatement pstmt = DB.prepareStatement(m_info.QueryDirect); 421 if (isNumber) 422 pstmt.setInt(1, Integer.parseInt(key.toString())); 423 else 424 pstmt.setString(1, key.toString()); 425 ResultSet rs = pstmt.executeQuery(); 426 if (rs.next()) 427 { 428 String name = rs.getString(3); 429 if (isNumber) 430 { 431 int keyValue = rs.getInt(1); 432 KeyNamePair p = new KeyNamePair(keyValue, name); 433 if (saveInCache) m_lookup.put(new Integer (keyValue), p); 435 directValue = p; 436 } 437 else 438 { 439 String value = rs.getString(2); 440 ValueNamePair p = new ValueNamePair(value, name); 441 if (saveInCache) m_lookup.put(value, p); 443 directValue = p; 444 } 445 if (rs.next()) 446 log.error(m_info.KeyColumn + ": getDirect - not unique (first returned) for " 447 + key + " SQL=" + m_info.QueryDirect); 448 } 449 else 450 { 451 m_directNullKey = key; 452 directValue = null; 453 } 454 455 rs.close(); 456 pstmt.close(); 457 if (Log.isTraceLevel(10)) 458 log.debug (m_info.KeyColumn + ": getDirect - " + directValue + " - " + m_info); 459 } 460 catch (SQLException e) 461 { 462 log.error(m_info.KeyColumn + ": getDirect - SQL=" + m_info.QueryDirect + "; Key=" + key, e); 463 directValue = null; 464 } 465 if (cacheLocal && !saveInCache && directValue != null) 467 { 468 if (m_lookupDirect == null) 469 m_lookupDirect = new HashMap(); 470 m_lookupDirect.put(key, directValue); 471 } 472 m_hasInactive = true; 473 return directValue; 474 } 476 480 public int getZoom() 481 { 482 return m_info.ZoomWindow; 483 } 485 490 public int getZoom(String isSOTrx) 491 { 492 if ("N".equals(isSOTrx) && m_info.ZoomWindowPO != 0) 493 return m_info.ZoomWindowPO; 494 return m_info.ZoomWindow; 495 } 497 501 public MQuery getZoomQuery() 502 { 503 return m_info.ZoomQuery; 504 } 506 510 public String getColumnName() 511 { 512 return m_info.KeyColumn; 513 } 515 520 public int refresh () 521 { 522 return refresh(true); 523 } 525 530 public int refresh (boolean loadParent) 531 { 532 if (!loadParent && m_info.IsParent) 533 return 0; 534 log.debug(m_info.KeyColumn + ": refresh - start"); 535 m_refreshing = true; 536 m_loader = new Loader(); 537 m_loader.start(); 538 loadComplete(); 539 log.info(m_info.KeyColumn + ": refresh - #" + m_lookup.size()); 540 m_refreshing = false; 541 return m_lookup.size(); 542 } 544 545 546 549 class Loader extends Thread implements Serializable 550 { 551 public Loader() 552 { 553 super("MLoader-" + m_info.KeyColumn); 554 } 556 private long m_startTime = System.currentTimeMillis(); 557 558 561 public void run() 562 { 563 long startTime = System.currentTimeMillis(); 564 MLookupCache.loadStart (m_info); 565 String sql = m_info.Query; 566 567 if (!m_info.IsValidated) 569 { 570 String validation = Env.parseContext(m_info.ctx, m_info.WindowNo, m_info.ValidationCode, false); 571 if (validation.length() == 0 && m_info.ValidationCode.length() > 0) 572 { 573 log.warn(m_info.KeyColumn + ": Loader.run - NOT Validated: " + m_info.ValidationCode); 574 return; 575 } 576 else 577 { 578 log.debug(m_info.KeyColumn + ": Loader.run - Validated: " + validation); 579 int posOrder = sql.lastIndexOf(" ORDER BY "); 580 if (posOrder != -1) 581 sql = sql.substring(0, posOrder) + " AND " + validation 582 + sql.substring(posOrder); 583 else 584 sql += " AND " + validation; 585 } 586 } 587 if (Log.isTraceLevel(7)) 589 Env.setContext(m_info.ctx, Env.WINDOW_MLOOKUP, m_info.Column_ID, m_info.KeyColumn, sql); 590 if (isInterrupted()) 592 { 593 log.error(m_info.KeyColumn + ": Loader.run interrupted"); 594 return; 595 } 596 597 if (Log.isTraceLevel(10)) 598 log.debug(m_info.KeyColumn + ": Loader.run - " + sql); 599 600 m_lookup.clear(); 602 boolean isNumber = m_info.KeyColumn.endsWith("_ID"); 603 m_hasInactive = false; 604 int rows = 0; 605 try 606 { 607 PreparedStatement pstmt = DB.prepareStatement(sql); 609 ResultSet rs = pstmt.executeQuery(); 610 611 m_allLoaded = true; 613 while (rs.next()) 614 { 615 if (rows++ > m_maxRows) 616 { 617 m_allLoaded = false; 618 break; 619 } 620 if (rows % 50 == 0 && isInterrupted()) 622 break; 623 624 String name = rs.getString(3); 626 boolean isActive = rs.getString(4).equals("Y"); 627 if (!isActive) 628 { 629 name = INACTIVE_S + name + INACTIVE_E; 630 m_hasInactive = true; 631 } 632 if (isNumber) 633 { 634 int key = rs.getInt(1); 635 KeyNamePair p = new KeyNamePair(key, name); 636 m_lookup.put(new Integer (key), p); 637 } 638 else 639 { 640 String value = rs.getString(2); 641 ValueNamePair p = new ValueNamePair(value, name); 642 m_lookup.put(value, p); 643 } 644 } 646 rs.close(); 647 pstmt.close(); 648 } 649 catch (SQLException e) 650 { 651 log.error(m_info.KeyColumn + ": Loader.run - SQL=" + sql, e); 652 } 653 int size = m_lookup.size(); 654 if (Log.isTraceLevel(8)) 655 log.debug(m_info.KeyColumn + ": Loader.run" 656 + " - complete #" + size 658 + " - ms=" + String.valueOf(System.currentTimeMillis()-m_startTime) 659 + " (" + String.valueOf(System.currentTimeMillis()-startTime) + ")"); 660 MLookupCache.loadEnd (m_info, m_lookup); 661 if (size > 1000) 662 log.warn(m_info.KeyColumn + ": Loader.run - Too many records=" + size); 663 } } 666 } | Popular Tags |