📄 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 Smart Business Solution. The Initial
* Developer of the Original Code is Jorg Janke. Portions created by Jorg Janke
* are Copyright (C) 1999-2005 Jorg Janke.
* All parts are Copyright (C) 1999-2005 ComPiere, Inc. All Rights Reserved.
* Contributor(s): ______________________________________.
*****************************************************************************/
package org.compiere.model;
import java.beans.*;
import java.io.*;
import java.math.*;
import java.sql.*;
import java.util.*;
import java.util.logging.*;
import org.compiere.util.*;
/**
* 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.88 2006/01/23 04:54:49 jjanke Exp $
*/
public final class MField
implements Serializable, Evaluatee
{
/**
* 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.fine( "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 = 60 */
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_valueNoFire = true;
/** Error Status */
private boolean m_error = false;
/** Parent Check */
private boolean m_parentChecked = 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;
/** Logger */
private static CLogger log = CLogger.getCLogger(MField.class);
/**************************************************************************
* Set Lookup for columns with lookup
*/
public void loadLookup()
{
if (!isLookup())
return;
log.config("(" + m_vo.ColumnName + ")");
if (DisplayType.isLookup(m_vo.displayType))
{
if (m_vo.lookupInfo == null)
{
log.log(Level.SEVERE, "(" + m_vo.ColumnName + ") - No LookupInfo");
return;
}
// Prevent loading of CreatedBy/UpdatedBy
if (m_vo.displayType == DisplayType.Table
&& (m_vo.ColumnName.equals("CreatedBy") || m_vo.ColumnName.equals("UpdatedBy")) )
m_vo.lookupInfo.IsCreadedUpdatedBy = true;
//
m_vo.lookupInfo.IsKey = isKey();
MLookup ml = new MLookup (m_vo.lookupInfo, m_vo.TabNo);
m_lookup = ml;
}
else if (m_vo.displayType == DisplayType.Location) // not cached
{
MLocationLookup ml = new MLocationLookup (m_vo.ctx, m_vo.WindowNo);
m_lookup = ml;
}
else if (m_vo.displayType == DisplayType.Locator)
{
MLocatorLookup ml = new MLocatorLookup (m_vo.ctx, m_vo.WindowNo);
m_lookup = ml;
}
else if (m_vo.displayType == DisplayType.Account) // not cached
{
MAccountLookup ma = new MAccountLookup (m_vo.ctx, m_vo.WindowNo);
m_lookup = ma;
}
else if (m_vo.displayType == DisplayType.PAttribute) // not cached
{
MPAttributeLookup pa = new MPAttributeLookup (m_vo.ctx, m_vo.WindowNo);
m_lookup = pa;
}
} // 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
|| m_vo.displayType == DisplayType.PAttribute)
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.fine("(" + 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<String> getDependentOn()
{
ArrayList<String> list = new ArrayList<String>();
// Display
parseDepends(list, m_vo.DisplayLogic);
parseDepends(list, m_vo.ReadOnlyLogic);
// Lookup
if (m_lookup != null)
parseDepends(list, m_lookup.getValidation());
//
if (list.size() > 0 && CLogMgt.isLevelFiner())
{
StringBuffer sb = new StringBuffer();
for (int i = 0; i < list.size(); i++)
sb.append(list.get(i)).append(" ");
log.finer("(" + 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<String> list, String parseString)
{
if (parseString == null || parseString.length() == 0)
return;
// log.fine( "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.fine( 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 || isVirtualColumn())
return false;
// Numeric Keys and Created/Updated as well as
// DocumentNo/Value/ASI ars not mandatory (persistency layer manages them)
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")
|| m_vo.ColumnName.equals("M_AttributeSetInstance_ID")) // 0 is valid
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)
{
if (isVirtualColumn())
return false;
// Fields always enabled (are usually not updateable)
if (m_vo.ColumnName.equals("Posted")
|| (m_vo.ColumnName.equals("Record_ID") && m_vo.displayType == DisplayType.Button)) // Zoom
return true;
// Fields always updareable
if (m_vo.IsAlwaysUpdateable) // Zoom
return true;
// Tab or field is R/O
if (m_vo.tabReadOnly || m_vo.IsReadOnly)
{
log.finest(m_vo.ColumnName + " NO - TabRO=" + m_vo.tabReadOnly + ", FieldRO=" + m_vo.IsReadOnly);
return false;
}
// Not Updateable - only editable if new updateable row
if (!m_vo.IsUpdateable && !m_inserting)
{
log.finest(m_vo.ColumnName + " NO - FieldUpdateable=" + m_vo.IsUpdateable);
return false;
}
// Field is the Link Column of the tab
if (m_vo.ColumnName.equals(Env.getContext(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "LinkColumnName")))
{
log.finest(m_vo.ColumnName + " NO - LinkColumn");
return false;
}
// Role Access & Column Access
if (checkContext)
{
int AD_Client_ID = Env.getContextAsInt(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "AD_Client_ID");
int AD_Org_ID = Env.getContextAsInt(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "AD_Org_ID");
String keyColumn = Env.getContext(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, "KeyColumnName");
int Record_ID = Env.getContextAsInt(m_vo.ctx, m_vo.WindowNo, m_vo.TabNo, keyColumn);
int AD_Table_ID = m_vo.AD_Table_ID;
if (!MRole.getDefault(m_vo.ctx, false).canUpdate(
AD_Client_ID, AD_Org_ID, AD_Table_ID, Record_ID, false))
return false;
if (!MRole.getDefault(m_vo.ctx, false).isColumnAccess(AD_Table_ID, m_vo.AD_Column_ID, false))
return false;
}
// Do we have a readonly rule
if (checkContext && m_vo.ReadOnlyLogic.length() > 0)
{
boolean retValue = !Evaluator.evaluateLogic(this, m_vo.ReadOnlyLogic);
log.finest(m_vo.ColumnName + " R/O(" + m_vo.ReadOnlyLogic + ") => R/W-" + retValue);
if (!retValue)
return false;
}
// Always editable if Active
if (m_vo.ColumnName.equals("Processing")
|| m_vo.ColumnName.equals("PaymentRule")
|| m_vo.ColumnName.equals("DocAction")
|| m_vo.ColumnName.equals("GenerateTo"))
return true;
// Record is Processed ***
if (checkContext && Env.getContext(m_vo.ctx, m_vo.WindowNo, "Processed").equals("Y"))
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;
// 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -