KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > compiere > model > MField


1 /******************************************************************************
2  * The contents of this file are subject to the Compiere License Version 1.1
3  * ("License"); You may not use this file except in compliance with the License
4  * You may obtain a copy of the License at http://www.compiere.org/license.html
5  * Software distributed under the License is distributed on an "AS IS" basis,
6  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
7  * the specific language governing rights and limitations under the License.
8  * The Original Code is Compiere ERP & CRM Business Solution
9  * The Initial Developer of the Original Code is Jorg Janke and ComPiere, Inc.
10  * Portions created by Jorg Janke are Copyright (C) 1999-2001 Jorg Janke, parts
11  * created by ComPiere are Copyright (C) ComPiere, Inc.; All Rights Reserved.
12  * Contributor(s): ______________________________________.
13  *****************************************************************************/

14 package org.compiere.model;
15
16 import java.awt.*;
17 import java.sql.*;
18 import java.util.*;
19 import java.math.*;
20 import java.beans.*;
21 import java.io.*;
22
23 import org.compiere.util.*;
24 import org.compiere.plaf.CompierePLAF;
25
26 /**
27  * Field Model.
28  * <p>
29  * Fields are a combination of AD_Field (the display attributes)
30  * and AD_Column (the storage attributes).
31  * <p>
32  * The Field maintains the current edited value. If the value is changed,
33  * it fire PropertyChange "FieldValue".
34  * If the background is changed the PropertyChange "FieldAttribute" is fired.
35  * <br>
36  * Usually editors listen to their fields.
37  *
38  * @author Jorg Janke
39  * @version $Id: MField.java,v 1.49 2003/11/07 06:36:36 jjanke Exp $
40  */

41 public final class MField implements Serializable
42 {
43     /**
44      * Field Constructor.
45      * requires initField for complete instatanciation
46      * @param vo ValueObjecy
47      */

48     public MField (MFieldVO vo)
49     {
50         m_vo = vo;
51         // Set Attributes
52
loadLookup();
53         setError(false);
54     } // MField
55

56     /** Value Object */
57     private MFieldVO m_vo;
58
59     /**
60      * Dispose
61      */

62     protected void dispose()
63     {
64     // Log.trace(Log.l5_DData, "MField.dispose = " + m_vo.ColumnName);
65
m_propertyChangeListeners = null;
66         if (m_lookup != null)
67             m_lookup.dispose();
68         m_lookup = null;
69         m_vo.lookupInfo = null;
70         m_vo = null;
71     } // dispose
72

73
74     /** Lookup for this field */
75     private Lookup m_lookup = null;
76     /** New Row / inserting */
77     private boolean m_inserting = false;
78
79
80     /** Max Display Length */
81     public static final int MAXDISPLAY_LENGTH = 60;
82
83     /** The current value */
84     private Object JavaDoc m_value = null;
85     /** The old to force Property Change */
86     private static Object JavaDoc s_oldValue = new Object JavaDoc();
87     /** The old/previous value */
88     private Object JavaDoc m_oldValue = s_oldValue;
89     /** Only fire Property Change if old value really changed */
90     private boolean m_setOldValue = true;
91     /** Error Status */
92     private boolean m_error = false;
93     /** Parent Check */
94     private boolean m_parentChecked = false;
95
96     /** Property Change */
97     private PropertyChangeSupport m_propertyChangeListeners = new PropertyChangeSupport(this);
98     /** PropertyChange Name */
99     public static final String JavaDoc PROPERTY = "FieldValue";
100     /** Indicator for new Value */
101     public static final String JavaDoc INSERTING = "FieldValueInserting";
102
103     /** Error Value for HTML interface */
104     private String JavaDoc m_errorValue = null;
105     /** Error Value indicator for HTML interface */
106     private boolean m_errorValueFlag = false;
107
108     /*************************************************************************/
109
110     /**
111      * Set Lookup for columns with lookup
112      */

113     public void loadLookup()
114     {
115         if (!isLookup())
116             return;
117         Log.trace(Log.l5_DData, "MField.loadLookup (" + m_vo.ColumnName + ")");
118
119         if (DisplayType.isLookup(m_vo.displayType))
120         {
121             if (m_vo.lookupInfo == null)
122             {
123                 Log.error("MField.loadLookup (" + m_vo.ColumnName + ") - No LookupInfo");
124                 return;
125             }
126             MLookup ml = new MLookup (m_vo.lookupInfo, m_vo.TabNo);
127             m_lookup = ml;
128         }
129         else if (m_vo.displayType == DisplayType.Location) // not cached
130
{
131             MLocation ml = new MLocation (m_vo.ctx, m_vo.WindowNo);
132             m_lookup = ml;
133         }
134         else if (m_vo.displayType == DisplayType.Locator)
135         {
136             MLocatorLookup ml = new MLocatorLookup (m_vo.ctx, m_vo.WindowNo);
137             m_lookup = ml;
138         }
139         else if (m_vo.displayType == DisplayType.Account) // not cached
140
{
141             MAccount ma = new MAccount (m_vo.ctx, m_vo.WindowNo);
142             m_lookup = ma;
143         }
144         else if (m_vo.displayType == DisplayType.PAttribute) // not cached
145
{
146             MPAttribute pa = new MPAttribute (m_vo.ctx, m_vo.WindowNo);
147             m_lookup = pa;
148         }
149     } // m_lookup
150

151     /**
152      * Wait until Load is complete
153      */

154     public void lookupLoadComplete()
155     {
156         if (m_lookup == null)
157             return;
158         m_lookup.loadComplete();
159     } // loadCompete
160

161     /**
162      * Get Lookup, may return null
163      * @return lookup
164      */

165     public Lookup getLookup()
166     {
167         return m_lookup;
168     } // getLookup
169

170     /**
171      * Is this field a Lookup?.
172      * @return true if lookup field
173      */

174     public boolean isLookup()
175     {
176         boolean retValue = false;
177         if (m_vo.IsKey)
178             retValue = false;
179     // else if (m_vo.ColumnName.equals("CreatedBy") || m_vo.ColumnName.equals("UpdatedBy"))
180
// retValue = false;
181
else if (DisplayType.isLookup(m_vo.displayType))
182             retValue = true;
183         else if (m_vo.displayType == DisplayType.Location
184             || m_vo.displayType == DisplayType.Locator
185             || m_vo.displayType == DisplayType.Account
186             || m_vo.displayType == DisplayType.PAttribute)
187             retValue = true;
188
189         return retValue;
190     } // isLookup
191

192     /**
193      * Refresh Lookup if the lookup is unstable
194      * @return true if lookup is validated
195      */

196     public boolean refreshLookup()
197     {
198         // if there is a validation string, the lookup is unstable
199
if (m_lookup == null || m_lookup.getValidation().length() == 0)
200             return true;
201         //
202
Log.trace(Log.l5_DData, "MField.refreshLookup (" + m_vo.ColumnName + ")");
203         m_lookup.refresh();
204         return m_lookup.isValidated();
205     } // refreshLookup
206

207     /**
208      * Get a list of fields, this field is dependent on.
209      * - for display purposes or
210      * - for lookup purposes
211      * @return ArrayList
212      */

213     public ArrayList getDependentOn()
214     {
215         ArrayList list = new ArrayList();
216         // Display
217
parseDepends(list, m_vo.DisplayLogic);
218         // Lookup
219
if (m_lookup != null)
220             parseDepends(list, m_lookup.getValidation());
221         //
222
if (list.size() > 0 && Log.getTraceLevel() > Log.l5_DData)
223         {
224             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
225             for (int i = 0; i < list.size(); i++)
226                 sb.append(list.get(i)).append(" ");
227             Log.trace(Log.l6_Database, "MField.getDependentOn (" + m_vo.ColumnName + ")",
228                 sb.toString());
229         }
230         return list;
231     } // getDependentOn
232

233     /**
234      * Parse String and add variables with @ to the list.
235      * @param list list to be added to
236      * @param parseString string to parse for variables
237      */

238     private void parseDepends (ArrayList list, String JavaDoc parseString)
239     {
240         if (parseString == null || parseString.length() == 0)
241             return;
242     // Log.trace(Log.l5_DData, "MField.parseDepends", parseString);
243
String JavaDoc s = parseString;
244         // while we have variables
245
while (s.indexOf("@") != -1)
246         {
247             int pos = s.indexOf("@");
248             s = s.substring(pos+1);
249             pos = s.indexOf("@");
250             if (pos == -1)
251                 continue; // error number of @@ not correct
252
String JavaDoc variable = s.substring(0, pos);
253             s = s.substring(pos+1);
254         // Log.trace(Log.l6_Database, variable);
255
list.add(variable);
256         }
257     } // parseDepends
258

259     /*************************************************************************/
260
261     /**
262      * Set Error.
263      * Used by editors to set the color
264      * @param error true if error
265      */

266     public void setError (boolean error)
267     {
268         m_error = error;
269     } // setBackground
270

271     /**
272      * Get Background Error.
273      * @return error
274      */

275     public boolean isError()
276     {
277         return m_error;
278     } // isError
279

280
281     /**
282      * Is it Mandatory to enter for user?
283      * Mandatory checking is dome in MTable.getMandatory
284      * @param checkContext - check environment (requires correct row position)
285      * @return true if mandatory
286      */

287     public boolean isMandatory (boolean checkContext)
288     {
289         // Not mandatory
290
if (!m_vo.IsMandatory)
291             return false;
292
293         // Numeric Keys and Created/Updated as well as DocumentNo/Value ars not mandatory
294
if ((m_vo.IsKey && m_vo.ColumnName.endsWith("_ID"))
295                 || m_vo.ColumnName.startsWith("Created") || m_vo.ColumnName.startsWith("Updated")
296                 || m_vo.ColumnName.equals("Value") || m_vo.ColumnName.equals("DocumentNo"))
297             return false;
298
299         // Mandatory if displayed
300
return isDisplayed (checkContext);
301     } // isMandatory
302

303     /**
304      * Is it Editable - checks IsActive, IsUpdateable, and isDisplayed
305      * @param checkContext if true checks Context for Active, IsProcessed, LinkColumn
306      * @return true, if editable
307      */

308     public boolean isEditable (boolean checkContext)
309     {
310         // Tab or field is R/O
311
if (m_vo.tabReadOnly || m_vo.IsReadOnly)
312         {
313             Log.trace (10, "MField.isEditable - " + m_vo.ColumnName + " NO - TabRO=" + m_vo.tabReadOnly + ", FieldRO=" + m_vo.IsReadOnly);
314             return false;
315         }
316
317         // Fields always enabled (are usually not updateable)
318
if (m_vo.ColumnName.equals("Record_ID") // Zoom
319
|| m_vo.ColumnName.equals("Posted"))
320             return true;
321
322         // Not Updateable - only editable if new updateable row
323
if (!m_vo.IsUpdateable && !m_inserting)
324         {
325             Log.trace (10, "MField.isEditable - " + m_vo.ColumnName + " NO - FieldUpdateable=" + m_vo.IsUpdateable);
326             return false;
327         }
328
329         // Field is the Link Column of the tab
330
if (m_vo.ColumnName.equals(Env.getContext(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "LinkColumnName")))
331         {
332             Log.trace (10, "MField.isEditable - " + m_vo.ColumnName + " NO - LinkColumn");
333             return false;
334         }
335
336         // Role Access & Column Access
337
if (checkContext)
338         {
339             int AD_Client_ID = Env.getContextAsInt(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "AD_Client_ID");
340             int AD_Org_ID = Env.getContextAsInt(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "AD_Org_ID");
341             int AD_Table_ID = Env.getContextAsInt(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "AD_Table_ID");
342             if (!MRole.getDefault(m_vo.ctx, false).canUpdate(AD_Client_ID, AD_Org_ID, AD_Table_ID, false))
343                 return false;
344             if (!MRole.getDefault(m_vo.ctx, false).isColumnAccess(AD_Table_ID, m_vo.AD_Column_ID, false))
345                 return false;
346         }
347             
348         // Do we have a readonly rule
349
if (checkContext && m_vo.ReadOnlyLogic.length() > 0)
350         {
351             boolean retValue = !evaluateLogic(m_vo.ReadOnlyLogic);
352             if (Log.isTraceLevel(7))
353                 Log.trace(8, "MField.isEditable - " + m_vo.ColumnName + " R/O(" + m_vo.ReadOnlyLogic + ") => R/W-" + retValue);
354             if (!retValue)
355                 return false;
356         }
357
358         // Always editable if Active
359
if (m_vo.ColumnName.equals("Processing")
360                 || m_vo.ColumnName.equals("PaymentRule")
361                 || m_vo.ColumnName.equals("DocAction")
362                 || m_vo.ColumnName.equals("GenerateTo"))
363             return true;
364
365         // Special fields allowed to change in Order/Invoice if Active
366
if (m_vo.AD_Column_ID == 2174 // Order.Description
367
|| m_vo.AD_Column_ID == 3045 // Order.POReference
368
|| m_vo.AD_Column_ID == 3782 // Invoice.POReference
369
|| m_vo.AD_Column_ID == 3785) // Invoice.POReference
370
return true;
371
372         // Record is Processed ***
373
if (checkContext && Env.getContext(m_vo.ctx, m_vo.WindowNo, "Processed").equals("Y"))
374             return false;
375
376         // IsActive field is editable, if record not processed
377
if (m_vo.ColumnName.equals("IsActive"))
378             return true;
379
380         // Record is not Active
381
if (checkContext && !Env.getContext(m_vo.ctx, m_vo.WindowNo, "IsActive").equals("Y"))
382             return false;
383
384         // ultimately visibily decides
385
return isDisplayed (checkContext);
386     } // isEditable
387

388     /**
389      * Set Inserting (allows to enter not updateable fields).
390      * Reset when setting the Field Value
391      * @param inserting true if inserting
392      */

393     public void setInserting (boolean inserting)
394     {
395         m_inserting = inserting;
396     } // setInserting
397

398     /*************************************************************************/
399
400     /**
401      * Create default value.
402      * <pre>
403      * (a) Key/Parent/IsActive/SystemAccess
404      * (b) SQL Default
405      * (c) User Preference
406      * (d) Column Default
407      * (e) System Preference
408      * (f) DataType Defaults
409      *
410      * Don't default from Context => use explicit defaultValue
411      * (would otherwise copy previous record)
412      * </pre>
413      * @return default value or null
414      */

415     public Object JavaDoc getDefault()
416     {
417         /**
418          * (a) Key/Parent/IsActive/SystemAccess
419          */

420
421         // No defaults for these fields
422
if (m_vo.IsKey || m_vo.displayType == DisplayType.RowID || m_vo.displayType == DisplayType.Binary)
423             return null;
424         // Set Parent to context
425
if (isParent())
426         {
427             String JavaDoc parent = Env.getContext(m_vo.ctx, m_vo.WindowNo, m_vo.ColumnName);
428             Log.trace(Log.l5_DData, "MField.getDefault [Parent] " + m_vo.ColumnName + "=" + parent);
429             return createDefault(parent);
430         }
431         // Always Active
432
if (m_vo.ColumnName.equals("IsActive"))
433         {
434             Log.trace(Log.l5_DData, "MField.getDefault [IsActive] " + m_vo.ColumnName + "=Y");
435             return "Y";
436         }
437         // Set Client & Org to System, if System access
438
if (X_AD_Table.ACCESSLEVEL_SystemOnly.equals(Env.getContext(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "AccessLevel"))
439             && (m_vo.ColumnName.equals("AD_Client_ID") || m_vo.ColumnName.equals("AD_Org_ID")))
440         {
441             Log.trace(Log.l5_DData, "MField.getDefault [SystemAccess] " + m_vo.ColumnName + "=0");
442             return new Integer JavaDoc(0);
443         }
444         // Set Org to System, if Client access
445
else if (X_AD_Table.ACCESSLEVEL_SystemPlusClient.equals(Env.getContext(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "AccessLevel"))
446             && m_vo.ColumnName.equals("AD_Org_ID"))
447         {
448             Log.trace(Log.l5_DData, "MField.getDefault [ClientAccess] " + m_vo.ColumnName + "=0");
449             return new Integer JavaDoc(0);
450         }
451
452         /**
453          * (b) SQL Statement (for data integity & consistency)
454          */

455         String JavaDoc defStr = "";
456         if (m_vo.DefaultValue.startsWith("@SQL="))
457         {
458             String JavaDoc SQL = m_vo.DefaultValue.substring(5); // w/o tag
459
SQL = Env.parseContext(m_vo.ctx, m_vo.WindowNo, SQL, false); // replace variables
460
if (SQL.equals(""))
461             {
462                 Log.error("MField.getDefault (" + m_vo.ColumnName + ") - Default SQL variable parse failed: "
463                     + m_vo.DefaultValue);
464             }
465             else
466             {
467                 try
468                 {
469                     PreparedStatement stmt = DB.prepareStatement(SQL);
470                     ResultSet rs = stmt.executeQuery();
471                     if (rs.next())
472                         defStr = rs.getString("DefaultValue");
473                     else
474                         Log.error("MField.getDefault (" + m_vo.ColumnName + ") - no Result: " + SQL);
475                     rs.close();
476                     stmt.close();
477                 }
478                 catch (SQLException e)
479                 {
480                     Log.error("MField.getDefault (" + m_vo.ColumnName + ") " + SQL, e);
481                 }
482             }
483             if (!defStr.equals(""))
484             {
485                 Log.trace(Log.l5_DData, "MField.getDefault [SQL] " + m_vo.ColumnName + "=" + defStr);
486                 return createDefault(defStr);
487             }
488         } // SQL Statement
489

490         /**
491          * (c) Preference (user) - P|
492          */

493         defStr = Env.getPreference (m_vo.ctx, m_vo.AD_Window_ID, m_vo.ColumnName, false);
494         if (!defStr.equals(""))
495         {
496             Log.trace(Log.l5_DData, "MField.getDefault [UserPreference] " + m_vo.ColumnName + "=" + defStr);
497             return createDefault(defStr);
498         }
499
500         /**
501          * (d) Field DefaultValue === similar code in AStartRPDialog.getDefault ===
502          */

503         if (!m_vo.DefaultValue.equals("") && !m_vo.DefaultValue.startsWith("@SQL="))
504         {
505             defStr = "";
506             // It is one or more variables/constants
507
StringTokenizer st = new StringTokenizer(m_vo.DefaultValue, ",;", false);
508             while (st.hasMoreTokens())
509             {
510                 defStr = st.nextToken().trim();
511                 if (defStr.equals("@SysDate@")) // System Time
512
return new Timestamp (System.currentTimeMillis());
513                 else if (defStr.indexOf('@') != -1) // it is a variable
514
defStr = Env.getContext(m_vo.ctx, m_vo.WindowNo, defStr.replace('@',' ').trim());
515                 else if (defStr.indexOf("'") != -1) // it is a 'String'
516
defStr = defStr.replace('\'', ' ').trim();
517
518                 if (!defStr.equals(""))
519                 {
520                     Log.trace(Log.l5_DData, "MField.getDefault [DefaultValue] " + m_vo.ColumnName + "=" + defStr);
521                     return createDefault(defStr);
522                  }
523             } // while more Tokens
524
} // Default value
525

526         /**
527          * (e) Preference (System) - # $
528          */

529         defStr = Env.getPreference (m_vo.ctx, m_vo.AD_Window_ID, m_vo.ColumnName, true);
530         if (!defStr.equals(""))
531         {
532             Log.trace(Log.l5_DData, "MField.getDefault [SystemPreference] " + m_vo.ColumnName + "=" + defStr);
533             return createDefault(defStr);
534         }
535
536         /**
537          * (f) DataType defaults
538          */

539
540         // Button to N
541
if (m_vo.displayType == DisplayType.Button && !m_vo.ColumnName.endsWith("_ID"))
542         {
543             Log.trace(Log.l5_DData, "MField.getDefault [Button=N] " + m_vo.ColumnName);
544             return "N";
545         }
546         // CheckBoxes default to No
547
if (m_vo.displayType == DisplayType.YesNo)
548         {
549             Log.trace(Log.l5_DData, "MField.getDefault [YesNo=N] " + m_vo.ColumnName);
550             return "N";
551         }
552         // lookups with one value
553
// if (DisplayType.isLookup(m_vo.displayType) && m_lookup.getSize() == 1)
554
// {
555
// /** @todo default if only one lookup value */
556
// }
557
// IDs remain null
558
if (m_vo.ColumnName.endsWith("_ID"))
559         {
560             Log.trace(Log.l5_DData, "MField.getDefault [ID=null] " + m_vo.ColumnName);
561             return null;
562         }
563         // actual Numbers default to zero
564
if (DisplayType.isNumeric(m_vo.displayType))
565         {
566             Log.trace(Log.l5_DData, "MField.getDefault [Number=0] " + m_vo.ColumnName);
567             return createDefault("0");
568         }
569
570         /**
571          * No resolution
572          */

573         Log.trace(Log.l5_DData, "MField.getDefault [NONE] " + m_vo.ColumnName);
574         return null;
575     } // getDefault
576

577     /**
578      * Create Default Object type.
579      * <pre>
580      * Integer (IDs)
581      * BigDecimal (Numbers)
582      * Timestamp (Dates)
583      * default: String
584      * </pre>
585      * @param value string
586      * @return type dependent converted object
587      */

588     private Object JavaDoc createDefault (String JavaDoc value)
589     {
590         // true NULL
591
if (value == null || value.toString().length() == 0)
592             return null;
593
594         try
595         {
596             // IDs
597
if (m_vo.ColumnName.endsWith("_ID"))
598                 return new Integer JavaDoc(value);
599             // Number
600
else if (DisplayType.isNumeric(m_vo.displayType))
601                 return new BigDecimal(value);
602             // Timestamps
603
if (DisplayType.isDate(m_vo.displayType))
604             {
605                 java.util.Date JavaDoc date = DisplayType.getDateFormat_JDBC().parse (value);
606                 return new Timestamp (date.getTime());
607             }
608             else
609                 return value;
610         }
611         catch (Exception JavaDoc e)
612         {
613             Log.error("MField.createDefault (" + m_vo.ColumnName + ") - " + e.getMessage());
614         }
615         return null;
616     } // createDefault
617

618     /**
619      * Validate initial Field Value.
620      * Called from MTab.dataNew and MTab.setCurrentRow when inserting
621      * @return true if valid
622      */

623     public boolean validateValue()
624     {
625         // null
626
if (m_value == null || m_value.toString().length() == 0)
627         {
628             if (isMandatory(true))
629             {
630                 m_error = true;
631                 return false;
632             }
633             else
634                 return true;
635         }
636         
637         // Search not cached
638
if (getDisplayType() == DisplayType.Search && m_lookup != null)
639         {
640             // need to re-set invalid values - OK BPartner in PO Line - not OK SalesRep in Invoice
641
if (m_lookup.getDirect(m_value, false, true) == null)
642             {
643                 Log.trace(8, "MField.validateValue " + m_vo.ColumnName + " Serach not valid - set to null");
644                 setValue(null, m_inserting);
645                 m_error = true;
646                 return false;
647             }
648             return true;
649         }
650
651         // cannot be validated
652
if (!isLookup()
653             || m_lookup.containsKey(m_value))
654             return true;
655         // it's not null, a lookup and does not have the key
656
if (isKey() || isParent()) // parents/ket are not validated
657
return true;
658             
659         Log.trace(8, "MField.validateValue " + m_vo.ColumnName + " - set to null");
660         setValue(null, m_inserting);
661         m_error = true;
662         return false;
663     } // validateValue
664

665
666     /*************************************************************************/
667
668     /**
669      * Is the Column Visible ?
670      * @param checkContext - check environment (requires correct row position)
671      * @return true, if visible
672      */

673     public boolean isDisplayed (boolean checkContext)
674     {
675         // ** static content **
676
// not displayed
677
if (!m_vo.IsDisplayed)
678             return false;
679         // no restrictions
680
if (m_vo.DisplayLogic.equals(""))
681             return true;
682
683         // ** dynamic content **
684
if (checkContext)
685         {
686             boolean retValue = evaluateLogic(m_vo.DisplayLogic);
687             Log.trace(9, "MField.isDisplayed", m_vo.ColumnName
688                 + " (" + m_vo.DisplayLogic + ") => " + retValue);
689             return retValue;
690         }
691         return true;
692     } // isDisplayed
693

694     /**
695      * Evaluate Logic and return true, if Field is displayed.
696      * <pre>
697      * format := <expression> [<logic> <expression>]
698      * expression := @<context>@<exLogic><value>
699      * logic := <|> | <&>
700      * exLogic := <=> | <!=>
701      *
702      * context := any global or window context
703      * value := strings can be with ' or "
704      * logic operators := AND or OR with the prevoius result from left to right
705      *
706      * Example '@AD_Table@=Test | @Language@=GERGER
707      * </pre>
708      * @param logic logic string
709      * @return locic result
710      */

711     private boolean evaluateLogic (String JavaDoc logic)
712     {
713         // Conditional
714
StringTokenizer st = new StringTokenizer(logic.trim(), "&|", true);
715         int it = st.countTokens();
716         if (((it/2) - ((it+1)/2)) == 0) // only uneven arguments
717
{
718             Log.error ("MField.evatuateLogic (" + getColumnName()
719                 + ") Logic does not comply with format "
720                 + "'<expression> [<logic> <expression>]' => " + logic);
721             return false;
722         }
723
724         boolean retValue = evaluateLogicTuple(st.nextToken());
725         while (st.hasMoreTokens())
726         {
727             String JavaDoc logOp = st.nextToken().trim();
728             boolean temp = evaluateLogicTuple(st.nextToken());
729             if (logOp.equals("&"))
730                 retValue = retValue & temp;
731             else if (logOp.equals("|"))
732                 retValue = retValue | temp;
733             else
734             {
735                 Log.error("MField.evaluateLogic (" + getColumnName()
736                     + ") Logic operant '|' or '&' expected => " + logic);
737                 return false;
738             }
739         } // hasMoreTokens
740
return retValue;
741     } // evaluateLogic
742

743     /**
744      * Evaluate @context@=value or @context@!value or @context@^value.
745      * <pre>
746      * value: strips ' and " always (no escape or mid stream)
747      * value: can also be a context variable
748      * </pre>
749      * @param logic logic touple
750      * @return true or false
751      */

752     private boolean evaluateLogicTuple (String JavaDoc logic)
753     {
754         StringTokenizer st = new StringTokenizer(logic.trim(), "!=^", true);
755         if (st.countTokens() != 3)
756         {
757             Log.error("MField.evaluateLogicTuple (" + getColumnName()
758                 + ") Logic touple does not comply with format "
759                 + "'@context@=value' or '@context@!value' => " + logic);
760             return false;
761         }
762         // Tag
763
String JavaDoc first = st.nextToken().trim(); // get '@tag@'
764
String JavaDoc firstEval = first.trim();
765         if (first.indexOf('@') != -1) // variable
766
{
767             first = first.replace ('@', ' ').trim (); // strip 'tag'
768
firstEval = Env.getContext (m_vo.ctx, m_vo.WindowNo, first, true); // replace with it's value
769
}
770         else // a constant
771
firstEval = firstEval.replace('\'', ' ').replace('"', ' ').trim(); // strip ' and "
772
// Comperator
773
String JavaDoc compare = st.nextToken();
774         // Value
775
String JavaDoc second = st.nextToken(); // get value
776
String JavaDoc secondEval = second.trim();
777         if (second.indexOf('@') != -1) // variable
778
{
779             second = second.replace('@', ' ').trim(); // strip tag
780
secondEval = Env.getContext(m_vo.ctx, m_vo.WindowNo, second, true); // replace with it's value
781
}
782         else // a constant
783
secondEval = secondEval.replace('\'', ' ').replace('"', ' ').trim(); // strip ' and "
784

785         // Handling of ID compare (null => 0)
786
if (first.indexOf("_ID") != -1 && firstEval.length() == 0)
787             firstEval = "0";
788         if (second.indexOf("_ID") != -1 && secondEval.length() == 0)
789             secondEval = "0";
790
791         // Logical Comparison
792
boolean result = firstEval.equals(secondEval);
793         if (!compare.equals("="))
794             result = !result;
795         //
796
if (Log.isTraceLevel(10))
797             Log.trace(10, "MField.evaluateLogicTuple - " + logic + "=> \"" + firstEval + "\" " + compare + " \"" + secondEval + "\" => " + result);
798         //
799
return result;
800     } // evaluateLogicTouple
801

802     /**
803      * Add Display Dependencies to given List.
804      * Source: DisplayLogic
805      * @param list list to be added to
806      */

807     public void addDependencies (ArrayList list)
808     {
809         // nothing to parse
810
if (!m_vo.IsDisplayed || m_vo.DisplayLogic.equals(""))
811             return;
812
813         StringTokenizer logic = new StringTokenizer(m_vo.DisplayLogic.trim(), "&|", false);
814
815         while (logic.hasMoreTokens())
816         {
817             StringTokenizer st = new StringTokenizer(logic.nextToken().trim(), "!=^", false);
818             while (st.hasMoreTokens())
819             {
820                 String JavaDoc tag = st.nextToken().trim(); // get '@tag@'
821
// Do we have a @variable@ ?
822
if (tag.indexOf('@') != -1)
823                 {
824                     tag = tag.replace('@', ' ').trim(); // strip 'tag'
825
// Add columns (they might not be a column, but then it is static)
826
if (!list.contains(tag))
827                         list.add(tag);
828                 }
829             }
830         }
831     } // addDependencies
832

833     /*************************************************************************/
834
835     /**
836      * Get Column Name
837      * @return column name
838      */

839     public String JavaDoc getColumnName()
840     {
841         return m_vo.ColumnName;
842     }
843     public String JavaDoc getHeader()
844     {
845         return m_vo.Header;
846     }
847     public int getDisplayType()
848     {
849         return m_vo.displayType;
850     }
851     public int getAD_Window_ID()
852     {
853         return m_vo.AD_Window_ID;
854     }
855     public int getWindowNo()
856     {
857         return m_vo.WindowNo;
858     }
859     public int getAD_Column_ID()
860     {
861         return m_vo.AD_Column_ID;
862     }
863     public int getDisplayLength()
864     {
865         return m_vo.DisplayLength;
866     }
867     public boolean isSameLine()
868     {
869         return m_vo.IsSameLine;
870     }
871     public boolean isDisplayed()
872     {
873         return m_vo.IsDisplayed;
874     }
875     public String JavaDoc getDisplayLogic()
876     {
877         return m_vo.DisplayLogic;
878     }
879     public String JavaDoc getDefaultValue()
880     {
881         return m_vo.DefaultValue;
882     }
883     public boolean isReadOnly()
884     {
885         return m_vo.IsReadOnly;
886     }
887     public boolean isUpdateable()
888     {
889         return m_vo.IsUpdateable;
890     }
891     public boolean isHeading()
892     {
893         return m_vo.IsHeading;
894     }
895     public boolean isFieldOnly()
896     {
897         return m_vo.IsFieldOnly;
898     }
899     public boolean isEncryptedField()
900     {
901         return m_vo.IsEncryptedField;
902     }
903     public boolean isSelectionColumn()
904     {
905         return m_vo.IsSelectionColumn;
906     }
907     public int getSortNo()
908     {
909         return m_vo.SortNo;
910     }
911     public int getFieldLength()
912     {
913         return m_vo.FieldLength;
914     }
915     public String JavaDoc getVFormat()
916     {
917         return m_vo.VFormat;
918     }
919     public String JavaDoc getValueMin()
920     {
921         return m_vo.ValueMin;
922     }
923     public String JavaDoc getValueMax()
924     {
925         return m_vo.ValueMax;
926     }
927     public String JavaDoc getFieldGroup()
928     {
929         return m_vo.FieldGroup;
930     }
931     public boolean isKey()
932     {
933         return m_vo.IsKey;
934     }
935     public boolean isParent()
936     {
937         if (m_parentChecked || m_vo.IsParent)
938             return m_vo.IsParent;
939         if (!DisplayType.isID(m_vo.displayType))
940         {
941             m_parentChecked = true;
942             return false;
943         }
944         String JavaDoc LinkColumnName = Env.getContext(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "LinkColumnName");
945         m_vo.IsParent = m_vo.ColumnName.equals(LinkColumnName);
946         if (m_vo.IsParent)
947             Log.trace(9, "MField.isParent - " + m_vo.IsParent
948                 + " - Link(" + LinkColumnName + ", W=" + m_vo.WindowNo + ",T=" + m_vo.TabNo
949                 + ") = " + m_vo.ColumnName);
950         return m_vo.IsParent;
951     }
952     public String JavaDoc getCallout()
953     {
954         return m_vo.Callout;
955     }
956     public int getAD_Process_ID()
957     {
958         return m_vo.AD_Process_ID;
959     }
960     public String JavaDoc getDescription()
961     {
962         return m_vo.Description;
963     }
964     public String JavaDoc getHelp()
965     {
966         return m_vo.Help;
967     }
968     public MFieldVO getVO()
969     {
970         return m_vo;
971     }
972
973     /**
974      * Is this a long (string/text) field (over 46/2=23 characters)
975      * @return true if long field
976      */

977     public boolean isLongField()
978     {
979         if (m_vo.displayType == DisplayType.String
980             || m_vo.displayType == DisplayType.Text
981             || m_vo.displayType == DisplayType.Memo
982             || m_vo.displayType == DisplayType.TextLong
983             || m_vo.displayType == DisplayType.Image)
984             return (m_vo.DisplayLength >= MAXDISPLAY_LENGTH/2);
985         return false;
986     } // isLongField
987

988     /**
989      * Set Value to null.
990      * <p>
991      * Do not update context
992      * Send Bean PropertyChange if there is a change
993      */

994     public void setValue ()
995     {
996     // Log.trace(Log.l5_DData, "MField.setValue - " + ColumnName + "=" + newValue);
997
if (m_setOldValue) // set the old value
998
m_oldValue = m_value;
999         m_value = null;
1000        m_inserting = false;
1001        m_error = false; // reset error
1002

1003        // Does not fire, if same value
1004
m_propertyChangeListeners.firePropertyChange(PROPERTY, m_oldValue, null);
1005    // m_propertyChangeListeners.firePropertyChange(PROPERTY, s_oldValue, null);
1006
} // setValue
1007

1008
1009    /**
1010     * Set Value.
1011     * <p>
1012     * Update context, if not text or RowID;
1013     * Send Bean PropertyChange if there is a change
1014     * @param newValue new value
1015     * @param inserting true if inserting
1016     */

1017    public void setValue (Object JavaDoc newValue, boolean inserting)
1018    {
1019    // Log.trace(Log.l5_DData, "MField.setValue - " + ColumnName + "=" + newValue);
1020
if (m_setOldValue) // set the old value
1021
m_oldValue = m_value;
1022        m_value = newValue;
1023        m_inserting = inserting;
1024        m_error = false; // reset error
1025

1026        //
1027
if (m_vo.displayType == DisplayType.Text || m_vo.displayType == DisplayType.RowID)
1028            ;
1029        else
1030            Env.setContext(m_vo.ctx, m_vo.WindowNo, m_vo.ColumnName, m_value==null ? null : m_value.toString());
1031        // Does not fire, if same value
1032
m_propertyChangeListeners.firePropertyChange(PROPERTY, inserting ? INSERTING : m_oldValue, newValue);
1033    } // setValue
1034

1035    /**
1036     * Get Value
1037     * @return current value
1038     */

1039    public Object JavaDoc getValue()
1040    {
1041        return m_value;
1042    } // getValue
1043

1044    /**
1045     * Set old/previous Value.
1046     * Used by VColor
1047     * @param value if false property change will always be fires
1048     */

1049    public void setOldValue (boolean value)
1050    {
1051        m_setOldValue = value;
1052    } // setOldValue
1053

1054    /**
1055     * Get old/previous Value
1056     * @return old value
1057     */

1058    public Object JavaDoc getOldValue()
1059    {
1060        return m_oldValue;
1061    } // getOldValue
1062

1063    /**
1064     * Set Error Value (the value, which cuased some Error)
1065     * @param errorValue error message
1066     */

1067    public void setErrorValue (String JavaDoc errorValue)
1068    {
1069        m_errorValue = errorValue;
1070        m_errorValueFlag = true;
1071    } // setErrorValue
1072

1073    /**
1074     * Get Error Value (the value, which cuased some Error) <b>AND</b> reset it to null
1075     * @return error value
1076     */

1077    public String JavaDoc getErrorValue ()
1078    {
1079        String JavaDoc s = m_errorValue;
1080        m_errorValue = null;
1081        m_errorValueFlag = false;
1082        return s;
1083    } // getErrorValue
1084

1085    /**
1086     * Return true, if value has Error (for HTML interface) <b>AND</b> reset it to false
1087     * @return has error
1088     */

1089    public boolean isErrorValue()
1090    {
1091        boolean b = m_errorValueFlag;
1092        m_errorValueFlag = false;
1093        return b;
1094    } // isErrorValue
1095

1096    /**
1097     * Overwrite default DisplayLength
1098     * @param length new length
1099     */

1100    public void setDisplayLength (int length)
1101    {
1102        m_vo.DisplayLength = length;
1103    } // setDisplayLength
1104

1105    /**
1106     * Overwrite Displayed
1107     * @param displayed trie if displayed
1108     */

1109    public void setDisplayed (boolean displayed)
1110    {
1111        m_vo.IsDisplayed = displayed;
1112    } // setDisplayed
1113

1114    /**
1115     * toString
1116     * @return string representation
1117     */

1118    public String JavaDoc toString()
1119    {
1120        StringBuffer JavaDoc sb = new StringBuffer JavaDoc("MField[");
1121        sb.append(m_vo.ColumnName).append("=").append(m_value).append("]");
1122        return sb.toString();
1123    } // toString
1124

1125    /*************************************************************************/
1126
1127    /**
1128     * Remove Property Change Listener
1129     * @param l listener
1130     */

1131    public synchronized void removePropertyChangeListener(PropertyChangeListener l)
1132    {
1133        m_propertyChangeListeners.removePropertyChangeListener(l);
1134    }
1135
1136    /**
1137     * Add Property Change Listener
1138     * @param l listener
1139     */

1140    public synchronized void addPropertyChangeListener(PropertyChangeListener l)
1141    {
1142        m_propertyChangeListeners.addPropertyChangeListener(l);
1143    }
1144} // MField
1145
Popular Tags