📄 mfield.java
字号:
/******************************************************************************
* The contents of this file are subject to the Compiere License Version 1.1
* ("License"); You may not use this file except in compliance with the License
* You may obtain a copy of the License at http://www.compiere.org/license.html
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
* The Original Code is Compiere ERP & CRM Business Solution
* The Initial Developer of the Original Code is Jorg Janke and ComPiere, Inc.
* Portions created by Jorg Janke are Copyright (C) 1999-2001 Jorg Janke, parts
* created by ComPiere are Copyright (C) ComPiere, Inc.; All Rights Reserved.
* Contributor(s): ______________________________________.
*****************************************************************************/
package org.compiere.model;
import java.awt.*;
import java.sql.*;
import java.util.*;
import java.math.*;
import java.beans.*;
import java.io.*;
import org.compiere.util.*;
import org.compiere.plaf.CompierePLAF;
/**
* Field Model
* <p>
* Fields are a combination of AD_Field (the display attributes)
* and AD_Column (the storage attributes).
* <p>
* The Field maintains the current edited value. If the value is changed,
* it fire PropertyChange "FieldValue".
* If the background is changed the PropertyChange "FieldAttribute" is fired.
* <br>
* Usually editors listen to their fields.
*
* @author Jorg Janke
* @version $Id: MField.java,v 1.36 2003/04/29 09:30:05 jpedersen Exp $
*/
public final class MField implements Serializable
{
/**
* Field Constructor.
* requires initField for complete instatanciation
* @param vo ValueObjecy
*/
public MField (MFieldVO vo)
{
m_vo = vo;
// Set Attributes
loadLookup();
setError(false);
} // MField
/** Value Object */
private MFieldVO m_vo;
/**
* Dispose
*/
protected void dispose()
{
// Log.trace(Log.l5_DData, "MField.dispose = " + m_vo.ColumnName);
m_propertyChangeListeners = null;
if (m_lookup != null)
m_lookup.dispose();
m_lookup = null;
m_vo.lookupInfo = null;
m_vo = null;
} // dispose
/** Lookup for this field */
private Lookup m_lookup = null;
/** New Row / inserting */
private boolean m_inserting = false;
/** Max Display Length */
public static final int MAXDISPLAY_LENGTH = 60;
/** The current value */
private Object m_value = null;
/** The old to force Property Change */
private static Object s_oldValue = new Object();
/** The old/previous value */
private Object m_oldValue = s_oldValue;
/** Only fire Property Change if old value really changed */
private boolean m_setOldValue = true;
/** Error Status */
private boolean m_error = false;
/** Property Change */
private PropertyChangeSupport m_propertyChangeListeners = new PropertyChangeSupport(this);
/** PropertyChange Name */
public static final String PROPERTY = "FieldValue";
/** Indicator for new Value */
public static final String INSERTING = "FieldValueInserting";
/** Error Value for HTML interface */
private String m_errorValue = null;
/** Error Value indicator for HTML interface */
private boolean m_errorValueFlag = false;
/*************************************************************************/
/**
* Set Lookup for columns with lookup
*/
public void loadLookup()
{
if (!isLookup())
return;
Log.trace(Log.l5_DData, "MField.loadLookup (" + m_vo.ColumnName + ")");
if (DisplayType.isLookup(m_vo.displayType))
{
if (m_vo.lookupInfo == null)
{
Log.error("MField.loadLookup - No LookupInfo");
return;
}
MLookup ml = new MLookup (m_vo.lookupInfo, m_vo.TabNo);
m_lookup = ml;
}
else if (m_vo.displayType == DisplayType.Location) // not cached
{
MLocation ml = new MLocation (m_vo.ctx, m_vo.WindowNo);
m_lookup = ml;
}
else if (m_vo.displayType == DisplayType.Locator)
{
MLocator ml = new MLocator (m_vo.ctx, m_vo.WindowNo);
m_lookup = ml;
}
else if (m_vo.displayType == DisplayType.Account) // not cached
{
MAccount ma = new MAccount (m_vo.ctx, m_vo.WindowNo);
m_lookup = ma;
}
} // m_lookup
/**
* Wait until Load is complete
*/
public void lookupLoadComplete()
{
if (m_lookup == null)
return;
m_lookup.loadComplete();
} // loadCompete
/**
* Get Lookup, may return null
* @return lookup
*/
public Lookup getLookup()
{
return m_lookup;
} // getLookup
/**
* Is this field a Lookup?.
* @return true if lookup field
*/
public boolean isLookup()
{
boolean retValue = false;
if (m_vo.IsKey)
retValue = false;
// else if (m_vo.ColumnName.equals("CreatedBy") || m_vo.ColumnName.equals("UpdatedBy"))
// retValue = false;
else if (DisplayType.isLookup(m_vo.displayType))
retValue = true;
else if (m_vo.displayType == DisplayType.Location
|| m_vo.displayType == DisplayType.Locator
|| m_vo.displayType == DisplayType.Account)
retValue = true;
return retValue;
} // isLookup
/**
* Refresh Lookup if the lookup is unstable
* @return true if lookup is validated
*/
public boolean refreshLookup()
{
// if there is a validation string, the lookup is unstable
if (m_lookup == null || m_lookup.getValidation().length() == 0)
return true;
//
Log.trace(Log.l5_DData, "MField.refreshLookup (" + m_vo.ColumnName + ")");
m_lookup.refresh();
return m_lookup.isValidated();
} // refreshLookup
/**
* Get a list of fields, this field is dependent on.
* - for display purposes or
* - for lookup purposes
* @return ArrayList
*/
public ArrayList getDependentOn()
{
ArrayList list = new ArrayList();
// Display
parseDepends(list, m_vo.DisplayLogic);
// Lookup
if (m_lookup != null)
parseDepends(list, m_lookup.getValidation());
//
if (list.size() > 0 && Log.getTraceLevel() > Log.l5_DData)
{
StringBuffer sb = new StringBuffer();
for (int i = 0; i < list.size(); i++)
sb.append(list.get(i)).append(" ");
Log.trace(Log.l6_Database, "MField.getDependentOn (" + m_vo.ColumnName + ")",
sb.toString());
}
return list;
} // getDependentOn
/**
* Parse String and add variables with @ to the list.
* @param list list to be added to
* @param parseString string to parse for variables
*/
private void parseDepends (ArrayList list, String parseString)
{
if (parseString == null || parseString.length() == 0)
return;
// Log.trace(Log.l5_DData, "MField.parseDepends", parseString);
String s = parseString;
// while we have variables
while (s.indexOf("@") != -1)
{
int pos = s.indexOf("@");
s = s.substring(pos+1);
pos = s.indexOf("@");
if (pos == -1)
continue; // error number of @@ not correct
String variable = s.substring(0, pos);
s = s.substring(pos+1);
// Log.trace(Log.l6_Database, variable);
list.add(variable);
}
} // parseDepends
/*************************************************************************/
/**
* Set Error.
* Used by editors to set the color
* @param error true if error
*/
public void setError (boolean error)
{
m_error = error;
} // setBackground
/**
* Get Background Error.
* @return error
*/
public boolean isError()
{
return m_error;
} // isError
/**
* Is it Mandatory to enter for user?
* Mandatory checking is dome in MTable.getMandatory
* @param checkContext - check environment (requires correct row position)
* @return true if mandatory
*/
public boolean isMandatory (boolean checkContext)
{
// Not mandatory
if (!m_vo.IsMandatory)
return false;
// Numeric Keys and Created/Updated as well as DocumentNo/Value ars not mandatory
if ((m_vo.IsKey && m_vo.ColumnName.endsWith("_ID"))
|| m_vo.ColumnName.startsWith("Created") || m_vo.ColumnName.startsWith("Updated")
|| m_vo.ColumnName.equals("Value") || m_vo.ColumnName.equals("DocumentNo"))
return false;
// Mandatory if displayed
return isDisplayed (checkContext);
} // isMandatory
/**
* Is it Editable - checks IsActive, IsUpdateable, and isDisplayed
* @param checkContext if true checks Context for Active, IsProcessed, LinkColumn
* @return true, if editable
*/
public boolean isEditable (boolean checkContext)
{
// Fields always enabled
if (m_vo.ColumnName.equals("Record_ID") // Zoom
|| m_vo.ColumnName.equals("Posted"))
return true;
// Do we have a readonly rule
if (m_vo.ReadOnlyLogic.length() > 0 && checkContext && evaluateLogic(m_vo.ReadOnlyLogic))
return false;
// Tab or field is R/O
if (m_vo.tabReadOnly || m_vo.IsReadOnly)
return false;
// only editable if new updateable row
if (!m_vo.IsUpdateable && !m_inserting)
return false;
// IsActive field is editable, if record not processed
if (m_vo.ColumnName.equals("IsActive"))
return true;
// Record is not active
if (checkContext && !Env.getContext(m_vo.ctx, m_vo.WindowNo, "IsActive").equals("Y"))
return false;
// fields always editable when record active
if (m_vo.ColumnName.equals("Processing")
|| m_vo.ColumnName.equals("PaymentRule")
|| m_vo.ColumnName.equals("DocAction")
|| m_vo.ColumnName.equals("GenerateTo"))
return true;
// Special fields allowed to change in Order/Invoice
if (m_vo.AD_Column_ID == 2174 // Order.Description
|| m_vo.AD_Column_ID == 3045 // Order.POReference
|| m_vo.AD_Column_ID == 3782 // Invoice.POReference
|| m_vo.AD_Column_ID == 3785) // Invoice.POReference
return true;
// Record is processed
if (checkContext && Env.getContext(m_vo.ctx, m_vo.WindowNo, "Processed").equals("Y"))
return false;
// if field is the Link Column of the tab
if (checkContext && m_vo.ColumnName.equals(Env.getContext(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "LinkColumnName")))
return false;
// ultimately visibily decides
return isDisplayed (checkContext);
} // isEditable
/**
* Set Inserting (allows to enter not updateable fields).
* Reset when setting the Field Value
* @param inserting true if inserting
*/
public void setInserting (boolean inserting)
{
m_inserting = inserting;
} // setInserting
/*************************************************************************/
/**
* Create default value.
* <pre>
* (a) Key/Parent/IsActive/SystemAccess
* (b) SQL Default
* (c) User Preference
* (d) Column Default
* (e) System Preference
* (f) DataType Defaults
*
* Don't default from Context => use explicit defaultValue
* (would otherwise copy previous record)
* </pre>
* @return default value or null
*/
public Object getDefault()
{
/**
* (a) Key/Parent/IsActive/SystemAccess
*/
// No defaults for these fields
if (m_vo.IsKey || m_vo.displayType == DisplayType.Binary)
return null;
// Set Parent to context
if (m_vo.IsParent || m_vo.ColumnName.equals(Env.getContext(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "LinkColumnName")))
{
String parent = Env.getContext(m_vo.ctx, m_vo.WindowNo, m_vo.ColumnName);
Log.trace(Log.l5_DData, "MField.getDefault [Parent] " + m_vo.ColumnName + "=" + parent);
return createDefault(parent);
}
// Always Active
if (m_vo.ColumnName.equals("IsActive"))
{
Log.trace(Log.l5_DData, "MField.getDefault [IsActive] " + m_vo.ColumnName + "=Y");
return "Y";
}
// Set Client & Org to System, if System access
if (Access.l4_System.equals(Env.getContext(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "AccessLevel"))
&& (m_vo.ColumnName.equals("AD_Client_ID") || m_vo.ColumnName.equals("AD_Org_ID")))
{
Log.trace(Log.l5_DData, "MField.getDefault [SystemAccess] " + m_vo.ColumnName + "=0");
return new Integer(0);
}
// Set Org to System, if Client access
else if (Access.l6_SystemClient.equals(Env.getContext(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "AccessLevel"))
&& m_vo.ColumnName.equals("AD_Org_ID"))
{
Log.trace(Log.l5_DData, "MField.getDefault [ClientAccess] " + m_vo.ColumnName + "=0");
return new Integer(0);
}
/**
* (b) SQL Statement (for data integity & consistency)
*/
String defStr = "";
if (m_vo.DefaultValue.startsWith("@SQL="))
{
String SQL = m_vo.DefaultValue.substring(5); // w/o tag
SQL = Env.parseContext(m_vo.ctx, m_vo.WindowNo, SQL, false); // replace variables
if (SQL.equals(""))
{
Log.error("MField.getDefault - Default SQL variable parse failed: "
+ m_vo.DefaultValue);
}
else
{
try
{
PreparedStatement stmt = DB.prepareStatement(SQL);
ResultSet rs = stmt.executeQuery();
if (rs.next())
defStr = rs.getString("DefaultValue");
else
Log.error("MField.getDefault SQL - no Result");
rs.close();
stmt.close();
}
catch(SQLException e)
{
Log.error("CField.getDefault SQL - no Result");
}
}
if (!defStr.equals(""))
{
Log.trace(Log.l5_DData, "MField.getDefault [SQL] " + m_vo.ColumnName + "=" + defStr);
return createDefault(defStr);
}
} // SQL Statement
/**
* (c) Preference (user) - P|
*/
defStr = Env.getPreference (m_vo.ctx, m_vo.AD_Window_ID, m_vo.ColumnName, false);
if (!defStr.equals(""))
{
Log.trace(Log.l5_DData, "MField.getDefault [UserPreference] " + m_vo.ColumnName + "=" + defStr);
return createDefault(defStr);
}
/**
* (d) Field DefaultValue === similar code in AStartRPDialog.getDefault ===
*/
if (!m_vo.DefaultValue.equals("") && !m_vo.DefaultValue.startsWith("@SQL="))
{
defStr = "";
// It is one or more variables/constants
StringTokenizer st = new StringTokenizer(m_vo.DefaultValue, ",;", false);
while (st.hasMoreTokens())
{
defStr = st.nextToken().trim();
if (defStr.equals("@SysDate@")) // System Time
return new Timestamp (System.currentTimeMillis());
else if (defStr.indexOf('@') != -1) // it is a variable
defStr = Env.getContext(m_vo.ctx, m_vo.WindowNo, defStr.replace('@',' ').trim());
else if (defStr.indexOf("'") != -1) // it is a 'String'
defStr = defStr.replace('\'', ' ').trim();
if (!defStr.equals(""))
{
Log.trace(Log.l5_DData, "MField.getDefault [DefaultValue] " + m_vo.ColumnName + "=" + defStr);
return createDefault(defStr);
}
} // while more Tokens
} // Default value
/**
* (e) Preference (System) - # $
*/
defStr = Env.getPreference (m_vo.ctx, m_vo.AD_Window_ID, m_vo.ColumnName, true);
if (!defStr.equals(""))
{
Log.trace(Log.l5_DData, "MField.getDefault [SystemPreference] " + m_vo.ColumnName + "=" + defStr);
return createDefault(defStr);
}
/**
* (f) DataType defaults
*/
// Button to N
if (m_vo.displayType == DisplayType.Button && !m_vo.ColumnName.endsWith("_ID"))
{
Log.trace(Log.l5_DData, "MField.getDefault [Button=N] " + m_vo.ColumnName);
return "N";
}
// CheckBoxes default to No
if (m_vo.displayType == DisplayType.YesNo)
{
Log.trace(Log.l5_DData, "MField.getDefault [YesNo=N] " + m_vo.ColumnName);
return "N";
}
// lookups with one value
// if (DisplayType.isLookup(m_vo.displayType) && m_lookup.getSize() == 1)
// {
// /** @todo default if only one lookup value */
// }
// IDs remain null
if (m_vo.ColumnName.endsWith("_ID"))
{
Log.trace(Log.l5_DData, "MField.getDefault [ID=null] " + m_vo.ColumnName);
return null;
}
// actual Numbers default to zero
if (DisplayType.isNumeric(m_vo.displayType))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -