You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by ad...@apache.org on 2015/01/18 22:03:42 UTC
svn commit: r1652852 [7/22] - in /ofbiz/trunk:
applications/content/src/org/ofbiz/content/cms/
applications/content/src/org/ofbiz/content/content/
applications/content/src/org/ofbiz/content/data/
applications/content/src/org/ofbiz/content/output/ appli...
Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelFormField.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelFormField.java?rev=1652852&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelFormField.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelFormField.java Sun Jan 18 21:03:40 2015
@@ -0,0 +1,3806 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.widget.model;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+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;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.TimeZone;
+
+import org.ofbiz.base.conversion.ConversionException;
+import org.ofbiz.base.conversion.DateTimeConverters;
+import org.ofbiz.base.conversion.DateTimeConverters.StringToTimestamp;
+import org.ofbiz.base.util.BshUtil;
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.GeneralException;
+import org.ofbiz.base.util.ObjectType;
+import org.ofbiz.base.util.StringUtil;
+import org.ofbiz.base.util.UtilCodec;
+import org.ofbiz.base.util.UtilDateTime;
+import org.ofbiz.base.util.UtilFormatOut;
+import org.ofbiz.base.util.UtilGenerics;
+import org.ofbiz.base.util.UtilMisc;
+import org.ofbiz.base.util.UtilProperties;
+import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.base.util.UtilXml;
+import org.ofbiz.base.util.collections.FlexibleMapAccessor;
+import org.ofbiz.base.util.collections.MapStack;
+import org.ofbiz.base.util.string.FlexibleStringExpander;
+import org.ofbiz.entity.Delegator;
+import org.ofbiz.entity.GenericEntity;
+import org.ofbiz.entity.GenericEntityException;
+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.util.EntityUtil;
+import org.ofbiz.widget.WidgetWorker;
+import org.ofbiz.widget.model.CommonWidgetModels.AutoEntityParameters;
+import org.ofbiz.widget.model.CommonWidgetModels.AutoServiceParameters;
+import org.ofbiz.widget.model.CommonWidgetModels.Image;
+import org.ofbiz.widget.model.CommonWidgetModels.Link;
+import org.ofbiz.widget.model.CommonWidgetModels.Parameter;
+import org.ofbiz.widget.model.ModelForm.UpdateArea;
+import org.ofbiz.widget.renderer.FormStringRenderer;
+import org.w3c.dom.Element;
+
+import bsh.EvalError;
+import bsh.Interpreter;
+
+/**
+ * Models the <field> element.
+ *
+ * @see <code>widget-form.xsd</code>
+ */
+public class ModelFormField {
+
+ /*
+ * ----------------------------------------------------------------------- *
+ * 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!
+ *
+ */
+
+ public static final String module = ModelFormField.class.getName();
+
+ public static ModelFormField from(ModelFormFieldBuilder builder) {
+ return new ModelFormField(builder);
+ }
+
+ 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 {
+ this.fieldInfo = null;
+ }
+ 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();
+ if (builder.getOnChangeUpdateAreas().isEmpty()) {
+ this.onChangeUpdateAreas = Collections.emptyList();
+ } else {
+ this.onChangeUpdateAreas = Collections.unmodifiableList(new ArrayList<UpdateArea>(builder.getOnChangeUpdateAreas()));
+ }
+ if (builder.getOnClickUpdateAreas().isEmpty()) {
+ this.onClickUpdateAreas = Collections.emptyList();
+ } else {
+ this.onClickUpdateAreas = Collections.unmodifiableList(new ArrayList<UpdateArea>(builder.getOnClickUpdateAreas()));
+ }
+ 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 FlexibleStringExpander getAction() {
+ return action;
+ }
+
+ public String getAction(Map<String, ? extends Object> context) {
+ if (UtilValidate.isNotEmpty(this.action))
+ return action.expandString(context);
+ return null;
+ }
+
+ /**
+ * Gets the name of the Service Attribute (aka Parameter) that corresponds
+ * with this field. This can be used to get additional information about the field.
+ * Use the getServiceName() method to get the Entity name that the field is in.
+ *
+ * @return returns the name of the Service Attribute
+ */
+ public String getAttributeName() {
+ if (UtilValidate.isNotEmpty(this.attributeName))
+ return this.attributeName;
+ 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();
+ }
+
+ /**
+ * 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 retrieved from the parameters Map in
+ * the context.
+ *
+ * @param context the context
+ * @return returns the entry from the context that corresponds to this field
+ */
+ public String getEntry(Map<String, ? extends Object> context) {
+ return this.getEntry(context, "");
+ }
+
+ public String getEntry(Map<String, ? extends Object> context, String defaultValue) {
+ Boolean isError = (Boolean) context.get("isError");
+ Boolean useRequestParameters = (Boolean) context.get("useRequestParameters");
+
+ Locale locale = (Locale) context.get("locale");
+ if (locale == null)
+ locale = Locale.getDefault();
+ TimeZone timeZone = (TimeZone) context.get("timeZone");
+ if (timeZone == null)
+ timeZone = TimeZone.getDefault();
+
+ String returnValue;
+
+ // if useRequestParameters is TRUE then parameters will always be used, if FALSE then parameters will never be used
+ // if isError is TRUE and useRequestParameters is not FALSE (ie is null or TRUE) then parameters will be used
+ if ((Boolean.TRUE.equals(isError) && !Boolean.FALSE.equals(useRequestParameters))
+ || (Boolean.TRUE.equals(useRequestParameters))) {
+ //Debug.logInfo("Getting entry, isError true so getting from parameters for field " + this.getName() + " of form " + this.modelForm.getName(), module);
+ Map<String, Object> parameters = UtilGenerics.checkMap(context.get("parameters"), String.class, Object.class);
+ String parameterName = this.getParameterName(context);
+ if (parameters != null && parameters.get(parameterName) != null) {
+ Object parameterValue = parameters.get(parameterName);
+ if (parameterValue instanceof String) {
+ returnValue = (String) parameterValue;
+ } else {
+ // we might want to do something else here in the future, but for now this is probably best
+ Debug.logWarning("Found a non-String parameter value for field [" + this.getModelForm().getName() + "."
+ + this.getFieldName() + "]", module);
+ returnValue = defaultValue;
+ }
+ } else {
+ returnValue = defaultValue;
+ }
+ } else {
+ //Debug.logInfo("Getting entry, isError false so getting from Map in context for field " + this.getName() + " of form " + this.modelForm.getName(), module);
+ Map<String, ? extends Object> dataMap = this.getMap(context);
+ boolean dataMapIsContext = false;
+ if (dataMap == null) {
+ //Debug.logInfo("Getting entry, no Map found with name " + this.getMapName() + ", using context for field " + this.getName() + " of form " + this.modelForm.getName(), module);
+ dataMap = context;
+ dataMapIsContext = true;
+ }
+ Object retVal = null;
+ if (UtilValidate.isNotEmpty(this.entryAcsr)) {
+ if (dataMap instanceof GenericEntity) {
+ GenericEntity genEnt = (GenericEntity) dataMap;
+ if (genEnt.getModelEntity().isField(this.entryAcsr.getOriginalName())) {
+ retVal = genEnt.get(this.entryAcsr.getOriginalName(), locale);
+ } else {
+ //TODO: this may never come up, but if necessary use the FlexibleStringExander to eval the name first: String evaled = this.entryAcsr
+ }
+ } else {
+ retVal = this.entryAcsr.get(dataMap, locale);
+ }
+ } else {
+ // if no entry name was specified, use the field's name
+ if (dataMap.containsKey(this.name)) {
+ retVal = dataMap.get(this.name);
+ }
+ }
+
+ // this is a special case to fill in fields during a create by default from parameters passed in
+ if (dataMapIsContext && retVal == null && !Boolean.FALSE.equals(useRequestParameters)) {
+ Map<String, ? extends Object> parameters = UtilGenerics.checkMap(context.get("parameters"));
+ if (parameters != null) {
+ if (UtilValidate.isNotEmpty(this.entryAcsr))
+ retVal = this.entryAcsr.get(parameters);
+ else
+ retVal = parameters.get(this.name);
+ }
+ }
+
+ if (retVal != null) {
+ // format string based on the user's locale and time zone
+ if (retVal instanceof Double || retVal instanceof Float || retVal instanceof BigDecimal) {
+ NumberFormat nf = NumberFormat.getInstance(locale);
+ nf.setMaximumFractionDigits(10);
+ return nf.format(retVal);
+ } else if (retVal instanceof java.sql.Date) {
+ DateFormat df = UtilDateTime.toDateFormat(UtilDateTime.DATE_FORMAT, timeZone, null);
+ return df.format((java.util.Date) retVal);
+ } else if (retVal instanceof java.sql.Time) {
+ DateFormat df = UtilDateTime.toTimeFormat(UtilDateTime.TIME_FORMAT, timeZone, null);
+ return df.format((java.util.Date) retVal);
+ } else if (retVal instanceof java.sql.Timestamp) {
+ DateFormat df = UtilDateTime.toDateTimeFormat(UtilDateTime.DATE_TIME_FORMAT, timeZone, null);
+ return df.format((java.util.Date) retVal);
+ } else if (retVal instanceof java.util.Date) {
+ DateFormat df = UtilDateTime.toDateTimeFormat("EEE MMM dd hh:mm:ss z yyyy", timeZone, null);
+ return df.format((java.util.Date) retVal);
+ } else {
+ returnValue = retVal.toString();
+ }
+ } else {
+ returnValue = defaultValue;
+ }
+ }
+
+ if (this.getEncodeOutput() && returnValue != null) {
+ UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
+ if (simpleEncoder != null)
+ returnValue = simpleEncoder.encode(returnValue);
+ }
+ 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);
+
+ // Debug.logInfo("Getting Map from mapAcsr for field " + this.getName() + ", map-name=" + mapAcsr.getOriginalName() + ", context type=" + context.getClass().toString(), module);
+ Map<String, ? extends Object> result = null;
+ try {
+ result = mapAcsr.get(context);
+ } catch (java.lang.ClassCastException e) {
+ String errMsg = "Got an unexpected object type (not a Map) for map-name [" + mapAcsr.getOriginalName()
+ + "] in field with name [" + this.getName() + "]: " + e.getMessage();
+ Debug.logError(errMsg, module);
+ throw new ClassCastException(errMsg);
+ }
+ return result;
+ }
+
+ public FlexibleMapAccessor<Map<String, ? extends Object>> getMapAcsr() {
+ return mapAcsr;
+ }
+
+ /** Get the name of the Map in the form context that contains the entry,
+ * available from the getEntryName() method. This entry is used to
+ * pre-populate the field widget when not in an error condition. In an
+ * error condition the parameter name is used to get the value from the
+ * parameters Map.
+ *
+ * @return returns the name of the Map in the form context that contains the entry
+ */
+ public String getMapName() {
+ if (UtilValidate.isNotEmpty(this.mapAcsr))
+ return this.mapAcsr.getOriginalName();
+ 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.
+ *
+ * @return returns the name to use for the parameter for this field in the form interpreter
+ */
+ public String getParameterName(Map<String, ? extends Object> context) {
+ String baseName;
+ if (UtilValidate.isNotEmpty(this.parameterName))
+ baseName = this.parameterName;
+ else
+ baseName = this.name;
+
+ Integer itemIndex = (Integer) context.get("itemIndex");
+ if (itemIndex != null && "multi".equals(this.modelForm.getType())) {
+ return baseName + this.modelForm.getItemIndexSeparator() + itemIndex.intValue();
+ } else {
+ return baseName;
+ }
+ }
+
+ public int getPosition() {
+ if (this.position == null)
+ return 1;
+ return position.intValue();
+ }
+
+ public String getRedWhen() {
+ return redWhen;
+ }
+
+ public boolean getRequiredField() {
+ return this.requiredField != null ? this.requiredField : false;
+ }
+
+ public String getRequiredFieldStyle() {
+ if (UtilValidate.isNotEmpty(this.requiredFieldStyle))
+ return this.requiredFieldStyle;
+ return this.modelForm.getDefaultRequiredFieldStyle();
+ }
+
+ public boolean getSeparateColumn() {
+ return this.separateColumn;
+ }
+
+ public String getServiceName() {
+ if (UtilValidate.isNotEmpty(this.serviceName))
+ return this.serviceName;
+ return this.modelForm.getDefaultServiceName();
+ }
+
+ public Boolean getSortField() {
+ return sortField;
+ }
+
+ public String getSortFieldAscStyle() {
+ return sortFieldAscStyle;
+ }
+
+ public String getSortFieldDescStyle() {
+ return sortFieldDescStyle;
+ }
+
+ public String getSortFieldHelpText() {
+ return sortFieldHelpText;
+ }
+
+ public String getSortFieldHelpText(Map<String, Object> context) {
+ return FlexibleStringExpander.expandString(this.sortFieldHelpText, context);
+ }
+
+ 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 getTitle() {
+ return title;
+ }
+
+ public String getTitle(Map<String, Object> context) {
+ if (UtilValidate.isNotEmpty(this.title))
+ return title.expandString(context);
+
+ // create a title from the name of this field; expecting a Java method/field style name, ie productName or productCategoryId
+ if (UtilValidate.isEmpty(this.name))
+ return ""; // this should never happen, ie name is required
+
+ // search for a localized label for the field's name
+ Map<String, String> uiLabelMap = UtilGenerics.checkMap(context.get("uiLabelMap"));
+ if (uiLabelMap != null) {
+ String titleFieldName = "FormFieldTitle_" + this.name;
+ String localizedName = uiLabelMap.get(titleFieldName);
+ if (!localizedName.equals(titleFieldName)) {
+ return localizedName;
+ }
+ } else {
+ Debug.logWarning("Could not find uiLabelMap in context while rendering form " + this.modelForm.getName(), module);
+ }
+
+ // create a title from the name of this field; expecting a Java method/field style name, ie productName or productCategoryId
+ StringBuilder autoTitlewriter = new StringBuilder();
+
+ // always use upper case first letter...
+ autoTitlewriter.append(Character.toUpperCase(this.name.charAt(0)));
+
+ // just put spaces before the upper case letters
+ for (int i = 1; i < this.name.length(); i++) {
+ char curChar = this.name.charAt(i);
+ if (Character.isUpperCase(curChar)) {
+ autoTitlewriter.append(' ');
+ }
+ autoTitlewriter.append(curChar);
+ }
+
+ return autoTitlewriter.toString();
+ }
+
+ public String getTitleAreaStyle() {
+ if (UtilValidate.isNotEmpty(this.titleAreaStyle))
+ return this.titleAreaStyle;
+ return this.modelForm.getDefaultTitleAreaStyle();
+ }
+
+ public String getTitleStyle() {
+ if (UtilValidate.isNotEmpty(this.titleStyle))
+ return this.titleStyle;
+ return this.modelForm.getDefaultTitleStyle();
+ }
+
+ public FlexibleStringExpander getTooltip() {
+ return tooltip;
+ }
+
+ public String getTooltip(Map<String, Object> context) {
+ String tooltipString = "";
+ if (UtilValidate.isNotEmpty(tooltip))
+ tooltipString = tooltip.expandString(context);
+ if (this.getEncodeOutput()) {
+ UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
+ if (simpleEncoder != null)
+ tooltipString = simpleEncoder.encode(tooltipString);
+ }
+ return tooltipString;
+ }
+
+ public String getTooltipStyle() {
+ if (UtilValidate.isNotEmpty(this.tooltipStyle))
+ return this.tooltipStyle;
+ return this.modelForm.getDefaultTooltipStyle();
+ }
+
+ public FlexibleStringExpander getUseWhen() {
+ return useWhen;
+ }
+
+ public String getUseWhen(Map<String, Object> context) {
+ if (UtilValidate.isNotEmpty(this.useWhen))
+ return this.useWhen.expandString(context);
+ return "";
+ }
+
+ public String getWidgetAreaStyle() {
+ if (UtilValidate.isNotEmpty(this.widgetAreaStyle))
+ return this.widgetAreaStyle;
+ return this.modelForm.getDefaultWidgetAreaStyle();
+ }
+
+ public String getWidgetStyle() {
+ if (UtilValidate.isNotEmpty(this.widgetStyle))
+ return this.widgetStyle;
+ return this.modelForm.getDefaultWidgetStyle();
+ }
+
+ /**
+ * Checks if field is a row submit field.
+ */
+ public boolean isRowSubmit() {
+ if (!"multi".equals(getModelForm().getType()))
+ return false;
+ if (getFieldInfo().getFieldType() != FieldInfo.CHECK)
+ return false;
+ if (!CheckField.ROW_SUBMIT_FIELD_NAME.equals(getName()))
+ return false;
+ return true;
+ }
+
+ public boolean isSortField() {
+ return this.sortField != null && this.sortField.booleanValue();
+ }
+
+ public boolean isUseWhenEmpty() {
+ if (this.useWhen == null) {
+ return true;
+ }
+
+ return this.useWhen.isEmpty();
+ }
+
+ public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
+ throws IOException {
+ this.fieldInfo.renderFieldString(writer, context, formStringRenderer);
+ }
+
+ /**
+ * 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;
+
+ if ("never".equals(redCondition))
+ return false;
+
+ // 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;
+ }
+ }
+
+ boolean isBeforeNow = false;
+ if ("before-now".equals(redCondition)) {
+ isBeforeNow = true;
+ } else if ("after-now".equals(redCondition)) {
+ isBeforeNow = false;
+ } else {
+ return false;
+ }
+
+ java.sql.Date dateVal = null;
+ java.sql.Time timeVal = null;
+ java.sql.Timestamp timestampVal = null;
+
+ //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...
+ }
+
+ if (timestampVal == null) {
+ try {
+ dateVal = java.sql.Date.valueOf(value);
+ } catch (Exception e) {
+ // okay, not a date...
+ }
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ 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);
+ }
+ }
+
+ /**
+ * Models the <auto-complete> 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 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");
+ }
+
+ public String getAutoSelect() {
+ return this.autoSelect;
+ }
+
+ public String getChoices() {
+ return this.choices;
+ }
+
+ public String getFrequency() {
+ return this.frequency;
+ }
+
+ public String getFullSearch() {
+ return this.fullSearch;
+ }
+
+ public String getIgnoreCase() {
+ return this.ignoreCase;
+ }
+
+ public String getMinChars() {
+ return this.minChars;
+ }
+
+ public String getPartialChars() {
+ return this.partialChars;
+ }
+
+ public String getPartialSearch() {
+ return this.partialSearch;
+ }
+ }
+
+ /**
+ * Models the <check> 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 CheckField(Element element, ModelFormField modelFormField) {
+ super(element, modelFormField);
+ allChecked = FlexibleStringExpander.getInstance(element.getAttribute("all-checked"));
+ }
+
+ public CheckField(int fieldSource, ModelFormField modelFormField) {
+ super(fieldSource, FieldInfo.CHECK, modelFormField);
+ this.allChecked = FlexibleStringExpander.getInstance("");
+ }
+
+ public CheckField(ModelFormField modelFormField) {
+ super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.CHECK, modelFormField);
+ this.allChecked = FlexibleStringExpander.getInstance("");
+ }
+
+ @Override
+ public void accept(ModelFieldVisitor visitor) throws Exception {
+ visitor.visit(this);
+ }
+
+ @Override
+ public FieldInfo copy(ModelFormField modelFormField) {
+ return new CheckField(this, modelFormField);
+ }
+
+ public FlexibleStringExpander getAllChecked() {
+ return allChecked;
+ }
+
+ 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;
+ }
+
+ @Override
+ public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
+ throws IOException {
+ formStringRenderer.renderCheckField(writer, context, this);
+ }
+ }
+
+ /**
+ * Models the <container> 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 ContainerField(Element element, ModelFormField modelFormField) {
+ super(element, modelFormField);
+ }
+
+ public ContainerField(int fieldSource, int fieldType, ModelFormField modelFormField) {
+ super(fieldSource, fieldType, modelFormField);
+ }
+
+ @Override
+ public void accept(ModelFieldVisitor visitor) throws Exception {
+ visitor.visit(this);
+ }
+
+ @Override
+ public FieldInfo copy(ModelFormField modelFormField) {
+ return new ContainerField(this, modelFormField);
+ }
+
+ @Override
+ public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
+ throws IOException {
+ formStringRenderer.renderContainerFindField(writer, context, this);
+ }
+ }
+
+ /**
+ * Models the <date-find> 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);
+ this.defaultOptionFrom = original.defaultOptionFrom;
+ this.defaultOptionThru = original.defaultOptionThru;
+ }
+
+ public DateFindField(Element element, ModelFormField modelFormField) {
+ super(element, modelFormField);
+ this.defaultOptionFrom = element.getAttribute("default-option-from");
+ this.defaultOptionThru = element.getAttribute("default-option-thru");
+ }
+
+ public DateFindField(int fieldSource, ModelFormField modelFormField) {
+ super(fieldSource, modelFormField);
+ this.defaultOptionFrom = "greaterThanEqualTo";
+ this.defaultOptionThru = "lessThanEqualTo";
+ }
+
+ public DateFindField(int fieldSource, String type) {
+ super(fieldSource, type);
+ this.defaultOptionFrom = "greaterThanEqualTo";
+ this.defaultOptionThru = "lessThanEqualTo";
+ }
+
+ @Override
+ public void accept(ModelFieldVisitor visitor) throws Exception {
+ visitor.visit(this);
+ }
+
+ @Override
+ public FieldInfo copy(ModelFormField modelFormField) {
+ return new DateFindField(this, modelFormField);
+ }
+
+ public String getDefaultOptionFrom() {
+ return this.defaultOptionFrom;
+ }
+
+ public String getDefaultOptionThru() {
+ return this.defaultOptionThru;
+ }
+
+ @Override
+ public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
+ throws IOException {
+ formStringRenderer.renderDateFindField(writer, context, this);
+ }
+ }
+
+ /**
+ * Models the <date-time> element.
+ *
+ * @see <code>widget-form.xsd</code>
+ */
+ public static class DateTimeField extends FieldInfo {
+ private final String clock;
+ private final FlexibleStringExpander defaultValue;
+ private final String inputMethod;
+ private final String mask;
+ private final String step;
+ private final String type;
+
+ protected DateTimeField(DateTimeField original, ModelFormField modelFormField) {
+ super(original.getFieldSource(), original.getFieldType(), modelFormField);
+ this.defaultValue = original.defaultValue;
+ this.type = original.type;
+ this.inputMethod = original.inputMethod;
+ this.clock = original.clock;
+ this.mask = original.mask;
+ this.step = original.step;
+ }
+
+ public DateTimeField(Element element, ModelFormField modelFormField) {
+ super(element, modelFormField);
+ this.defaultValue = FlexibleStringExpander.getInstance(element.getAttribute("default-value"));
+ this.type = element.getAttribute("type");
+ this.inputMethod = element.getAttribute("input-method");
+ this.clock = element.getAttribute("clock");
+ this.mask = element.getAttribute("mask");
+ String step = element.getAttribute("step");
+ if (step.isEmpty()) {
+ step = "1";
+ }
+ this.step = step;
+ }
+
+ public DateTimeField(int fieldSource, ModelFormField modelFormField) {
+ super(fieldSource, FieldInfo.DATE_TIME, modelFormField);
+ this.defaultValue = FlexibleStringExpander.getInstance("");
+ this.type = "";
+ this.inputMethod = "";
+ this.clock = "";
+ this.mask = "";
+ this.step = "1";
+ }
+
+ public DateTimeField(int fieldSource, String type) {
+ super(fieldSource, FieldInfo.DATE_TIME, null);
+ this.defaultValue = FlexibleStringExpander.getInstance("");
+ this.type = type;
+ this.inputMethod = "";
+ this.clock = "";
+ this.mask = "";
+ this.step = "1";
+ }
+
+ public DateTimeField(ModelFormField modelFormField) {
+ super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.DATE_TIME, modelFormField);
+ this.defaultValue = FlexibleStringExpander.getInstance("");
+ this.type = "";
+ this.inputMethod = "";
+ this.clock = "";
+ this.mask = "";
+ this.step = "1";
+ }
+
+ @Override
+ public void accept(ModelFieldVisitor visitor) throws Exception {
+ visitor.visit(this);
+ }
+
+ @Override
+ public FieldInfo copy(ModelFormField modelFormField) {
+ return new DateTimeField(this, modelFormField);
+ }
+
+ public String getClock() {
+ return this.clock;
+ }
+
+ /**
+ * Returns the default-value if specified, otherwise the current date, time or timestamp
+ *
+ * @param context Context Map
+ * @return Default value string for date-time
+ */
+ public String getDefaultDateTimeString(Map<String, Object> context) {
+ if (UtilValidate.isNotEmpty(this.defaultValue))
+ return this.getDefaultValue(context);
+
+ if ("date".equals(this.type))
+ return (new java.sql.Date(System.currentTimeMillis())).toString();
+ else if ("time".equals(this.type))
+ return (new java.sql.Time(System.currentTimeMillis())).toString();
+ else
+ return UtilDateTime.nowTimestamp().toString();
+ }
+
+ public FlexibleStringExpander getDefaultValue() {
+ return defaultValue;
+ }
+
+ public String getDefaultValue(Map<String, Object> context) {
+ if (this.defaultValue != null) {
+ return this.defaultValue.expandString(context);
+ } else {
+ return "";
+ }
+ }
+
+ public String getInputMethod() {
+ return this.inputMethod;
+ }
+
+ public String getMask() {
+ return this.mask;
+ }
+
+ public String getStep() {
+ return this.step;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ @Override
+ public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
+ throws IOException {
+ formStringRenderer.renderDateTimeField(writer, context, this);
+ }
+ }
+
+ /**
+ * Models the <display-entity> element.
+ *
+ * @see <code>widget-form.xsd</code>
+ */
+ public static class DisplayEntityField extends DisplayField {
+ private final boolean cache;
+ private final String entityName;
+ private final String keyFieldName;
+ private final SubHyperlink subHyperlink;
+
+ private DisplayEntityField(DisplayEntityField original, ModelFormField modelFormField) {
+ super(original, modelFormField);
+ this.cache = original.cache;
+ this.entityName = original.entityName;
+ this.keyFieldName = original.keyFieldName;
+ if (original.subHyperlink != null) {
+ this.subHyperlink = new SubHyperlink(original.subHyperlink, modelFormField);
+ } else {
+ this.subHyperlink = null;
+ }
+ }
+
+ public DisplayEntityField(Element element, ModelFormField modelFormField) {
+ super(element, modelFormField);
+ this.cache = !"false".equals(element.getAttribute("cache"));
+ this.entityName = element.getAttribute("entity-name");
+ this.keyFieldName = element.getAttribute("key-field-name");
+ Element subHyperlinkElement = UtilXml.firstChildElement(element, "sub-hyperlink");
+ if (subHyperlinkElement != null) {
+ this.subHyperlink = new SubHyperlink(subHyperlinkElement, modelFormField);
+ } else {
+ this.subHyperlink = null;
+ }
+ }
+
+ public DisplayEntityField(int fieldSource, ModelFormField modelFormField) {
+ super(fieldSource, FieldInfo.DISPLAY_ENTITY, modelFormField);
+ this.cache = true;
+ this.entityName = "";
+ this.keyFieldName = "";
+ this.subHyperlink = null;
+ }
+
+ public DisplayEntityField(ModelFormField modelFormField) {
+ super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.DISPLAY_ENTITY, modelFormField);
+ this.cache = true;
+ this.entityName = "";
+ this.keyFieldName = "";
+ this.subHyperlink = null;
+ }
+
+ @Override
+ public void accept(ModelFieldVisitor visitor) throws Exception {
+ visitor.visit(this);
+ }
+
+ @Override
+ public FieldInfo copy(ModelFormField modelFormField) {
+ return new DisplayEntityField(this, modelFormField);
+ }
+
+ public boolean getCache() {
+ return cache;
+ }
+
+ @Override
+ public String getDescription(Map<String, Object> context) {
+ Locale locale = UtilMisc.ensureLocale(context.get("locale"));
+
+ // rather than using the context to expand the string, lookup the given entity and use it to expand the string
+ GenericValue value = null;
+ String fieldKey = this.keyFieldName;
+ if (UtilValidate.isEmpty(fieldKey))
+ fieldKey = getModelFormField().fieldName;
+
+ Delegator delegator = WidgetWorker.getDelegator(context);
+ String fieldValue = getModelFormField().getEntry(context);
+ try {
+ value = delegator.findOne(this.entityName, this.cache, fieldKey, fieldValue);
+ } catch (GenericEntityException e) {
+ String errMsg = "Error getting value from the database for display of field [" + getModelFormField().getName()
+ + "] on form [" + getModelFormField().modelForm.getName() + "]: " + e.toString();
+ Debug.logError(e, errMsg, module);
+ throw new IllegalArgumentException(errMsg);
+ }
+
+ String retVal = null;
+ if (value != null) {
+ // 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
+ retVal = this.getDescription().expandString(localContext, locale);
+ }
+ // try to get the entry for the field if description doesn't expand to anything
+ if (UtilValidate.isEmpty(retVal))
+ retVal = fieldValue;
+ if (UtilValidate.isEmpty(retVal))
+ retVal = "";
+ return retVal;
+ }
+
+ public String getEntityName() {
+ return entityName;
+ }
+
+ public String getKeyFieldName() {
+ return keyFieldName;
+ }
+
+ public SubHyperlink getSubHyperlink() {
+ return this.subHyperlink;
+ }
+ }
+
+ /**
+ * Models the <display> element.
+ *
+ * @see <code>widget-form.xsd</code>
+ */
+ public static class DisplayField extends FieldInfo {
+ private final boolean alsoHidden;
+ private final FlexibleStringExpander currency;
+ private final FlexibleStringExpander date;
+ private final FlexibleStringExpander defaultValue;
+ private final FlexibleStringExpander description;
+ private final FlexibleStringExpander imageLocation;
+ private final InPlaceEditor inPlaceEditor;
+ private final String size; // maximum number of characters to display
+ private final String type; // matches type of field, currently text or currency
+
+ protected DisplayField(DisplayField original, ModelFormField modelFormField) {
+ super(original.getFieldSource(), original.getFieldType(), modelFormField);
+ this.alsoHidden = original.alsoHidden;
+ this.currency = original.currency;
+ this.date = original.date;
+ this.defaultValue = original.defaultValue;
+ this.description = original.description;
+ this.imageLocation = original.imageLocation;
+ this.inPlaceEditor = original.inPlaceEditor;
+ this.size = original.size;
+ this.type = original.type;
+ }
+
+ public DisplayField(Element element, ModelFormField modelFormField) {
+ super(element, modelFormField);
+ this.alsoHidden = !"false".equals(element.getAttribute("also-hidden"));
+ this.currency = FlexibleStringExpander.getInstance(element.getAttribute("currency"));
+ this.date = FlexibleStringExpander.getInstance(element.getAttribute("date"));
+ this.defaultValue = FlexibleStringExpander.getInstance(element.getAttribute("default-value"));
+ this.description = FlexibleStringExpander.getInstance(element.getAttribute("description"));
+ this.imageLocation = FlexibleStringExpander.getInstance(element.getAttribute("image-location"));
+ Element inPlaceEditorElement = UtilXml.firstChildElement(element, "in-place-editor");
+ if (inPlaceEditorElement != null) {
+ this.inPlaceEditor = new InPlaceEditor(inPlaceEditorElement);
+ } else {
+ this.inPlaceEditor = null;
+ }
+ this.size = element.getAttribute("size");
+ this.type = element.getAttribute("type");
+ }
+
+ public DisplayField(int fieldSource, int fieldType, ModelFormField modelFormField) {
+ super(fieldSource, fieldType, modelFormField);
+ this.alsoHidden = true;
+ this.currency = FlexibleStringExpander.getInstance("");
+ this.date = FlexibleStringExpander.getInstance("");
+ this.defaultValue = FlexibleStringExpander.getInstance("");
+ this.description = FlexibleStringExpander.getInstance("");
+ this.imageLocation = FlexibleStringExpander.getInstance("");
+ this.inPlaceEditor = null;
+ this.size = "";
+ this.type = "";
+ }
+
+ public DisplayField(int fieldSource, ModelFormField modelFormField) {
+ super(fieldSource, FieldInfo.DISPLAY, modelFormField);
+ this.alsoHidden = true;
+ this.currency = FlexibleStringExpander.getInstance("");
+ this.date = FlexibleStringExpander.getInstance("");
+ this.defaultValue = FlexibleStringExpander.getInstance("");
+ this.description = FlexibleStringExpander.getInstance("");
+ this.imageLocation = FlexibleStringExpander.getInstance("");
+ this.inPlaceEditor = null;
+ this.size = "";
+ this.type = "";
+ }
+
+ public DisplayField(ModelFormField modelFormField) {
+ super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.DISPLAY, modelFormField);
+ this.alsoHidden = true;
+ this.currency = FlexibleStringExpander.getInstance("");
+ this.date = FlexibleStringExpander.getInstance("");
+ this.defaultValue = FlexibleStringExpander.getInstance("");
+ this.description = FlexibleStringExpander.getInstance("");
+ this.imageLocation = FlexibleStringExpander.getInstance("");
+ this.inPlaceEditor = null;
+ this.size = "";
+ this.type = "";
+ }
+
+ @Override
+ public void accept(ModelFieldVisitor visitor) throws Exception {
+ visitor.visit(this);
+ }
+
+ @Override
+ public FieldInfo copy(ModelFormField modelFormField) {
+ return new DisplayField(this, modelFormField);
+ }
+
+ public boolean getAlsoHidden() {
+ return alsoHidden;
+ }
+
+ public FlexibleStringExpander getCurrency() {
+ return currency;
+ }
+
+ public FlexibleStringExpander getDate() {
+ return date;
+ }
+
+ public FlexibleStringExpander getDefaultValue() {
+ return defaultValue;
+ }
+
+ public String getDefaultValue(Map<String, Object> context) {
+ if (this.defaultValue != null) {
+ return this.defaultValue.expandString(context);
+ } else {
+ return "";
+ }
+ }
+
+ public FlexibleStringExpander getDescription() {
+ return description;
+ }
+
+ public String getDescription(Map<String, Object> context) {
+ String retVal = null;
+ if (UtilValidate.isNotEmpty(this.description))
+ retVal = this.description.expandString(context);
+ else
+ retVal = getModelFormField().getEntry(context);
+
+ if (UtilValidate.isEmpty(retVal)) {
+ retVal = this.getDefaultValue(context);
+ } else if ("currency".equals(type)) {
+ retVal = retVal.replaceAll(" ", " "); // FIXME : encoding currency is a problem for some locale, we should not have any in retVal other case may arise in future...
+ Locale locale = (Locale) context.get("locale");
+ if (locale == null)
+ locale = Locale.getDefault();
+ String isoCode = null;
+ if (UtilValidate.isNotEmpty(this.currency))
+ isoCode = this.currency.expandString(context);
+
+ try {
+ BigDecimal parsedRetVal = (BigDecimal) ObjectType.simpleTypeConvert(retVal, "BigDecimal", null, null, locale,
+ true);
+ retVal = UtilFormatOut.formatCurrency(parsedRetVal, isoCode, locale, 10); // we set the max to 10 digits as an hack to not round numbers in the ui
+ } catch (GeneralException e) {
+ String errMsg = "Error formatting currency value [" + retVal + "]: " + e.toString();
+ Debug.logError(e, errMsg, module);
+ throw new IllegalArgumentException(errMsg);
+ }
+ } else if ("date".equals(this.type) && retVal.length() > 10) {
+ Locale locale = (Locale) context.get("locale");
+ if (locale == null) {
+ locale = Locale.getDefault();
+ }
+
+ StringToTimestamp stringToTimestamp = new DateTimeConverters.StringToTimestamp();
+ Timestamp timestamp = null;
+ try {
+ timestamp = stringToTimestamp.convert(retVal);
+ Date date = new Date(timestamp.getTime());
+
+ DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.SHORT, locale);
+ retVal = dateFormatter.format(date);
+ } catch (ConversionException e) {
+ String errMsg = "Error formatting date using default instead [" + retVal + "]: " + e.toString();
+ Debug.logError(e, errMsg, module);
+ // create default date value from timestamp string
+ retVal = retVal.substring(0, 10);
+ }
+
+ } else if ("date-time".equals(this.type) && retVal.length() > 16) {
+ Locale locale = (Locale) context.get("locale");
+ TimeZone timeZone = (TimeZone) context.get("timeZone");
+ if (locale == null) {
+ locale = Locale.getDefault();
+ }
+ if (timeZone == null) {
+ timeZone = TimeZone.getDefault();
+ }
+
+ StringToTimestamp stringToTimestamp = new DateTimeConverters.StringToTimestamp();
+ Timestamp timestamp = null;
+ try {
+ timestamp = stringToTimestamp.convert(retVal);
+ Date date = new Date(timestamp.getTime());
+
+ DateFormat dateFormatter = UtilDateTime.toDateTimeFormat(null, timeZone, locale);
+ retVal = dateFormatter.format(date);
+ } catch (ConversionException e) {
+ String errMsg = "Error formatting date/time using default instead [" + retVal + "]: " + e.toString();
+ Debug.logError(e, errMsg, module);
+ // create default date/time value from timestamp string
+ retVal = retVal.substring(0, 16);
+ }
+ } else if ("accounting-number".equals(this.type)) {
+ Locale locale = (Locale) context.get("locale");
+ if (locale == null) {
+ locale = Locale.getDefault();
+ }
+ try {
+ Double parsedRetVal = (Double) ObjectType.simpleTypeConvert(retVal, "Double", null, locale, false);
+ String template = UtilProperties.getPropertyValue("arithmetic", "accounting-number.format",
+ "#,##0.00;(#,##0.00)");
+ retVal = UtilFormatOut.formatDecimalNumber(parsedRetVal.doubleValue(), template, locale);
+ } catch (GeneralException e) {
+ String errMsg = "Error formatting number [" + retVal + "]: " + e.toString();
+ Debug.logError(e, errMsg, module);
+ throw new IllegalArgumentException(errMsg);
+ }
+ }
+ if (UtilValidate.isNotEmpty(this.description) && retVal != null && this.getModelFormField().getEncodeOutput()) {
+ UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
+ if (simpleEncoder != null) {
+ retVal = simpleEncoder.encode(retVal);
+ }
+ }
+ return retVal;
+ }
+
+ public FlexibleStringExpander getImageLocation() {
+ return imageLocation;
+ }
+
+ public String getImageLocation(Map<String, Object> context) {
+ if (this.imageLocation != null)
+ return this.imageLocation.expandString(context);
+ return "";
+ }
+
+ public InPlaceEditor getInPlaceEditor() {
+ return this.inPlaceEditor;
+ }
+
+ public String getSize() {
+ return this.size;
+ }
+
+ public String getType() {
+ return this.type;
+ }
+
+ @Override
+ public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
+ throws IOException {
+ formStringRenderer.renderDisplayField(writer, context, this);
+ }
+ }
+
+ /**
+ * Models the <drop-down> element.
+ *
+ * @see <code>widget-form.xsd</code>
+ */
+ public static class DropDownField extends FieldInfoWithOptions {
+ private final boolean allowEmpty;
+ private final boolean allowMulti;
+ private final AutoComplete autoComplete;
+ private final String current;
+ private final FlexibleStringExpander currentDescription;
+ private final int otherFieldSize;
+ private final String size;
+ private final SubHyperlink subHyperlink;
+ private final String textSize;
+
+ private DropDownField(DropDownField original, ModelFormField modelFormField) {
+ super(original, modelFormField);
+ this.allowEmpty = original.allowEmpty;
+ this.allowMulti = original.allowMulti;
+ this.autoComplete = original.autoComplete;
+ this.current = original.current;
+ this.currentDescription = original.currentDescription;
+ this.otherFieldSize = original.otherFieldSize;
+ this.size = original.size;
+ if (original.subHyperlink != null) {
+ this.subHyperlink = new SubHyperlink(original.subHyperlink, modelFormField);
+ } else {
+ this.subHyperlink = null;
+ }
+ this.textSize = original.textSize;
+ }
+
+ public DropDownField(Element element, ModelFormField modelFormField) {
+ super(element, modelFormField);
+ this.allowEmpty = "true".equals(element.getAttribute("allow-empty"));
+ this.allowMulti = "true".equals(element.getAttribute("allow-multiple"));
+ Element autoCompleteElement = UtilXml.firstChildElement(element, "auto-complete");
+ if (autoCompleteElement != null) {
+ this.autoComplete = new AutoComplete(autoCompleteElement);
+ } else {
+ this.autoComplete = null;
+ }
+ this.current = element.getAttribute("current");
+ this.currentDescription = FlexibleStringExpander.getInstance(element.getAttribute("current-description"));
+ int otherFieldSize = 0;
+ String sizeStr = element.getAttribute("other-field-size");
+ if (!sizeStr.isEmpty()) {
+ try {
+ otherFieldSize = Integer.parseInt(sizeStr);
+ } catch (Exception e) {
+ Debug.logError("Could not parse the size value of the text element: [" + sizeStr
+ + "], setting to the default of 0", module);
+ }
+ }
+ this.otherFieldSize = otherFieldSize;
+ String size = element.getAttribute("size");
+ if (size.isEmpty()) {
+ size = "1";
+ }
+ this.size = size;
+ Element subHyperlinkElement = UtilXml.firstChildElement(element, "sub-hyperlink");
+ if (subHyperlinkElement != null) {
+ this.subHyperlink = new SubHyperlink(subHyperlinkElement, this.getModelFormField());
+ } else {
+ this.subHyperlink = null;
+ }
+ String textSize = element.getAttribute("text-size");
+ if (textSize.isEmpty()) {
+ textSize = "0";
+ }
+ this.textSize = textSize;
+ }
+
+ public DropDownField(int fieldSource, List<OptionSource> optionSources) {
+ super(fieldSource, FieldInfo.DROP_DOWN, optionSources);
+ this.allowEmpty = false;
+ this.allowMulti = false;
+ this.autoComplete = null;
+ this.current = "";
+ this.currentDescription = FlexibleStringExpander.getInstance("");
+ this.otherFieldSize = 0;
+ this.size = "1";
+ this.subHyperlink = null;
+ this.textSize = "0";
+ }
+
+ public DropDownField(int fieldSource, ModelFormField modelFormField) {
+ super(fieldSource, FieldInfo.DROP_DOWN, modelFormField);
+ this.allowEmpty = false;
+ this.allowMulti = false;
+ this.autoComplete = null;
+ this.current = "";
+ this.currentDescription = FlexibleStringExpander.getInstance("");
+ this.otherFieldSize = 0;
+ this.size = "1";
+ this.subHyperlink = null;
+ this.textSize = "0";
+ }
+
+ public DropDownField(ModelFormField modelFormField) {
+ super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.DROP_DOWN, modelFormField);
+ this.allowEmpty = false;
+ this.allowMulti = false;
+ this.autoComplete = null;
+ this.current = "";
+ this.currentDescription = FlexibleStringExpander.getInstance("");
+ this.otherFieldSize = 0;
+ this.size = "1";
+ this.subHyperlink = null;
+ this.textSize = "0";
+ }
+
+ @Override
+ public void accept(ModelFieldVisitor visitor) throws Exception {
+ visitor.visit(this);
+ }
+
+ @Override
+ public FieldInfo copy(ModelFormField modelFormField) {
+ return new DropDownField(this, modelFormField);
+ }
+
+ public boolean getAllowMulti() {
+ return allowMulti;
+ }
+
+ public AutoComplete getAutoComplete() {
+ return this.autoComplete;
+ }
+
+ public String getCurrent() {
+ if (UtilValidate.isEmpty(this.current))
+ return "first-in-list";
+ return this.current;
+ }
+
+ public FlexibleStringExpander getCurrentDescription() {
+ return currentDescription;
+ }
+
+ public String getCurrentDescription(Map<String, Object> context) {
+ if (this.currentDescription == null)
+ return null;
+ return this.currentDescription.expandString(context);
+ }
+
+ public int getOtherFieldSize() {
+ return this.otherFieldSize;
+ }
+
+ /**
+ * Get the name to use for the parameter for this field in the form interpreter.
+ * For HTML forms this is the request parameter name.
+ * @param context the context
+ * @return returns the name to use for the parameter for this field in the form interpreter.
+ */
+ public String getParameterNameOther(Map<String, Object> context) {
+ String baseName;
+ if (UtilValidate.isNotEmpty(getModelFormField().parameterName))
+ baseName = getModelFormField().parameterName;
+ else
+ baseName = getModelFormField().name;
+
+ baseName += "_OTHER";
+ Integer itemIndex = (Integer) context.get("itemIndex");
+ if (itemIndex != null && "multi".equals(getModelFormField().modelForm.getType())) {
+ return baseName + getModelFormField().modelForm.getItemIndexSeparator() + itemIndex.intValue();
+ } else {
+ return baseName;
+ }
+ }
+
+ public String getSize() {
+ return this.size;
+ }
+
+ public SubHyperlink getSubHyperlink() {
+ return this.subHyperlink;
+ }
+
+ public String getTextSize() {
+ return this.textSize;
+ }
+
+ public boolean getAllowEmpty() {
+ return this.allowEmpty;
+ }
+
+ public boolean getAllowMultiple() {
+ return this.allowMulti;
+ }
+
+ @Override
+ public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
+ throws IOException {
+ formStringRenderer.renderDropDownField(writer, context, this);
+ }
+ }
+
+ /**
+ * Models the <entity-options> element.
+ *
+ * @see <code>widget-form.xsd</code>
+ */
+ public static class EntityOptions extends OptionSource {
+ private final boolean cache;
+ private final List<EntityFinderUtil.ConditionExpr> constraintList;
+ private final FlexibleStringExpander description;
+ private final String entityName;
+ private final String filterByDate;
+ private final String keyFieldName;
+ private final List<String> orderByList;
+
+ public EntityOptions(Element entityOptionsElement, ModelFormField modelFormField) {
+ super(modelFormField);
+ this.cache = !"false".equals(entityOptionsElement.getAttribute("cache"));
+ List<? extends Element> constraintElements = UtilXml.childElementList(entityOptionsElement, "entity-constraint");
+ if (!constraintElements.isEmpty()) {
+ List<EntityFinderUtil.ConditionExpr> constraintList = new ArrayList<EntityFinderUtil.ConditionExpr>(
+ constraintElements.size());
+ for (Element constraintElement : constraintElements) {
+ constraintList.add(new EntityFinderUtil.ConditionExpr(constraintElement));
+ }
+ this.constraintList = Collections.unmodifiableList(constraintList);
+ } else {
+ this.constraintList = Collections.emptyList();
+ }
+ this.description = FlexibleStringExpander.getInstance(entityOptionsElement.getAttribute("description"));
+ this.entityName = entityOptionsElement.getAttribute("entity-name");
+ this.filterByDate = entityOptionsElement.getAttribute("filter-by-date");
+ this.keyFieldName = entityOptionsElement.getAttribute("key-field-name");
+ List<? extends Element> orderByElements = UtilXml.childElementList(entityOptionsElement, "entity-order-by");
+ if (!orderByElements.isEmpty()) {
+ List<String> orderByList = new ArrayList<String>(orderByElements.size());
+ for (Element orderByElement : orderByElements) {
+ orderByList.add(orderByElement.getAttribute("field-name"));
+ }
+ this.orderByList = Collections.unmodifiableList(orderByList);
+ } else {
+ this.orderByList = Collections.emptyList();
+ }
+ }
+
+ private EntityOptions(EntityOptions original, ModelFormField modelFormField) {
+ super(modelFormField);
+ this.cache = original.cache;
+ this.constraintList = original.constraintList;
+ this.description = original.description;
+ this.entityName = original.entityName;
+ this.filterByDate = original.filterByDate;
+ this.keyFieldName = original.keyFieldName;
+ this.orderByList = original.orderByList;
+ }
+
+ public EntityOptions(ModelFormField modelFormField) {
+ super(modelFormField);
+ this.cache = true;
+ this.constraintList = Collections.emptyList();
+ this.description = FlexibleStringExpander.getInstance("");
+ this.entityName = "";
+ this.filterByDate = "";
+ this.keyFieldName = "";
+ this.orderByList = Collections.emptyList();
+ }
+
+ @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 = delegator.findList(this.entityName, findCondition, null, this.orderByList, null, this.cache);
+
+ // 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);
+ }
+ }
+
+ @Override
+ public OptionSource copy(ModelFormField modelFormField) {
+ return new EntityOptions(this, modelFormField);
+ }
+
+ public boolean getCache() {
+ return cache;
+ }
+
+ public List<EntityFinderUtil.ConditionExpr> getConstraintList() {
+ return constraintList;
+ }
+
+ public FlexibleStringExpander getDescription() {
+ return description;
+ }
+
+ public String getEntityName() {
+ return entityName;
+ }
+
+ public String getFilterByDate() {
+ return filterByDate;
+ }
+
+ public String getKeyFieldName() {
+ if (UtilValidate.isNotEmpty(this.keyFieldName))
+ return this.keyFieldName;
+ return getModelFormField().getFieldName(); // get the modelFormField fieldName
+ }
+
+ public List<String> getOrderByList() {
+ return orderByList;
+ }
+ }
+
+ public static abstract class FieldInfoWithOptions extends FieldInfo {
+
+ 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();
+ }
+ }
+
+ // if we get here we didn't find a match, just return the key
+ return key;
+ }
+
+ private final FlexibleStringExpander noCurrentSelectedKey;
+ private final List<OptionSource> optionSources;
+
+ public FieldInfoWithOptions(Element element, ModelFormField modelFormField) {
+ super(element, modelFormField);
+ this.noCurrentSelectedKey = FlexibleStringExpander.getInstance(element.getAttribute("no-current-selected-key"));
+ // read all option and entity-options sub-elements, maintaining order
+ ArrayList<OptionSource> optionSources = new ArrayList<OptionSource>();
+ List<? extends Element> childElements = UtilXml.childElementList(element);
+ if (childElements.size() > 0) {
+ for (Element childElement : childElements) {
+ if ("option".equals(childElement.getTagName())) {
+ optionSources.add(new SingleOption(childElement, modelFormField));
+ } else if ("list-options".equals(childElement.getTagName())) {
+ optionSources.add(new ListOptions(childElement, modelFormField));
+ } else if ("entity-options".equals(childElement.getTagName())) {
+ optionSources.add(new EntityOptions(childElement, modelFormField));
+ }
+ }
+ } else {
+ // this must be added or the multi-form select box options would not show up
+ optionSources.add(new SingleOption("Y", " ", modelFormField));
+ }
+ optionSources.trimToSize();
+ this.optionSources = Collections.unmodifiableList(optionSources);
+ }
+
+ // Copy constructor.
+ protected FieldInfoWithOptions(FieldInfoWithOptions original, ModelFormField modelFormField) {
+ super(original.getFieldSource(), original.getFieldType(), modelFormField);
+ this.noCurrentSelectedKey = original.noCurrentSelectedKey;
+ if (original.optionSources.isEmpty()) {
+ this.optionSources = original.optionSources;
+ } else {
+ List<OptionSource> optionSources = new ArrayList<OptionSource>(original.optionSources.size());
+ for (OptionSource source : original.optionSources) {
+ optionSources.add(source.copy(modelFormField));
+ }
+ this.optionSources = Collections.unmodifiableList(optionSources);
+ }
+ }
+
+ protected FieldInfoWithOptions(int fieldSource, int fieldType, List<OptionSource> optionSources) {
+ super(fieldSource, fieldType, null);
+ this.noCurrentSelectedKey = FlexibleStringExpander.getInstance("");
+ this.optionSources = Collections.unmodifiableList(new ArrayList<OptionSource>(optionSources));
+ }
+
+ public FieldInfoWithOptions(int fieldSource, int fieldType, ModelFormField modelFormField) {
+ super(fieldSource, fieldType, modelFormField);
+ this.noCurrentSelectedKey = FlexibleStringExpander.getInstance("");
+ this.optionSources = Collections.emptyList();
+ }
+
+ 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);
+ }
+ return optionValues;
+ }
+
+ public FlexibleStringExpander getNoCurrentSelectedKey() {
+ return noCurrentSelectedKey;
+ }
+
+ public String getNoCurrentSelectedKey(Map<String, Object> context) {
+ return this.noCurrentSelectedKey.expandString(context);
+ }
+
+ public List<OptionSource> getOptionSources() {
+ return optionSources;
+ }
+ }
+
+ /**
+ * Models the <file> element.
+ *
+ * @see <code>widget-form.xsd</code>
+ */
+ public static class FileField extends TextField {
+
+ public FileField(Element element, ModelFormField modelFormField) {
+ super(element, modelFormField);
+ }
+
+ private FileField(FileField original, ModelFormField modelFormField) {
+ super(original, modelFormField);
+ }
+
+ public FileField(int fieldSource, ModelFormField modelFormField) {
+ super(fieldSource, modelFormField);
+ }
+
+ @Override
+ public void accept(ModelFieldVisitor visitor) throws Exception {
+ visitor.visit(this);
+ }
+
+ @Override
+ public FieldInfo copy(ModelFormField modelFormField) {
+ return new FileField(this, modelFormField);
+ }
+
+ @Override
+ public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
+ throws IOException {
+ formStringRenderer.renderFileField(writer, context, this);
+ }
+ }
+
+ /**
+ * Models the <hidden> element.
+ *
+ * @see <code>widget-form.xsd</code>
+ */
+ public static class HiddenField extends FieldInfo {
+ private final FlexibleStringExpander value;
+
+ public HiddenField(Element element, ModelFormField modelFormField) {
+ super(element, modelFormField);
+ this.value = FlexibleStringExpander.getInstance(element.getAttribute("value"));
+ }
+
+ private HiddenField(HiddenField original, ModelFormField modelFormField) {
+ super(original.getFieldSource(), original.getFieldType(), modelFormField);
+ this.value = original.value;
+ }
+
+ public HiddenField(int fieldSource, ModelFormField modelFormField) {
+ super(fieldSource, FieldInfo.HIDDEN, modelFormField);
+ this.value = FlexibleStringExpander.getInstance("");
+ }
+
+ public HiddenField(ModelFormField modelFormField) {
+ super(FieldInfo.SOURCE_EXPLICIT, FieldInfo.HIDDEN, modelFormField);
+ this.value = FlexibleStringExpander.getInstance("");
+ }
+
+ @Override
+ public void accept(ModelFieldVisitor visitor) throws Exception {
+ visitor.visit(this);
+ }
+
+ @Override
+ public FieldInfo copy(ModelFormField modelFormField) {
+ return new HiddenField(this, modelFormField);
+ }
+
+ public FlexibleStringExpander getValue() {
+ return value;
+ }
+
+ public String getValue(Map<String, Object> context) {
+ if (UtilValidate.isNotEmpty(this.value)) {
+ String valueEnc = this.value.expandString(context);
+ UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder");
+ if (simpleEncoder != null) {
+ valueEnc = simpleEncoder.encode(valueEnc);
+ }
+ return valueEnc;
+ } else {
+ return getModelFormField().getEntry(context);
+ }
+ }
+
+ @Override
+ public void renderFieldString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer)
+ throws IOException {
+ formStringRenderer.renderHiddenField(writer, context, this);
+ }
+ }
+
+ /**
+ * Models the <hyperlink> element.
+ *
+ * @see <code>widget-form.xsd</code>
+ */
+ public static class HyperlinkField extends FieldInfo {
+
+ private final boolean alsoHidden;
+ private final FlexibleStringExpander confirmationMsgExdr;
+ private final FlexibleStringExpander description;
+ private final boolean requestConfirmation;
+ private final Link link;
+ public HyperlinkField(Element element, ModelFormField modelFormField) {
+ super(element, modelFormField);
+ this.alsoHidden = !"false".equals(element.getAttribute("also-hidden"));
+ this.confirmationMsgExdr = FlexibleStringExpander.getInstance(element.getAttribute("confirmation-message"));
[... 1699 lines stripped ...]