PageRenderTime 54ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/org.adempiere.base/src/org/compiere/model/PO.java

https://bitbucket.org/idempiere/idempiere/
Java | 4737 lines | 3385 code | 295 blank | 1057 comment | 1081 complexity | a1e28fef5a408d013f14412b0a13ea0f MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /******************************************************************************
  2. * Product: Adempiere ERP & CRM Smart Business Solution *
  3. * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
  4. * This program is free software; you can redistribute it and/or modify it *
  5. * under the terms version 2 of the GNU General Public License as published *
  6. * by the Free Software Foundation. This program is distributed in the hope *
  7. * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
  8. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
  9. * See the GNU General Public License for more details. *
  10. * You should have received a copy of the GNU General Public License along *
  11. * with this program; if not, write to the Free Software Foundation, Inc., *
  12. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
  13. * For the text or an alternative of this public license, you may reach us *
  14. * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
  15. * or via info@compiere.org or http://www.compiere.org/license.html *
  16. *****************************************************************************/
  17. package org.compiere.model;
  18. import java.io.IOException;
  19. import java.io.ObjectInputStream;
  20. import java.io.Serializable;
  21. import java.io.StringWriter;
  22. import java.math.BigDecimal;
  23. import java.sql.Blob;
  24. import java.sql.Clob;
  25. import java.sql.PreparedStatement;
  26. import java.sql.ResultSet;
  27. import java.sql.SQLException;
  28. import java.sql.Savepoint;
  29. import java.sql.Timestamp;
  30. import java.text.Collator;
  31. import java.util.ArrayList;
  32. import java.util.Comparator;
  33. import java.util.HashMap;
  34. import java.util.Iterator;
  35. import java.util.List;
  36. import java.util.Properties;
  37. import java.util.UUID;
  38. import java.util.logging.Level;
  39. import javax.xml.parsers.DocumentBuilder;
  40. import javax.xml.parsers.DocumentBuilderFactory;
  41. import javax.xml.transform.Transformer;
  42. import javax.xml.transform.TransformerFactory;
  43. import javax.xml.transform.dom.DOMSource;
  44. import javax.xml.transform.stream.StreamResult;
  45. import org.adempiere.base.event.EventManager;
  46. import org.adempiere.base.event.IEventTopics;
  47. import org.adempiere.exceptions.AdempiereException;
  48. import org.adempiere.exceptions.DBException;
  49. import org.adempiere.process.UUIDGenerator;
  50. import org.compiere.Adempiere;
  51. import org.compiere.acct.Doc;
  52. import org.compiere.util.CCache;
  53. import org.compiere.util.CLogMgt;
  54. import org.compiere.util.CLogger;
  55. import org.compiere.util.CacheMgt;
  56. import org.compiere.util.DB;
  57. import org.compiere.util.DisplayType;
  58. import org.compiere.util.Env;
  59. import org.compiere.util.Evaluatee;
  60. import org.compiere.util.Ini;
  61. import org.compiere.util.Language;
  62. import org.compiere.util.Msg;
  63. import org.compiere.util.SecureEngine;
  64. import org.compiere.util.Trace;
  65. import org.compiere.util.Trx;
  66. import org.compiere.util.ValueNamePair;
  67. import org.osgi.service.event.Event;
  68. import org.w3c.dom.Document;
  69. import org.w3c.dom.Element;
  70. /**
  71. * Persistent Object.
  72. * Superclass for actual implementations
  73. *
  74. * @author Jorg Janke
  75. * @version $Id: PO.java,v 1.12 2006/08/09 16:38:47 jjanke Exp $
  76. *
  77. * @author Teo Sarca, SC ARHIPAC SERVICE SRL
  78. * <li>FR [ 1675490 ] ModelValidator on modelChange after events
  79. * <li>BF [ 1704828 ] PO.is_Changed() and PO.is_ValueChanged are not consistent
  80. * <li>FR [ 1720995 ] Add PO.saveEx() and PO.deleteEx() methods
  81. * <li>BF [ 1990856 ] PO.set_Value* : truncate string more than needed
  82. * <li>FR [ 2042844 ] PO.get_Translation improvements
  83. * <li>FR [ 2818369 ] Implement PO.get_ValueAs*(columnName)
  84. * https://sourceforge.net/tracker/?func=detail&aid=2818369&group_id=176962&atid=879335
  85. * <li>BF [ 2849122 ] PO.AfterSave is not rollback on error
  86. * https://sourceforge.net/tracker/?func=detail&aid=2849122&group_id=176962&atid=879332
  87. * <li>BF [ 2859125 ] Can't set AD_OrgBP_ID
  88. * https://sourceforge.net/tracker/index.php?func=detail&aid=2859125&group_id=176962&atid=879332
  89. * <li>BF [ 2866493 ] VTreePanel is not saving who did the node move
  90. * https://sourceforge.net/tracker/?func=detail&atid=879332&aid=2866493&group_id=176962
  91. * @author Teo Sarca, teo.sarca@gmail.com
  92. * <li>BF [ 2876259 ] PO.insertTranslation query is not correct
  93. * https://sourceforge.net/tracker/?func=detail&aid=2876259&group_id=176962&atid=879332
  94. * @author Victor Perez, e-Evolution SC
  95. * <li>[ 2195894 ] Improve performance in PO engine
  96. * <li>http://sourceforge.net/tracker/index.php?func=detail&aid=2195894&group_id=176962&atid=879335
  97. * <li>BF [2947622] The replication ID (Primary Key) is not working
  98. * <li>https://sourceforge.net/tracker/?func=detail&aid=2947622&group_id=176962&atid=879332
  99. */
  100. public abstract class PO
  101. implements Serializable, Comparator<Object>, Evaluatee, Cloneable
  102. {
  103. /**
  104. *
  105. */
  106. private static final long serialVersionUID = -2997116608353367498L;
  107. public static final String LOCAL_TRX_PREFIX = "POSave";
  108. private static final String USE_TIMEOUT_FOR_UPDATE = "org.adempiere.po.useTimeoutForUpdate";
  109. /** default timeout, 300 seconds **/
  110. private static final int QUERY_TIME_OUT = 300;
  111. /**
  112. * Set Document Value Workflow Manager
  113. * @param docWFMgr mgr
  114. */
  115. public static void setDocWorkflowMgr (DocWorkflowMgr docWFMgr)
  116. {
  117. s_docWFMgr = docWFMgr;
  118. s_log.config (s_docWFMgr.toString());
  119. } // setDocWorkflowMgr
  120. /** Document Value Workflow Manager */
  121. private static DocWorkflowMgr s_docWFMgr = null;
  122. /** User Maintained Entity Type */
  123. static public final String ENTITYTYPE_UserMaintained = "U";
  124. /** Dictionary Maintained Entity Type */
  125. static public final String ENTITYTYPE_Dictionary = "D";
  126. /**************************************************************************
  127. * Create New Persistent Object
  128. * @param ctx context
  129. */
  130. public PO (Properties ctx)
  131. {
  132. this (ctx, 0, null, null);
  133. } // PO
  134. /**
  135. * Create & Load existing Persistent Object
  136. * @param ID The unique ID of the object
  137. * @param ctx context
  138. * @param trxName transaction name
  139. */
  140. public PO (Properties ctx, int ID, String trxName)
  141. {
  142. this (ctx, ID, trxName, null);
  143. } // PO
  144. /**
  145. * Create & Load existing Persistent Object.
  146. * @param ctx context
  147. * @param rs optional - load from current result set position (no navigation, not closed)
  148. * if null, a new record is created.
  149. * @param trxName transaction name
  150. */
  151. public PO (Properties ctx, ResultSet rs, String trxName)
  152. {
  153. this (ctx, 0, trxName, rs);
  154. } // PO
  155. /**
  156. * Create & Load existing Persistent Object.
  157. * <pre>
  158. * You load
  159. * - an existing single key record with new PO (ctx, Record_ID)
  160. * or new PO (ctx, Record_ID, trxName)
  161. * or new PO (ctx, rs, get_TrxName())
  162. * - a new single key record with new PO (ctx, 0)
  163. * - an existing multi key record with new PO (ctx, rs, get_TrxName())
  164. * - a new multi key record with new PO (ctx, null)
  165. * The ID for new single key records is created automatically,
  166. * you need to set the IDs for multi-key records explicitly.
  167. * </pre>
  168. * @param ctx context
  169. * @param ID the ID if 0, the record defaults are applied - ignored if re exists
  170. * @param trxName transaction name
  171. * @param rs optional - load from current result set position (no navigation, not closed)
  172. */
  173. public PO (Properties ctx, int ID, String trxName, ResultSet rs)
  174. {
  175. p_ctx = ctx != null ? ctx : Env.getCtx();
  176. m_trxName = trxName;
  177. p_info = initPO(ctx);
  178. if (p_info == null || p_info.getTableName() == null)
  179. throw new IllegalArgumentException ("Invalid PO Info - " + p_info);
  180. //
  181. int size = p_info.getColumnCount();
  182. m_oldValues = new Object[size];
  183. m_newValues = new Object[size];
  184. m_setErrors = new ValueNamePair[size];
  185. if (rs != null)
  186. load(rs); // will not have virtual columns
  187. else
  188. load(ID, trxName);
  189. } // PO
  190. /**
  191. * Create New PO by Copying existing (key not copied).
  192. * @param ctx context
  193. * @param source source object
  194. * @param AD_Client_ID client
  195. * @param AD_Org_ID org
  196. */
  197. public PO (Properties ctx, PO source, int AD_Client_ID, int AD_Org_ID)
  198. {
  199. this (ctx, 0, null, null); // create new
  200. //
  201. if (source != null)
  202. copyValues (source, this);
  203. setAD_Client_ID(AD_Client_ID);
  204. setAD_Org_ID(AD_Org_ID);
  205. } // PO
  206. /** Logger */
  207. protected transient CLogger log = CLogger.getCLogger (getClass());
  208. /** Static Logger */
  209. private static CLogger s_log = CLogger.getCLogger (PO.class);
  210. /** Context */
  211. protected Properties p_ctx;
  212. /** Model Info */
  213. protected volatile POInfo p_info = null;
  214. /** Original Values */
  215. private Object[] m_oldValues = null;
  216. /** New Values */
  217. private Object[] m_newValues = null;
  218. /** Errors when setting */
  219. private ValueNamePair[] m_setErrors = null;
  220. /** Record_IDs */
  221. private Object[] m_IDs = new Object[] {I_ZERO};
  222. /** Key Columns */
  223. private String[] m_KeyColumns = null;
  224. /** Create New for Multi Key */
  225. private boolean m_createNew = false;
  226. /** Attachment with entries */
  227. private MAttachment m_attachment = null;
  228. /** Deleted ID */
  229. private int m_idOld = 0;
  230. /** Custom Columns */
  231. private HashMap<String,String> m_custom = null;
  232. /** Attributes */
  233. private HashMap<String,Object> m_attributes = null;
  234. /** Zero Integer */
  235. protected static final Integer I_ZERO = new Integer(0);
  236. /** Accounting Columns */
  237. private ArrayList <String> s_acctColumns = null;
  238. /** Trifon - Indicates that this record is created by replication functionality.*/
  239. private boolean m_isReplication = false;
  240. /** Access Level S__ 100 4 System info */
  241. public static final int ACCESSLEVEL_SYSTEM = 4;
  242. /** Access Level _C_ 010 2 Client info */
  243. public static final int ACCESSLEVEL_CLIENT = 2;
  244. /** Access Level __O 001 1 Organization info */
  245. public static final int ACCESSLEVEL_ORG = 1;
  246. /** Access Level SCO 111 7 System shared info */
  247. public static final int ACCESSLEVEL_ALL = 7;
  248. /** Access Level SC_ 110 6 System/Client info */
  249. public static final int ACCESSLEVEL_SYSTEMCLIENT = 6;
  250. /** Access Level _CO 011 3 Client shared info */
  251. public static final int ACCESSLEVEL_CLIENTORG = 3;
  252. /**
  253. * Initialize and return PO_Info
  254. * @param ctx context
  255. * @return POInfo
  256. */
  257. abstract protected POInfo initPO (Properties ctx);
  258. /**
  259. * Get Table Access Level
  260. * @return Access Level
  261. */
  262. abstract protected int get_AccessLevel();
  263. /**
  264. * String representation
  265. * @return String representation
  266. */
  267. public String toString()
  268. {
  269. StringBuilder sb = new StringBuilder("PO[")
  270. .append(get_WhereClause(true)).append("]");
  271. return sb.toString();
  272. } // toString
  273. /**
  274. * Equals based on ID
  275. * @param cmp comparator
  276. * @return true if ID the same
  277. */
  278. public boolean equals (Object cmp)
  279. {
  280. if (cmp == null)
  281. return false;
  282. if (!(cmp instanceof PO))
  283. return false;
  284. if (cmp.getClass().equals(this.getClass()))
  285. // if both ID's are zero they can't be compared by ID
  286. if (((PO)cmp).get_ID() == 0 && get_ID() == 0)
  287. return super.equals(cmp);
  288. else
  289. return ((PO)cmp).get_ID() == get_ID();
  290. return super.equals(cmp);
  291. } // equals
  292. public int hashCode()
  293. {
  294. assert false : "hashCode not designed";
  295. return 42; // any arbitrary constant will do
  296. }
  297. /**
  298. * Compare based on DocumentNo, Value, Name, Description
  299. * @param o1 Object 1
  300. * @param o2 Object 2
  301. * @return -1 if o1 < o2
  302. */
  303. public int compare (Object o1, Object o2)
  304. {
  305. if (o1 == null)
  306. return -1;
  307. else if (o2 == null)
  308. return 1;
  309. if (!(o1 instanceof PO))
  310. throw new ClassCastException ("Not PO -1- " + o1);
  311. if (!(o2 instanceof PO))
  312. throw new ClassCastException ("Not PO -2- " + o2);
  313. // same class
  314. Collator collator = Collator.getInstance();
  315. if (o1.getClass().equals(o2.getClass()))
  316. {
  317. int index = get_ColumnIndex("DocumentNo");
  318. if (index == -1)
  319. index = get_ColumnIndex("Value");
  320. if (index == -1)
  321. index = get_ColumnIndex("Name");
  322. if (index == -1)
  323. index = get_ColumnIndex("Description");
  324. if (index != -1)
  325. {
  326. PO po1 = (PO)o1;
  327. Object comp1 = po1.get_Value(index);
  328. PO po2 = (PO)o2;
  329. Object comp2 = po2.get_Value(index);
  330. if (comp1 == null)
  331. return -1;
  332. else if (comp2 == null)
  333. return 1;
  334. return collator.compare(comp1.toString(), comp2.toString());
  335. }
  336. }
  337. return collator.compare(o1.toString(), o2.toString());
  338. } // compare
  339. /**
  340. * Get TableName.
  341. * @return table name
  342. */
  343. public String get_TableName()
  344. {
  345. return p_info.getTableName();
  346. } // get_TableName
  347. /**
  348. * Get Key Columns.
  349. * @return table name
  350. */
  351. public String[] get_KeyColumns()
  352. {
  353. return m_KeyColumns;
  354. } // get_KeyColumns
  355. /**
  356. * Get Table ID.
  357. * @return table id
  358. */
  359. public int get_Table_ID()
  360. {
  361. return p_info.getAD_Table_ID();
  362. } // get_TableID
  363. /**
  364. * Return Single Key Record ID
  365. * @return ID or 0
  366. */
  367. public int get_ID()
  368. {
  369. Object oo = m_IDs[0];
  370. if (oo != null && oo instanceof Integer)
  371. return ((Integer)oo).intValue();
  372. return 0;
  373. } // getID
  374. /**
  375. * Return Deleted Single Key Record ID
  376. * @return ID or 0
  377. */
  378. public int get_IDOld()
  379. {
  380. return m_idOld;
  381. } // getID
  382. /**
  383. * Get Context
  384. * @return context
  385. */
  386. public Properties getCtx()
  387. {
  388. return p_ctx;
  389. } // getCtx
  390. /**
  391. * Get Logger
  392. * @return logger
  393. */
  394. public CLogger get_Logger()
  395. {
  396. return log;
  397. } // getLogger
  398. /**************************************************************************
  399. * Get Value
  400. * @param index index
  401. * @return value
  402. */
  403. public final Object get_Value (int index)
  404. {
  405. if (index < 0 || index >= get_ColumnCount())
  406. {
  407. log.log(Level.WARNING, "Index invalid - " + index);
  408. return null;
  409. }
  410. if (m_newValues[index] != null)
  411. {
  412. if (m_newValues[index].equals(Null.NULL))
  413. return null;
  414. return m_newValues[index];
  415. }
  416. return m_oldValues[index];
  417. } // get_Value
  418. /**
  419. * Get Value as int
  420. * @param index index
  421. * @return int value or 0
  422. */
  423. public int get_ValueAsInt (int index)
  424. {
  425. Object value = get_Value(index);
  426. if (value == null)
  427. return 0;
  428. if (value instanceof Integer)
  429. return ((Integer)value).intValue();
  430. try
  431. {
  432. return Integer.parseInt(value.toString());
  433. }
  434. catch (NumberFormatException ex)
  435. {
  436. log.warning(p_info.getColumnName(index) + " - " + ex.getMessage());
  437. return 0;
  438. }
  439. } // get_ValueAsInt
  440. /**
  441. * Get Value
  442. * @param columnName column name
  443. * @return value or null
  444. */
  445. public final Object get_Value (String columnName)
  446. {
  447. int index = get_ColumnIndex(columnName);
  448. if (index < 0)
  449. {
  450. log.log(Level.WARNING, "Column not found - " + columnName);
  451. Trace.printStack();
  452. return null;
  453. }
  454. return get_Value (index);
  455. } // get_Value
  456. /**
  457. * Get Encrypted Value
  458. * @param columnName column name
  459. * @return value or null
  460. */
  461. protected final Object get_ValueE (String columnName)
  462. {
  463. return get_Value (columnName);
  464. } // get_ValueE
  465. /**
  466. * Get Column Value
  467. * @param variableName name
  468. * @return value or ""
  469. */
  470. public String get_ValueAsString (String variableName)
  471. {
  472. Object value = get_Value (variableName);
  473. if (value == null)
  474. return "";
  475. return value.toString();
  476. } // get_ValueAsString
  477. /**
  478. * Get Value of Column
  479. * @param AD_Column_ID column
  480. * @return value or null
  481. */
  482. public final Object get_ValueOfColumn (int AD_Column_ID)
  483. {
  484. int index = p_info.getColumnIndex(AD_Column_ID);
  485. if (index < 0)
  486. {
  487. log.log(Level.WARNING, "Not found - AD_Column_ID=" + AD_Column_ID);
  488. return null;
  489. }
  490. return get_Value (index);
  491. } // get_ValueOfColumn
  492. /**
  493. * Get Old Value
  494. * @param index index
  495. * @return value
  496. */
  497. public final Object get_ValueOld (int index)
  498. {
  499. if (index < 0 || index >= get_ColumnCount())
  500. {
  501. log.log(Level.WARNING, "Index invalid - " + index);
  502. return null;
  503. }
  504. return m_oldValues[index];
  505. } // get_ValueOld
  506. /**
  507. * Get Old Value
  508. * @param columnName column name
  509. * @return value or null
  510. */
  511. public final Object get_ValueOld (String columnName)
  512. {
  513. int index = get_ColumnIndex(columnName);
  514. if (index < 0)
  515. {
  516. log.log(Level.WARNING, "Column not found - " + columnName);
  517. return null;
  518. }
  519. return get_ValueOld (index);
  520. } // get_ValueOld
  521. /**
  522. * Get Old Value as int
  523. * @param columnName column name
  524. * @return int value or 0
  525. */
  526. public int get_ValueOldAsInt (String columnName)
  527. {
  528. Object value = get_ValueOld(columnName);
  529. if (value == null)
  530. return 0;
  531. if (value instanceof Integer)
  532. return ((Integer)value).intValue();
  533. try
  534. {
  535. return Integer.parseInt(value.toString());
  536. }
  537. catch (NumberFormatException ex)
  538. {
  539. log.warning(columnName + " - " + ex.getMessage());
  540. return 0;
  541. }
  542. } // get_ValueOldAsInt
  543. /**
  544. * Is Value Changed
  545. * @param index index
  546. * @return true if changed
  547. */
  548. public final boolean is_ValueChanged (int index)
  549. {
  550. if (index < 0 || index >= get_ColumnCount())
  551. {
  552. log.log(Level.WARNING, "Index invalid - " + index);
  553. return false;
  554. }
  555. if (m_newValues[index] == null)
  556. return false;
  557. if (m_newValues[index] == Null.NULL && m_oldValues[index] == null)
  558. return false;
  559. return !m_newValues[index].equals(m_oldValues[index]);
  560. } // is_ValueChanged
  561. /**
  562. * Is Value Changed
  563. * @param columnName column name
  564. * @return true if changed
  565. */
  566. public final boolean is_ValueChanged (String columnName)
  567. {
  568. int index = get_ColumnIndex(columnName);
  569. if (index < 0)
  570. {
  571. log.log(Level.WARNING, "Column not found - " + columnName);
  572. return false;
  573. }
  574. return is_ValueChanged (index);
  575. } // is_ValueChanged
  576. /**
  577. * Return new - old.
  578. * - New Value if Old Value is null
  579. * - New Value - Old Value if Number
  580. * - otherwise null
  581. * @param index index
  582. * @return new - old or null if not appropriate or not changed
  583. */
  584. public final Object get_ValueDifference (int index)
  585. {
  586. if (index < 0 || index >= get_ColumnCount())
  587. {
  588. log.log(Level.WARNING, "Index invalid - " + index);
  589. return null;
  590. }
  591. Object nValue = m_newValues[index];
  592. // No new Value or NULL
  593. if (nValue == null || nValue == Null.NULL)
  594. return null;
  595. //
  596. Object oValue = m_oldValues[index];
  597. if (oValue == null || oValue == Null.NULL)
  598. return nValue;
  599. if (nValue instanceof BigDecimal)
  600. {
  601. BigDecimal obd = (BigDecimal)oValue;
  602. return ((BigDecimal)nValue).subtract(obd);
  603. }
  604. else if (nValue instanceof Integer)
  605. {
  606. int result = ((Integer)nValue).intValue();
  607. result -= ((Integer)oValue).intValue();
  608. return new Integer(result);
  609. }
  610. //
  611. log.warning("Invalid type - New=" + nValue);
  612. return null;
  613. } // get_ValueDifference
  614. /**
  615. * Return new - old.
  616. * - New Value if Old Value is null
  617. * - New Value - Old Value if Number
  618. * - otherwise null
  619. * @param columnName column name
  620. * @return new - old or null if not appropriate or not changed
  621. */
  622. public final Object get_ValueDifference (String columnName)
  623. {
  624. int index = get_ColumnIndex(columnName);
  625. if (index < 0)
  626. {
  627. log.log(Level.WARNING, "Column not found - " + columnName);
  628. return null;
  629. }
  630. return get_ValueDifference (index);
  631. } // get_ValueDifference
  632. /**************************************************************************
  633. * Set Value
  634. * @param ColumnName column name
  635. * @param value value
  636. * @return true if value set
  637. */
  638. protected final boolean set_Value (String ColumnName, Object value)
  639. {
  640. return set_Value(ColumnName, value, true);
  641. }
  642. /**************************************************************************
  643. * Set Value
  644. * @param ColumnName column name
  645. * @param value value
  646. * @param checkWritable
  647. * @return true if value set
  648. */
  649. protected final boolean set_Value (String ColumnName, Object value, boolean checkWritable)
  650. {
  651. if (value instanceof String && ColumnName.equals("WhereClause")
  652. && value.toString().toUpperCase().indexOf("=NULL") != -1)
  653. log.warning("Invalid Null Value - " + ColumnName + "=" + value);
  654. int index = get_ColumnIndex(ColumnName);
  655. if (index < 0)
  656. {
  657. log.log(Level.SEVERE, "Column not found - " + ColumnName);
  658. log.saveError("ColumnNotFound", "Column not found - " + ColumnName);
  659. return false;
  660. }
  661. if (ColumnName.endsWith("_ID") && value instanceof String )
  662. {
  663. // Convert to Integer only if info class is Integer - teo_sarca [ 2859125 ]
  664. Class<?> clazz = p_info.getColumnClass(p_info.getColumnIndex(ColumnName));
  665. if (Integer.class == clazz)
  666. {
  667. log.severe("Invalid Data Type for " + ColumnName + "=" + value);
  668. value = Integer.parseInt((String)value);
  669. }
  670. }
  671. return set_Value (index, value, checkWritable);
  672. } // setValue
  673. /**
  674. * Set Encrypted Value
  675. * @param ColumnName column name
  676. * @param value value
  677. * @return true if value set
  678. */
  679. protected final boolean set_ValueE (String ColumnName, Object value)
  680. {
  681. return set_Value (ColumnName, value);
  682. } // setValueE
  683. /**
  684. * Set Value if updateable and correct class.
  685. * (and to NULL if not mandatory)
  686. * @param index index
  687. * @param value value
  688. * @return true if value set
  689. */
  690. protected final boolean set_Value (int index, Object value)
  691. {
  692. return set_Value(index, value, true);
  693. }
  694. /**
  695. * Set Value if updateable and correct class.
  696. * (and to NULL if not mandatory)
  697. * @param index index
  698. * @param value value
  699. * @param checkWritable
  700. * @return true if value set
  701. */
  702. protected final boolean set_Value (int index, Object value, boolean checkWritable)
  703. {
  704. if (index < 0 || index >= get_ColumnCount())
  705. {
  706. log.log(Level.WARNING, "Index invalid - " + index);
  707. return false;
  708. }
  709. String ColumnName = p_info.getColumnName(index);
  710. String colInfo = " - " + ColumnName;
  711. //
  712. m_setErrors[index] = null;
  713. if (checkWritable)
  714. {
  715. if (p_info.isVirtualColumn(index))
  716. {
  717. log.log(Level.WARNING, "Virtual Column" + colInfo);
  718. log.saveError("VirtualColumn", "Virtual Column" + colInfo);
  719. m_setErrors[index] = new ValueNamePair("VirtualColumn", "Virtual Column" + colInfo);
  720. return false;
  721. }
  722. //
  723. // globalqss -- Bug 1618469 - is throwing not updateable even on new records
  724. // if (!p_info.isColumnUpdateable(index))
  725. if ( ( ! p_info.isColumnUpdateable(index) ) && ( ! is_new() ) )
  726. {
  727. colInfo += " - NewValue=" + value + " - OldValue=" + get_Value(index);
  728. log.log(Level.WARNING, "Column not updateable" + colInfo);
  729. log.saveError("ColumnReadonly", "Column not updateable" + colInfo);
  730. m_setErrors[index] = new ValueNamePair("ColumnReadonly", "Column not updateable" + colInfo);
  731. return false;
  732. }
  733. }
  734. //
  735. if (value == null)
  736. {
  737. if (checkWritable && p_info.isColumnMandatory(index))
  738. {
  739. log.saveError("FillMandatory", ColumnName + " is mandatory.");
  740. m_setErrors[index] = new ValueNamePair("FillMandatory", ColumnName + " is mandatory.");
  741. return false;
  742. }
  743. m_newValues[index] = Null.NULL; // correct
  744. if (log.isLoggable(Level.FINER)) log.finer(ColumnName + " = null");
  745. }
  746. else
  747. {
  748. // matching class or generic object
  749. if (value.getClass().equals(p_info.getColumnClass(index))
  750. || p_info.getColumnClass(index) == Object.class)
  751. m_newValues[index] = value; // correct
  752. // Integer can be set as BigDecimal
  753. else if (value.getClass() == BigDecimal.class
  754. && p_info.getColumnClass(index) == Integer.class)
  755. m_newValues[index] = new Integer (((BigDecimal)value).intValue());
  756. // Set Boolean
  757. else if (p_info.getColumnClass(index) == Boolean.class
  758. && ("Y".equals(value) || "N".equals(value)) )
  759. m_newValues[index] = new Boolean("Y".equals(value));
  760. // added by vpj-cd
  761. // To solve BUG [ 1618423 ] Set Project Type button in Project window throws warning
  762. // generated because C_Project.C_Project_Type_ID is defined as button in dictionary
  763. // although is ID (integer) in database
  764. else if (value.getClass() == Integer.class
  765. && p_info.getColumnClass(index) == String.class)
  766. m_newValues[index] = value;
  767. else if (value.getClass() == String.class
  768. && p_info.getColumnClass(index) == Integer.class)
  769. try
  770. {
  771. m_newValues[index] = new Integer((String)value);
  772. }
  773. catch (NumberFormatException e)
  774. {
  775. String errmsg = ColumnName
  776. + " - Class invalid: " + value.getClass().toString()
  777. + ", Should be " + p_info.getColumnClass(index).toString() + ": " + value;
  778. log.log(Level.SEVERE, errmsg);
  779. log.saveError("WrongDataType", errmsg);
  780. m_setErrors[index] = new ValueNamePair("WrongDataType", errmsg);
  781. return false;
  782. }
  783. else
  784. {
  785. String errmsg = ColumnName
  786. + " - Class invalid: " + value.getClass().toString()
  787. + ", Should be " + p_info.getColumnClass(index).toString() + ": " + value;
  788. log.log(Level.SEVERE, errmsg);
  789. log.saveError("WrongDataType", errmsg);
  790. m_setErrors[index] = new ValueNamePair("WrongDataType", errmsg);
  791. return false;
  792. }
  793. // Validate (Min/Max)
  794. String error = p_info.validate(index, value);
  795. if (error != null)
  796. {
  797. log.log(Level.WARNING, ColumnName + "=" + value + " - " + error);
  798. int separatorIndex = error.indexOf(";");
  799. if (separatorIndex > 0) {
  800. log.saveError(error.substring(0,separatorIndex), error.substring(separatorIndex+1));
  801. m_setErrors[index] = new ValueNamePair(error.substring(0,separatorIndex), error.substring(separatorIndex+1));
  802. } else {
  803. log.saveError(error, ColumnName);
  804. m_setErrors[index] = new ValueNamePair(error, ColumnName);
  805. }
  806. return false;
  807. }
  808. // Length for String
  809. if (p_info.getColumnClass(index) == String.class)
  810. {
  811. String stringValue = value.toString();
  812. int length = p_info.getFieldLength(index);
  813. if (stringValue.length() > length && length > 0)
  814. {
  815. log.warning(ColumnName + " - Value too long - truncated to length=" + length);
  816. m_newValues[index] = stringValue.substring(0,length);
  817. }
  818. }
  819. // Validate reference list [1762461]
  820. if (p_info.getColumn(index).DisplayType == DisplayType.List &&
  821. p_info.getColumn(index).AD_Reference_Value_ID > 0 &&
  822. value instanceof String) {
  823. if (MRefList.get(getCtx(), p_info.getColumn(index).AD_Reference_Value_ID,
  824. (String) value, get_TrxName()) != null)
  825. ;
  826. else {
  827. StringBuilder validValues = new StringBuilder();
  828. for (ValueNamePair vp : MRefList.getList(getCtx(), p_info.getColumn(index).AD_Reference_Value_ID, false))
  829. validValues.append(" - ").append(vp.getValue());
  830. String errmsg = ColumnName + " Invalid value - "
  831. + value + " - Reference_ID=" + p_info.getColumn(index).AD_Reference_Value_ID + validValues.toString();
  832. log.saveError("Validate", errmsg);
  833. m_setErrors[index] = new ValueNamePair("Validate", errmsg);
  834. return false;
  835. }
  836. }
  837. if (log.isLoggable(Level.FINEST)) log.finest(ColumnName + " = " + m_newValues[index] + " (OldValue="+m_oldValues[index]+")");
  838. }
  839. set_Keys (ColumnName, m_newValues[index]);
  840. // FR 2962094 Fill ProcessedOn when the Processed column is changing from N to Y
  841. setProcessedOn(ColumnName, value, m_oldValues[index]);
  842. return true;
  843. } // setValue
  844. /* FR 2962094 - Finish implementation of weighted average costing
  845. Fill the column ProcessedOn (if it exists) with a bigdecimal representation of current timestamp (with nanoseconds)
  846. */
  847. public void setProcessedOn(String ColumnName, Object value, Object oldValue) {
  848. if ("Processed".equals(ColumnName)
  849. && value instanceof Boolean
  850. && ((Boolean)value).booleanValue() == true
  851. && (oldValue == null
  852. || (oldValue instanceof Boolean
  853. && ((Boolean)oldValue).booleanValue() == false))) {
  854. if (get_ColumnIndex("ProcessedOn") > 0) {
  855. // fill processed on column
  856. //get current time from db
  857. Timestamp ts = DB.getSQLValueTS(null, "SELECT CURRENT_TIMESTAMP FROM DUAL");
  858. long mili = ts.getTime();
  859. int nano = ts.getNanos();
  860. double doublets = Double.parseDouble(Long.toString(mili) + "." + Integer.toString(nano));
  861. BigDecimal bdtimestamp = BigDecimal.valueOf(doublets);
  862. set_Value("ProcessedOn", bdtimestamp);
  863. }
  864. }
  865. }
  866. /**
  867. * Set Value w/o check (update, r/o, ..).
  868. * Used when Column is R/O
  869. * Required for key and parent values
  870. * @param ColumnName column name
  871. * @param value value
  872. * @return true if value set
  873. */
  874. public final boolean set_ValueNoCheck (String ColumnName, Object value)
  875. {
  876. return set_Value(ColumnName, value, false);
  877. } // set_ValueNoCheck
  878. /**
  879. * Set Encrypted Value w/o check (update, r/o, ..).
  880. * Used when Column is R/O
  881. * Required for key and parent values
  882. * @param ColumnName column name
  883. * @param value value
  884. * @return true if value set
  885. */
  886. protected final boolean set_ValueNoCheckE (String ColumnName, Object value)
  887. {
  888. return set_ValueNoCheck (ColumnName, value);
  889. } // set_ValueNoCheckE
  890. /**
  891. * Set value of Column
  892. * @param columnName
  893. * @param value
  894. */
  895. public final void set_ValueOfColumn(String columnName, Object value)
  896. {
  897. set_ValueOfColumnReturningBoolean(columnName, value);
  898. }
  899. /**
  900. * Set value of Column returning boolean
  901. * @param columnName
  902. * @param value
  903. * @returns boolean indicating success or failure
  904. */
  905. public final boolean set_ValueOfColumnReturningBoolean(String columnName, Object value)
  906. {
  907. int AD_Column_ID = p_info.getAD_Column_ID(columnName);
  908. if (AD_Column_ID > 0)
  909. return set_ValueOfColumnReturningBoolean(AD_Column_ID, value);
  910. else
  911. return false;
  912. }
  913. /**
  914. * Set Value of Column
  915. * @param AD_Column_ID column
  916. * @param value value
  917. */
  918. public final void set_ValueOfColumn (int AD_Column_ID, Object value)
  919. {
  920. set_ValueOfColumnReturningBoolean (AD_Column_ID, value);
  921. } // setValueOfColumn
  922. /**
  923. * Set Value of Column
  924. * @param AD_Column_ID column
  925. * @param value value
  926. * @returns boolean indicating success or failure
  927. */
  928. public final boolean set_ValueOfColumnReturningBoolean (int AD_Column_ID, Object value)
  929. {
  930. int index = p_info.getColumnIndex(AD_Column_ID);
  931. if (index < 0)
  932. log.log(Level.SEVERE, "Not found - AD_Column_ID=" + AD_Column_ID);
  933. String ColumnName = p_info.getColumnName(index);
  934. if (ColumnName.equals("IsApproved"))
  935. return set_ValueNoCheck(ColumnName, value);
  936. else
  937. return set_Value (index, value);
  938. } // setValueOfColumn
  939. /**
  940. * Set Custom Column
  941. * @param columnName column
  942. * @param value value
  943. */
  944. public final void set_CustomColumn (String columnName, Object value)
  945. {
  946. set_CustomColumnReturningBoolean (columnName, value);
  947. } // set_CustomColumn
  948. /**
  949. * Set Custom Column returning boolean
  950. * @param columnName column
  951. * @param value value
  952. * @returns boolean indicating success or failure
  953. */
  954. public final boolean set_CustomColumnReturningBoolean (String columnName, Object value)
  955. {
  956. // [ 1845793 ] PO.set_CustomColumn not updating correctly m_newValues
  957. // this is for columns not in PO - verify and call proper method if exists
  958. int poIndex = get_ColumnIndex(columnName);
  959. if (poIndex > 0) {
  960. // is not custom column - it exists in the PO
  961. return set_Value(columnName, value);
  962. }
  963. if (m_custom == null)
  964. m_custom = new HashMap<String,String>();
  965. String valueString = "NULL";
  966. if (value == null)
  967. ;
  968. else if (value instanceof Number)
  969. valueString = value.toString();
  970. else if (value instanceof Boolean)
  971. valueString = ((Boolean)value).booleanValue() ? "'Y'" : "'N'";
  972. else if (value instanceof Timestamp)
  973. valueString = DB.TO_DATE((Timestamp)value, false);
  974. else // if (value instanceof String)
  975. valueString = DB.TO_STRING(value.toString());
  976. // Save it
  977. if (log.isLoggable(Level.INFO))log.log(Level.INFO, columnName + "=" + valueString);
  978. m_custom.put(columnName, valueString);
  979. return true;
  980. } // set_CustomColumn
  981. /**
  982. * Set (numeric) Key Value
  983. * @param ColumnName column name
  984. * @param value value
  985. */
  986. private void set_Keys (String ColumnName, Object value)
  987. {
  988. // Update if KeyColumn
  989. for (int i = 0; i < m_IDs.length; i++)
  990. {
  991. if (ColumnName.equals (m_KeyColumns[i]))
  992. {
  993. m_IDs[i] = value;
  994. }
  995. } // for all key columns
  996. } // setKeys
  997. /**************************************************************************
  998. * Get Column Count
  999. * @return column count
  1000. */
  1001. public int get_ColumnCount()
  1002. {
  1003. return p_info.getColumnCount();
  1004. } // getColumnCount
  1005. /**
  1006. * Get Column Name
  1007. * @param index index
  1008. * @return ColumnName
  1009. */
  1010. public String get_ColumnName (int index)
  1011. {
  1012. return p_info.getColumnName (index);
  1013. } // getColumnName
  1014. /**
  1015. * Get Column Label
  1016. * @param index index
  1017. * @return Column Label
  1018. */
  1019. protected String get_ColumnLabel (int index)
  1020. {
  1021. return p_info.getColumnLabel (index);
  1022. } // getColumnLabel
  1023. /**
  1024. * Get Column Description
  1025. * @param index index
  1026. * @return column description
  1027. */
  1028. protected String get_ColumnDescription (int index)
  1029. {
  1030. return p_info.getColumnDescription (index);
  1031. } // getColumnDescription
  1032. /**
  1033. * Is Column Mandatory
  1034. * @param index index
  1035. * @return true if column mandatory
  1036. */
  1037. protected boolean isColumnMandatory (int index)
  1038. {
  1039. return p_info.isColumnMandatory(index);
  1040. } // isColumnNandatory
  1041. /**
  1042. * Is Column Updateable
  1043. * @param index index
  1044. * @return true if column updateable
  1045. */
  1046. protected boolean isColumnUpdateable (int index)
  1047. {
  1048. return p_info.isColumnUpdateable(index);
  1049. } // isColumnUpdateable
  1050. /**
  1051. * Set Column Updateable
  1052. * @param index index
  1053. * @param updateable column updateable
  1054. */
  1055. protected void set_ColumnUpdateable (int index, boolean updateable)
  1056. {
  1057. p_info.setColumnUpdateable(index, updateable);
  1058. } // setColumnUpdateable
  1059. /**
  1060. * Set all columns updateable
  1061. * @param updateable updateable
  1062. */
  1063. protected void setUpdateable (boolean updateable)
  1064. {
  1065. p_info.setUpdateable (updateable);
  1066. } // setUpdateable
  1067. /**
  1068. * Get Column DisplayType
  1069. * @param index index
  1070. * @return display type
  1071. */
  1072. protected int get_ColumnDisplayType (int index)
  1073. {
  1074. return p_info.getColumnDisplayType(index);
  1075. } // getColumnDisplayType
  1076. /**
  1077. * Get Lookup
  1078. * @param index index
  1079. * @return Lookup or null
  1080. */
  1081. protected Lookup get_ColumnLookup(int index)
  1082. {
  1083. return p_info.getColumnLookup(index);
  1084. } // getColumnLookup
  1085. /**
  1086. * Get Column Index
  1087. * @param columnName column name
  1088. * @return index of column with ColumnName or -1 if not found
  1089. */
  1090. public final int get_ColumnIndex (String columnName)
  1091. {
  1092. return p_info.getColumnIndex(columnName);
  1093. } // getColumnIndex
  1094. /**
  1095. * Get Display Value of value
  1096. * @param columnName columnName
  1097. * @param currentValue current value
  1098. * @return String value with "./." as null
  1099. */
  1100. public String get_DisplayValue(String columnName, boolean currentValue)
  1101. {
  1102. Object value = currentValue ? get_Value(columnName) : get_ValueOld(columnName);
  1103. if (value == null)
  1104. return "./.";
  1105. String retValue = value.toString();
  1106. int index = get_ColumnIndex(columnName);
  1107. if (index < 0)
  1108. return retValue;
  1109. int dt = get_ColumnDisplayType(index);
  1110. if (DisplayType.isText(dt) || DisplayType.YesNo == dt)
  1111. return retValue;
  1112. // Lookup
  1113. Lookup lookup = get_ColumnLookup(index);
  1114. if (lookup != null)
  1115. return lookup.getDisplay(value);
  1116. // Other
  1117. return retValue;
  1118. } // get_DisplayValue
  1119. /**
  1120. * Copy old values of From to new values of To.
  1121. * Does not copy Keys
  1122. * @param from old, existing & unchanged PO
  1123. * @param to new, not saved PO
  1124. * @param AD_Client_ID client
  1125. * @param AD_Org_ID org
  1126. */
  1127. protected static void copyValues (PO from, PO to, int AD_Client_ID, int AD_Org_ID)
  1128. {
  1129. copyValues (from, to);
  1130. to.setAD_Client_ID(AD_Client_ID);
  1131. to.setAD_Org_ID(AD_Org_ID);
  1132. } // copyValues
  1133. /**
  1134. * Copy old values of From to new values of To.
  1135. * Does not copy Keys and AD_Client_ID/AD_Org_ID
  1136. * @param from old, existing & unchanged PO
  1137. * @param to new, not saved PO
  1138. */
  1139. public static void copyValues (PO from, PO to)
  1140. {
  1141. if (s_log.isLoggable(Level.FINE)) s_log.fine("From ID=" + from.get_ID() + " - To ID=" + to.get_ID());
  1142. // Different Classes
  1143. if (from.getClass() != to.getClass())
  1144. {
  1145. for (int i1 = 0; i1 < from.m_oldValues.length; i1++)
  1146. {
  1147. String colName = from.p_info.getColumnName(i1);
  1148. MColumn column = MColumn.get(from.getCtx(), from.p_info.getAD_Column_ID(colName));
  1149. if ( column.isVirtualColumn()
  1150. || column.isKey() // KeyColumn
  1151. || column.isUUIDColumn() // IDEMPIERE-67
  1152. || column.isStandardColumn()
  1153. || ! column.isAllowCopy())
  1154. continue;
  1155. for (int i2 = 0; i2 < to.m_oldValues.length; i2++)
  1156. {
  1157. if (to.p_info.getColumnName(i2).equals(colName))
  1158. {
  1159. to.m_newValues[i2] = from.m_oldValues[i1];
  1160. break;
  1161. }
  1162. }
  1163. } // from loop
  1164. }
  1165. else // same class
  1166. {
  1167. for (int i = 0; i < from.m_oldValues.length; i++)
  1168. {
  1169. String colName = from.p_info.getColumnName(i);
  1170. MColumn column = MColumn.get(from.getCtx(), from.p_info.getAD_Column_ID(colName));
  1171. if ( column.isVirtualColumn()
  1172. || column.isKey() // KeyColumn
  1173. || column.isUUIDColumn()
  1174. || column.isStandardColumn()
  1175. || ! column.isAllowCopy())
  1176. continue;
  1177. to.m_newValues[i] = from.m_oldValues[i];
  1178. }
  1179. } // same class
  1180. } // copy
  1181. /**************************************************************************
  1182. * Load record with ID
  1183. * @param ID ID
  1184. * @param trxName transaction name
  1185. */
  1186. protected void load (int ID, String trxName)
  1187. {
  1188. if (log.isLoggable(Level.FINEST)) log.finest("ID=" + ID);
  1189. if (ID > 0)
  1190. {
  1191. setKeyInfo();
  1192. m_IDs = new Object[] {new Integer(ID)};
  1193. //m_KeyColumns = new String[] {p_info.getTableName() + "_ID"};
  1194. load(trxName);
  1195. }
  1196. else // new
  1197. {
  1198. loadDefaults();
  1199. m_createNew = true;
  1200. setKeyInfo(); // sets m_IDs
  1201. loadComplete(true);
  1202. }
  1203. } // load
  1204. /**
  1205. * (re)Load record with m_ID[*]
  1206. * @param trxName transaction
  1207. * @return true if loaded
  1208. */
  1209. public boolean load (String trxName)
  1210. {
  1211. m_trxName = trxName;
  1212. boolean success = true;
  1213. StringBuilder sql = new StringBuilder("SELECT ");
  1214. int size = get_ColumnCount();
  1215. for (int i = 0; i < size; i++)
  1216. {
  1217. if (i != 0)
  1218. sql.append(",");
  1219. sql.append(p_info.getColumnSQL(i)); // Normal and Virtual Column
  1220. }
  1221. sql.append(" FROM ").append(p_info.getTableName())
  1222. .append(" WHERE ")
  1223. .append(get_WhereClause(false));
  1224. //
  1225. // int index = -1;
  1226. if (log.isLoggable(Level.FINEST)) log.finest(get_WhereClause(true));
  1227. PreparedStatement pstmt = null;
  1228. ResultSet rs = null;
  1229. try
  1230. {
  1231. pstmt = DB.prepareStatement(sql.toString(), m_trxName); // local trx only
  1232. for (int i = 0; i < m_IDs.length; i++)
  1233. {
  1234. Object oo = m_IDs[i];
  1235. if (oo instanceof Integer)
  1236. pstmt.setInt(i+1, ((Integer)m_IDs[i]).intValue());
  1237. else if (oo instanceof Boolean)
  1238. pstmt.setString(i+1, ((Boolean) m_IDs[i] ? "Y" : "N"));
  1239. else if (oo instanceof Timestamp)
  1240. pstmt.setTimestamp(i+1, (Timestamp)m_IDs[i]);
  1241. else
  1242. pstmt.setString(i+1, m_IDs[i].toString());
  1243. }
  1244. rs = pstmt.executeQuery();
  1245. if (rs.next())
  1246. {
  1247. success = load(rs);
  1248. }
  1249. else
  1250. {
  1251. log.log(Level.SEVERE, "NO Data found for " + get_WhereClause(true), new Exception());
  1252. m_IDs = new Object[] {I_ZERO};
  1253. success = false;
  1254. // throw new DBException("NO Data found for " + get_WhereClause(true));
  1255. }
  1256. m_createNew = false;
  1257. // reset new values
  1258. m_newValues = new Object[size];
  1259. }
  1260. catch (Exception e)
  1261. {
  1262. String msg = "";
  1263. if (m_trxName != null)
  1264. msg = "[" + m_trxName + "] - ";
  1265. msg += get_WhereClause(true)
  1266. // + ", Index=" + index
  1267. // + ", Column=" + get_ColumnName(index)
  1268. // + ", " + p_info.toString(index)
  1269. + ", SQL=" + sql.toString();
  1270. success = false;
  1271. m_IDs = new Object[] {I_ZERO};
  1272. log.log(Level.SEVERE, msg, e);
  1273. // throw new DBException(e);
  1274. }
  1275. // Finish
  1276. finally {
  1277. DB.close(rs, pstmt);
  1278. rs = null; pstmt = null;
  1279. }
  1280. loadComplete(success);
  1281. return success;
  1282. } // load
  1283. /**
  1284. * Load from the current position of a ResultSet
  1285. * @param rs result set
  1286. * @return true if loaded
  1287. */
  1288. protected boolean load (ResultSet rs)
  1289. {
  1290. int size = get_ColumnCount();
  1291. boolean success = true;
  1292. int index = 0;
  1293. log.finest("(rs)");
  1294. // load column values
  1295. for (index = 0; index < size; index++)
  1296. {
  1297. String columnName = p_info.getColumnName(index);
  1298. Class<?> clazz = p_info.getColumnClass(index);
  1299. int dt = p_info.getColumnDisplayType(index);
  1300. try
  1301. {
  1302. if (clazz == Integer.class)
  1303. m_oldValues[index] = decrypt(index, new Integer(rs.getInt(columnName)));
  1304. else if (clazz == BigDecimal.class)
  1305. m_oldValues[index] = decrypt(index, rs.getBigDecimal(columnName));
  1306. else if (clazz == Boolean.class)
  1307. m_oldValues[index] = new Boolean ("Y".equals(decrypt(index, rs.getString(columnName))));
  1308. else if (clazz == Timestamp.class)
  1309. m_oldValues[index] = decrypt(index, rs.getTimestamp(columnName));
  1310. else if (DisplayType.isLOB(dt))
  1311. m_oldValues[index] = get_LOB (rs.getObject(columnName));
  1312. else if (clazz == String.class)
  1313. {
  1314. String value = (String)decrypt(index, rs.getString(columnName));
  1315. if (value != null)
  1316. {
  1317. if (get_Table_ID() == I_AD_Column.Table_ID || get_Table_ID() == I_AD_Element.Table_ID
  1318. || get_Table_ID() == I_AD_Field.Table_ID)
  1319. {
  1320. if ("Description".equals(columnName) || "Help".equals(columnName))
  1321. {
  1322. value = value.intern();
  1323. }
  1324. }
  1325. }
  1326. m_oldValues[index] = value;
  1327. }
  1328. else
  1329. m_oldValues[index] = loadSpecial(rs, index);
  1330. // NULL
  1331. if (rs.wasNull() && m_oldValues[index] != null)
  1332. m_oldValues[index] = null;
  1333. //
  1334. if (CLogMgt.isLevelAll())
  1335. log.finest(String.valueOf(index) + ": " + p_info.getColumnName(index)
  1336. + "(" + p_info.getColumnClass(index) + ") = " + m_oldValues[index]);
  1337. }
  1338. catch (SQLException e)
  1339. {
  1340. if (p_info.isVirtualColumn(index)) { // if rs constructor used
  1341. if (log.isLoggable(Level.FINER))log.log(Level.FINER, "Virtual Column not loaded: " + columnName);
  1342. } else {
  1343. log.log(Level.SEVERE, "(rs) - " + String.valueOf(index)
  1344. + ": " + p_info.getTableName() + "." + p_info.getColumnName(index)
  1345. + " (" + p_info.getColumnClass(index) + ") - " + e);
  1346. success = false;
  1347. }
  1348. }
  1349. }
  1350. m_createNew = false;
  1351. setKeyInfo();
  1352. loadComplete(success);
  1353. return success;
  1354. } // load
  1355. /**
  1356. * Load from HashMap
  1357. * @param hmIn hash map
  1358. * @return true if loaded
  1359. */
  1360. protected boolean load (HashMap<String,String> hmIn)
  1361. {
  1362. int size = get_ColumnCount();
  1363. boolean success = true;
  1364. int index = 0;
  1365. log.finest("(hm)");
  1366. // load column values
  1367. for (index = 0; index < size; index++)
  1368. {
  1369. String columnName = p_info.getColumnName(index);
  1370. String value = (String)hmIn.get(columnName);
  1371. if (value == null)
  1372. continue;
  1373. Class<?> clazz = p_info.getColumnClass(index);
  1374. int dt = p_info.getColumnDisplayType(index);
  1375. try
  1376. {
  1377. if (clazz == Integer.class)
  1378. m_oldValues[index] = new Integer(value);
  1379. else if (clazz == BigDecimal.class)
  1380. m_oldValues[index] = new BigDecimal(value);
  1381. else if (clazz == Boolean.class)
  1382. m_oldValues[index] = new Boolean ("Y".equals(value));
  1383. else if (clazz == Timestamp.class)
  1384. m_oldValues[index] = Timestamp.valueOf(value);
  1385. else if (DisplayType.isLOB(dt))
  1386. m_oldValues[index] = null; // get_LOB (rs.getObject(columnName));
  1387. else if (clazz == String.class)
  1388. m_oldValues[index] = value;
  1389. else
  1390. m_oldValues[index] = null; // loadSpecial(rs, index);
  1391. //
  1392. if (CLogMgt.isLevelAll())
  1393. log.finest(String.valueOf(index) + ": " + p_info.getColumnName(index)
  1394. + "(" + p_info.getColumnClass(index) + ") = " + m_oldValues[index]);
  1395. }
  1396. catch (Exception e)
  1397. {
  1398. if (p_info.isVirtualColumn(index)) { // if rs constructor used
  1399. if (log.isLoggable(Level.FINER))log.log(Level.FINER, "Virtual Column not loaded: " + columnName);
  1400. } else {
  1401. log.log(Level.SEVERE, "(ht) - " + String.valueOf(index)
  1402. + ": " + p_info.getTableName() + "." + p_info.getColumnName(index)
  1403. + " (" + p_info.getColumnClass(index) + ") - " + e);
  1404. success = false;
  1405. }
  1406. }
  1407. }
  1408. m_createNew = false;
  1409. // Overwrite
  1410. setStandardDefaults();
  1411. setKeyInfo();
  1412. loadComplete(success);
  1413. return success;
  1414. } // load
  1415. /**
  1416. * Create Hashmap with data as Strings
  1417. * @return HashMap
  1418. */
  1419. protected HashMap<String,String> get_HashMap()
  1420. {
  1421. HashMap<String,String> hmOut = new HashMap<String,String>();
  1422. int size = get_ColumnCount();
  1423. for (int i = 0; i < size; i++)
  1424. {
  1425. Object value = get_Value(i);
  1426. // Don't insert NULL values (allows Database defaults)
  1427. if (value == null
  1428. || p_info.isVirtualColumn(i))
  1429. continue;
  1430. // Display Type
  1431. int dt = p_info.getColumnDisplayType(i);
  1432. // Based on class of definition, not class of value
  1433. Class<?> c = p_info.getColumnClass(i);
  1434. String stringValue = null;
  1435. if (c == Object.class)
  1436. ; // saveNewSpecial (value, i));
  1437. else if (value == null || value.equals (Null.NULL))
  1438. ;
  1439. else if (value instanceof Integer || value instanceof BigDecimal)
  1440. stringValue = value.toString();
  1441. else if (c == Boolean.class)
  1442. {
  1443. boolean bValue = false;
  1444. if (value instanceof Boolean)
  1445. bValue = ((Boolean)value).booleanValue();
  1446. else
  1447. bValue = "Y".equals(value);
  1448. stringValue = bValue ? "Y" : "N";
  1449. }
  1450. else if (value instanceof Timestamp)
  1451. stringValue = value.toString();
  1452. else if (c == String.class)
  1453. stringValue = (String)value;
  1454. else if (DisplayType.isLOB(dt))
  1455. ;
  1456. else
  1457. ; // saveNewSpecial (value, i));
  1458. //
  1459. if (stringValue != null)
  1460. hmOut.put(p_info.getColumnName(i), stringValue);
  1461. }
  1462. // Custom Columns
  1463. if (m_custom != null)
  1464. {
  1465. Iterator<String> it = m_custom.keySet().iterator();
  1466. while (it.hasNext())
  1467. {
  1468. String column = (String)it.next();
  1469. // int index = p_info.getColumnIndex(column);
  1470. String value = (String)m_custom.get(column);
  1471. if (value != null)
  1472. hmOut.put(column, value);
  1473. }
  1474. m_custom = null;
  1475. }
  1476. return hmOut;
  1477. } // get_HashMap
  1478. /**
  1479. * Load Special data (images, ..).
  1480. * To be extended by sub-classes
  1481. * @param rs result set
  1482. * @param index zero based index
  1483. * @return value value
  1484. * @throws SQLException
  1485. */
  1486. protected Object loadSpecial (ResultSet rs, int index) throws SQLException
  1487. {
  1488. if (log.isLoggable(Level.FINEST)) log.finest("(NOP) - " + p_info.getColumnName(index));
  1489. return null;
  1490. } // loadSpecial
  1491. /**
  1492. * Load is complete
  1493. * @param success success
  1494. * To be extended by sub-classes
  1495. */
  1496. protected void loadComplete (boolean success)
  1497. {
  1498. } // loadComplete
  1499. /**
  1500. * Load Defaults
  1501. */
  1502. protected void loadDefaults()
  1503. {
  1504. setStandardDefaults();
  1505. //
  1506. /** @todo defaults from Field */
  1507. // MField.getDefault(p_info.getDefaultLogic(i));
  1508. } // loadDefaults
  1509. /**
  1510. * Set Default values.
  1511. * Client, Org, Created/Updated, *By, IsActive
  1512. */
  1513. protected void setStandardDefaults()
  1514. {
  1515. int size = get_ColumnCount();
  1516. for (int i = 0; i < size; i++)
  1517. {
  1518. if (p_info.isVirtualColumn(i))
  1519. continue;
  1520. String colName = p_info.getColumnName(i);
  1521. // Set Standard Values
  1522. if (colName.endsWith("tedBy"))
  1523. m_newValues[i] = new Integer (Env.getContextAsInt(p_ctx, "#AD_User_ID"));
  1524. else if (colName.equals("Created") || colName.equals("Updated"))
  1525. m_newValues[i] = new Timestamp (System.currentTimeMillis());
  1526. else if (colName.equals(p_info.getTableName() + "_ID")) // KeyColumn
  1527. m_newValues[i] = I_ZERO;
  1528. else if (colName.equals("IsActive"))
  1529. m_newValues[i] = new Boolean(true);
  1530. else if (colName.equals("AD_Client_ID"))
  1531. m_newValues[i] = new Integer(Env.getAD_Client_ID(p_ctx));
  1532. else if (colName.equals("AD_Org_ID"))
  1533. m_newValues[i] = new Integer(Env.getAD_Org_ID(p_ctx));
  1534. else if (colName.equals("Processed"))
  1535. m_newValues[i] = new Boolean(false);
  1536. else if (colName.equals("Processing"))
  1537. m_newValues[i] = new Boolean(false);
  1538. else if (colName.equals("Posted"))
  1539. m_newValues[i] = new Boolean(false);
  1540. }
  1541. } // setDefaults
  1542. /**
  1543. * Set Key Info (IDs and KeyColumns).
  1544. */
  1545. private void setKeyInfo()
  1546. {
  1547. // Search for Primary Key
  1548. for (int i = 0; i < p_info.getColumnCount(); i++)
  1549. {
  1550. if (p_info.isKey(i))
  1551. {
  1552. String ColumnName = p_info.getColumnName(i);
  1553. m_KeyColumns = new String[] {ColumnName};
  1554. if (p_info.getColumnName(i).endsWith("_ID"))
  1555. {
  1556. Integer ii = (Integer)get_Value(i);
  1557. if (ii == null)
  1558. m_IDs = new Object[] {I_ZERO};
  1559. else
  1560. m_IDs = new Object[] {ii};
  1561. if (log.isLoggable(Level.FINEST)) log.finest("(PK) " + ColumnName + "=" + ii);
  1562. }
  1563. else
  1564. {
  1565. Object oo = get_Value(i);
  1566. if (oo == null)
  1567. m_IDs = new Object[] {null};
  1568. else
  1569. m_IDs = new Object[] {oo};
  1570. if (log.isLoggable(Level.FINEST)) log.finest("(PK) " + ColumnName + "=" + oo);
  1571. }
  1572. return;
  1573. }
  1574. } // primary key search
  1575. // Search for Parents
  1576. ArrayList<String> columnNames = new ArrayList<String>();
  1577. for (int i = 0; i < p_info.getColumnCount(); i++)
  1578. {
  1579. if (p_info.isColumnParent(i))
  1580. columnNames.add(p_info.getColumnName(i));
  1581. }
  1582. // Set FKs
  1583. int size = columnNames.size();
  1584. if (size == 0)
  1585. throw new IllegalStateException("No PK nor FK - " + p_info.getTableName());
  1586. m_IDs = new Object[size];
  1587. m_KeyColumns = new String[size];
  1588. for (int i = 0; i < size; i++)
  1589. {
  1590. m_KeyColumns[i] = (String)columnNames.get(i);
  1591. if (m_KeyColumns[i].endsWith("_ID"))
  1592. {
  1593. Integer ii = null;
  1594. try
  1595. {
  1596. ii = (Integer)get_Value(m_KeyColumns[i]);
  1597. }
  1598. catch (Exception e)
  1599. {
  1600. log.log(Level.SEVERE, "", e);
  1601. }
  1602. if (ii != null)
  1603. m_IDs[i] = ii;
  1604. }
  1605. else
  1606. m_IDs[i] = get_Value(m_KeyColumns[i]);
  1607. if (log.isLoggable(Level.FINEST)) log.finest("(FK) " + m_KeyColumns[i] + "=" + m_IDs[i]);
  1608. }
  1609. } // setKeyInfo
  1610. /**************************************************************************
  1611. * Are all mandatory Fields filled (i.e. can we save)?.
  1612. * Stops at first null mandatory field
  1613. * @return true if all mandatory fields are ok
  1614. */
  1615. protected boolean isMandatoryOK()
  1616. {
  1617. int size = get_ColumnCo

Large files files are truncated, but you can click here to view the full file