Modified: 
ofbiz/trunk/framework/widget/src/org/ofbiz/widget/form/ModelFormField.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/form/ModelFormField.java?rev=1647936&r1=1647935&r2=1647936&view=diff
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/form/ModelFormField.java 
(original)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/form/ModelFormField.java 
Fri Dec 26 06:47:13 2014
@@ -24,6 +24,7 @@ import java.sql.Timestamp;
 import java.text.DateFormat;
 import java.text.NumberFormat;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.LinkedList;
@@ -58,14 +59,7 @@ import org.ofbiz.entity.GenericValue;
 import org.ofbiz.entity.condition.EntityCondition;
 import org.ofbiz.entity.finder.EntityFinderUtil;
 import org.ofbiz.entity.model.ModelEntity;
-import org.ofbiz.entity.model.ModelField;
-import org.ofbiz.entity.model.ModelReader;
-import org.ofbiz.entity.util.EntityQuery;
 import org.ofbiz.entity.util.EntityUtil;
-import org.ofbiz.service.DispatchContext;
-import org.ofbiz.service.GenericServiceException;
-import org.ofbiz.service.ModelParam;
-import org.ofbiz.service.ModelService;
 import org.ofbiz.widget.ModelFieldVisitor;
 import org.ofbiz.widget.WidgetWorker;
 import org.ofbiz.widget.form.ModelForm.UpdateArea;
@@ -75,534 +69,129 @@ import bsh.EvalError;
 import bsh.Interpreter;
 
 /**
- * Widget Library - Form model class
+ * Models the <field> element.
+ * 
+ * @see <code>widget-form.xsd</code>
  */
 public class ModelFormField {
 
-    public static final String module = ModelFormField.class.getName();
-
-    protected ModelForm modelForm;
-
-    protected String name;
-    protected FlexibleMapAccessor<Map<String, ? extends Object>> mapAcsr;
-    protected String entityName;
-    protected String serviceName;
-    protected FlexibleMapAccessor<Object> entryAcsr;
-    protected String parameterName;
-    protected String fieldName;
-    protected String attributeName;
-    protected FlexibleStringExpander title;
-    protected FlexibleStringExpander tooltip;
-    protected String titleAreaStyle;
-    protected String widgetAreaStyle;
-    protected String titleStyle;
-    protected String widgetStyle;
-    protected String tooltipStyle;
-    protected String requiredFieldStyle;
-    protected String sortFieldStyle;
-    protected String sortFieldAscStyle;
-    protected String sortFieldDescStyle;
-    protected Integer position = null;
-    protected String redWhen;
-    protected FlexibleStringExpander useWhen;
-    protected boolean encodeOutput = true;
-    protected String event;
-    protected FlexibleStringExpander action;
-
-    protected FieldInfo fieldInfo = null;
-    protected String idName;
-    protected boolean separateColumn = false;
-    protected Boolean requiredField = null;
-    protected Boolean sortField = null;
-    protected String sortFieldHelpText = "";
-    protected String headerLink;
-    protected String headerLinkStyle;
-
-    /** On Change Event areas to be updated. */
-    protected List<UpdateArea> onChangeUpdateAreas;
-    /** On Click Event areas to be updated. */
-    protected List<UpdateArea> onClickUpdateAreas;
-
-    // ===== CONSTRUCTORS =====
-    /** Default Constructor */
-    public ModelFormField(ModelForm modelForm) {
-        this.modelForm = modelForm;
-    }
-
-    /** XML Constructor */
-    public ModelFormField(Element fieldElement, ModelForm modelForm, 
ModelReader entityModelReader,
-            DispatchContext dispatchContext) {
-        this.modelForm = modelForm;
-        this.name = fieldElement.getAttribute("name");
-        this.setMapName(fieldElement.getAttribute("map-name"));
-        this.entityName = fieldElement.getAttribute("entity-name");
-        this.serviceName = fieldElement.getAttribute("service-name");
-        
this.setEntryName(UtilXml.checkEmpty(fieldElement.getAttribute("entry-name"), 
this.name));
-        this.parameterName = 
UtilXml.checkEmpty(fieldElement.getAttribute("parameter-name"), this.name);
-        this.fieldName = 
UtilXml.checkEmpty(fieldElement.getAttribute("field-name"), this.name);
-        this.attributeName = 
UtilXml.checkEmpty(fieldElement.getAttribute("attribute-name"), this.name);
-        this.setTitle(fieldElement.hasAttribute("title") ? 
fieldElement.getAttribute("title") : null);
-        this.setTooltip(fieldElement.getAttribute("tooltip"));
-        this.titleAreaStyle = fieldElement.getAttribute("title-area-style");
-        this.widgetAreaStyle = fieldElement.getAttribute("widget-area-style");
-        this.titleStyle = fieldElement.getAttribute("title-style");
-        this.widgetStyle = fieldElement.getAttribute("widget-style");
-        this.tooltipStyle = fieldElement.getAttribute("tooltip-style");
-        this.requiredFieldStyle = 
fieldElement.getAttribute("required-field-style");
-        this.sortFieldStyle = fieldElement.getAttribute("sort-field-style");
-        this.sortFieldAscStyle = 
fieldElement.getAttribute("sort-field-asc-style");
-        this.sortFieldDescStyle = 
fieldElement.getAttribute("sort-field-desc-style");
-        this.redWhen = fieldElement.getAttribute("red-when");
-        this.setUseWhen(fieldElement.getAttribute("use-when"));
-        this.encodeOutput = 
!"false".equals(fieldElement.getAttribute("encode-output"));
-        this.event = fieldElement.getAttribute("event");
-        this.setAction(fieldElement.hasAttribute("action") ? 
fieldElement.getAttribute("action") : null);
-        this.idName = fieldElement.getAttribute("id-name");
-        this.separateColumn = 
"true".equals(fieldElement.getAttribute("separate-column"));
-        this.requiredField = fieldElement.hasAttribute("required-field") ? 
"true".equals(fieldElement
-                .getAttribute("required-field")) : null;
-        this.sortField = fieldElement.hasAttribute("sort-field") ? 
"true".equals(fieldElement.getAttribute("sort-field")) : null;
-        this.sortFieldHelpText = 
fieldElement.getAttribute("sort-field-help-text");
-        this.headerLink = fieldElement.getAttribute("header-link");
-        this.headerLinkStyle = fieldElement.getAttribute("header-link-style");
-
-        String positionStr = fieldElement.getAttribute("position");
-        try {
-            if (UtilValidate.isNotEmpty(positionStr))
-                position = Integer.valueOf(positionStr);
-        } catch (Exception e) {
-            Debug.logError(e, "Could not convert position attribute of the 
field element to an integer: [" + positionStr
-                    + "], using the default of the form renderer", module);
-        }
-
-        // get sub-element and set fieldInfo
-        List<? extends Element> subElements = 
UtilXml.childElementList(fieldElement);
-        for (Element subElement : subElements) {
-            String subElementName = subElement.getTagName();
-            if (Debug.verboseOn())
-                Debug.logVerbose("Processing field " + this.name + " with type 
info tag " + subElementName, module);
-
-            if (UtilValidate.isEmpty(subElementName)) {
-                this.fieldInfo = null;
-                this.induceFieldInfo(null, entityModelReader, 
dispatchContext); //no defaultFieldType specified here, will default to edit
-            } else if ("display".equals(subElementName))
-                this.fieldInfo = new DisplayField(subElement, this);
-            else if ("display-entity".equals(subElementName))
-                this.fieldInfo = new DisplayEntityField(subElement, this);
-            else if ("hyperlink".equals(subElementName))
-                this.fieldInfo = new HyperlinkField(subElement, this);
-            else if ("text".equals(subElementName))
-                this.fieldInfo = new TextField(subElement, this);
-            else if ("textarea".equals(subElementName))
-                this.fieldInfo = new TextareaField(subElement, this);
-            else if ("date-time".equals(subElementName))
-                this.fieldInfo = new DateTimeField(subElement, this);
-            else if ("drop-down".equals(subElementName))
-                this.fieldInfo = new DropDownField(subElement, this);
-            else if ("check".equals(subElementName))
-                this.fieldInfo = new CheckField(subElement, this);
-            else if ("radio".equals(subElementName))
-                this.fieldInfo = new RadioField(subElement, this);
-            else if ("submit".equals(subElementName))
-                this.fieldInfo = new SubmitField(subElement, this);
-            else if ("reset".equals(subElementName))
-                this.fieldInfo = new ResetField(subElement, this);
-            else if ("hidden".equals(subElementName))
-                this.fieldInfo = new HiddenField(subElement, this);
-            else if ("ignored".equals(subElementName))
-                this.fieldInfo = new IgnoredField(subElement, this);
-            else if ("text-find".equals(subElementName))
-                this.fieldInfo = new TextFindField(subElement, this);
-            else if ("date-find".equals(subElementName))
-                this.fieldInfo = new DateFindField(subElement, this);
-            else if ("range-find".equals(subElementName))
-                this.fieldInfo = new RangeFindField(subElement, this);
-            else if ("lookup".equals(subElementName))
-                this.fieldInfo = new LookupField(subElement, this);
-            else if ("file".equals(subElementName))
-                this.fieldInfo = new FileField(subElement, this);
-            else if ("password".equals(subElementName))
-                this.fieldInfo = new PasswordField(subElement, this);
-            else if ("image".equals(subElementName))
-                this.fieldInfo = new ImageField(subElement, this);
-            else if ("container".equals(subElementName))
-                this.fieldInfo = new ContainerField(subElement, this);
-            else if ("on-field-event-update-area".equals(subElementName))
-                addOnEventUpdateArea(new UpdateArea(subElement));
-            else
-                throw new IllegalArgumentException("The field sub-element with 
name " + subElementName + " is not supported");
-        }
-    }
-
-    private void addOnEventUpdateArea(UpdateArea updateArea) {
-        // Event types are sorted as a convenience for the rendering classes
-        Debug.logInfo(this.modelForm.getName() + ":" + this.name + " adding 
UpdateArea type " + updateArea.getEventType(), module);
-        if ("change".equals(updateArea.getEventType()))
-            addOnChangeUpdateArea(updateArea);
-        else if ("click".equals(updateArea.getEventType()))
-            addOnClickUpdateArea(updateArea);
-    }
-
-    private void addOnChangeUpdateArea(UpdateArea updateArea) {
-        if (onChangeUpdateAreas == null)
-            onChangeUpdateAreas = new ArrayList<UpdateArea>();
-        onChangeUpdateAreas.add(updateArea);
-        Debug.logInfo(this.modelForm.getName() + ":" + this.name + " 
onChangeUpdateAreas size = " + onChangeUpdateAreas.size(),
-                module);
-    }
-
-    private void addOnClickUpdateArea(UpdateArea updateArea) {
-        if (onClickUpdateAreas == null)
-            onClickUpdateAreas = new ArrayList<UpdateArea>();
-        onClickUpdateAreas.add(updateArea);
-    }
-
-    public void mergeOverrideModelFormField(ModelFormField overrideFormField) {
-        if (overrideFormField == null)
-            return;
-
-        // incorporate updates for values that are not empty in the 
overrideFormField
-        if (UtilValidate.isNotEmpty(overrideFormField.name))
-            this.name = overrideFormField.name;
-        if (UtilValidate.isNotEmpty(overrideFormField.mapAcsr))
-            this.mapAcsr = overrideFormField.mapAcsr; 
//Debug.logInfo("overriding mapAcsr, old=" + 
(this.mapAcsr==null?"null":this.mapAcsr.getOriginalName()) + ", new=" + 
overrideFormField.mapAcsr.getOriginalName(), module);
-        if (UtilValidate.isNotEmpty(overrideFormField.entityName))
-            this.entityName = overrideFormField.entityName;
-        if (UtilValidate.isNotEmpty(overrideFormField.serviceName))
-            this.serviceName = overrideFormField.serviceName;
-        if (UtilValidate.isNotEmpty(overrideFormField.entryAcsr))
-            this.entryAcsr = overrideFormField.entryAcsr;
-        if (UtilValidate.isNotEmpty(overrideFormField.parameterName))
-            this.parameterName = overrideFormField.parameterName;
-        if (UtilValidate.isNotEmpty(overrideFormField.fieldName))
-            this.fieldName = overrideFormField.fieldName;
-        if (UtilValidate.isNotEmpty(overrideFormField.attributeName))
-            this.attributeName = overrideFormField.attributeName;
-        if (UtilValidate.isNotEmpty(overrideFormField.title))
-            this.title = overrideFormField.title; // title="" can be used to 
override the original value
-        if (UtilValidate.isNotEmpty(overrideFormField.tooltip))
-            this.tooltip = overrideFormField.tooltip;
-        if (overrideFormField.requiredField != null)
-            this.requiredField = overrideFormField.requiredField;
-        if (overrideFormField.sortField != null)
-            this.sortField = overrideFormField.sortField;
-        if (UtilValidate.isNotEmpty(overrideFormField.sortFieldHelpText))
-            this.sortFieldHelpText = overrideFormField.sortFieldHelpText;
-        if (UtilValidate.isNotEmpty(overrideFormField.titleAreaStyle))
-            this.titleAreaStyle = overrideFormField.titleAreaStyle;
-        if (UtilValidate.isNotEmpty(overrideFormField.widgetAreaStyle))
-            this.widgetAreaStyle = overrideFormField.widgetAreaStyle;
-        if (UtilValidate.isNotEmpty(overrideFormField.titleStyle))
-            this.titleStyle = overrideFormField.titleStyle;
-        if (UtilValidate.isNotEmpty(overrideFormField.widgetStyle))
-            this.widgetStyle = overrideFormField.widgetStyle;
-        if (overrideFormField.position != null)
-            this.position = overrideFormField.position;
-        if (UtilValidate.isNotEmpty(overrideFormField.redWhen))
-            this.redWhen = overrideFormField.redWhen;
-        if (UtilValidate.isNotEmpty(overrideFormField.event))
-            this.event = overrideFormField.event;
-        if (UtilValidate.isNotEmpty(overrideFormField.action))
-            this.action = overrideFormField.action;
-        if (UtilValidate.isNotEmpty(overrideFormField.useWhen))
-            this.useWhen = overrideFormField.useWhen;
-        if (overrideFormField.fieldInfo != null)
-            this.setFieldInfo(overrideFormField.fieldInfo);
-        if (overrideFormField.headerLink != null)
-            this.setHeaderLink(overrideFormField.headerLink);
-        if (UtilValidate.isNotEmpty(overrideFormField.idName))
-            this.idName = overrideFormField.idName;
-        if (overrideFormField.onChangeUpdateAreas != null)
-            this.onChangeUpdateAreas = overrideFormField.onChangeUpdateAreas;
-        if (overrideFormField.onClickUpdateAreas != null)
-            this.onClickUpdateAreas = overrideFormField.onClickUpdateAreas;
-        this.encodeOutput = overrideFormField.encodeOutput;
-    }
-
-    private boolean induceFieldInfo(String defaultFieldType, ModelReader 
entityModelReader, DispatchContext dispatchContext) {
-        if (this.induceFieldInfoFromEntityField(defaultFieldType, 
entityModelReader))
-            return true;
-        if (this.induceFieldInfoFromServiceParam(defaultFieldType, 
entityModelReader, dispatchContext))
-            return true;
-        return false;
-    }
+    /*
+     * ----------------------------------------------------------------------- 
*
+     *                     DEVELOPERS PLEASE READ
+     * ----------------------------------------------------------------------- 
*
+     * 
+     * This model is intended to be a read-only data structure that represents
+     * an XML element. Outside of object construction, the class should not
+     * have any behaviors. All behavior should be contained in model visitors.
+     * 
+     * Instances of this class will be shared by multiple threads - therefore
+     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!
+     * 
+     */
 
-    private boolean induceFieldInfoFromServiceParam(String defaultFieldType, 
ModelReader entityModelReader,
-            DispatchContext dispatchContext) {
-        if (UtilValidate.isEmpty(this.getServiceName()) || 
UtilValidate.isEmpty(this.getAttributeName()))
-            return false;
-        try {
-            ModelService modelService = 
dispatchContext.getModelService(this.getServiceName());
-            if (modelService != null) {
-                ModelParam modelParam = 
modelService.getParam(this.getAttributeName());
-                if (modelParam != null) {
-                    if (UtilValidate.isNotEmpty(modelParam.entityName) && 
UtilValidate.isNotEmpty(modelParam.fieldName)) {
-                        this.entityName = modelParam.entityName;
-                        this.fieldName = modelParam.fieldName;
-                        if 
(this.induceFieldInfoFromEntityField(defaultFieldType, entityModelReader)) {
-                            return true;
-                        }
-                    }
+    public static final String module = ModelFormField.class.getName();
 
-                    this.induceFieldInfoFromServiceParam(modelService, 
modelParam, defaultFieldType);
-                    return true;
-                }
-            }
-        } catch (GenericServiceException e) {
-            Debug.logError(e,
-                    "error getting service parameter definition for auto-field 
with serviceName: " + this.getServiceName()
-                            + ", and attributeName: " + 
this.getAttributeName(), module);
-        }
-        return false;
+    public static ModelFormField from(ModelFormFieldBuilder builder) {
+        return new ModelFormField(builder);
     }
 
-    public boolean induceFieldInfoFromServiceParam(ModelService modelService, 
ModelParam modelParam, String defaultFieldType) {
-        if (modelService == null || modelParam == null)
-            return false;
-
-        this.serviceName = modelService.name;
-        this.attributeName = modelParam.name;
-
-        if ("find".equals(defaultFieldType)) {
-            if (modelParam.type.indexOf("Double") != -1 || 
modelParam.type.indexOf("Float") != -1
-                    || modelParam.type.indexOf("Long") != -1 || 
modelParam.type.indexOf("Integer") != -1) {
-                ModelFormField.RangeFindField textField = new 
ModelFormField.RangeFindField(FieldInfo.SOURCE_AUTO_SERVICE, this);
-                textField.setSize(6);
-                this.setFieldInfo(textField);
-            } else if (modelParam.type.indexOf("Timestamp") != -1) {
-                ModelFormField.DateFindField dateTimeField = new 
ModelFormField.DateFindField(FieldInfo.SOURCE_AUTO_SERVICE, this);
-                dateTimeField.setType("timestamp");
-                this.setFieldInfo(dateTimeField);
-            } else if (modelParam.type.indexOf("Date") != -1) {
-                ModelFormField.DateFindField dateTimeField = new 
ModelFormField.DateFindField(FieldInfo.SOURCE_AUTO_SERVICE, this);
-                dateTimeField.setType("date");
-                this.setFieldInfo(dateTimeField);
-            } else if (modelParam.type.indexOf("Time") != -1) {
-                ModelFormField.DateFindField dateTimeField = new 
ModelFormField.DateFindField(FieldInfo.SOURCE_AUTO_SERVICE, this);
-                dateTimeField.setType("time");
-                this.setFieldInfo(dateTimeField);
-            } else {
-                ModelFormField.TextFindField textField = new 
ModelFormField.TextFindField(FieldInfo.SOURCE_AUTO_SERVICE, this);
-                this.setFieldInfo(textField);
-            }
-        } else if ("display".equals(defaultFieldType)) {
-            ModelFormField.DisplayField displayField = new 
ModelFormField.DisplayField(FieldInfo.SOURCE_AUTO_SERVICE, this);
-            this.setFieldInfo(displayField);
+    private final FlexibleStringExpander action;
+    private final String attributeName;
+    private final boolean encodeOutput;
+    private final String entityName;
+    private final FlexibleMapAccessor<Object> entryAcsr;
+    private final String event;
+    private final FieldInfo fieldInfo;
+    private final String fieldName;
+    private final String headerLink;
+    private final String headerLinkStyle;
+    private final String idName;
+    private final FlexibleMapAccessor<Map<String, ? extends Object>> mapAcsr;
+    private final ModelForm modelForm;
+    private final String name;
+    private final List<UpdateArea> onChangeUpdateAreas;
+    private final List<UpdateArea> onClickUpdateAreas;
+    private final String parameterName;
+    private final Integer position;
+    private final String redWhen;
+    private final Boolean requiredField;
+    private final String requiredFieldStyle;
+    private final boolean separateColumn;
+    private final String serviceName;
+    private final Boolean sortField;
+    private final String sortFieldAscStyle;
+    private final String sortFieldDescStyle;
+    private final String sortFieldHelpText;
+    private final String sortFieldStyle;
+    private final FlexibleStringExpander title;
+    private final String titleAreaStyle;
+    private final String titleStyle;
+    private final FlexibleStringExpander tooltip;
+    private final String tooltipStyle;
+    private final FlexibleStringExpander useWhen;
+    private final String widgetAreaStyle;
+    private final String widgetStyle;
+
+    private ModelFormField(ModelFormFieldBuilder builder) {
+        this.action = builder.getAction();
+        this.attributeName = builder.getAttributeName();
+        this.encodeOutput = builder.getEncodeOutput();
+        this.entityName = builder.getEntityName();
+        this.entryAcsr = builder.getEntryAcsr();
+        this.event = builder.getEvent();
+        if (builder.getFieldInfo() != null) {
+            this.fieldInfo = builder.getFieldInfo().copy(this);
         } else {
-            // default to "edit"
-            if (modelParam.type.indexOf("Double") != -1 || 
modelParam.type.indexOf("Float") != -1
-                    || modelParam.type.indexOf("Long") != -1 || 
modelParam.type.indexOf("Integer") != -1) {
-                ModelFormField.TextField textField = new 
ModelFormField.TextField(FieldInfo.SOURCE_AUTO_SERVICE, this);
-                textField.setSize(6);
-                this.setFieldInfo(textField);
-            } else if (modelParam.type.indexOf("Timestamp") != -1) {
-                ModelFormField.DateTimeField dateTimeField = new 
ModelFormField.DateTimeField(FieldInfo.SOURCE_AUTO_SERVICE, this);
-                dateTimeField.setType("timestamp");
-                this.setFieldInfo(dateTimeField);
-            } else if (modelParam.type.indexOf("Date") != -1) {
-                ModelFormField.DateTimeField dateTimeField = new 
ModelFormField.DateTimeField(FieldInfo.SOURCE_AUTO_SERVICE, this);
-                dateTimeField.setType("date");
-                this.setFieldInfo(dateTimeField);
-            } else if (modelParam.type.indexOf("Time") != -1) {
-                ModelFormField.DateTimeField dateTimeField = new 
ModelFormField.DateTimeField(FieldInfo.SOURCE_AUTO_SERVICE, this);
-                dateTimeField.setType("time");
-                this.setFieldInfo(dateTimeField);
-            } else {
-                ModelFormField.TextField textField = new 
ModelFormField.TextField(FieldInfo.SOURCE_AUTO_SERVICE, this);
-                this.setFieldInfo(textField);
-            }
+            this.fieldInfo = null;
         }
-
-        return true;
-    }
-
-    private boolean induceFieldInfoFromEntityField(String defaultFieldType, 
ModelReader entityModelReader) {
-        if (UtilValidate.isEmpty(this.getEntityName()) || 
UtilValidate.isEmpty(this.getFieldName()))
-            return false;
-        try {
-            ModelEntity modelEntity = 
entityModelReader.getModelEntity(this.getEntityName());
-            if (modelEntity != null) {
-                ModelField modelField = 
modelEntity.getField(this.getFieldName());
-                if (modelField != null) {
-                    // okay, populate using the entity field info...
-                    this.induceFieldInfoFromEntityField(modelEntity, 
modelField, defaultFieldType);
-                    return true;
-                }
-            }
-        } catch (GenericEntityException e) {
-            Debug.logError(e, module);
+        this.fieldName = builder.getFieldName();
+        this.headerLink = builder.getHeaderLink();
+        this.headerLinkStyle = builder.getHeaderLinkStyle();
+        this.idName = builder.getIdName();
+        this.mapAcsr = builder.getMapAcsr();
+        this.modelForm = builder.getModelForm();
+        this.name = builder.getName();
+        Debug.logInfo("name = " + name + ", fieldInfo = " + fieldInfo, module);
+        if (builder.getOnChangeUpdateAreas().isEmpty()) {
+            this.onChangeUpdateAreas = Collections.emptyList();
+        } else {
+            this.onChangeUpdateAreas = Collections.unmodifiableList(new 
ArrayList<UpdateArea>(builder.getOnChangeUpdateAreas()));
         }
-        return false;
-    }
-
-    public boolean induceFieldInfoFromEntityField(ModelEntity modelEntity, 
ModelField modelField, String defaultFieldType) {
-        if (modelEntity == null || modelField == null)
-            return false;
-
-        this.entityName = modelEntity.getEntityName();
-        this.fieldName = modelField.getName();
-
-        if ("find".equals(defaultFieldType)) {
-            if ("id".equals(modelField.getType()) || 
"id-ne".equals(modelField.getType())) {
-                ModelFormField.TextFindField textField = new 
ModelFormField.TextFindField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                textField.setSize(20);
-                textField.setMaxlength(Integer.valueOf(20));
-                this.setFieldInfo(textField);
-            } else if ("id-long".equals(modelField.getType()) || 
"id-long-ne".equals(modelField.getType())) {
-                ModelFormField.TextFindField textField = new 
ModelFormField.TextFindField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                textField.setSize(40);
-                textField.setMaxlength(Integer.valueOf(60));
-                this.setFieldInfo(textField);
-            } else if ("id-vlong".equals(modelField.getType()) || 
"id-vlong-ne".equals(modelField.getType())) {
-                ModelFormField.TextFindField textField = new 
ModelFormField.TextFindField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                textField.setSize(60);
-                textField.setMaxlength(Integer.valueOf(250));
-                this.setFieldInfo(textField);
-            } else if ("very-short".equals(modelField.getType())) {
-                ModelFormField.TextField textField = new 
ModelFormField.TextField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                textField.setSize(6);
-                textField.setMaxlength(Integer.valueOf(10));
-                this.setFieldInfo(textField);
-            } else if ("name".equals(modelField.getType()) || 
"short-varchar".equals(modelField.getType())) {
-                ModelFormField.TextFindField textField = new 
ModelFormField.TextFindField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                textField.setSize(40);
-                textField.setMaxlength(Integer.valueOf(60));
-                this.setFieldInfo(textField);
-            } else if ("value".equals(modelField.getType()) || 
"comment".equals(modelField.getType())
-                    || "description".equals(modelField.getType()) || 
"long-varchar".equals(modelField.getType())
-                    || "url".equals(modelField.getType()) || 
"email".equals(modelField.getType())) {
-                ModelFormField.TextFindField textField = new 
ModelFormField.TextFindField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                textField.setSize(60);
-                textField.setMaxlength(Integer.valueOf(250));
-                this.setFieldInfo(textField);
-            } else if ("floating-point".equals(modelField.getType()) || 
"currency-amount".equals(modelField.getType())
-                    || "numeric".equals(modelField.getType())) {
-                ModelFormField.RangeFindField textField = new 
ModelFormField.RangeFindField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                textField.setSize(6);
-                this.setFieldInfo(textField);
-            } else if ("date-time".equals(modelField.getType()) || 
"date".equals(modelField.getType())
-                    || "time".equals(modelField.getType())) {
-                ModelFormField.DateFindField dateTimeField = new 
ModelFormField.DateFindField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                if ("date-time".equals(modelField.getType())) {
-                    dateTimeField.setType("timestamp");
-                } else if ("date".equals(modelField.getType())) {
-                    dateTimeField.setType("date");
-                } else if ("time".equals(modelField.getType())) {
-                    dateTimeField.setType("time");
-                }
-                this.setFieldInfo(dateTimeField);
-            } else {
-                ModelFormField.TextFindField textField = new 
ModelFormField.TextFindField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                this.setFieldInfo(textField);
-            }
-        } else if ("display".equals(defaultFieldType)) {
-            ModelFormField.DisplayField displayField = new 
ModelFormField.DisplayField(FieldInfo.SOURCE_AUTO_SERVICE, this);
-            this.setFieldInfo(displayField);
-        } else if ("hidden".equals(defaultFieldType)) {
-            ModelFormField.HiddenField hiddenField = new 
ModelFormField.HiddenField(FieldInfo.SOURCE_AUTO_SERVICE, this);
-            this.setFieldInfo(hiddenField);
+        if (builder.getOnClickUpdateAreas().isEmpty()) {
+            this.onClickUpdateAreas = Collections.emptyList();
         } else {
-            if ("id".equals(modelField.getType()) || 
"id-ne".equals(modelField.getType())) {
-                ModelFormField.TextField textField = new 
ModelFormField.TextField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                textField.setSize(20);
-                textField.setMaxlength(Integer.valueOf(20));
-                this.setFieldInfo(textField);
-            } else if ("id-long".equals(modelField.getType()) || 
"id-long-ne".equals(modelField.getType())) {
-                ModelFormField.TextField textField = new 
ModelFormField.TextField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                textField.setSize(40);
-                textField.setMaxlength(Integer.valueOf(60));
-                this.setFieldInfo(textField);
-            } else if ("id-vlong".equals(modelField.getType()) || 
"id-vlong-ne".equals(modelField.getType())) {
-                ModelFormField.TextField textField = new 
ModelFormField.TextField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                textField.setSize(60);
-                textField.setMaxlength(Integer.valueOf(250));
-                this.setFieldInfo(textField);
-            } else if ("indicator".equals(modelField.getType())) {
-                ModelFormField.DropDownField dropDownField = new 
ModelFormField.DropDownField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                dropDownField.setAllowEmpty(false);
-                dropDownField.addOptionSource(new 
ModelFormField.SingleOption("Y", null, dropDownField));
-                dropDownField.addOptionSource(new 
ModelFormField.SingleOption("N", null, dropDownField));
-                this.setFieldInfo(dropDownField);
-                //ModelFormField.TextField textField = new 
ModelFormField.TextField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                //textField.setSize(1);
-                //textField.setMaxlength(Integer.valueOf(1));
-                //this.setFieldInfo(textField);
-            } else if ("very-short".equals(modelField.getType())) {
-                ModelFormField.TextField textField = new 
ModelFormField.TextField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                textField.setSize(6);
-                textField.setMaxlength(Integer.valueOf(10));
-                this.setFieldInfo(textField);
-            } else if ("very-long".equals(modelField.getType())) {
-                ModelFormField.TextareaField textareaField = new 
ModelFormField.TextareaField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                textareaField.setCols(60);
-                textareaField.setRows(2);
-                this.setFieldInfo(textareaField);
-            } else if ("name".equals(modelField.getType()) || 
"short-varchar".equals(modelField.getType())) {
-                ModelFormField.TextField textField = new 
ModelFormField.TextField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                textField.setSize(40);
-                textField.setMaxlength(Integer.valueOf(60));
-                this.setFieldInfo(textField);
-            } else if ("value".equals(modelField.getType()) || 
"comment".equals(modelField.getType())
-                    || "description".equals(modelField.getType()) || 
"long-varchar".equals(modelField.getType())
-                    || "url".equals(modelField.getType()) || 
"email".equals(modelField.getType())) {
-                ModelFormField.TextField textField = new 
ModelFormField.TextField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                textField.setSize(60);
-                textField.setMaxlength(Integer.valueOf(250));
-                this.setFieldInfo(textField);
-            } else if ("floating-point".equals(modelField.getType()) || 
"currency-amount".equals(modelField.getType())
-                    || "numeric".equals(modelField.getType())) {
-                ModelFormField.TextField textField = new 
ModelFormField.TextField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                textField.setSize(6);
-                this.setFieldInfo(textField);
-            } else if ("date-time".equals(modelField.getType()) || 
"date".equals(modelField.getType())
-                    || "time".equals(modelField.getType())) {
-                ModelFormField.DateTimeField dateTimeField = new 
ModelFormField.DateTimeField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                if ("date-time".equals(modelField.getType())) {
-                    dateTimeField.setType("timestamp");
-                } else if ("date".equals(modelField.getType())) {
-                    dateTimeField.setType("date");
-                } else if ("time".equals(modelField.getType())) {
-                    dateTimeField.setType("time");
-                }
-                this.setFieldInfo(dateTimeField);
-            } else {
-                ModelFormField.TextField textField = new 
ModelFormField.TextField(FieldInfo.SOURCE_AUTO_ENTITY, this);
-                this.setFieldInfo(textField);
-            }
+            this.onClickUpdateAreas = Collections.unmodifiableList(new 
ArrayList<UpdateArea>(builder.getOnClickUpdateAreas()));
         }
-
-        return true;
-    }
-
-    public void renderFieldString(Appendable writer, Map<String, Object> 
context, FormStringRenderer formStringRenderer)
-            throws IOException {
-        this.fieldInfo.renderFieldString(writer, context, formStringRenderer);
-    }
-
-    public List<UpdateArea> getOnChangeUpdateAreas() {
-        return onChangeUpdateAreas;
-    }
-
-    public List<UpdateArea> getOnClickUpdateAreas() {
-        return onClickUpdateAreas;
-    }
-
-    public FieldInfo getFieldInfo() {
-        return fieldInfo;
+        this.parameterName = builder.getParameterName();
+        this.position = builder.getPosition();
+        this.redWhen = builder.getRedWhen();
+        this.requiredField = builder.getRequiredField();
+        this.requiredFieldStyle = builder.getRequiredFieldStyle();
+        this.separateColumn = builder.getSeparateColumn();
+        this.serviceName = builder.getServiceName();
+        this.sortField = builder.getSortField();
+        this.sortFieldAscStyle = builder.getSortFieldAscStyle();
+        this.sortFieldDescStyle = builder.getSortFieldDescStyle();
+        this.sortFieldHelpText = builder.getSortFieldHelpText();
+        this.sortFieldStyle = builder.getSortFieldStyle();
+        this.title = builder.getTitle();
+        this.titleAreaStyle = builder.getTitleAreaStyle();
+        this.titleStyle = builder.getTitleStyle();
+        this.tooltip = builder.getTooltip();
+        this.tooltipStyle = builder.getTooltipStyle();
+        this.useWhen = builder.getUseWhen();
+        this.widgetAreaStyle = builder.getWidgetAreaStyle();
+        this.widgetStyle = builder.getWidgetStyle();
     }
 
-    public ModelForm getModelForm() {
-        return modelForm;
+    public FlexibleStringExpander getAction() {
+        return action;
     }
 
-    /**
-     * @param fieldInfo
-     */
-    public void setFieldInfo(FieldInfo fieldInfo) {
-        // field info is a little different, check source for priority
-        if (fieldInfo != null && (this.fieldInfo == null || 
(fieldInfo.getFieldSource() <= this.fieldInfo.getFieldSource()))) {
-            this.fieldInfo = fieldInfo.copy(this);
-        }
+    public String getAction(Map<String, ? extends Object> context) {
+        if (UtilValidate.isNotEmpty(this.action))
+            return action.expandString(context);
+        return null;
     }
 
     /**
@@ -618,22 +207,35 @@ public class ModelFormField {
         return this.name;
     }
 
+    public String getCurrentContainerId(Map<String, Object> context) {
+        ModelForm modelForm = this.getModelForm();
+        String idName = FlexibleStringExpander.expandString(this.getIdName(), 
context);
+
+        if (modelForm != null) {
+            Integer itemIndex = (Integer) context.get("itemIndex");
+            if ("list".equals(modelForm.getType()) || 
"multi".equals(modelForm.getType())) {
+                if (itemIndex != null) {
+                    return idName + modelForm.getItemIndexSeparator() + 
itemIndex.intValue();
+                }
+            }
+        }
+        return idName;
+    }
+
+    public boolean getEncodeOutput() {
+        return this.encodeOutput;
+    }
+
     public String getEntityName() {
         if (UtilValidate.isNotEmpty(this.entityName))
             return this.entityName;
         return this.modelForm.getDefaultEntityName();
     }
 
-    public String getEntryName() {
-        if (UtilValidate.isNotEmpty(this.entryAcsr))
-            return this.entryAcsr.getOriginalName();
-        return this.name;
-    }
-
     /**
      * Gets the entry from the context that corresponds to this field; if this
      * form is being rendered in an error condition (ie isError in the context
-     * is true) then the value will be retreived from the parameters Map in
+     * is true) then the value will be retrieved from the parameters Map in
      * the context.
      *
      * @param context the context
@@ -749,6 +351,51 @@ public class ModelFormField {
         return returnValue;
     }
 
+    public FlexibleMapAccessor<Object> getEntryAcsr() {
+        return entryAcsr;
+    }
+
+    public String getEntryName() {
+        if (UtilValidate.isNotEmpty(this.entryAcsr))
+            return this.entryAcsr.getOriginalName();
+        return this.name;
+    }
+
+    public String getEvent() {
+        return event;
+    }
+
+    public FieldInfo getFieldInfo() {
+        return fieldInfo;
+    }
+
+    /**
+     * Gets the name of the Entity Field that corresponds
+     * with this field. This can be used to get additional information about 
the field.
+     * Use the getEntityName() method to get the Entity name that the field is 
in.
+     *
+     * @return return the name of the Entity Field that corresponds with this 
field
+     */
+    public String getFieldName() {
+        if (UtilValidate.isNotEmpty(this.fieldName))
+            return this.fieldName;
+        return this.name;
+    }
+
+    public String getHeaderLink() {
+        return headerLink;
+    }
+
+    public String getHeaderLinkStyle() {
+        return headerLinkStyle;
+    }
+
+    public String getIdName() {
+        if (UtilValidate.isNotEmpty(idName))
+            return idName;
+        return this.modelForm.getName() + "_" + this.getFieldName();
+    }
+
     public Map<String, ? extends Object> getMap(Map<String, ? extends Object> 
context) {
         if (UtilValidate.isEmpty(this.mapAcsr))
             return this.modelForm.getDefaultMap(context); 
//Debug.logInfo("Getting Map from default of the form because of no mapAcsr for 
field " + this.getName(), module);
@@ -766,17 +413,8 @@ public class ModelFormField {
         return result;
     }
 
-    /**
-     * Gets the name of the Entity Field that corresponds
-     * with this field. This can be used to get additional information about 
the field.
-     * Use the getEntityName() method to get the Entity name that the field is 
in.
-     *
-     * @return return the name of the Entity Field that corresponds with this 
field
-     */
-    public String getFieldName() {
-        if (UtilValidate.isNotEmpty(this.fieldName))
-            return this.fieldName;
-        return this.name;
+    public FlexibleMapAccessor<Map<String, ? extends Object>> getMapAcsr() {
+        return mapAcsr;
     }
 
     /** Get the name of the Map in the form context that contains the entry,
@@ -793,10 +431,26 @@ public class ModelFormField {
         return this.modelForm.getDefaultMapName();
     }
 
+    public ModelForm getModelForm() {
+        return modelForm;
+    }
+
     public String getName() {
         return name;
     }
 
+    public List<UpdateArea> getOnChangeUpdateAreas() {
+        return onChangeUpdateAreas;
+    }
+
+    public List<UpdateArea> getOnClickUpdateAreas() {
+        return onClickUpdateAreas;
+    }
+
+    public String getParameterName() {
+        return parameterName;
+    }
+
     /**
      * Get the name to use for the parameter for this field in the form 
interpreter.
      * For HTML forms this is the request parameter name.
@@ -828,135 +482,66 @@ public class ModelFormField {
         return redWhen;
     }
 
-    public String getEvent() {
-        return event;
+    public boolean getRequiredField() {
+        return this.requiredField != null ? this.requiredField : false;
     }
 
-    public String getAction(Map<String, ? extends Object> context) {
-        if (UtilValidate.isNotEmpty(this.action))
-            return action.expandString(context);
-        return null;
+    public String getRequiredFieldStyle() {
+        if (UtilValidate.isNotEmpty(this.requiredFieldStyle))
+            return this.requiredFieldStyle;
+        return this.modelForm.getDefaultRequiredFieldStyle();
     }
 
-    /**
-     * the widget/interaction part will be red if the date value is
-     *  before-now (for ex. thruDate), after-now (for ex. fromDate), or 
by-name (if the
-     *  field's name or entry-name or fromDate or thruDate the corresponding
-     *  action will be done); only applicable when the field is a timestamp
-     *
-     * @param context the context
-     * @return true if the field should be read otherwise false
-     */
-    public boolean shouldBeRed(Map<String, Object> context) {
-        // red-when (never | before-now | after-now | by-name) "by-name"
-
-        String redCondition = this.redWhen;
+    public boolean getSeparateColumn() {
+        return this.separateColumn;
+    }
 
-        if ("never".equals(redCondition))
-            return false;
+    public String getServiceName() {
+        if (UtilValidate.isNotEmpty(this.serviceName))
+            return this.serviceName;
+        return this.modelForm.getDefaultServiceName();
+    }
 
-        // for performance resaons we check this first, most fields will be 
eliminated here and the valueOfs will not be necessary
-        if (UtilValidate.isEmpty(redCondition) || 
"by-name".equals(redCondition)) {
-            if ("fromDate".equals(this.name) || (this.entryAcsr != null && 
"fromDate".equals(this.entryAcsr.getOriginalName()))) {
-                redCondition = "after-now";
-            } else if ("thruDate".equals(this.name)
-                    || (this.entryAcsr != null && 
"thruDate".equals(this.entryAcsr.getOriginalName()))) {
-                redCondition = "before-now";
-            } else {
-                return false;
-            }
-        }
+    public Boolean getSortField() {
+        return sortField;
+    }
 
-        boolean isBeforeNow = false;
-        if ("before-now".equals(redCondition)) {
-            isBeforeNow = true;
-        } else if ("after-now".equals(redCondition)) {
-            isBeforeNow = false;
-        } else {
-            return false;
-        }
+    public String getSortFieldAscStyle() {
+        return sortFieldAscStyle;
+    }
 
-        java.sql.Date dateVal = null;
-        java.sql.Time timeVal = null;
-        java.sql.Timestamp timestampVal = null;
+    public String getSortFieldDescStyle() {
+        return sortFieldDescStyle;
+    }
 
-        //now before going on, check to see if the current entry is a valid 
date and/or time and get the value
-        String value = this.getEntry(context, null);
-        try {
-            timestampVal = java.sql.Timestamp.valueOf(value);
-        } catch (Exception e) {
-            // okay, not a timestamp...
-        }
+    public String getSortFieldHelpText() {
+        return sortFieldHelpText;
+    }
 
-        if (timestampVal == null) {
-            try {
-                dateVal = java.sql.Date.valueOf(value);
-            } catch (Exception e) {
-                // okay, not a date...
-            }
-        }
+    public String getSortFieldHelpText(Map<String, Object> context) {
+        return FlexibleStringExpander.expandString(this.sortFieldHelpText, 
context);
+    }
 
-        if (timestampVal == null && dateVal == null) {
-            try {
-                timeVal = java.sql.Time.valueOf(value);
-            } catch (Exception e) {
-                // okay, not a time...
-            }
-        }
-
-        if (timestampVal == null && dateVal == null && timeVal == null) {
-            return false;
-        }
+    public String getSortFieldStyle() {
+        if (UtilValidate.isNotEmpty(this.sortFieldStyle))
+            return this.sortFieldStyle;
+        return this.modelForm.getDefaultSortFieldStyle();
+    }
 
-        long nowMillis = System.currentTimeMillis();
-        if (timestampVal != null) {
-            java.sql.Timestamp nowStamp = new java.sql.Timestamp(nowMillis);
-            if (!timestampVal.equals(nowStamp)) {
-                if (isBeforeNow) {
-                    if (timestampVal.before(nowStamp)) {
-                        return true;
-                    }
-                } else {
-                    if (timestampVal.after(nowStamp)) {
-                        return true;
-                    }
-                }
-            }
-        } else if (dateVal != null) {
-            java.sql.Date nowDate = new java.sql.Date(nowMillis);
-            if (!dateVal.equals(nowDate)) {
-                if (isBeforeNow) {
-                    if (dateVal.before(nowDate)) {
-                        return true;
-                    }
-                } else {
-                    if (dateVal.after(nowDate)) {
-                        return true;
-                    }
-                }
-            }
-        } else if (timeVal != null) {
-            java.sql.Time nowTime = new java.sql.Time(nowMillis);
-            if (!timeVal.equals(nowTime)) {
-                if (isBeforeNow) {
-                    if (timeVal.before(nowTime)) {
-                        return true;
-                    }
-                } else {
-                    if (timeVal.after(nowTime)) {
-                        return true;
-                    }
-                }
-            }
-        }
+    public String getSortFieldStyleAsc() {
+        if (UtilValidate.isNotEmpty(this.sortFieldAscStyle))
+            return this.sortFieldAscStyle;
+        return this.modelForm.getDefaultSortFieldAscStyle();
+    }
 
-        return false;
+    public String getSortFieldStyleDesc() {
+        if (UtilValidate.isNotEmpty(this.sortFieldDescStyle))
+            return this.sortFieldDescStyle;
+        return this.modelForm.getDefaultSortFieldDescStyle();
     }
 
-    public String getServiceName() {
-        if (UtilValidate.isNotEmpty(this.serviceName))
-            return this.serviceName;
-        return this.modelForm.getDefaultServiceName();
+    public FlexibleStringExpander getTitle() {
+        return title;
     }
 
     public String getTitle(Map<String, Object> context) {
@@ -1009,28 +594,8 @@ public class ModelFormField {
         return this.modelForm.getDefaultTitleStyle();
     }
 
-    public String getRequiredFieldStyle() {
-        if (UtilValidate.isNotEmpty(this.requiredFieldStyle))
-            return this.requiredFieldStyle;
-        return this.modelForm.getDefaultRequiredFieldStyle();
-    }
-
-    public String getSortFieldStyle() {
-        if (UtilValidate.isNotEmpty(this.sortFieldStyle))
-            return this.sortFieldStyle;
-        return this.modelForm.getDefaultSortFieldStyle();
-    }
-
-    public String getSortFieldStyleAsc() {
-        if (UtilValidate.isNotEmpty(this.sortFieldAscStyle))
-            return this.sortFieldAscStyle;
-        return this.modelForm.getDefaultSortFieldAscStyle();
-    }
-
-    public String getSortFieldStyleDesc() {
-        if (UtilValidate.isNotEmpty(this.sortFieldDescStyle))
-            return this.sortFieldDescStyle;
-        return this.modelForm.getDefaultSortFieldDescStyle();
+    public FlexibleStringExpander getTooltip() {
+        return tooltip;
     }
 
     public String getTooltip(Map<String, Object> context) {
@@ -1045,87 +610,32 @@ public class ModelFormField {
         return tooltipString;
     }
 
-    public String getUseWhen(Map<String, Object> context) {
-        if (UtilValidate.isNotEmpty(this.useWhen))
-            return this.useWhen.expandString(context);
-        return "";
-    }
-
-    public boolean getEncodeOutput() {
-        return this.encodeOutput;
-    }
-
-    public String getIdName() {
-        if (UtilValidate.isNotEmpty(idName))
-            return idName;
-        return this.modelForm.getName() + "_" + this.getFieldName();
-    }
-
-    public String getCurrentContainerId(Map<String, Object> context) {
-        ModelForm modelForm = this.getModelForm();
-        String idName = FlexibleStringExpander.expandString(this.getIdName(), 
context);
-
-        if (modelForm != null) {
-            Integer itemIndex = (Integer) context.get("itemIndex");
-            if ("list".equals(modelForm.getType()) || 
"multi".equals(modelForm.getType())) {
-                if (itemIndex != null) {
-                    return idName + modelForm.getItemIndexSeparator() + 
itemIndex.intValue();
-                }
-            }
-        }
-        return idName;
-    }
-
-    public String getHeaderLink() {
-        return headerLink;
+    public String getTooltipStyle() {
+        if (UtilValidate.isNotEmpty(this.tooltipStyle))
+            return this.tooltipStyle;
+        return this.modelForm.getDefaultTooltipStyle();
     }
 
-    public String getHeaderLinkStyle() {
-        return headerLinkStyle;
+    public FlexibleStringExpander getUseWhen() {
+        return useWhen;
     }
 
-    /**
-     * @param string
-     */
-    public void setIdName(String string) {
-        idName = string;
+    public String getUseWhen(Map<String, Object> context) {
+        if (UtilValidate.isNotEmpty(this.useWhen))
+            return this.useWhen.expandString(context);
+        return "";
     }
 
-    public boolean isUseWhenEmpty() {
-        if (this.useWhen == null) {
-            return true;
-        }
-
-        return this.useWhen.isEmpty();
+    public String getWidgetAreaStyle() {
+        if (UtilValidate.isNotEmpty(this.widgetAreaStyle))
+            return this.widgetAreaStyle;
+        return this.modelForm.getDefaultWidgetAreaStyle();
     }
 
-    public boolean shouldUse(Map<String, Object> context) {
-        String useWhenStr = this.getUseWhen(context);
-        if (UtilValidate.isEmpty(useWhenStr))
-            return true;
-
-        try {
-            Interpreter bsh = this.modelForm.getBshInterpreter(context);
-            Object retVal = 
bsh.eval(StringUtil.convertOperatorSubstitutions(useWhenStr));
-            boolean condTrue = false;
-            // retVal should be a Boolean, if not something weird is up...
-            if (retVal instanceof Boolean) {
-                Boolean boolVal = (Boolean) retVal;
-                condTrue = boolVal.booleanValue();
-            } else {
-                throw new IllegalArgumentException("Return value from use-when 
condition eval was not a Boolean: "
-                        + (retVal != null ? retVal.getClass().getName() : 
"null") + " [" + retVal + "] on the field " + this.name
-                        + " of form " + this.modelForm.getName());
-            }
-
-            return condTrue;
-        } catch (EvalError e) {
-            String errMsg = "Error evaluating BeanShell use-when condition [" 
+ useWhenStr + "] on the field " + this.name
-                    + " of form " + this.modelForm.getName() + ": " + 
e.toString();
-            Debug.logError(e, errMsg, module);
-            //Debug.logError("For use-when eval error context is: " + context, 
module);
-            throw new IllegalArgumentException(errMsg);
-        }
+    public String getWidgetStyle() {
+        if (UtilValidate.isNotEmpty(this.widgetStyle))
+            return this.widgetStyle;
+        return this.modelForm.getDefaultWidgetStyle();
     }
 
     /**
@@ -1141,862 +651,754 @@ public class ModelFormField {
         return true;
     }
 
-    public String getWidgetAreaStyle() {
-        if (UtilValidate.isNotEmpty(this.widgetAreaStyle))
-            return this.widgetAreaStyle;
-        return this.modelForm.getDefaultWidgetAreaStyle();
+    public boolean isSortField() {
+        return this.sortField != null && this.sortField.booleanValue();
     }
 
-    public String getWidgetStyle() {
-        if (UtilValidate.isNotEmpty(this.widgetStyle))
-            return this.widgetStyle;
-        return this.modelForm.getDefaultWidgetStyle();
-    }
+    public boolean isUseWhenEmpty() {
+        if (this.useWhen == null) {
+            return true;
+        }
 
-    public String getTooltipStyle() {
-        if (UtilValidate.isNotEmpty(this.tooltipStyle))
-            return this.tooltipStyle;
-        return this.modelForm.getDefaultTooltipStyle();
+        return this.useWhen.isEmpty();
     }
 
-    /**
-     * @param string
-     */
-    public void setAttributeName(String string) {
-        attributeName = string;
+    public void renderFieldString(Appendable writer, Map<String, Object> 
context, FormStringRenderer formStringRenderer)
+            throws IOException {
+        this.fieldInfo.renderFieldString(writer, context, formStringRenderer);
     }
 
     /**
-     * @param string
+     * the widget/interaction part will be red if the date value is
+     *  before-now (for ex. thruDate), after-now (for ex. fromDate), or 
by-name (if the
+     *  field's name or entry-name or fromDate or thruDate the corresponding
+     *  action will be done); only applicable when the field is a timestamp
+     *
+     * @param context the context
+     * @return true if the field should be read otherwise false
      */
-    public void setEntityName(String string) {
-        entityName = string;
-    }
+    public boolean shouldBeRed(Map<String, Object> context) {
+        // red-when (never | before-now | after-now | by-name) "by-name"
 
-    /**
-     * @param string
-     */
-    public void setEntryName(String string) {
-        entryAcsr = FlexibleMapAccessor.getInstance(string);
-    }
+        String redCondition = this.redWhen;
 
-    /**
-     * @param string
-     */
-    public void setFieldName(String string) {
-        fieldName = string;
-    }
+        if ("never".equals(redCondition))
+            return false;
 
-    /**
-     * @param string
-     */
-    public void setMapName(String string) {
-        this.mapAcsr = FlexibleMapAccessor.getInstance(string);
-    }
+        // for performance resaons we check this first, most fields will be 
eliminated here and the valueOfs will not be necessary
+        if (UtilValidate.isEmpty(redCondition) || 
"by-name".equals(redCondition)) {
+            if ("fromDate".equals(this.name) || (this.entryAcsr != null && 
"fromDate".equals(this.entryAcsr.getOriginalName()))) {
+                redCondition = "after-now";
+            } else if ("thruDate".equals(this.name)
+                    || (this.entryAcsr != null && 
"thruDate".equals(this.entryAcsr.getOriginalName()))) {
+                redCondition = "before-now";
+            } else {
+                return false;
+            }
+        }
 
-    /**
-     * @param string
-     */
-    public void setName(String string) {
-        name = string;
-    }
+        boolean isBeforeNow = false;
+        if ("before-now".equals(redCondition)) {
+            isBeforeNow = true;
+        } else if ("after-now".equals(redCondition)) {
+            isBeforeNow = false;
+        } else {
+            return false;
+        }
 
-    /**
-     * @param string
-     */
-    public void setParameterName(String string) {
-        parameterName = string;
-    }
+        java.sql.Date dateVal = null;
+        java.sql.Time timeVal = null;
+        java.sql.Timestamp timestampVal = null;
 
-    /**
-     * @param i
-     */
-    public void setPosition(int i) {
-        position = Integer.valueOf(i);
-    }
-
-    /**
-     * @param string
-     */
-    public void setRedWhen(String string) {
-        redWhen = string;
-    }
-
-    /**
-     * @param string
-     */
-    public void setEvent(String string) {
-        event = string;
-    }
-
-    /**
-     * @param string
-     */
-    public void setAction(String string) {
-        this.action = FlexibleStringExpander.getInstance(string);
-    }
-
-    /**
-     * @param string
-     */
-    public void setServiceName(String string) {
-        serviceName = string;
-    }
-
-    /**
-     * @param string
-     */
-    public void setTitle(String string) {
-        this.title = FlexibleStringExpander.getInstance(string);
-    }
-
-    /**
-     * @param string
-     */
-    public void setTitleAreaStyle(String string) {
-        this.titleAreaStyle = string;
-    }
-
-    /**
-     * @param string
-     */
-    public void setTitleStyle(String string) {
-        this.titleStyle = string;
-    }
-
-    /**
-     * @param string
-     */
-    public void setTooltip(String string) {
-        this.tooltip = FlexibleStringExpander.getInstance(string);
-    }
-
-    /**
-     * @param string
-     */
-    public void setUseWhen(String string) {
-        this.useWhen = FlexibleStringExpander.getInstance(string);
-    }
-
-    public void setEncodeOutput(boolean encodeOutput) {
-        this.encodeOutput = encodeOutput;
-    }
-
-    /**
-     * @param string
-     */
-    public void setWidgetAreaStyle(String string) {
-        this.widgetAreaStyle = string;
-    }
-
-    /**
-     * @param string
-     */
-    public void setWidgetStyle(String string) {
-        this.widgetStyle = string;
-    }
-
-    /**
-     * @param string
-     */
-    public void setTooltipStyle(String string) {
-        this.tooltipStyle = string;
-    }
-
-    public boolean getSeparateColumn() {
-        return this.separateColumn;
-    }
-
-    /**
-     * @param string
-     */
-    public void setHeaderLink(String string) {
-        this.headerLink = string;
-    }
-
-    /**
-     * @param string
-     */
-    public void setHeaderLinkStyle(String string) {
-        this.headerLinkStyle = string;
-    }
-
-    public boolean getRequiredField() {
-        return this.requiredField != null ? this.requiredField : false;
-    }
-
-    /**
-     * @param required the field is required 
-     */
-    public void setRequiredField(boolean required) {
-        this.requiredField = required;
-    }
-
-    public String getSortFieldHelpText(Map<String, Object> context) {
-        return FlexibleStringExpander.expandString(this.sortFieldHelpText, 
context);
-    }
-
-    public boolean isSortField() {
-        return this.sortField != null && this.sortField.booleanValue();
-    }
-
-    /**
-     * @param sort set as sort field
-     */
-    public void setSortField(boolean sort) {
-        this.sortField = Boolean.valueOf(sort);
-    }
-
-    /**
-     * @param modelForm the model form
-     */
-    public void setModelForm(ModelForm modelForm) {
-        this.modelForm = modelForm;
-    }
-
-    public static abstract class FieldInfoWithOptions extends FieldInfo {
-
-        protected FlexibleStringExpander noCurrentSelectedKey = null;
-        protected List<OptionSource> optionSources = new 
LinkedList<OptionSource>();
-
-        public FieldInfoWithOptions(int fieldSource, int fieldType, 
ModelFormField modelFormField) {
-            super(fieldSource, fieldType, modelFormField);
+        //now before going on, check to see if the current entry is a valid 
date and/or time and get the value
+        String value = this.getEntry(context, null);
+        try {
+            timestampVal = java.sql.Timestamp.valueOf(value);
+        } catch (Exception e) {
+            // okay, not a timestamp...
         }
 
-        // Copy constructor.
-        protected FieldInfoWithOptions(FieldInfoWithOptions original, 
ModelFormField modelFormField) {
-            super(original.getFieldSource(), original.getFieldType(), 
modelFormField);
-            this.noCurrentSelectedKey = original.noCurrentSelectedKey;
-            this.optionSources.addAll(original.optionSources);
+        if (timestampVal == null) {
+            try {
+                dateVal = java.sql.Date.valueOf(value);
+            } catch (Exception e) {
+                // okay, not a date...
+            }
         }
 
-        public FieldInfoWithOptions(Element element, ModelFormField 
modelFormField) {
-            super(element, modelFormField);
-
-            noCurrentSelectedKey = 
FlexibleStringExpander.getInstance(element.getAttribute("no-current-selected-key"));
-
-            // read all option and entity-options sub-elements, maintaining 
order
-            List<? extends Element> childElements = 
UtilXml.childElementList(element);
-            if (childElements.size() > 0) {
-                for (Element childElement : childElements) {
-                    if ("option".equals(childElement.getTagName())) {
-                        this.addOptionSource(new SingleOption(childElement, 
this));
-                    } else if 
("list-options".equals(childElement.getTagName())) {
-                        this.addOptionSource(new ListOptions(childElement, 
this));
-                    } else if 
("entity-options".equals(childElement.getTagName())) {
-                        this.addOptionSource(new EntityOptions(childElement, 
this));
-                    }
-                }
-            } else {
-                // this must be added or the multi-form select box options 
would not show up
-                this.addOptionSource(new SingleOption("Y", " ", this));
+        if (timestampVal == null && dateVal == null) {
+            try {
+                timeVal = java.sql.Time.valueOf(value);
+            } catch (Exception e) {
+                // okay, not a time...
             }
         }
 
-        public List<OptionSource> getOptionSources() {
-            return optionSources;
+        if (timestampVal == null && dateVal == null && timeVal == null) {
+            return false;
         }
 
-        public List<OptionValue> getAllOptionValues(Map<String, Object> 
context, Delegator delegator) {
-            List<OptionValue> optionValues = new LinkedList<OptionValue>();
-            for (OptionSource optionSource : this.optionSources) {
-                optionSource.addOptionValues(optionValues, context, delegator);
+        long nowMillis = System.currentTimeMillis();
+        if (timestampVal != null) {
+            java.sql.Timestamp nowStamp = new java.sql.Timestamp(nowMillis);
+            if (!timestampVal.equals(nowStamp)) {
+                if (isBeforeNow) {
+                    if (timestampVal.before(nowStamp)) {
+                        return true;
+                    }
+                } else {
+                    if (timestampVal.after(nowStamp)) {
+                        return true;
+                    }
+                }
             }
-            return optionValues;
-        }
-
-        public static String getDescriptionForOptionKey(String key, 
List<OptionValue> allOptionValues) {
-            if (UtilValidate.isEmpty(key))
-                return "";
-
-            if (UtilValidate.isEmpty(allOptionValues))
-                return key;
-
-            for (OptionValue optionValue : allOptionValues) {
-                if (key.equals(optionValue.getKey())) {
-                    return optionValue.getDescription();
+        } else if (dateVal != null) {
+            java.sql.Date nowDate = new java.sql.Date(nowMillis);
+            if (!dateVal.equals(nowDate)) {
+                if (isBeforeNow) {
+                    if (dateVal.before(nowDate)) {
+                        return true;
+                    }
+                } else {
+                    if (dateVal.after(nowDate)) {
+                        return true;
+                    }
                 }
             }
-
-            // if we get here we didn't find a match, just return the key
-            return key;
-        }
-
-        public String getNoCurrentSelectedKey(Map<String, Object> context) {
-            if (this.noCurrentSelectedKey == null) {
-                return null;
+        } else if (timeVal != null) {
+            java.sql.Time nowTime = new java.sql.Time(nowMillis);
+            if (!timeVal.equals(nowTime)) {
+                if (isBeforeNow) {
+                    if (timeVal.before(nowTime)) {
+                        return true;
+                    }
+                } else {
+                    if (timeVal.after(nowTime)) {
+                        return true;
+                    }
+                }
             }
-            return this.noCurrentSelectedKey.expandString(context);
-        }
-
-        public void setNoCurrentSelectedKey(String string) {
-            this.noCurrentSelectedKey = 
FlexibleStringExpander.getInstance(string);
-        }
-
-        public void addOptionSource(OptionSource optionSource) {
-            this.optionSources.add(optionSource);
         }
-    }
-
-    public static class OptionValue {
-        protected String key;
-        protected String description;
 
-        public OptionValue(String key, String description) {
-            this.key = key;
-            this.description = description;
-        }
-
-        public String getKey() {
-            return key;
-        }
-
-        public String getDescription() {
-            return description;
-        }
-    }
-
-    public static abstract class OptionSource {
-        protected FieldInfo fieldInfo;
-
-        public abstract void addOptionValues(List<OptionValue> optionValues, 
Map<String, Object> context, Delegator delegator);
+        return false;
     }
 
-    public static class SingleOption extends OptionSource {
-        protected FlexibleStringExpander key;
-        protected FlexibleStringExpander description;
-
-        public SingleOption(String key, String description, FieldInfo 
fieldInfo) {
-            this.key = FlexibleStringExpander.getInstance(key);
-            this.description = 
FlexibleStringExpander.getInstance(UtilXml.checkEmpty(description, key));
-            this.fieldInfo = fieldInfo;
-        }
+    public boolean shouldUse(Map<String, Object> context) {
+        String useWhenStr = this.getUseWhen(context);
+        if (UtilValidate.isEmpty(useWhenStr))
+            return true;
 
-        public SingleOption(Element optionElement, FieldInfo fieldInfo) {
-            this.key = 
FlexibleStringExpander.getInstance(optionElement.getAttribute("key"));
-            this.description = 
FlexibleStringExpander.getInstance(UtilXml.checkEmpty(optionElement.getAttribute("description"),
-                    optionElement.getAttribute("key")));
-            this.fieldInfo = fieldInfo;
-        }
+        try {
+            Interpreter bsh = this.modelForm.getBshInterpreter(context);
+            Object retVal = 
bsh.eval(StringUtil.convertOperatorSubstitutions(useWhenStr));
+            boolean condTrue = false;
+            // retVal should be a Boolean, if not something weird is up...
+            if (retVal instanceof Boolean) {
+                Boolean boolVal = (Boolean) retVal;
+                condTrue = boolVal.booleanValue();
+            } else {
+                throw new IllegalArgumentException("Return value from use-when 
condition eval was not a Boolean: "
+                        + (retVal != null ? retVal.getClass().getName() : 
"null") + " [" + retVal + "] on the field " + this.name
+                        + " of form " + this.modelForm.getName());
+            }
 
-        @Override
-        public void addOptionValues(List<OptionValue> optionValues, 
Map<String, Object> context, Delegator delegator) {
-            optionValues.add(new OptionValue(key.expandString(context), 
description.expandString(context)));
+            return condTrue;
+        } catch (EvalError e) {
+            String errMsg = "Error evaluating BeanShell use-when condition [" 
+ useWhenStr + "] on the field " + this.name
+                    + " of form " + this.modelForm.getName() + ": " + 
e.toString();
+            Debug.logError(e, errMsg, module);
+            //Debug.logError("For use-when eval error context is: " + context, 
module);
+            throw new IllegalArgumentException(errMsg);
         }
     }
 
-    public static class ListOptions extends OptionSource {
-        protected FlexibleMapAccessor<List<? extends Object>> listAcsr;
-        protected String listEntryName;
-        protected FlexibleMapAccessor<Object> keyAcsr;
-        protected FlexibleStringExpander description;
-
-        public ListOptions(String listName, String listEntryName, String 
keyName, String description, FieldInfo fieldInfo) {
-            this.listAcsr = FlexibleMapAccessor.getInstance(listName);
-            this.listEntryName = listEntryName;
-            this.keyAcsr = FlexibleMapAccessor.getInstance(keyName);
-            this.description = FlexibleStringExpander.getInstance(description);
-            this.fieldInfo = fieldInfo;
-        }
+    /**
+     * Models the &lt;auto-complete&gt; element.
+     * 
+     * @see <code>widget-form.xsd</code>
+     */
+    public static class AutoComplete {
+        private final String autoSelect;
+        private final String choices;
+        private final String frequency;
+        private final String fullSearch;
+        private final String ignoreCase;
+        private final String minChars;
+        private final String partialChars;
+        private final String partialSearch;
 
-        public ListOptions(Element optionElement, FieldInfo fieldInfo) {
-            this.listEntryName = optionElement.getAttribute("list-entry-name");
-            this.keyAcsr = 
FlexibleMapAccessor.getInstance(optionElement.getAttribute("key-name"));
-            this.listAcsr = 
FlexibleMapAccessor.getInstance(optionElement.getAttribute("list-name"));
-            this.listEntryName = optionElement.getAttribute("list-entry-name");
-            this.description = 
FlexibleStringExpander.getInstance(optionElement.getAttribute("description"));
-            this.fieldInfo = fieldInfo;
+        public AutoComplete(Element element) {
+            this.autoSelect = element.getAttribute("auto-select");
+            this.frequency = element.getAttribute("frequency");
+            this.minChars = element.getAttribute("min-chars");
+            this.choices = element.getAttribute("choices");
+            this.partialSearch = element.getAttribute("partial-search");
+            this.partialChars = element.getAttribute("partial-chars");
+            this.ignoreCase = element.getAttribute("ignore-case");
+            this.fullSearch = element.getAttribute("full-search");
         }
 
-        @Override
-        public void addOptionValues(List<OptionValue> optionValues, 
Map<String, Object> context, Delegator delegator) {
-            List<? extends Object> dataList = 
UtilGenerics.checkList(this.listAcsr.get(context));
-            if (dataList != null && dataList.size() != 0) {
-                for (Object data : dataList) {
-                    Map<String, Object> localContext = new HashMap<String, 
Object>();
-                    localContext.putAll(context);
-                    if (UtilValidate.isNotEmpty(this.listEntryName)) {
-                        localContext.put(this.listEntryName, data);
-                    } else {
-                        Map<String, Object> dataMap = 
UtilGenerics.checkMap(data);
-                        localContext.putAll(dataMap);
-                    }
-                    Object keyObj = keyAcsr.get(localContext);
-                    String key = null;
-                    if (keyObj instanceof String) {
-                        key = (String) keyObj;
-                    } else {
-                        try {
-                            key = (String) 
ObjectType.simpleTypeConvert(keyObj, "String", null, null);
-                        } catch (GeneralException e) {
-                            String errMsg = "Could not convert field value for 
the field: [" + this.keyAcsr.toString()
-                                    + "] to String for the value [" + keyObj + 
"]: " + e.toString();
-                            Debug.logError(e, errMsg, module);
-                        }
-                    }
-                    optionValues.add(new OptionValue(key, 
description.expandString(localContext)));
-                }
-            }
+        public String getAutoSelect() {
+            return this.autoSelect;
         }
-    }
-
-    public static class EntityOptions extends OptionSource {
-        protected String entityName;
-        protected String keyFieldName;
-        protected FlexibleStringExpander description;
-        protected boolean cache = true;
-        protected String filterByDate;
 
-        protected List<EntityFinderUtil.ConditionExpr> constraintList = null;
-        protected List<String> orderByList = null;
-
-        public EntityOptions(FieldInfo fieldInfo) {
-            this.fieldInfo = fieldInfo;
+        public String getChoices() {
+            return this.choices;
         }
 
-        public EntityOptions(Element entityOptionsElement, FieldInfo 
fieldInfo) {
-            this.entityName = entityOptionsElement.getAttribute("entity-name");
-            this.keyFieldName = 
entityOptionsElement.getAttribute("key-field-name");
-            this.description = 
FlexibleStringExpander.getInstance(entityOptionsElement.getAttribute("description"));
-            this.cache = 
!"false".equals(entityOptionsElement.getAttribute("cache"));
-            this.filterByDate = 
entityOptionsElement.getAttribute("filter-by-date");
-
-            List<? extends Element> constraintElements = 
UtilXml.childElementList(entityOptionsElement, "entity-constraint");
-            if (UtilValidate.isNotEmpty(constraintElements)) {
-                this.constraintList = new 
LinkedList<EntityFinderUtil.ConditionExpr>();
-                for (Element constraintElement : constraintElements) {
-                    constraintList.add(new 
EntityFinderUtil.ConditionExpr(constraintElement));
-                }
-            }
-
-            List<? extends Element> orderByElements = 
UtilXml.childElementList(entityOptionsElement, "entity-order-by");
-            if (UtilValidate.isNotEmpty(orderByElements)) {
-                this.orderByList = new LinkedList<String>();
-                for (Element orderByElement : orderByElements) {
-                    orderByList.add(orderByElement.getAttribute("field-name"));
-                }
-            }
-
-            this.fieldInfo = fieldInfo;
+        public String getFrequency() {
+            return this.frequency;
         }
 
-        public String getEntityName() {
-            return entityName;
+        public String getFullSearch() {
+            return this.fullSearch;
         }
 
-        public String getKeyFieldName() {
-            if (UtilValidate.isNotEmpty(this.keyFieldName))
-                return this.keyFieldName;
-            return this.fieldInfo.getModelFormField().getFieldName(); // get 
the modelFormField fieldName
+        public String getIgnoreCase() {
+            return this.ignoreCase;
         }
 
-        @Override
-        public void addOptionValues(List<OptionValue> optionValues, 
Map<String, Object> context, Delegator delegator) {
-            // first expand any conditions that need expanding based on the 
current context
-            EntityCondition findCondition = null;
-            if (UtilValidate.isNotEmpty(this.constraintList)) {
-                List<EntityCondition> expandedConditionList = new 
LinkedList<EntityCondition>();
-                for (EntityFinderUtil.Condition condition : constraintList) {
-                    ModelEntity modelEntity = 
delegator.getModelEntity(this.entityName);
-                    if (modelEntity == null) {
-                        throw new IllegalArgumentException("Error in 
entity-options: could not find entity [" + this.entityName
-                                + "]");
-                    }
-                    EntityCondition createdCondition = 
condition.createCondition(context, modelEntity,
-                            delegator.getModelFieldTypeReader(modelEntity));
-                    if (createdCondition != null) {
-                        expandedConditionList.add(createdCondition);
-                    }
-                }
-                findCondition = 
EntityCondition.makeCondition(expandedConditionList);
-            }
-
-            try {
-                Locale locale = UtilMisc.ensureLocale(context.get("locale"));
-
-                List<GenericValue> values = null;
-                values = 
EntityQuery.use(delegator).from(this.entityName).where(findCondition).orderBy(this.orderByList).cache(this.cache).queryList();
-                // filter-by-date if requested
-                if ("true".equals(this.filterByDate)) {
-                    values = EntityUtil.filterByDate(values, true);
-                } else if (!"false".equals(this.filterByDate)) {
-                    // not explicitly true or false, check to see if has 
fromDate and thruDate, if so do the filter
-                    ModelEntity modelEntity = 
delegator.getModelEntity(this.entityName);
-                    if (modelEntity != null && modelEntity.isField("fromDate") 
&& modelEntity.isField("thruDate")) {
-                        values = EntityUtil.filterByDate(values, true);
-                    }
-                }
-
-                for (GenericValue value : values) {
-                    // add key and description with string expansion, ie 
expanding ${} stuff, passing locale explicitly to expand value string because 
it won't be found in the Entity
-                    MapStack<String> localContext = MapStack.create(context);
-                    // Rendering code might try to modify the GenericEntity 
instance,
-                    // so we make a copy of it.
-                    Map<String, Object> genericEntityClone = 
UtilGenerics.cast(value.clone());
-                    localContext.push(genericEntityClone);
-
-                    // expand with the new localContext, which is locale aware
-                    String optionDesc = 
this.description.expandString(localContext, locale);
-
-                    Object keyFieldObject = value.get(this.getKeyFieldName());
-                    if (keyFieldObject == null) {
-                        throw new IllegalArgumentException(
-                                "The entity-options identifier (from key-name 
attribute, or default to the field name) ["
-                                        + this.getKeyFieldName() + "], may not 
be a valid key field name for the entity ["
-                                        + this.entityName + "].");
-                    }
-                    String keyFieldValue = keyFieldObject.toString();
-                    optionValues.add(new OptionValue(keyFieldValue, 
optionDesc));
-                }
-            } catch (GenericEntityException e) {
-                Debug.logError(e, "Error getting entity options in form", 
module);
-            }
+        public String getMinChars() {
+            return this.minChars;
         }
-    }
-
-    public static class InPlaceEditor {
-        protected FlexibleStringExpander url;
-        protected String cancelControl;
-        protected String cancelText;
-        protected String clickToEditText;
-        protected String fieldPostCreation;
-        protected String formClassName;
-        protected String highlightColor;
-        protected String highlightEndColor;
-        protected String hoverClassName;
-        protected String htmlResponse;
-        protected String loadingClassName;
-        protected String loadingText;
-        protected String okControl;
-        protected String okText;
-        protected String paramName;
-        protected String savingClassName;
-        protected String savingText;
-        protected String submitOnBlur;
-        protected String textBeforeControls;
-        protected String textAfterControls;
-        protected String textBetweenControls;
-        protected String updateAfterRequestCall;
-        protected String rows;
-        protected String cols;
-        protected Map<FlexibleMapAccessor<Object>, Object> fieldMap;
 
-        public InPlaceEditor(Element element) {
-            this.setUrl(element.getAttribute("url"));
-            this.cancelControl = element.getAttribute("cancel-control");
-            this.cancelText = element.getAttribute("cancel-text");
-            this.clickToEditText = element.getAttribute("click-to-edit-text");
-            this.fieldPostCreation = 
element.getAttribute("field-post-creation");
-            this.formClassName = element.getAttribute("form-class-name");
-            this.highlightColor = element.getAttribute("highlight-color");
-            this.highlightEndColor = 
element.getAttribute("highlight-end-color");
-            this.hoverClassName = element.getAttribute("hover-class-name");
-            this.htmlResponse = element.getAttribute("html-response");
-            this.loadingClassName = element.getAttribute("loading-class-name");
-            this.loadingText = element.getAttribute("loading-text");
-            this.okControl = element.getAttribute("ok-control");
-            this.okText = element.getAttribute("ok-text");
-            this.paramName = element.getAttribute("param-name");
-            this.savingClassName = element.getAttribute("saving-class-name");
-            this.savingText = element.getAttribute("saving-text");
-            this.submitOnBlur = element.getAttribute("submit-on-blur");
-            this.textBeforeControls = 
element.getAttribute("text-before-controls");
-            this.textAfterControls = 
element.getAttribute("text-after-controls");
-            this.textBetweenControls = 
element.getAttribute("text-between-controls");
-            this.updateAfterRequestCall = 
element.getAttribute("update-after-request-call");
+        public String getPartialChars() {
+            return this.partialChars;
+        }
 
-            Element simpleElement = UtilXml.firstChildElement(element, 
"simple-editor");
-            this.rows = simpleElement.getAttribute("rows");
-            this.cols = simpleElement.getAttribute("cols");
+        public String getPartialSearch() {
+            return this.partialSearch;
+        }
+    }
 
-            this.fieldMap = EntityFinderUtil.makeFieldMap(element);
+    /**
+     * Models the &lt;check&gt; element.
+     * 
+     * @see <code>widget-form.xsd</code>
+     */
+    public static class CheckField extends FieldInfoWithOptions {
+        public final static String ROW_SUBMIT_FIELD_NAME = "_rowSubmit";
+        private final FlexibleStringExpander allChecked;
+
+        private CheckField(CheckField original, ModelFormField modelFormField) 
{
+            super(original, modelFormField);
+            this.allChecked = original.allChecked;
         }
 
-        public String getUrl(Map<String, Object> context) {
-            if (this.url != null) {
-                return this.url.expandString(context);
-            } else {
-                return "";
-            }
+        public CheckField(Element element, ModelFormField modelFormField) {
+            super(element, modelFormField);
+            allChecked = 
FlexibleStringExpander.getInstance(element.getAttribute("all-checked"));
         }
 
-        public String getCancelControl() {
-            return this.cancelControl;
+        public CheckField(int fieldSource, ModelFormField modelFormField) {
+            super(fieldSource, FieldInfo.CHECK, modelFormField);
+            this.allChecked = FlexibleStringExpander.getInstance("");
         }
 
-        public String getCancelText() {
-            return this.cancelText;
+        public CheckField(ModelFormField modelFormField) {
+            super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.CHECK, modelFormField);
+            this.allChecked = FlexibleStringExpander.getInstance("");
         }
 
-        public String getClickToEditText() {
-            return this.clickToEditText;
+        @Override
+        public void accept(ModelFieldVisitor visitor) {
+            visitor.visit(this);
         }
 
-        public String getFieldPostCreation() {
-            return this.fieldPostCreation;
+        @Override
+        public FieldInfo copy(ModelFormField modelFormField) {
+            return new CheckField(this, modelFormField);
         }
 
-        public String getFormClassName() {
-            return this.formClassName;
+        public FlexibleStringExpander getAllChecked() {
+            return allChecked;
         }
 
-        public String getHighlightColor() {
-            return this.highlightColor;
+        public Boolean isAllChecked(Map<String, Object> context) {
+            String allCheckedStr = this.allChecked.expandString(context);
+            if (!allCheckedStr.isEmpty())
+                return Boolean.valueOf("true".equals(allCheckedStr));
+            else
+                return null;
         }
 
-        public String getHighlightEndColor() {
-            return this.highlightEndColor;
+        @Override
+        public void renderFieldString(Appendable writer, Map<String, Object> 
context, FormStringRenderer formStringRenderer)
+                throws IOException {
+            formStringRenderer.renderCheckField(writer, context, this);
         }
+    }
 
-        public String getHoverClassName() {
-            return this.hoverClassName;
+    /**
+     * Models the &lt;container&gt; element.
+     * 
+     * @see <code>widget-form.xsd</code>
+     */
+    public static class ContainerField extends FieldInfo {
+
+        private ContainerField(ContainerField original, ModelFormField 
modelFormField) {
+            super(original.getFieldSource(), original.getFieldType(), 
modelFormField);
         }
 
-        public String getHtmlResponse() {
-            return this.htmlResponse;
+        public ContainerField(Element element, ModelFormField modelFormField) {
+            super(element, modelFormField);
         }
 
-        public String getLoadingClassName() {
-            return this.loadingClassName;
+        public ContainerField(int fieldSource, int fieldType, ModelFormField 
modelFormField) {
+            super(fieldSource, fieldType, modelFormField);
         }
 
-        public String getLoadingText() {
-            return this.loadingText;
+        @Override
+        public void accept(ModelFieldVisitor visitor) {
+            visitor.visit(this);
         }
 
-        public String getOkControl() {
-            return this.okControl;
+        @Override
+        public FieldInfo copy(ModelFormField modelFormField) {
+            return new ContainerField(this, modelFormField);
         }
 
-        public String getOkText() {
-            return this.okText;
+        @Override
+        public void renderFieldString(Appendable writer, Map<String, Object> 
context, FormStringRenderer formStringRenderer)
+                throws IOException {
+            formStringRenderer.renderContainerFindField(writer, context, this);
         }
+    }
 
-        public String getParamName() {
-            return this.paramName;
+    /**
+     * Models the &lt;date-find&gt; element.
+     * 
+     * @see <code>widget-form.xsd</code>
+     */
+    public static class DateFindField extends DateTimeField {
+        private final String defaultOptionFrom;
+        private final String defaultOptionThru;
+
+        private DateFindField(DateFindField original, ModelFormField 
modelFormField) {
+            super(original, modelFormField);

[... 4377 lines stripped ...]

Reply via email to