blob: 0aea4da69f63e7281c359002b84731b57760e991 [file] [log] [blame]
/*******************************************************************************
* 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.form;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import groovy.lang.GroovyShell;
import javolution.util.FastList;
import javolution.util.FastMap;
import javolution.util.FastSet;
import org.codehaus.groovy.control.CompilationFailedException;
import org.ofbiz.base.util.*;
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.GenericEntityException;
import org.ofbiz.entity.model.ModelEntity;
import org.ofbiz.entity.model.ModelField;
import org.ofbiz.entity.model.ModelReader;
import org.ofbiz.entity.util.EntityListIterator;
import org.ofbiz.service.DispatchContext;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.ModelParam;
import org.ofbiz.service.ModelService;
import org.ofbiz.webapp.control.ConfigXMLReader;
import org.ofbiz.widget.ModelWidget;
import org.ofbiz.widget.WidgetWorker;
import org.w3c.dom.Element;
/**
* Widget Library - Form model class
*/
@SuppressWarnings("serial")
public class ModelForm extends ModelWidget {
public static final String module = ModelForm.class.getName();
public static final String DEFAULT_FORM_RESULT_LIST_NAME = "defaultFormResultList";
protected ModelReader entityModelReader;
protected DispatchContext dispatchContext;
protected String formLocation;
protected String parentFormName;
protected String parentFormLocation;
protected String type;
protected FlexibleStringExpander target;
protected String targetType;
protected String containerId;
protected String containerStyle;
protected String focusFieldName;
protected String title;
protected String tooltip;
protected String listName;
protected String listEntryName;
protected FlexibleMapAccessor<Map<String, ? extends Object>> defaultMapName;
protected String defaultEntityName;
protected String defaultServiceName;
protected String formTitleAreaStyle;
protected String formWidgetAreaStyle;
protected String defaultTitleAreaStyle;
protected String defaultWidgetAreaStyle;
protected String defaultTitleStyle;
protected String defaultWidgetStyle;
protected String defaultTooltipStyle;
protected String itemIndexSeparator;
protected FlexibleStringExpander paginate;
protected FlexibleStringExpander paginateTarget;
protected FlexibleStringExpander paginateIndexField;
protected FlexibleStringExpander paginateSizeField;
protected FlexibleStringExpander overrideListSize;
protected FlexibleStringExpander paginateFirstLabel;
protected FlexibleStringExpander paginatePreviousLabel;
protected FlexibleStringExpander paginateNextLabel;
protected FlexibleStringExpander paginateLastLabel;
protected FlexibleStringExpander paginateViewSizeLabel;
protected String paginateTargetAnchor;
protected String paginateStyle;
protected boolean separateColumns = false;
protected boolean groupColumns = true;
protected boolean useRowSubmit = false;
protected FlexibleStringExpander targetWindowExdr;
protected String defaultRequiredFieldStyle;
protected String defaultSortFieldStyle;
protected String defaultSortFieldAscStyle;
protected String defaultSortFieldDescStyle;
protected String oddRowStyle;
protected String evenRowStyle;
protected String defaultTableStyle;
protected String headerRowStyle;
protected boolean skipStart = false;
protected boolean skipEnd = false;
protected boolean hideHeader = false;
protected boolean overridenListSize = false;
protected boolean clientAutocompleteFields = true;
protected List<AltTarget> altTargets = FastList.newInstance();
protected List<AutoFieldsService> autoFieldsServices = FastList.newInstance();
protected List<AutoFieldsEntity> autoFieldsEntities = FastList.newInstance();
protected List<SortField> sortOrderFields = FastList.newInstance();
protected List<AltRowStyle> altRowStyles = FastList.newInstance();
/** This List will contain one copy of each field for each field name in the order
* they were encountered in the service, entity, or form definition; field definitions
* with constraints will also be in this list but may appear multiple times for the same
* field name.
*
* When rendering the form the order in this list should be following and it should not be
* necessary to use the Map. The Map is used when loading the form definition to keep the
* list clean and implement the override features for field definitions.
*/
protected List<ModelFormField> fieldList = FastList.newInstance();
/** This Map is keyed with the field name and has a ModelFormField for the value.
*/
protected Map<String, ModelFormField> fieldMap = FastMap.newInstance();
/** Keeps track of conditional fields to help ensure that only one is rendered
*/
protected Set<String> useWhenFields = FastSet.newInstance();
/** This is a list of FieldGroups in the order they were created.
* Can also include Banner objects.
*/
protected List<FieldGroupBase> fieldGroupList = FastList.newInstance();
/** This Map is keyed with the field name and has a FieldGroup for the value.
* Can also include Banner objects.
*/
protected Map<String, FieldGroupBase> fieldGroupMap = FastMap.newInstance();
/** This field group will be the "catch-all" group for fields that are not
* included in an explicit field-group.
*/
protected FieldGroup defaultFieldGroup;
/** Default hyperlink target. */
public static String DEFAULT_TARGET_TYPE = "intra-app";
/** Pagination settings and defaults. */
public static int DEFAULT_PAGE_SIZE = 10;
public static int MAX_PAGE_SIZE = 10000;
protected int defaultViewSize = DEFAULT_PAGE_SIZE;
public static String DEFAULT_PAG_INDEX_FIELD = "viewIndex";
public static String DEFAULT_PAG_SIZE_FIELD = "viewSize";
public static String DEFAULT_PAG_STYLE = "nav-pager";
public static String DEFAULT_PAG_FIRST_STYLE = "nav-first";
public static String DEFAULT_PAG_PREV_STYLE = "nav-previous";
public static String DEFAULT_PAG_NEXT_STYLE = "nav-next";
public static String DEFAULT_PAG_LAST_STYLE = "nav-last";
/** Sort field default styles. */
public static String DEFAULT_SORT_FIELD_STYLE = "sort-order";
public static String DEFAULT_SORT_FIELD_ASC_STYLE = "sort-order-asc";
public static String DEFAULT_SORT_FIELD_DESC_STYLE = "sort-order-desc";
protected List<ModelFormAction> actions;
protected List<ModelFormAction> rowActions;
protected FlexibleStringExpander rowCountExdr;
protected List<ModelFormField> multiSubmitFields = FastList.newInstance();
protected int rowCount = 0;
/** On Submit areas to be updated. */
protected List<UpdateArea> onSubmitUpdateAreas;
/** On Paginate areas to be updated. */
protected List<UpdateArea> onPaginateUpdateAreas;
// ===== CONSTRUCTORS =====
/** Default Constructor */
public ModelForm() {}
/** XML Constructor */
public ModelForm(Element formElement, ModelReader entityModelReader, DispatchContext dispatchContext) {
super(formElement);
this.entityModelReader = entityModelReader;
this.dispatchContext = dispatchContext;
try {
initForm(formElement);
} catch (RuntimeException e) {
Debug.logError(e, "Error parsing form [" + formElement.getAttribute("name") + "]: " + e.toString(), module);
throw e;
}
}
public ModelForm(Element formElement) {
super(formElement);
initForm(formElement);
}
public void initForm(Element formElement) {
setDefaultViewSize(UtilProperties.getPropertyValue("widget.properties", "widget.form.defaultViewSize"));
// check if there is a parent form to inherit from
String parentResource = formElement.getAttribute("extends-resource");
String parentForm = formElement.getAttribute("extends");
if (parentForm.length() > 0) {
ModelForm parent = null;
// check if we have a resource name (part of the string before the ?)
if (parentResource.length() > 0) {
try {
parent = FormFactory.getFormFromLocation(parentResource, parentForm, entityModelReader, dispatchContext);
this.parentFormName = parentForm;
this.parentFormLocation = parentResource;
} catch (Exception e) {
Debug.logError(e, "Failed to load parent form definition '" + parentForm + "' at resource '" + parentResource + "'", module);
}
} else if (!parentForm.equals(formElement.getAttribute("name"))) {
// try to find a form definition in the same file
Element rootElement = formElement.getOwnerDocument().getDocumentElement();
List<? extends Element> formElements = UtilXml.childElementList(rootElement, "form");
//Uncomment below to add support for abstract forms
//formElements.addAll(UtilXml.childElementList(rootElement, "abstract-form"));
for (Element formElementEntry: formElements) {
if (formElementEntry.getAttribute("name").equals(parentForm)) {
parent = new ModelForm(formElementEntry, entityModelReader, dispatchContext);
break;
}
}
if (parent == null) {
Debug.logError("Failed to find parent form definition '" + parentForm + "' in same document.", module);
} else {
this.parentFormName = parentForm;
}
} else {
Debug.logError("Recursive form definition found for '" + formElement.getAttribute("name") + ".'", module);
}
if (parent != null) {
this.type = parent.type;
this.target = parent.target;
this.containerId = parent.containerId;
this.containerStyle = parent.containerStyle;
this.focusFieldName = parent.focusFieldName;
this.title = parent.title;
this.tooltip = parent.tooltip;
this.listName = parent.listName;
this.listEntryName = parent.listEntryName;
this.tooltip = parent.tooltip;
this.defaultEntityName = parent.defaultEntityName;
this.defaultServiceName = parent.defaultServiceName;
this.formTitleAreaStyle = parent.formTitleAreaStyle;
this.formWidgetAreaStyle = parent.formWidgetAreaStyle;
this.defaultTitleAreaStyle = parent.defaultTitleAreaStyle;
this.defaultWidgetAreaStyle = parent.defaultWidgetAreaStyle;
this.oddRowStyle = parent.oddRowStyle;
this.evenRowStyle = parent.evenRowStyle;
this.defaultTableStyle = parent.defaultTableStyle;
this.headerRowStyle = parent.headerRowStyle;
this.defaultTitleStyle = parent.defaultTitleStyle;
this.defaultWidgetStyle = parent.defaultWidgetStyle;
this.defaultTooltipStyle = parent.defaultTooltipStyle;
this.itemIndexSeparator = parent.itemIndexSeparator;
this.separateColumns = parent.separateColumns;
this.groupColumns = parent.groupColumns;
this.targetType = parent.targetType;
this.defaultMapName = parent.defaultMapName;
this.targetWindowExdr = parent.targetWindowExdr;
this.hideHeader = parent.hideHeader;
this.clientAutocompleteFields = parent.clientAutocompleteFields;
this.paginateTarget = parent.paginateTarget;
this.altTargets.addAll(parent.altTargets);
this.actions = parent.actions;
this.rowActions = parent.rowActions;
this.defaultViewSize = parent.defaultViewSize;
this.onSubmitUpdateAreas = parent.onSubmitUpdateAreas;
this.onPaginateUpdateAreas = parent.onPaginateUpdateAreas;
this.altRowStyles = parent.altRowStyles;
this.useWhenFields = parent.useWhenFields;
//these are done below in a special way...
//this.fieldList = parent.fieldList;
//this.fieldMap = parent.fieldMap;
// Create this fieldList/Map from clones of parent's
for (ModelFormField parentChildField: parent.fieldList) {
ModelFormField childField = new ModelFormField(this);
childField.mergeOverrideModelFormField(parentChildField);
this.fieldList.add(childField);
this.fieldMap.put(childField.getName(), childField);
}
this.fieldGroupMap = parent.fieldGroupMap;
this.fieldGroupList = parent.fieldGroupList;
}
}
if (this.type == null || formElement.hasAttribute("type")) {
this.type = formElement.getAttribute("type");
}
if (this.target == null || formElement.hasAttribute("target")) {
setTarget(formElement.getAttribute("target"));
}
if (this.targetWindowExdr == null || formElement.hasAttribute("target-window")) {
setTargetWindow(formElement.getAttribute("target-window"));
}
if (this.containerId == null || formElement.hasAttribute("id")) {
this.containerId = formElement.getAttribute("id");
}
if (this.containerStyle == null || formElement.hasAttribute("style")) {
this.containerStyle = formElement.getAttribute("style");
}
if (this.focusFieldName == null || formElement.hasAttribute("focus-field-name")) {
this.focusFieldName = formElement.getAttribute("focus-field-name");
}
if (this.title == null || formElement.hasAttribute("title")) {
this.title = formElement.getAttribute("title");
}
if (this.tooltip == null || formElement.hasAttribute("tooltip")) {
this.tooltip = formElement.getAttribute("tooltip");
}
if (this.listName == null || formElement.hasAttribute("list-name")) {
this.listName = formElement.getAttribute("list-name");
}
// if no list-name then look in the list-iterator-name; this is deprecated but we'll look at it anyway
if (UtilValidate.isEmpty(this.listName) && formElement.hasAttribute("list-iterator-name")) {
this.listName = formElement.getAttribute("list-iterator-name");
}
if (this.listEntryName == null || formElement.hasAttribute("list-entry-name")) {
this.listEntryName = formElement.getAttribute("list-entry-name");
}
if (this.defaultMapName == null || formElement.hasAttribute("default-map-name")) {
this.setDefaultMapName(formElement.getAttribute("default-map-name"));
}
if (this.defaultServiceName == null || formElement.hasAttribute("default-service-name")) {
this.defaultServiceName = formElement.getAttribute("default-service-name");
}
if (this.defaultEntityName == null || formElement.hasAttribute("default-entity-name")) {
this.defaultEntityName = formElement.getAttribute("default-entity-name");
}
if (this.formTitleAreaStyle == null || formElement.hasAttribute("form-title-area-style")) {
this.formTitleAreaStyle = formElement.getAttribute("form-title-area-style");
}
if (this.formWidgetAreaStyle == null || formElement.hasAttribute("form-widget-area-style")) {
this.formWidgetAreaStyle = formElement.getAttribute("form-widget-area-style");
}
if (this.defaultTitleAreaStyle == null || formElement.hasAttribute("default-title-area-style")) {
this.defaultTitleAreaStyle = formElement.getAttribute("default-title-area-style");
}
if (this.defaultWidgetAreaStyle == null || formElement.hasAttribute("default-widget-area-style")) {
this.defaultWidgetAreaStyle = formElement.getAttribute("default-widget-area-style");
}
if (this.oddRowStyle == null || formElement.hasAttribute("odd-row-style")) {
this.oddRowStyle = formElement.getAttribute("odd-row-style");
}
if (this.evenRowStyle == null || formElement.hasAttribute("even-row-style")) {
this.evenRowStyle = formElement.getAttribute("even-row-style");
}
if (this.defaultTableStyle == null || formElement.hasAttribute("default-table-style")) {
this.defaultTableStyle = formElement.getAttribute("default-table-style");
}
if (this.headerRowStyle == null || formElement.hasAttribute("header-row-style")) {
this.headerRowStyle = formElement.getAttribute("header-row-style");
}
if (this.defaultTitleStyle == null || formElement.hasAttribute("header-row-style")) {
this.defaultTitleStyle = formElement.getAttribute("default-title-style");
}
if (this.defaultWidgetStyle == null || formElement.hasAttribute("default-widget-style")) {
this.defaultWidgetStyle = formElement.getAttribute("default-widget-style");
}
if (this.defaultTooltipStyle == null || formElement.hasAttribute("default-tooltip-style")) {
this.defaultTooltipStyle = formElement.getAttribute("default-tooltip-style");
}
if (this.itemIndexSeparator == null || formElement.hasAttribute("item-index-separator")) {
this.itemIndexSeparator = formElement.getAttribute("item-index-separator");
}
if (this.targetType == null || formElement.hasAttribute("target-type")) {
this.targetType = formElement.getAttribute("target-type");
}
if (this.defaultRequiredFieldStyle == null || formElement.hasAttribute("default-required-field-style")) {
this.defaultRequiredFieldStyle = formElement.getAttribute("default-required-field-style");
}
if (this.defaultSortFieldStyle == null || formElement.hasAttribute("default-sort-field-style")) {
this.defaultSortFieldStyle = formElement.getAttribute("default-sort-field-style");
}
if (this.defaultSortFieldAscStyle == null || formElement.hasAttribute("default-sort-field-asc-style")) {
this.defaultSortFieldAscStyle = formElement.getAttribute("default-sort-field-asc-style");
}
if (this.defaultSortFieldDescStyle == null || formElement.hasAttribute("default-sort-field-desc-style")) {
this.defaultSortFieldDescStyle = formElement.getAttribute("default-sort-field-desc-style");
}
// pagination settings
if (this.paginateTarget == null || formElement.hasAttribute("paginate-target")) {
setPaginateTarget(formElement.getAttribute("paginate-target"));
}
if (this.paginateTargetAnchor == null || formElement.hasAttribute("paginate-target-anchor")) {
this.paginateTargetAnchor = formElement.getAttribute("paginate-target-anchor");
}
if (this.paginateIndexField == null || formElement.hasAttribute("paginate-index-field")) {
setPaginateIndexField(formElement.getAttribute("paginate-index-field"));
}
if (this.paginateSizeField == null || formElement.hasAttribute("paginate-size-field")) {
setPaginateSizeField(formElement.getAttribute("paginate-size-field"));
}
if (this.overrideListSize == null || formElement.hasAttribute("override-list-size")) {
this.overrideListSize = FlexibleStringExpander.getInstance(formElement.getAttribute("override-list-size"));
}
if (this.paginateFirstLabel == null || formElement.hasAttribute("paginate-first-label")) {
this.paginateFirstLabel = FlexibleStringExpander.getInstance(formElement.getAttribute("paginate-first-label"));
}
if (this.paginatePreviousLabel == null || formElement.hasAttribute("paginate-previous-label")) {
this.paginatePreviousLabel = FlexibleStringExpander.getInstance(formElement.getAttribute("paginate-previous-label"));
}
if (this.paginateNextLabel == null || formElement.hasAttribute("paginate-next-label")) {
this.paginateNextLabel = FlexibleStringExpander.getInstance(formElement.getAttribute("paginate-next-label"));
}
if (this.paginateLastLabel == null || formElement.hasAttribute("paginate-last-label")) {
this.paginateLastLabel = FlexibleStringExpander.getInstance(formElement.getAttribute("paginate-last-label"));
}
if (this.paginateViewSizeLabel == null || formElement.hasAttribute("paginate-viewsize-label")) {
this.paginateViewSizeLabel = FlexibleStringExpander.getInstance(formElement.getAttribute("paginate-viewsize-label"));
}
if (this.paginateStyle == null || formElement.hasAttribute("paginate-style")) {
setPaginateStyle(formElement.getAttribute("paginate-style"));
}
if (this.paginate == null || formElement.hasAttribute("paginate")) {
this.paginate = FlexibleStringExpander.getInstance(formElement.getAttribute("paginate"));
}
this.skipStart = "true".equals(formElement.getAttribute("skip-start"));
this.skipEnd = "true".equals(formElement.getAttribute("skip-end"));
this.hideHeader = "true".equals(formElement.getAttribute("hide-header"));
this.clientAutocompleteFields = !"false".equals(formElement.getAttribute("client-autocomplete-fields"));
if (formElement.hasAttribute("separate-columns")) {
String sepColumns = formElement.getAttribute("separate-columns");
if (sepColumns != null && sepColumns.equalsIgnoreCase("true"))
separateColumns = true;
}
if (formElement.hasAttribute("group-columns")) {
String groupColumnsStr = formElement.getAttribute("group-columns");
if (groupColumnsStr != null && groupColumnsStr.equalsIgnoreCase("false"))
groupColumns = false;
}
if (formElement.hasAttribute("use-row-submit")) {
String rowSubmit = formElement.getAttribute("use-row-submit");
if (rowSubmit != null && rowSubmit.equalsIgnoreCase("true"))
useRowSubmit = true;
}
if (formElement.hasAttribute("view-size")) {
setDefaultViewSize(formElement.getAttribute("view-size"));
}
if (this.rowCountExdr == null || formElement.hasAttribute("row-count")) {
this.rowCountExdr = FlexibleStringExpander.getInstance(formElement.getAttribute("row-count"));
}
//alt-row-styles
for (Element altRowStyleElement : UtilXml.childElementList(formElement, "alt-row-style")) {
AltRowStyle altRowStyle = new AltRowStyle(altRowStyleElement);
this.altRowStyles.add(altRowStyle);
}
// alt-target
for (Element altTargetElement: UtilXml.childElementList(formElement, "alt-target")) {
AltTarget altTarget = new AltTarget(altTargetElement);
this.addAltTarget(altTarget);
}
// on-event-update-area
for (Element updateAreaElement : UtilXml.childElementList(formElement, "on-event-update-area")) {
UpdateArea updateArea = new UpdateArea(updateAreaElement);
this.addOnEventUpdateArea(updateArea);
}
// auto-fields-service
for (Element autoFieldsServiceElement: UtilXml.childElementList(formElement, "auto-fields-service")) {
AutoFieldsService autoFieldsService = new AutoFieldsService(autoFieldsServiceElement);
this.addAutoFieldsFromService(autoFieldsService);
}
// auto-fields-entity
for (Element autoFieldsEntityElement: UtilXml.childElementList(formElement, "auto-fields-entity")) {
AutoFieldsEntity autoFieldsEntity = new AutoFieldsEntity(autoFieldsEntityElement);
this.addAutoFieldsFromEntity(autoFieldsEntity);
}
// read in add field defs, add/override one by one using the fieldList and fieldMap
String thisType = this.getType();
for (Element fieldElement: UtilXml.childElementList(formElement, "field")) {
ModelFormField modelFormField = new ModelFormField(fieldElement, this);
ModelFormField.FieldInfo fieldInfo = modelFormField.getFieldInfo();
if (thisType.equals("multi") && fieldInfo instanceof ModelFormField.SubmitField) {
multiSubmitFields.add(modelFormField);
} else {
modelFormField = this.addUpdateField(modelFormField);
}
//Debug.logInfo("Added field " + modelFormField.getName() + " from def, mapName=" + modelFormField.getMapName(), module);
}
// Create the default field group
defaultFieldGroup = new FieldGroup(null, this);
// get the sort-order
Element sortOrderElement = UtilXml.firstChildElement(formElement, "sort-order");
if (sortOrderElement != null) {
FieldGroup lastFieldGroup = new FieldGroup(null, this);
this.fieldGroupList.add(lastFieldGroup);
// read in sort-field
for (Element sortFieldElement: UtilXml.childElementList(sortOrderElement)) {
String tagName = sortFieldElement.getTagName();
if (tagName.equals("sort-field")) {
String fieldName = sortFieldElement.getAttribute("name");
String position = sortFieldElement.getAttribute("position");
this.sortOrderFields.add(new SortField(fieldName, position));
this.fieldGroupMap.put(fieldName, lastFieldGroup);
} else if (tagName.equals("banner")) {
Banner thisBanner = new Banner(sortFieldElement, this);
this.fieldGroupList.add(thisBanner);
lastFieldGroup = new FieldGroup(null, this);
this.fieldGroupList.add(lastFieldGroup);
} else if (tagName.equals("field-group")) {
FieldGroup thisFieldGroup = new FieldGroup(sortFieldElement, this);
this.fieldGroupList.add(thisFieldGroup);
lastFieldGroup = new FieldGroup(null, this);
this.fieldGroupList.add(lastFieldGroup);
}
}
}
// reorder fields according to sort order
if (sortOrderFields.size() > 0) {
List<ModelFormField> sortedFields = FastList.newInstance();
for (SortField sortField: this.sortOrderFields) {
String fieldName = sortField.getFieldName();
if (UtilValidate.isEmpty(fieldName)) {
continue;
}
// get all fields with the given name from the existing list and put them in the sorted list
Iterator<ModelFormField> fieldIter = this.fieldList.iterator();
while (fieldIter.hasNext()) {
ModelFormField modelFormField = fieldIter.next();
if (fieldName.equals(modelFormField.getName())) {
// matched the name; remove from the original last and add to the sorted list
if (UtilValidate.isNotEmpty(sortField.getPosition())) {
modelFormField.setPosition(sortField.getPosition());
}
fieldIter.remove();
sortedFields.add(modelFormField);
}
}
}
// now add all of the rest of the fields from fieldList, ie those that were not explicitly listed in the sort order
sortedFields.addAll(this.fieldList);
// sortedFields all done, set fieldList
this.fieldList = sortedFields;
}
// read all actions under the "actions" element
Element actionsElement = UtilXml.firstChildElement(formElement, "actions");
if (actionsElement != null) {
this.actions = ModelFormAction.readSubActions(this, actionsElement);
}
// read all actions under the "row-actions" element
Element rowActionsElement = UtilXml.firstChildElement(formElement, "row-actions");
if (rowActionsElement != null) {
this.rowActions = ModelFormAction.readSubActions(this, rowActionsElement);
}
}
/**
* add/override modelFormField using the fieldList and fieldMap
*
* @return The same ModelFormField, or if merged with an existing field, the existing field.
*/
public ModelFormField addUpdateField(ModelFormField modelFormField) {
if (!modelFormField.isUseWhenEmpty() || useWhenFields.contains(modelFormField.getName())) {
useWhenFields.add(modelFormField.getName());
// is a conditional field, add to the List but don't worry about the Map
//for adding to list, see if there is another field with that name in the list and if so, put it before that one
boolean inserted = false;
for (int i = 0; i < this.fieldList.size(); i++) {
ModelFormField curField = this.fieldList.get(i);
if (curField.getName() != null && curField.getName().equals(modelFormField.getName())) {
this.fieldList.add(i, modelFormField);
inserted = true;
break;
}
}
if (!inserted) {
this.fieldList.add(modelFormField);
}
return modelFormField;
} else {
// not a conditional field, see if a named field exists in Map
ModelFormField existingField = this.fieldMap.get(modelFormField.getName());
if (existingField != null) {
// does exist, update the field by doing a merge/override
existingField.mergeOverrideModelFormField(modelFormField);
return existingField;
} else {
// does not exist, add to List and Map
this.fieldList.add(modelFormField);
this.fieldMap.put(modelFormField.getName(), modelFormField);
return modelFormField;
}
}
}
public void addAltTarget(AltTarget altTarget) {
int index = altTargets.indexOf(altTarget);
if (index != -1) {
altTargets.set(index, altTarget);
} else {
altTargets.add(altTarget);
}
}
public void addOnEventUpdateArea(UpdateArea updateArea) {
// Event types are sorted as a convenience
// for the rendering classes
if ("paginate".equals(updateArea.getEventType())) {
addOnPaginateUpdateArea(updateArea);
} else if ("submit".equals(updateArea.getEventType())) {
addOnSubmitUpdateArea(updateArea);
}
}
protected void addOnSubmitUpdateArea(UpdateArea updateArea) {
if (onSubmitUpdateAreas == null) {
onSubmitUpdateAreas = FastList.newInstance();
}
int index = onSubmitUpdateAreas.indexOf(updateArea);
if (index != -1) {
onSubmitUpdateAreas.set(index, updateArea);
} else {
onSubmitUpdateAreas.add(updateArea);
}
}
protected void addOnPaginateUpdateArea(UpdateArea updateArea) {
if (onPaginateUpdateAreas == null) {
onPaginateUpdateAreas = FastList.newInstance();
}
int index = onPaginateUpdateAreas.indexOf(updateArea);
if (index != -1) {
if (UtilValidate.isNotEmpty(updateArea.areaTarget)) {
onPaginateUpdateAreas.set(index, updateArea);
} else {
// blank target indicates a removing override
onPaginateUpdateAreas.remove(index);
}
} else {
onPaginateUpdateAreas.add(updateArea);
}
}
public void addAutoFieldsFromService(AutoFieldsService autoFieldsService) {
autoFieldsServices.add(autoFieldsService);
// read service def and auto-create fields
ModelService modelService = null;
try {
modelService = this.dispatchContext.getModelService(autoFieldsService.serviceName);
} catch (GenericServiceException e) {
String errmsg = "Error finding Service with name " + autoFieldsService.serviceName + " for auto-fields-service in a form widget";
Debug.logError(e, errmsg, module);
throw new IllegalArgumentException(errmsg);
}
for (ModelParam modelParam: modelService.getInModelParamList()) {
// skip auto params that the service engine populates...
if ("userLogin".equals(modelParam.name) || "locale".equals(modelParam.name) || "timeZone".equals(modelParam.name) || "login.username".equals(modelParam.name) || "login.password".equals(modelParam.name)) {
continue;
}
if (modelParam.formDisplay) {
if (UtilValidate.isNotEmpty(modelParam.entityName) && UtilValidate.isNotEmpty(modelParam.fieldName)) {
ModelEntity modelEntity;
try {
modelEntity = this.entityModelReader.getModelEntity(modelParam.entityName);
if (modelEntity != null) {
ModelField modelField = modelEntity.getField(modelParam.fieldName);
if (modelField != null) {
// okay, populate using the entity field info...
ModelFormField modelFormField = this.addFieldFromEntityField(modelEntity, modelField, autoFieldsService.defaultFieldType, autoFieldsService.defaultPosition);
if (UtilValidate.isNotEmpty(autoFieldsService.mapName)) {
modelFormField.setMapName(autoFieldsService.mapName);
}
modelFormField.setRequiredField(!modelParam.optional);
// continue to skip creating based on service param
continue;
}
}
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
}
ModelFormField modelFormField = this.addFieldFromServiceParam(modelService, modelParam, autoFieldsService.defaultFieldType, autoFieldsService.defaultPosition);
if (UtilValidate.isNotEmpty(autoFieldsService.mapName)) {
modelFormField.setMapName(autoFieldsService.mapName);
}
}
}
}
public ModelFormField addFieldFromServiceParam(ModelService modelService, ModelParam modelParam, String defaultFieldType, int defaultPosition) {
// create field def from service param def
ModelFormField newFormField = new ModelFormField(this);
newFormField.setName(modelParam.name);
newFormField.setServiceName(modelService.name);
newFormField.setAttributeName(modelParam.name);
newFormField.setTitle(modelParam.formLabel);
newFormField.setRequiredField(!modelParam.optional);
newFormField.induceFieldInfoFromServiceParam(modelService, modelParam, defaultFieldType);
newFormField.setPosition(defaultPosition);
return this.addUpdateField(newFormField);
}
public void addAutoFieldsFromEntity(AutoFieldsEntity autoFieldsEntity) {
autoFieldsEntities.add(autoFieldsEntity);
// read entity def and auto-create fields
ModelEntity modelEntity = null;
try {
modelEntity = this.entityModelReader.getModelEntity(autoFieldsEntity.entityName);
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
if (modelEntity == null) {
throw new IllegalArgumentException("Error finding Entity with name " + autoFieldsEntity.entityName + " for auto-fields-entity in a form widget");
}
Iterator<ModelField> modelFieldIter = modelEntity.getFieldsIterator();
while (modelFieldIter.hasNext()) {
ModelField modelField = modelFieldIter.next();
if (modelField.getIsAutoCreatedInternal()) {
// don't ever auto-add these, should only be added if explicitly referenced
continue;
}
ModelFormField modelFormField = this.addFieldFromEntityField(modelEntity, modelField, autoFieldsEntity.defaultFieldType, autoFieldsEntity.defaultPosition);
if (UtilValidate.isNotEmpty(autoFieldsEntity.mapName)) {
modelFormField.setMapName(autoFieldsEntity.mapName);
}
}
}
public ModelFormField addFieldFromEntityField(ModelEntity modelEntity, ModelField modelField, String defaultFieldType, int defaultPosition) {
// create field def from entity field def
ModelFormField newFormField = new ModelFormField(this);
newFormField.setName(modelField.getName());
newFormField.setEntityName(modelEntity.getEntityName());
newFormField.setFieldName(modelField.getName());
newFormField.induceFieldInfoFromEntityField(modelEntity, modelField, defaultFieldType);
newFormField.setPosition(defaultPosition);
return this.addUpdateField(newFormField);
}
public void runFormActions(Map<String, Object> context) {
ModelFormAction.runSubActions(this.actions, context);
}
/**
* Renders this form to a String, i.e. in a text format, as defined with the
* FormStringRenderer implementation.
*
* @param writer The Writer that the form text will be written to
* @param context Map containing the form context; the following are
* reserved words in this context: parameters (Map), isError (Boolean),
* itemIndex (Integer, for lists only, otherwise null), bshInterpreter,
* formName (String, optional alternate name for form, defaults to the
* value of the name attribute)
* @param formStringRenderer An implementation of the FormStringRenderer
* interface that is responsible for the actual text generation for
* different form elements; implementing your own makes it possible to
* use the same form definitions for many types of form UIs
*/
public void renderFormString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer) throws IOException {
// increment the paginator, only for list and multi forms
if ("list".equals(this.type) || "multi".equals(this.type)) {
WidgetWorker.incrementPaginatorNumber(context);
}
//if pagination is disabled, update the defualt view size
if (!getPaginate(context)) {
setDefaultViewSize(ModelForm.MAX_PAGE_SIZE);
}
// Populate the viewSize and viewIndex so they are available for use during form actions
context.put("viewIndex", this.getViewIndex(context));
context.put("viewSize", this.getViewSize(context));
runFormActions(context);
// if this is a list form, don't useRequestParameters
if ("list".equals(this.type) || "multi".equals(this.type)) {
context.put("useRequestParameters", Boolean.FALSE);
}
// find the highest position number to get the max positions used
int positions = 1;
for (ModelFormField modelFormField: this.fieldList) {
int curPos = modelFormField.getPosition();
if (curPos > positions) {
positions = curPos;
}
ModelFormField.FieldInfo currentFieldInfo = modelFormField.getFieldInfo();
if (currentFieldInfo != null) {
ModelFormField fieldInfoFormField = currentFieldInfo.getModelFormField();
if (fieldInfoFormField != null) {
fieldInfoFormField.setModelForm(this);
}
} else {
throw new IllegalArgumentException("Error rendering form, a field has no FieldInfo, ie no sub-element for the type of field for field named: " + modelFormField.getName());
}
}
if ("single".equals(this.type)) {
this.renderSingleFormString(writer, context, formStringRenderer, positions);
} else if ("list".equals(this.type)) {
this.renderListFormString(writer, context, formStringRenderer, positions);
} else if ("multi".equals(this.type)) {
this.renderMultiFormString(writer, context, formStringRenderer, positions);
} else if ("upload".equals(this.type)) {
this.renderSingleFormString(writer, context, formStringRenderer, positions);
} else {
if (UtilValidate.isEmpty(this.getType())) {
throw new IllegalArgumentException("The form 'type' tag is missing or empty on the form with the name " + this.getName());
} else {
throw new IllegalArgumentException("The form type " + this.getType() + " is not supported for form with name " + this.getName());
}
}
}
public void renderSingleFormString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer, int positions) throws IOException {
List<ModelFormField> tempFieldList = FastList.newInstance();
tempFieldList.addAll(this.fieldList);
// Check to see if there is a field, same name and same use-when (could come from extended form)
for (int j = 0; j < tempFieldList.size(); j++) {
ModelFormField modelFormField = tempFieldList.get(j);
if (this.useWhenFields.contains(modelFormField.getName())) {
boolean shouldUse1 = modelFormField.shouldUse(context);
for (int i = j+1; i < tempFieldList.size(); i++) {
ModelFormField curField = tempFieldList.get(i);
if (curField.getName() != null && curField.getName().equals(modelFormField.getName())) {
boolean shouldUse2 = curField.shouldUse(context);
if (shouldUse1 == shouldUse2) {
tempFieldList.remove(i--);
}
} else {
continue;
}
}
}
}
Set<String> alreadyRendered = new TreeSet<String>();
FieldGroup lastFieldGroup = null;
// render form open
if (!skipStart) formStringRenderer.renderFormOpen(writer, context, this);
// render all hidden & ignored fields
List<ModelFormField> hiddenIgnoredFieldList = this.getHiddenIgnoredFields(context, alreadyRendered, tempFieldList, -1);
this.renderHiddenIgnoredFields(writer, context, formStringRenderer, hiddenIgnoredFieldList);
// render formatting wrapper open
// This should be covered by fieldGroup.renderStartString
//formStringRenderer.renderFormatSingleWrapperOpen(writer, context, this);
// render each field row, except hidden & ignored rows
Iterator<ModelFormField> fieldIter = tempFieldList.iterator();
ModelFormField lastFormField = null;
ModelFormField currentFormField = null;
ModelFormField nextFormField = null;
if (fieldIter.hasNext()) {
currentFormField = fieldIter.next();
}
if (fieldIter.hasNext()) {
nextFormField = fieldIter.next();
}
FieldGroup currentFieldGroup = null;
String currentFieldGroupName = null;
String lastFieldGroupName = null;
if (currentFormField != null) {
currentFieldGroup = (FieldGroup)fieldGroupMap.get(currentFormField.getFieldName());
if (currentFieldGroup == null) {
currentFieldGroup = defaultFieldGroup;
}
if (currentFieldGroup != null) {
currentFieldGroupName = currentFieldGroup.getId();
}
}
boolean isFirstPass = true;
boolean haveRenderedOpenFieldRow = false;
while (currentFormField != null) {
// do the check/get next stuff at the beginning so we can still use the continue stuff easily
// don't do it on the first pass though...
if (isFirstPass) {
isFirstPass = false;
List<FieldGroupBase> inbetweenList = getInbetweenList(lastFieldGroup, currentFieldGroup);
for (FieldGroupBase obj: inbetweenList) {
if (obj instanceof ModelForm.Banner) {
((ModelForm.Banner) obj).renderString(writer, context, formStringRenderer);
}
}
if (currentFieldGroup != null && (lastFieldGroup == null || !lastFieldGroupName.equals(currentFieldGroupName))) {
currentFieldGroup.renderStartString(writer, context, formStringRenderer);
lastFieldGroup = currentFieldGroup;
}
} else {
if (fieldIter.hasNext()) {
// at least two loops left
lastFormField = currentFormField;
currentFormField = nextFormField;
nextFormField = fieldIter.next();
} else if (nextFormField != null) {
// okay, just one loop left
lastFormField = currentFormField;
currentFormField = nextFormField;
nextFormField = null;
} else {
// at the end...
lastFormField = currentFormField;
currentFormField = null;
// nextFormField is already null
break;
}
currentFieldGroup = null;
if (currentFormField != null) {
currentFieldGroup = (FieldGroup) fieldGroupMap.get(currentFormField.getName());
}
if (currentFieldGroup == null) {
currentFieldGroup = defaultFieldGroup;
}
currentFieldGroupName = currentFieldGroup.getId();
if (lastFieldGroup != null) {
lastFieldGroupName = lastFieldGroup.getId();
if (!lastFieldGroupName.equals(currentFieldGroupName)) {
if (haveRenderedOpenFieldRow) {
formStringRenderer.renderFormatFieldRowClose(writer, context, this);
haveRenderedOpenFieldRow = false;
}
lastFieldGroup.renderEndString(writer, context, formStringRenderer);
List<FieldGroupBase> inbetweenList = getInbetweenList(lastFieldGroup, currentFieldGroup);
for (FieldGroupBase obj: inbetweenList) {
if (obj instanceof ModelForm.Banner) {
((ModelForm.Banner) obj).renderString(writer, context, formStringRenderer);
}
}
}
}
if (lastFieldGroup == null || !lastFieldGroupName.equals(currentFieldGroupName)) {
currentFieldGroup.renderStartString(writer, context, formStringRenderer);
lastFieldGroup = currentFieldGroup;
}
}
ModelFormField.FieldInfo fieldInfo = currentFormField.getFieldInfo();
if (fieldInfo.getFieldType() == ModelFormField.FieldInfo.HIDDEN || fieldInfo.getFieldType() == ModelFormField.FieldInfo.IGNORED) {
continue;
}
if (alreadyRendered.contains(currentFormField.getName())) {
continue;
}
//Debug.logInfo("In single form evaluating use-when for field " + currentFormField.getName() + ": " + currentFormField.getUseWhen(), module);
if (!currentFormField.shouldUse(context)) {
continue;
}
alreadyRendered.add(currentFormField.getName());
boolean stayingOnRow = false;
if (lastFormField != null) {
if (lastFormField.getPosition() >= currentFormField.getPosition()) {
// moving to next row
stayingOnRow = false;
} else {
// staying on same row
stayingOnRow = true;
}
}
int positionSpan = 1;
Integer nextPositionInRow = null;
if (nextFormField != null) {
if (nextFormField.getPosition() > currentFormField.getPosition()) {
positionSpan = nextFormField.getPosition() - currentFormField.getPosition() - 1;
nextPositionInRow = Integer.valueOf(nextFormField.getPosition());
} else {
positionSpan = positions - currentFormField.getPosition();
if (!stayingOnRow && nextFormField.getPosition() > 1) {
// TODO: here is a weird case where it is setup such
//that the first position(s) in the row are skipped
// not sure what to do about this right now...
}
}
}
if (stayingOnRow) {
// no spacer cell, might add later though...
//formStringRenderer.renderFormatFieldRowSpacerCell(writer, context, currentFormField);
} else {
if (haveRenderedOpenFieldRow) {
// render row formatting close
formStringRenderer.renderFormatFieldRowClose(writer, context, this);
haveRenderedOpenFieldRow = false;
}
// render row formatting open
formStringRenderer.renderFormatFieldRowOpen(writer, context, this);
haveRenderedOpenFieldRow = true;
}
//
// It must be a row open before rendering a field. If not, open it
//
if (!haveRenderedOpenFieldRow) {
formStringRenderer.renderFormatFieldRowOpen(writer, context, this);
haveRenderedOpenFieldRow = true;
}
// render title formatting open
formStringRenderer.renderFormatFieldRowTitleCellOpen(writer, context, currentFormField);
// render title (unless this is a submit or a reset field)
if (fieldInfo.getFieldType() != ModelFormField.FieldInfo.SUBMIT && fieldInfo.getFieldType() != ModelFormField.FieldInfo.RESET) {
formStringRenderer.renderFieldTitle(writer, context, currentFormField);
} else {
formStringRenderer.renderFormatEmptySpace(writer, context, this);
}
// render title formatting close
formStringRenderer.renderFormatFieldRowTitleCellClose(writer, context, currentFormField);
// render separator
formStringRenderer.renderFormatFieldRowSpacerCell(writer, context, currentFormField);
// render widget formatting open
formStringRenderer.renderFormatFieldRowWidgetCellOpen(writer, context, currentFormField, positions, positionSpan, nextPositionInRow);
// render widget
currentFormField.renderFieldString(writer, context, formStringRenderer);
// render widget formatting close
formStringRenderer.renderFormatFieldRowWidgetCellClose(writer, context, currentFormField, positions, positionSpan, nextPositionInRow);
}
// render row formatting close after the end if needed
if (haveRenderedOpenFieldRow) {
formStringRenderer.renderFormatFieldRowClose(writer, context, this);
}
if (lastFieldGroup != null) {
lastFieldGroup.renderEndString(writer, context, formStringRenderer);
}
// render formatting wrapper close
// should be handled by renderEndString
//formStringRenderer.renderFormatSingleWrapperClose(writer, context, this);
// render form close
if (!skipEnd) formStringRenderer.renderFormClose(writer, context, this);
}
public void renderListFormString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer, int positions) throws IOException {
// render list/tabular type forms
// prepare the items iterator and compute the pagination parameters
this.preparePager(context);
// render formatting wrapper open
formStringRenderer.renderFormatListWrapperOpen(writer, context, this);
int numOfColumns = 0;
// ===== render header row =====
if (!getHideHeader()) {
numOfColumns = this.renderHeaderRow(writer, context, formStringRenderer);
}
// ===== render the item rows =====
this.renderItemRows(writer, context, formStringRenderer, true, numOfColumns);
// render formatting wrapper close
formStringRenderer.renderFormatListWrapperClose(writer, context, this);
}
public void renderMultiFormString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer, int positions) throws IOException {
if (!skipStart) {
formStringRenderer.renderFormOpen(writer, context, this);
}
// prepare the items iterator and compute the pagination parameters
this.preparePager(context);
// render formatting wrapper open
formStringRenderer.renderFormatListWrapperOpen(writer, context, this);
int numOfColumns = 0;
// ===== render header row =====
if (!getHideHeader()) {
numOfColumns = this.renderHeaderRow(writer, context, formStringRenderer);
}
// ===== render the item rows =====
this.renderItemRows(writer, context, formStringRenderer, false, numOfColumns);
formStringRenderer.renderFormatListWrapperClose(writer, context, this);
if (!skipEnd) {
formStringRenderer.renderMultiFormClose(writer, context, this);
}
}
public int renderHeaderRow(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer) throws IOException {
int maxNumOfColumns = 0;
// We will render one title/column for all the fields with the same name
// in this model: we can have more fields with the same name when use-when
// conditions are used or when a form is extended or when the fields are
// automatically retrieved by a service or entity definition.
List<ModelFormField> tempFieldList = FastList.newInstance();
tempFieldList.addAll(this.fieldList);
for (int j = 0; j < tempFieldList.size(); j++) {
ModelFormField modelFormField = tempFieldList.get(j);
for (int i = j+1; i < tempFieldList.size(); i++) {
ModelFormField curField = tempFieldList.get(i);
if (curField.getName() != null && curField.getName().equals(modelFormField.getName())) {
tempFieldList.remove(i--);
}
}
}
// ===========================
// Preprocessing
// ===========================
// We get a sorted (by position, ascending) set of lists;
// each list contains all the fields with that position.
Collection<List<ModelFormField>> fieldListsByPosition = this.getFieldListsByPosition(tempFieldList);
List<Map<String, List<ModelFormField>>> fieldRowsByPosition = FastList.newInstance(); // this list will contain maps, each one containing the list of fields for a position
for (List<ModelFormField> mainFieldList: fieldListsByPosition) {
int numOfColumns = 0;
List<ModelFormField> innerDisplayHyperlinkFieldsBegin = FastList.newInstance();
List<ModelFormField> innerFormFields = FastList.newInstance();
List<ModelFormField> innerDisplayHyperlinkFieldsEnd = FastList.newInstance();
// render title for each field, except hidden & ignored, etc
// start by rendering all display and hyperlink fields, until we
//get to a field that should go into the form cell, then render
//the form cell with all non-display and non-hyperlink fields, then
//do a start after the first form input field and
//render all display and hyperlink fields after the form
// prepare the two lists of display and hyperlink fields
// the fields in the first list will be rendered as columns before the
// combined column for the input fields; the fields in the second list
// will be rendered as columns after it
boolean inputFieldFound = false;
for (ModelFormField modelFormField: mainFieldList) {
ModelFormField.FieldInfo fieldInfo = modelFormField.getFieldInfo();
// if the field's title is explicitly set to "" (title="") then
// the header is not created for it; this is useful for position list
// where one line can be rendered with more than one row, and we
// only want to display the title header for the main row
String modelFormFieldTitle = modelFormField.getTitle(context);
if ("".equals(modelFormFieldTitle)) {
continue;
}
// don't do any header for hidden or ignored fields
if (fieldInfo.getFieldType() == ModelFormField.FieldInfo.HIDDEN || fieldInfo.getFieldType() == ModelFormField.FieldInfo.IGNORED) {
continue;
}
if (fieldInfo.getFieldType() != ModelFormField.FieldInfo.DISPLAY && fieldInfo.getFieldType() != ModelFormField.FieldInfo.DISPLAY_ENTITY && fieldInfo.getFieldType() != ModelFormField.FieldInfo.HYPERLINK) {
inputFieldFound = true;
continue;
}
// separate into two lists the display/hyperlink fields found before and after the first input fields
if (!inputFieldFound) {
innerDisplayHyperlinkFieldsBegin.add(modelFormField);
} else {
innerDisplayHyperlinkFieldsEnd.add(modelFormField);
}
numOfColumns++;
}
// prepare the combined title for the column that will contain the form/input fields
for (ModelFormField modelFormField: mainFieldList) {
ModelFormField.FieldInfo fieldInfo = modelFormField.getFieldInfo();
// don't do any header for hidden or ignored fields
if (fieldInfo.getFieldType() == ModelFormField.FieldInfo.HIDDEN || fieldInfo.getFieldType() == ModelFormField.FieldInfo.IGNORED) {
continue;
}
// skip all of the display/hyperlink fields
if (fieldInfo.getFieldType() == ModelFormField.FieldInfo.DISPLAY || fieldInfo.getFieldType() == ModelFormField.FieldInfo.DISPLAY_ENTITY || fieldInfo.getFieldType() == ModelFormField.FieldInfo.HYPERLINK) {
continue;
}
innerFormFields.add(modelFormField);
}
if (innerFormFields.size() > 0) {
numOfColumns++;
}
if (maxNumOfColumns < numOfColumns) {
maxNumOfColumns = numOfColumns;
}
Map<String, List<ModelFormField>> fieldRow = UtilMisc.toMap("displayBefore", innerDisplayHyperlinkFieldsBegin,
"inputFields", innerFormFields,
"displayAfter", innerDisplayHyperlinkFieldsEnd,
"mainFieldList", mainFieldList);
fieldRowsByPosition.add(fieldRow);
}
// ===========================
// Rendering
// ===========================
for (Map<String, List<ModelFormField>> listsMap: fieldRowsByPosition) {
List<ModelFormField> innerDisplayHyperlinkFieldsBegin = listsMap.get("displayBefore");
List<ModelFormField> innerFormFields = listsMap.get("inputFields");
List<ModelFormField> innerDisplayHyperlinkFieldsEnd = listsMap.get("displayAfter");
List<ModelFormField> mainFieldList = listsMap.get("mainFieldList");
int numOfCells = innerDisplayHyperlinkFieldsBegin.size() +
innerDisplayHyperlinkFieldsEnd.size() +
(innerFormFields.size() > 0? 1: 0);
int numOfColumnsToSpan = maxNumOfColumns - numOfCells + 1;
if (numOfColumnsToSpan < 1) {
numOfColumnsToSpan = 1;
}
if (numOfCells > 0) {
formStringRenderer.renderFormatHeaderRowOpen(writer, context, this);
if (this.groupColumns) {
Iterator<ModelFormField> innerDisplayHyperlinkFieldsBeginIt = innerDisplayHyperlinkFieldsBegin.iterator();
while (innerDisplayHyperlinkFieldsBeginIt.hasNext()) {
ModelFormField modelFormField = innerDisplayHyperlinkFieldsBeginIt.next();
// span columns only if this is the last column in the row (not just in this first list)
if (innerDisplayHyperlinkFieldsBeginIt.hasNext() || numOfCells > innerDisplayHyperlinkFieldsBegin.size()) {
formStringRenderer.renderFormatHeaderRowCellOpen(writer, context, this, modelFormField, 1);
} else {
formStringRenderer.renderFormatHeaderRowCellOpen(writer, context, this, modelFormField, numOfColumnsToSpan);
}
formStringRenderer.renderFieldTitle(writer, context, modelFormField);
formStringRenderer.renderFormatHeaderRowCellClose(writer, context, this, modelFormField);
}
if (innerFormFields.size() > 0) {
// TODO: manage colspan
formStringRenderer.renderFormatHeaderRowFormCellOpen(writer, context, this);
Iterator<ModelFormField> innerFormFieldsIt = innerFormFields.iterator();
while (innerFormFieldsIt.hasNext()) {
ModelFormField modelFormField = innerFormFieldsIt.next();
if (separateColumns || modelFormField.getSeparateColumn()) {
formStringRenderer.renderFormatItemRowCellOpen(writer, context, this, modelFormField, 1);
}
// render title (unless this is a submit or a reset field)
formStringRenderer.renderFieldTitle(writer, context, modelFormField);
if (separateColumns || modelFormField.getSeparateColumn()) {
formStringRenderer.renderFormatItemRowCellClose(writer, context, this, modelFormField);
}
if (innerFormFieldsIt.hasNext()) {
// TODO: determine somehow if this is the last one... how?
if (!separateColumns && !modelFormField.getSeparateColumn()) {
formStringRenderer.renderFormatHeaderRowFormCellTitleSeparator(writer, context, this, modelFormField, false);
}
}
}
formStringRenderer.renderFormatHeaderRowFormCellClose(writer, context, this);
}
Iterator<ModelFormField> innerDisplayHyperlinkFieldsEndIt = innerDisplayHyperlinkFieldsEnd.iterator();
while (innerDisplayHyperlinkFieldsEndIt.hasNext()) {
ModelFormField modelFormField = innerDisplayHyperlinkFieldsEndIt.next();
// span columns only if this is the last column in the row (not just in this first list)
if (innerDisplayHyperlinkFieldsEndIt.hasNext() || numOfCells > innerDisplayHyperlinkFieldsEnd.size()) {
formStringRenderer.renderFormatHeaderRowCellOpen(writer, context, this, modelFormField, 1);
} else {
formStringRenderer.renderFormatHeaderRowCellOpen(writer, context, this, modelFormField, numOfColumnsToSpan);
}
formStringRenderer.renderFieldTitle(writer, context, modelFormField);
formStringRenderer.renderFormatHeaderRowCellClose(writer, context, this, modelFormField);
}
} else {
Iterator<ModelFormField> mainFieldListIter = mainFieldList.iterator();
while (mainFieldListIter.hasNext()) {
ModelFormField modelFormField = mainFieldListIter.next();
// don't do any header for hidden or ignored fields
ModelFormField.FieldInfo fieldInfo = modelFormField.getFieldInfo();
if (fieldInfo.getFieldType() == ModelFormField.FieldInfo.HIDDEN || fieldInfo.getFieldType() == ModelFormField.FieldInfo.IGNORED) {
continue;
}
// span columns only if this is the last column in the row (not just in this first list)
if (mainFieldListIter.hasNext() || numOfCells > mainFieldList.size()) {
formStringRenderer.renderFormatHeaderRowCellOpen(writer, context, this, modelFormField, 1);
} else {
formStringRenderer.renderFormatHeaderRowCellOpen(writer, context, this, modelFormField, numOfColumnsToSpan);
}
formStringRenderer.renderFieldTitle(writer, context, modelFormField);
formStringRenderer.renderFormatHeaderRowCellClose(writer, context, this, modelFormField);
}
}
formStringRenderer.renderFormatHeaderRowClose(writer, context, this);
}
}
return maxNumOfColumns;
}
protected <X> X safeNext(Iterator<X> iterator) {
try {
return iterator.next();
} catch (NoSuchElementException e) {
return null;
}
}
public void preparePager(Map<String, Object> context) {
this.rowCount = 0;
String lookupName = this.getListName();
if (UtilValidate.isEmpty(lookupName)) {
Debug.logError("No value for list or iterator name found.", module);
return;
}
Object obj = context.get(lookupName);
if (obj == null) {
if (Debug.verboseOn()) Debug.logVerbose("No object for list or iterator name [" + lookupName + "] found, so not running pagination.", module);
return;
}
// if list is empty, do not render rows
Iterator<?> iter = null;
if (obj instanceof Iterator<?>) {
iter = (Iterator<?>) obj;
} else if (obj instanceof List<?>) {
iter = ((List<?>) obj).listIterator();
}
// set low and high index
getListLimits(context, obj);
int listSize = ((Integer) context.get("listSize")).intValue();
int lowIndex = ((Integer) context.get("lowIndex")).intValue();
int highIndex = ((Integer) context.get("highIndex")).intValue();
// Debug.logInfo("preparePager: low - high = " + lowIndex + " - " + highIndex, module);
// we're passed a subset of the list, so use (0, viewSize) range
if (isOverridenListSize()) {
lowIndex = 0;
highIndex = ((Integer) context.get("viewSize")).intValue();
}
if (iter == null) return;
// count item rows
int itemIndex = -1;
Object item = this.safeNext(iter);
while (item != null && itemIndex < highIndex) {
itemIndex++;
item = this.safeNext(iter);
}
// Debug.logInfo("preparePager: Found rows = " + itemIndex, module);
// reduce the highIndex if number of items falls short
if ((itemIndex + 1) < highIndex) {
highIndex = itemIndex + 1;
// if list size is overridden, use full listSize
context.put("highIndex", Integer.valueOf(isOverridenListSize() ? listSize : highIndex));
}
context.put("actualPageSize", Integer.valueOf(highIndex - lowIndex));
if (iter instanceof EntityListIterator) {
try {
((EntityListIterator) iter).beforeFirst();
} catch (GenericEntityException e) {
Debug.logError(e, "Error rewinding list form render EntityListIterator: " + e.toString(), module);
}
}
}
public void renderItemRows(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer, boolean formPerItem, int numOfColumns) throws IOException {
this.rowCount = 0;
String lookupName = this.getListName();
if (UtilValidate.isEmpty(lookupName)) {
Debug.logError("No value for list or iterator name found.", module);
return;
}
Object obj = context.get(lookupName);
if (obj == null) {
if (Debug.verboseOn()) Debug.logVerbose("No object for list or iterator name [" + lookupName + "] found, so not rendering rows.", module);
return;
}
// if list is empty, do not render rows
Iterator<?> iter = null;
if (obj instanceof Iterator<?>) {
iter = (Iterator<?>) obj;
} else if (obj instanceof List<?>) {
iter = ((List<?>) obj).listIterator();
}
// set low and high index
getListLimits(context, obj);
int listSize = ((Integer) context.get("listSize")).intValue();
//int viewIndex = ((Integer) context.get("viewIndex")).intValue();
//int viewSize = ((Integer) context.get("viewSize")).intValue();
int lowIndex = ((Integer) context.get("lowIndex")).intValue();
int highIndex = ((Integer) context.get("highIndex")).intValue();
// we're passed a subset of the list, so use (0, viewSize) range
if (isOverridenListSize()) {
lowIndex = 0;
highIndex = ((Integer) context.get("viewSize")).intValue();
}
if (iter != null) {
// render item rows
int itemIndex = -1;
Object item = null;
context.put("wholeFormContext", context);
Map<String, Object> previousItem = FastMap.newInstance();
while ((item = this.safeNext(iter)) != null) {
itemIndex++;
if (itemIndex >= highIndex) {
break;
}
// TODO: this is a bad design, for EntityListIterators we should skip to the lowIndex and go from there, MUCH more efficient...
if (itemIndex < lowIndex) {
continue;
}
Map<String, Object> itemMap = UtilGenerics.checkMap(item);
MapStack<String> localContext = MapStack.create(context);
if (UtilValidate.isNotEmpty(this.getListEntryName())) {
localContext.put(this.getListEntryName(), item);
} else {
localContext.push(itemMap);
}
// reset/remove the BshInterpreter now as well as later because chances are there is an interpreter at this level of the stack too
this.resetGroovyShell(localContext);
localContext.push();
localContext.put("previousItem", previousItem);
previousItem = FastMap.newInstance();
previousItem.putAll(itemMap);
ModelFormAction.runSubActions(this.rowActions, localContext);
localContext.put("itemIndex", Integer.valueOf(itemIndex - lowIndex));
if (UtilValidate.isNotEmpty(context.get("renderFormSeqNumber"))) {
localContext.put("formUniqueId", "_"+context.get("renderFormSeqNumber"));
}
this.resetGroovyShell(localContext);
if (Debug.verboseOn()) Debug.logVerbose("In form got another row, context is: " + localContext, module);
// Check to see if there is a field, same name and same use-when (could come from extended form)
List<ModelFormField> tempFieldList = FastList.newInstance();
tempFieldList.addAll(this.fieldList);
for (int j = 0; j < tempFieldList.size(); j++) {
ModelFormField modelFormField = tempFieldList.get(j);
if (!modelFormField.isUseWhenEmpty()) {
boolean shouldUse1 = modelFormField.shouldUse(localContext);
for (int i = j+1; i < tempFieldList.size(); i++) {
ModelFormField curField = tempFieldList.get(i);
if (curField.getName() != null && curField.getName().equals(modelFormField.getName())) {
boolean shouldUse2 = curField.shouldUse(localContext);
if (shouldUse1 == shouldUse2) {
tempFieldList.remove(i--);
}
} else {
continue;
}
}
}
}
// Each single item is rendered in one or more rows if its fields have
// different "position" attributes. All the fields with the same position
// are rendered in the same row.
// The default position is 1, and represents the main row:
// it contains the fields that are in the list header (columns).
// The positions lower than 1 are rendered in rows before the main one;
// positions higher than 1 are rendered after the main one.
// We get a sorted (by position, ascending) set of lists;
// each list contains all the fields with that position.
Collection<List<ModelFormField>> fieldListsByPosition = this.getFieldListsByPosition(tempFieldList);
//List hiddenIgnoredFieldList = getHiddenIgnoredFields(localContext, null, tempFieldList);
for (List<ModelFormField> fieldListByPosition: fieldListsByPosition) {
// For each position (the subset of fields with the same position attribute)
// we have two phases: preprocessing and rendering
this.rowCount++;
List<ModelFormField> innerDisplayHyperlinkFieldsBegin = FastList.newInstance();
List<ModelFormField> innerFormFields = FastList.newInstance();
List<ModelFormField> innerDisplayHyperlinkFieldsEnd = FastList.newInstance();
// Preprocessing:
// all the form fields are evaluated and the ones that will
// appear in the form are put into three separate lists:
// - hyperlink fields that will appear at the beginning of the row
// - fields of other types
// - hyperlink fields that will appear at the end of the row
Iterator<ModelFormField> innerDisplayHyperlinkFieldIter = fieldListByPosition.iterator();
int currentPosition = 1;
while (innerDisplayHyperlinkFieldIter.hasNext()) {
ModelFormField modelFormField = innerDisplayHyperlinkFieldIter.next();
ModelFormField.FieldInfo fieldInfo = modelFormField.getFieldInfo();
// don't do any header for hidden or ignored fields
if (fieldInfo.getFieldType() == ModelFormField.FieldInfo.HIDDEN || fieldInfo.getFieldType() == ModelFormField.FieldInfo.IGNORED) {
continue;
}
if (fieldInfo.getFieldType() != ModelFormField.FieldInfo.DISPLAY && fieldInfo.getFieldType() != ModelFormField.FieldInfo.DISPLAY_ENTITY && fieldInfo.getFieldType() != ModelFormField.FieldInfo.HYPERLINK) {
// okay, now do the form cell
break;
}
// if this is a list or multi form don't skip here because we don't want to skip the table cell, will skip the actual field later
if (!"list".equals(this.getType()) && !"multi".equals(this.getType()) &&
!modelFormField.shouldUse(localContext)) {
continue;
}
innerDisplayHyperlinkFieldsBegin.add(modelFormField);
currentPosition = modelFormField.getPosition();
}
Iterator<ModelFormField> innerFormFieldIter = fieldListByPosition.iterator();
while (innerFormFieldIter.hasNext()) {
ModelFormField modelFormField = innerFormFieldIter.next();
ModelFormField.FieldInfo fieldInfo = modelFormField.getFieldInfo();
// don't do any header for hidden or ignored fields
if (fieldInfo.getFieldType() == ModelFormField.FieldInfo.HIDDEN || fieldInfo.getFieldType() == ModelFormField.FieldInfo.IGNORED) {
continue;
}
// skip all of the display/hyperlink fields
if (fieldInfo.getFieldType() == ModelFormField.FieldInfo.DISPLAY || fieldInfo.getFieldType() == ModelFormField.FieldInfo.DISPLAY_ENTITY || fieldInfo.getFieldType() == ModelFormField.FieldInfo.HYPERLINK) {
continue;
}
// if this is a list or multi form don't skip here because we don't want to skip the table cell, will skip the actual field later
if (!"list".equals(this.getType()) && !"multi".equals(this.getType()) &&
!modelFormField.shouldUse(localContext)) {
continue;
}
innerFormFields.add(modelFormField);
currentPosition = modelFormField.getPosition();
}
while (innerDisplayHyperlinkFieldIter.hasNext()) {
ModelFormField modelFormField = innerDisplayHyperlinkFieldIter.next();
ModelFormField.FieldInfo fieldInfo = modelFormField.getFieldInfo();
// don't do any header for hidden or ignored fields
if (fieldInfo.getFieldType() == ModelFormField.FieldInfo.HIDDEN || fieldInfo.getFieldType() == ModelFormField.FieldInfo.IGNORED) {
continue;
}
// skip all non-display and non-hyperlink fields
if (fieldInfo.getFieldType() != ModelFormField.FieldInfo.DISPLAY && fieldInfo.getFieldType() != ModelFormField.FieldInfo.DISPLAY_ENTITY && fieldInfo.getFieldType() != ModelFormField.FieldInfo.HYPERLINK) {
continue;
}
// if this is a list or multi form don't skip here because we don't want to skip the table cell, will skip the actual field later
if (!"list".equals(this.getType()) && !"multi".equals(this.getType()) &&
!modelFormField.shouldUse(localContext)) {
continue;
}
innerDisplayHyperlinkFieldsEnd.add(modelFormField);
currentPosition = modelFormField.getPosition();
}
List<ModelFormField> hiddenIgnoredFieldList = getHiddenIgnoredFields(localContext, null, tempFieldList, currentPosition);
// Rendering:
// the fields in the three lists created in the preprocessing phase
// are now rendered: this will create a visual representation
// of one row (for the current position).
if (innerDisplayHyperlinkFieldsBegin.size() > 0 || innerFormFields.size() > 0 || innerDisplayHyperlinkFieldsEnd.size() > 0) {
this.renderItemRow(writer, localContext, formStringRenderer, formPerItem, hiddenIgnoredFieldList,
innerDisplayHyperlinkFieldsBegin, innerFormFields, innerDisplayHyperlinkFieldsEnd, fieldListByPosition,
currentPosition, numOfColumns);
}
} // iteration on positions
} // iteration on items
// reduce the highIndex if number of items falls short
if ((itemIndex + 1) < highIndex) {
highIndex = itemIndex + 1;
// if list size is overridden, use full listSize
context.put("highIndex", Integer.valueOf(isOverridenListSize() ? listSize : highIndex));
}
context.put("actualPageSize", Integer.valueOf(highIndex - lowIndex));
if (iter instanceof EntityListIterator) {
try {
((EntityListIterator) iter).close();
} catch (GenericEntityException e) {
Debug.logError(e, "Error closing list form render EntityListIterator: " + e.toString(), module);
}
}
}
}
// The fields in the three lists, usually created in the preprocessing phase
// of the renderItemRows method are rendered: this will create a visual representation
// of one row (corresponding to one position).
public void renderItemRow(Appendable writer, Map<String, Object> localContext, FormStringRenderer formStringRenderer,
boolean formPerItem, List<ModelFormField> hiddenIgnoredFieldList, List<ModelFormField> innerDisplayHyperlinkFieldsBegin,
List<ModelFormField> innerFormFields, List<ModelFormField> innerDisplayHyperlinkFieldsEnd, List<ModelFormField> mainFieldList,
int position, int numOfColumns) throws IOException {
int numOfCells = innerDisplayHyperlinkFieldsBegin.size() +
innerDisplayHyperlinkFieldsEnd.size() +
(innerFormFields.size() > 0? 1: 0);
int numOfColumnsToSpan = numOfColumns - numOfCells + 1;
if (numOfColumnsToSpan < 1) {
numOfColumnsToSpan = 1;
}
// render row formatting open
formStringRenderer.renderFormatItemRowOpen(writer, localContext, this);
Iterator<ModelFormField> innerDisplayHyperlinkFieldsBeginIter = innerDisplayHyperlinkFieldsBegin.iterator();
Map<String, Integer> fieldCount = FastMap.newInstance();
while(innerDisplayHyperlinkFieldsBeginIter.hasNext()){
ModelFormField modelFormField = innerDisplayHyperlinkFieldsBeginIter.next();
if(fieldCount.containsKey(modelFormField.getFieldName())){
fieldCount.put(modelFormField.getFieldName(), fieldCount.get(modelFormField.getFieldName())+1);
}
else{
fieldCount.put(modelFormField.getFieldName(), 1);
}
}
if (this.groupColumns) {
// do the first part of display and hyperlink fields
Iterator<ModelFormField> innerDisplayHyperlinkFieldIter = innerDisplayHyperlinkFieldsBegin.iterator();
while (innerDisplayHyperlinkFieldIter.hasNext()) {
boolean cellOpen = false;
ModelFormField modelFormField = innerDisplayHyperlinkFieldIter.next();
// span columns only if this is the last column in the row (not just in this first list)
if( fieldCount.get(modelFormField.getName()) < 2 ){
if ((innerDisplayHyperlinkFieldIter.hasNext() || numOfCells > innerDisplayHyperlinkFieldsBegin.size())) {
formStringRenderer.renderFormatItemRowCellOpen(writer, localContext, this, modelFormField, 1);
} else {
formStringRenderer.renderFormatItemRowCellOpen(writer, localContext, this, modelFormField, numOfColumnsToSpan);
}
cellOpen = true;
}
if ((!"list".equals(this.getType()) && !"multi".equals(this.getType())) || modelFormField.shouldUse(localContext)) {
if(( fieldCount.get(modelFormField.getName()) > 1 )){
if ((innerDisplayHyperlinkFieldIter.hasNext() || numOfCells > innerDisplayHyperlinkFieldsBegin.size())) {
formStringRenderer.renderFormatItemRowCellOpen(writer, localContext, this, modelFormField, 1);
} else {
formStringRenderer.renderFormatItemRowCellOpen(writer, localContext, this, modelFormField, numOfColumnsToSpan);
}
cellOpen = true;
}
modelFormField.renderFieldString(writer, localContext, formStringRenderer);
}
if (cellOpen) {
formStringRenderer.renderFormatItemRowCellClose(writer, localContext, this, modelFormField);
}
}
// The form cell is rendered only if there is at least an input field
if (innerFormFields.size() > 0) {
// render the "form" cell
formStringRenderer.renderFormatItemRowFormCellOpen(writer, localContext, this); // TODO: colspan
if (formPerItem) {
formStringRenderer.renderFormOpen(writer, localContext, this);
}
// do all of the hidden fields...
this.renderHiddenIgnoredFields(writer, localContext, formStringRenderer, hiddenIgnoredFieldList);
Iterator<ModelFormField> innerFormFieldIter = innerFormFields.iterator();
while (innerFormFieldIter.hasNext()) {
ModelFormField modelFormField = innerFormFieldIter.next();
if (separateColumns || modelFormField.getSeparateColumn()) {
formStringRenderer.renderFormatItemRowCellOpen(writer, localContext, this, modelFormField, 1);
}
// render field widget
if ((!"list".equals(this.getType()) && !"multi".equals(this.getType())) || modelFormField.shouldUse(localContext)) {
modelFormField.renderFieldString(writer, localContext, formStringRenderer);
}
if (separateColumns || modelFormField.getSeparateColumn()) {
formStringRenderer.renderFormatItemRowCellClose(writer, localContext, this, modelFormField);
}
}
if (formPerItem) {
formStringRenderer.renderFormClose(writer, localContext, this);
}
formStringRenderer.renderFormatItemRowFormCellClose(writer, localContext, this);
}
// render the rest of the display/hyperlink fields
innerDisplayHyperlinkFieldIter = innerDisplayHyperlinkFieldsEnd.iterator();
while (innerDisplayHyperlinkFieldIter.hasNext()) {
ModelFormField modelFormField = innerDisplayHyperlinkFieldIter.next();
// span columns only if this is the last column in the row
if (innerDisplayHyperlinkFieldIter.hasNext()) {
formStringRenderer.renderFormatItemRowCellOpen(writer, localContext, this, modelFormField, 1);
} else {
formStringRenderer.renderFormatItemRowCellOpen(writer, localContext, this, modelFormField, numOfColumnsToSpan);
}
if ((!"list".equals(this.getType()) && !"multi".equals(this.getType())) || modelFormField.shouldUse(localContext)) {
modelFormField.renderFieldString(writer, localContext, formStringRenderer);
}
formStringRenderer.renderFormatItemRowCellClose(writer, localContext, this, modelFormField);
}
} else {
// do all of the hidden fields...
this.renderHiddenIgnoredFields(writer, localContext, formStringRenderer, hiddenIgnoredFieldList);
Iterator<ModelFormField> mainFieldIter = mainFieldList.iterator();
while (mainFieldIter.hasNext()) {
ModelFormField modelFormField = mainFieldIter.next();
// don't do any header for hidden or ignored fields inside this loop
ModelFormField.FieldInfo fieldInfo = modelFormField.getFieldInfo();
if (fieldInfo.getFieldType() == ModelFormField.FieldInfo.HIDDEN || fieldInfo.getFieldType() == ModelFormField.FieldInfo.IGNORED) {
continue;
}
// span columns only if this is the last column in the row
if (mainFieldIter.hasNext()) {
formStringRenderer.renderFormatItemRowCellOpen(writer, localContext, this, modelFormField, 1);
} else {
formStringRenderer.renderFormatItemRowCellOpen(writer, localContext, this, modelFormField, numOfColumnsToSpan);
}
if ((!"list".equals(this.getType()) && !"multi".equals(this.getType())) || modelFormField.shouldUse(localContext)) {
modelFormField.renderFieldString(writer, localContext, formStringRenderer);
}
formStringRenderer.renderFormatItemRowCellClose(writer, localContext, this, modelFormField);
}
}
// render row formatting close
formStringRenderer.renderFormatItemRowClose(writer, localContext, this);
}
public List<ModelFormField> getHiddenIgnoredFields(Map<String, Object> context, Set<String> alreadyRendered, List<ModelFormField> fieldList, int position) {
List<ModelFormField> hiddenIgnoredFieldList = FastList.newInstance();
for (ModelFormField modelFormField: fieldList) {
// with position == -1 then gets all the hidden fields
if (position != -1 && modelFormField.getPosition() != position) {
continue;
}
ModelFormField.FieldInfo fieldInfo = modelFormField.getFieldInfo();
// render hidden/ignored field widget
switch (fieldInfo.getFieldType()) {
case ModelFormField.FieldInfo.HIDDEN :
case ModelFormField.FieldInfo.IGNORED :
if (modelFormField.shouldUse(context)) {
hiddenIgnoredFieldList.add(modelFormField);
if (alreadyRendered != null)
alreadyRendered.add(modelFormField.getName());
}
break;
case ModelFormField.FieldInfo.DISPLAY :
case ModelFormField.FieldInfo.DISPLAY_ENTITY :
ModelFormField.DisplayField displayField = (ModelFormField.DisplayField) fieldInfo;
if (displayField.getAlsoHidden() && modelFormField.shouldUse(context)) {
hiddenIgnoredFieldList.add(modelFormField);
// don't add to already rendered here, or the display won't ger rendered: if (alreadyRendered != null) alreadyRendered.add(modelFormField.getName());
}
break;
case ModelFormField.FieldInfo.HYPERLINK :
ModelFormField.HyperlinkField hyperlinkField = (ModelFormField.HyperlinkField) fieldInfo;
if (hyperlinkField.getAlsoHidden() && modelFormField.shouldUse(context)) {
hiddenIgnoredFieldList.add(modelFormField);
// don't add to already rendered here, or the hyperlink won't ger rendered: if (alreadyRendered != null) alreadyRendered.add(modelFormField.getName());
}
break;
}
}
return hiddenIgnoredFieldList;
}
public void renderHiddenIgnoredFields(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer, List<ModelFormField> fieldList) throws IOException {
for (ModelFormField modelFormField: fieldList) {
ModelFormField.FieldInfo fieldInfo = modelFormField.getFieldInfo();
// render hidden/ignored field widget
switch (fieldInfo.getFieldType()) {
case ModelFormField.FieldInfo.HIDDEN :
case ModelFormField.FieldInfo.IGNORED :
modelFormField.renderFieldString(writer, context, formStringRenderer);
break;
case ModelFormField.FieldInfo.DISPLAY :
case ModelFormField.FieldInfo.DISPLAY_ENTITY :
case ModelFormField.FieldInfo.HYPERLINK :
formStringRenderer.renderHiddenField(writer, context, modelFormField, modelFormField.getEntry(context));
break;
}
}
}
public Collection<List<ModelFormField>> getFieldListsByPosition(List<ModelFormField> modelFormFieldList) {
Map<Integer, List<ModelFormField>> fieldsByPosition = new TreeMap<Integer, List<ModelFormField>>();
for (ModelFormField modelFormField: modelFormFieldList) {
Integer position = Integer.valueOf(modelFormField.getPosition());
List<ModelFormField> fieldListByPosition = fieldsByPosition.get(position);
if (fieldListByPosition == null) {
fieldListByPosition = FastList.newInstance();
fieldsByPosition.put(position, fieldListByPosition);
}
fieldListByPosition.add(modelFormField);
}
return fieldsByPosition.values();
}
public List<ModelFormField> getFieldListByPosition(List<ModelFormField> modelFormFieldList, int position) {
List<ModelFormField> fieldListByPosition = FastList.newInstance();
for (ModelFormField modelFormField: modelFormFieldList) {
if (modelFormField.getPosition() == position) {
fieldListByPosition.add(modelFormField);
}
}
return fieldListByPosition;
}
public String getTargetType() {
return this.targetType;
}
public String getParentFormName() {
return this.parentFormName;
}
public String getParentFormLocation() {
if (this.parentFormName != null && this.parentFormLocation == null) {
return this.formLocation;
}
return this.parentFormLocation;
}
public String getDefaultEntityName() {
return this.defaultEntityName;
}
public String getDefaultMapName() {
return this.defaultMapName.getOriginalName();
}
public Map<String, ? extends Object> getDefaultMap(Map<String, ? extends Object> context) {
return this.defaultMapName.get(context);
}
public String getDefaultRequiredFieldStyle() {
return this.defaultRequiredFieldStyle;
}
public String getDefaultSortFieldStyle() {
return (UtilValidate.isEmpty(this.defaultSortFieldStyle) ? DEFAULT_SORT_FIELD_STYLE : this.defaultSortFieldStyle);
}
public String getDefaultSortFieldAscStyle() {
return (UtilValidate.isEmpty(this.defaultSortFieldAscStyle) ? DEFAULT_SORT_FIELD_ASC_STYLE : this.defaultSortFieldAscStyle);
}
public String getDefaultSortFieldDescStyle() {
return (UtilValidate.isEmpty(this.defaultSortFieldDescStyle) ? DEFAULT_SORT_FIELD_DESC_STYLE : this.defaultSortFieldDescStyle);
}
public String getDefaultServiceName() {
return this.defaultServiceName;
}
public String getFormTitleAreaStyle() {
return this.formTitleAreaStyle;
}
public String getFormWidgetAreaStyle() {
return this.formWidgetAreaStyle;
}
public String getDefaultTitleAreaStyle() {
return this.defaultTitleAreaStyle;
}
public String getDefaultWidgetAreaStyle() {
return this.defaultWidgetAreaStyle;
}
public String getOddRowStyle() {
return this.oddRowStyle;
}
public String getEvenRowStyle() {
return this.evenRowStyle;
}
public String getDefaultTableStyle() {
return this.defaultTableStyle;
}
public String getHeaderRowStyle() {
return this.headerRowStyle;
}
public String getDefaultTitleStyle() {
return this.defaultTitleStyle;
}
public String getDefaultWidgetStyle() {
return this.defaultWidgetStyle;
}
public String getDefaultTooltipStyle() {
return this.defaultTooltipStyle;
}
public String getItemIndexSeparator() {
if (UtilValidate.isNotEmpty(this.itemIndexSeparator)) {
return this.itemIndexSeparator;
} else {
return "_o_";
}
}
public String getListEntryName() {
return this.listEntryName;
}
public String getListName() {
String lstNm = this.listName;
if (UtilValidate.isEmpty(lstNm)) {
lstNm = DEFAULT_FORM_RESULT_LIST_NAME;
}
return lstNm;
}
@Override
public String getName() {
return this.name;
}
public String getCurrentFormName(Map<String, Object> context) {
Integer itemIndex = (Integer) context.get("itemIndex");
String formName = (String) context.get("formName");
if (UtilValidate.isEmpty(formName)) {
formName = this.getName();
}
if (itemIndex != null && "list".equals(this.getType())) {
return formName + this.getItemIndexSeparator() + itemIndex.intValue();
} else {
return formName;
}
}
/** iterate through altTargets list to see if any should be used, if not return original target
* @return The target for this Form
*/
public String getTarget(Map<String, Object> context, String targetType) {
Map<String, Object> expanderContext = context;
StringUtil.SimpleEncoder simpleEncoder = (StringUtil.SimpleEncoder) context.get("simpleEncoder");
if (simpleEncoder != null) {
expanderContext = StringUtil.HtmlEncodingMapWrapper.getHtmlEncodingMapWrapper(context, simpleEncoder);
}
try {
// use the same Interpreter (ie with the same context setup) for all evals
GroovyShell shell = this.getGroovyShell(context);
for (AltTarget altTarget: this.altTargets) {
Object retVal = shell.evaluate(StringUtil.convertOperatorSubstitutions(altTarget.useWhen));
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 target condition eval was not a Boolean: " + retVal.getClass().getName() + " [" + retVal + "] of form " + this.name);
}
if (condTrue && !targetType.equals("inter-app")) {
return altTarget.targetExdr.expandString(expanderContext);
}
}
} catch (CompilationFailedException e) {
String errmsg = "Error evaluating BeanShell target conditions on form " + this.name;
Debug.logError(e, errmsg, module);
throw new IllegalArgumentException(errmsg);
}
return target.expandString(expanderContext);
}
public String getContainerId() {
// use the name if there is no id
if (UtilValidate.isNotEmpty(this.containerId)) {
return this.containerId;
} else {
return this.getName();
}
}
public String getCurrentContainerId(Map<String, Object> context) {
Locale locale = UtilMisc.ensureLocale(context.get("locale"));
String retVal = FlexibleStringExpander.expandString(this.getContainerId(), context, locale);
Integer itemIndex = (Integer) context.get("itemIndex");
if (itemIndex != null && "list".equals(this.getType())) {
return retVal + this.getItemIndexSeparator() + itemIndex.intValue();
}
return retVal;
}
public String getContainerStyle() {
return this.containerStyle;
}
public String getfocusFieldName() {
return this.focusFieldName;
}
public String getTitle() {
return this.title;
}
public String getTooltip() {
return this.tooltip;
}
public String getType() {
return this.type;
}
@Override
public String getBoundaryCommentName() {
return formLocation + "#" + name;
}
public void resetGroovyShell(Map<String, Object> context) {
context.remove("groovyShell");
}
public GroovyShell getGroovyShell(Map<String, Object> context) throws CompilationFailedException {
GroovyShell shell = (GroovyShell) context.get("groovyShell");
if (shell == null) {
shell = new GroovyShell(GroovyUtil.getBinding(context));
context.put("groovyShell", shell);
}
return shell;
}
/**
* @param string
*/
public void setDefaultEntityName(String string) {
this.defaultEntityName = string;
}
/**
* @param string
*/
public void setDefaultMapName(String string) {
this.defaultMapName = FlexibleMapAccessor.getInstance(string);
}
/**
* @param string
*/
public void setDefaultServiceName(String string) {
this.defaultServiceName = string;
}
/**
* @param string
*/
public void setFormTitleAreaStyle(String string) {
this.formTitleAreaStyle = string;
}
/**
* @param string
*/
public void setFormWidgetAreaStyle(String string) {
this.formWidgetAreaStyle = string;
}
/**
* @param string
*/
public void setDefaultTitleAreaStyle(String string) {
this.defaultTitleAreaStyle = string;
}
/**
* @param string
*/
public void setDefaultWidgetAreaStyle(String string) {
this.defaultWidgetAreaStyle = string;
}
/**
* @param string
*/
public void setOddRowStyle(String string) {
this.oddRowStyle = string;
}
/**
* @param string
*/
public void setEvenRowStyle(String string) {
this.evenRowStyle = string;
}
/**
* @param string
*/
public void setDefaultTableStyle(String string) {
this.defaultTableStyle = string;
}
/**
* @param string
*/
public void setHeaderRowStyle(String string) {
this.headerRowStyle = string;
}
/**
* @param string
*/
public void setDefaultTitleStyle(String string) {
this.defaultTitleStyle = string;
}
/**
* @param string
*/
public void setDefaultWidgetStyle(String string) {
this.defaultWidgetStyle = string;
}
/**
* @param string
*/
public void setDefaultTooltipStyle(String string) {
this.defaultTooltipStyle = string;
}
/**
* @param string
*/
public void setItemIndexSeparator(String string) {
this.itemIndexSeparator = string;
}
/**
* @param formLocation string Form's location
*/
public void setFormLocation(String formLocation) {
this.formLocation = formLocation;
}
public String getFormLocation() {
return this.formLocation;
}
/**
* @param string
*/
public void setListEntryName(String string) {
this.listEntryName = string;
}
/**
* @param string
*/
public void setListName(String string) {
this.listName = string;
}
/**
* @param string
*/
public void setName(String string) {
this.name = string;
}
/**
* @param string
*/
public void setTarget(String string) {
this.target = FlexibleStringExpander.getInstance(string);
}
/**
* @param string
*/
public void setContainerId(String string) {
this.containerId = string;
}
/**
* @param string
*/
public void setfocusFieldName(String string) {
this.focusFieldName = string;
}
/**
* @param string
*/
public void setTitle(String string) {
this.title = string;
}
/**
* @param string
*/
public void setTooltip(String string) {
this.tooltip = string;
}
/**
* @param string
*/
public void setType(String string) {
this.type = string;
}
public List<UpdateArea> getOnPaginateUpdateAreas() {
return this.onPaginateUpdateAreas;
}
public String getPaginateTarget(Map<String, Object> context) {
String targ = this.paginateTarget.expandString(context);
if (UtilValidate.isEmpty(targ)) {
Map<String, ?> parameters = UtilGenerics.cast(context.get("parameters"));
if (parameters != null && parameters.containsKey("targetRequestUri")) {
targ = (String) parameters.get("targetRequestUri");
}
}
return targ;
}
public String getPaginateTargetAnchor() {
return this.paginateTargetAnchor;
}
public String getPaginateIndexField(Map<String, Object> context) {
String field = this.paginateIndexField.expandString(context);
if (UtilValidate.isEmpty(field)) {
field = DEFAULT_PAG_INDEX_FIELD;
}
return field;
}
public String getMultiPaginateIndexField(Map<String, Object> context) {
String field = this.paginateIndexField.expandString(context);
if (UtilValidate.isEmpty(field)) {
field = DEFAULT_PAG_INDEX_FIELD;
}
// append the paginator number
field = field + "_" + WidgetWorker.getPaginatorNumber(context);
return field;
}
public int getPaginateIndex(Map<String, Object> context) {
String field = this.getMultiPaginateIndexField(context);
int viewIndex = 0;
try {
Object value = context.get(field);
if (value == null) {
// try parameters.VIEW_INDEX as that is an old OFBiz convention
Map<String, Object> parameters = UtilGenerics.cast(context.get("parameters"));
if (parameters != null) {
value = parameters.get("VIEW_INDEX" + "_" + WidgetWorker.getPaginatorNumber(context));
if (value == null) {
value = parameters.get(field);
}
}
}
// try paginate index field without paginator number
if (value == null) {
field = this.getPaginateIndexField(context);
value = context.get(field);
}
if (value instanceof Integer) {
viewIndex = ((Integer) value).intValue();
} else if (value instanceof String) {
viewIndex = Integer.parseInt((String) value);
}
} catch (Exception e) {
Debug.logWarning(e, "Error getting paginate view index: " + e.toString(), module);
}
return viewIndex;
}
public String getPaginateSizeField(Map<String, Object> context) {
String field = this.paginateSizeField.expandString(context);
if (UtilValidate.isEmpty(field)) {
field = DEFAULT_PAG_SIZE_FIELD;
}
return field;
}
public String getMultiPaginateSizeField(Map<String, Object> context) {
String field = this.paginateSizeField.expandString(context);
if (UtilValidate.isEmpty(field)) {
field = DEFAULT_PAG_SIZE_FIELD;
}
// append the paginator number
field = field + "_" + WidgetWorker.getPaginatorNumber(context);
return field;
}
public int getPaginateSize(Map<String, Object> context) {
String field = this.getMultiPaginateSizeField(context);
int viewSize = this.defaultViewSize;
try {
Object value = context.get(field);
if (value == null) {
// try parameters.VIEW_SIZE as that is an old OFBiz convention
Map<String, Object> parameters = UtilGenerics.cast(context.get("parameters"));
if (parameters != null) {
value = parameters.get("VIEW_SIZE" + "_" + WidgetWorker.getPaginatorNumber(context));
if (value == null) {
value = parameters.get(field);
}
}
}
// try the page size field without paginator number
if (value == null) {
field = this.getPaginateSizeField(context);
value = context.get(field);
}
if (value instanceof Integer) {
viewSize = ((Integer) value).intValue();
} else if (value instanceof String && UtilValidate.isNotEmpty(value)) {
viewSize = Integer.parseInt((String) value);
}
} catch (Exception e) {
Debug.logWarning(e, "Error getting paginate view size: " + e.toString(), module);
}
return viewSize;
}
public String getPaginateFirstLabel(Map<String, Object> context) {
Locale locale = (Locale)context.get("locale");
String field = this.paginateFirstLabel.expandString(context);
if (UtilValidate.isEmpty(field)) {
field = UtilProperties.getMessage("CommonUiLabels", "CommonFirst", locale);
}
return field;
}
public String getPaginatePreviousLabel(Map<String, Object> context) {
Locale locale = (Locale)context.get("locale");
String field = this.paginatePreviousLabel.expandString(context);
if (UtilValidate.isEmpty(field)) {
field = UtilProperties.getMessage("CommonUiLabels", "CommonPrevious", locale);
}
return field;
}
public String getPaginateNextLabel(Map<String, Object> context) {
Locale locale = (Locale)context.get("locale");
String field = this.paginateNextLabel.expandString(context);
if (UtilValidate.isEmpty(field)) {
field = UtilProperties.getMessage("CommonUiLabels", "CommonNext", locale);
}
return field;
}
public String getPaginateLastLabel(Map<String, Object> context) {
Locale locale = (Locale)context.get("locale");
String field = this.paginateLastLabel.expandString(context);
if (UtilValidate.isEmpty(field)) {
field = UtilProperties.getMessage("CommonUiLabels", "CommonLast", locale);
}
return field;
}
public String getPaginateViewSizeLabel(Map<String, Object> context) {
Locale locale = (Locale)context.get("locale");
String field = this.paginateViewSizeLabel.expandString(context);
if (UtilValidate.isEmpty(field)) {
field = UtilProperties.getMessage("CommonUiLabels", "CommonItemsPerPage", locale);
}
return field;
}
public String getPaginateStyle() {
return this.paginateStyle;
}
public String getPaginateFirstStyle() {
return DEFAULT_PAG_FIRST_STYLE;
}
public String getPaginatePreviousStyle() {
return DEFAULT_PAG_PREV_STYLE;
}
public String getPaginateNextStyle() {
return DEFAULT_PAG_NEXT_STYLE;
}
public String getPaginateLastStyle() {
return DEFAULT_PAG_LAST_STYLE;
}
public String getTargetWindow(Map<String, Object> context) {
return this.targetWindowExdr.expandString(context);
}
public void setTargetWindow(String val) {
this.targetWindowExdr = FlexibleStringExpander.getInstance(val);
}
public boolean getSeparateColumns() {
return this.separateColumns;
}
public boolean getPaginate(Map<String, Object> context) {
if (UtilValidate.isNotEmpty(this.paginate) && UtilValidate.isNotEmpty(this.paginate.expandString(context))) {
return Boolean.valueOf(this.paginate.expandString(context)).booleanValue();
} else {
return true;
}
}
public boolean getSkipStart() {
return this.skipStart;
}
public boolean getSkipEnd() {
return this.skipEnd;
}
public boolean isOverridenListSize() {
return this.overridenListSize;
}
public void setSkipStart(boolean val) {
this.skipStart = val;
}
public void setSkipEnd(boolean val) {
this.skipEnd = val;
}
public boolean getHideHeader() {
return this.hideHeader;
}
public boolean getClientAutocompleteFields() {
return this.clientAutocompleteFields;
}
public void setPaginate(boolean val) {
this.paginate = FlexibleStringExpander.getInstance(Boolean.valueOf(val).toString());
}
public void setOverridenListSize(boolean overridenListSize) {
this.overridenListSize = overridenListSize;
}
public void setPaginateTarget(String string) {
this.paginateTarget = FlexibleStringExpander.getInstance(string);
}
public void setPaginateIndexField(String string) {
this.paginateIndexField = FlexibleStringExpander.getInstance(string);
}
public void setPaginateSizeField(String string) {
this.paginateSizeField = FlexibleStringExpander.getInstance(string);
}
public void setPaginateStyle(String string) {
this.paginateStyle = (UtilValidate.isEmpty(string) ? DEFAULT_PAG_STYLE : string);
}
public void setDefaultViewSize(int val) {
defaultViewSize = val;
}
public void setDefaultViewSize(String val) {
try {
Integer sz = Integer.valueOf(val);
defaultViewSize = sz.intValue();
} catch (NumberFormatException e) {
defaultViewSize = DEFAULT_PAGE_SIZE;
}
}
public int getListSize(Map<String, Object> context) {
Integer value = (Integer) context.get("listSize");
return value != null ? value.intValue() : 0;
}
public int getViewIndex(Map<String, Object> context) {
return getPaginateIndex(context);
}
public int getViewSize(Map<String, Object> context) {
return getPaginateSize(context);
}
public int getLowIndex(Map<String, Object> context) {
Integer value = (Integer) context.get("lowIndex");
return value != null ? value.intValue() : 0;
}
public int getHighIndex(Map<String, Object> context) {
Integer value = (Integer) context.get("highIndex");
return value != null ? value.intValue() : 0;
}
public int getActualPageSize(Map<String, Object> context) {
Integer value = (Integer) context.get("actualPageSize");
return value != null ? value.intValue() : (getHighIndex(context) - getLowIndex(context));
}
public List<ModelFormField> getFieldList() {
return fieldList;
}
private int getOverrideListSize(Map<String, Object> context) {
int listSize = 0;
String size = this.overrideListSize.expandString(context);
if (UtilValidate.isNotEmpty(size)) {
try {
listSize = Integer.parseInt(size);
} catch (NumberFormatException e) {
Debug.logError(e, "Error getting override list size from value " + size, module);
}
}
return listSize;
}
public void getListLimits(Map<String, Object> context, Object entryList) {
int listSize = 0;
int viewIndex = 0;
int viewSize = 0;
int lowIndex = 0;
int highIndex = 0;
listSize = getOverrideListSize(context);
if (listSize > 0) {
setOverridenListSize(true);
} else if (entryList instanceof EntityListIterator) {
EntityListIterator iter = (EntityListIterator) entryList;
try {
listSize = iter.getResultsSizeAfterPartialList();
} catch (GenericEntityException e) {
Debug.logError(e, "Error getting list size", module);
listSize = 0;
}
} else if (entryList instanceof List<?>) {
List<?> items = (List<?>) entryList;
listSize = items.size();
}
if (getPaginate(context)) {
viewIndex = this.getPaginateIndex(context);
viewSize = this.getPaginateSize(context);
lowIndex = viewIndex * viewSize;
highIndex = (viewIndex + 1) * viewSize;
} else {
viewIndex = 0;
viewSize = MAX_PAGE_SIZE;
lowIndex = 0;
highIndex = MAX_PAGE_SIZE;
}
context.put("listSize", Integer.valueOf(listSize));
context.put("viewIndex", Integer.valueOf(viewIndex));
context.put("viewSize", Integer.valueOf(viewSize));
context.put("lowIndex", Integer.valueOf(lowIndex));
context.put("highIndex", Integer.valueOf(highIndex));
}
public String getPassedRowCount(Map<String, Object> context) {
return rowCountExdr.expandString(context);
}
public int getRowCount() {
return this.rowCount;
}
public boolean getUseRowSubmit() {
return this.useRowSubmit;
}
public List<ModelFormField> getMultiSubmitFields() {
return this.multiSubmitFields;
}
public List<FieldGroupBase> getInbetweenList(FieldGroup startFieldGroup, FieldGroup endFieldGroup) {
ArrayList<FieldGroupBase> inbetweenList = new ArrayList<FieldGroupBase>();
boolean firstFound = false;
String startFieldGroupId = null;
String endFieldGroupId = null;
if (endFieldGroup != null) {
endFieldGroupId = endFieldGroup.getId();
}
if (startFieldGroup == null) {
firstFound = true;
} else {
startFieldGroupId = startFieldGroup.getId();
}
Iterator<FieldGroupBase> iter = fieldGroupList.iterator();
while (iter.hasNext()) {
FieldGroupBase obj = iter.next();
if (obj instanceof ModelForm.Banner) {
if (firstFound) inbetweenList.add(obj);
} else {
FieldGroup fieldGroup = (FieldGroup)obj;
String fieldGroupId = fieldGroup.getId();
if (!firstFound) {
if (fieldGroupId.equals(startFieldGroupId)) {
firstFound = true;
continue;
}
}
if (firstFound) {
if (fieldGroupId.equals(endFieldGroupId)) {
break;
} else {
inbetweenList.add(fieldGroup);
}
}
}
}
return inbetweenList;
}
public String getSortField(Map<String, Object> context) {
String field = "sortField";
String value = null;
try {
value = (String)context.get(field);
if (value == null) {
Map<String, String> parameters = UtilGenerics.cast(context.get("parameters"));
if (parameters != null) {
value = parameters.get(field);
}
}
} catch (Exception e) {
Debug.logWarning(e, "Error getting sortField: " + e.toString(), module);
}
return value;
}
/* Returns the list of ModelForm.UpdateArea objects.
*/
public List<UpdateArea> getOnSubmitUpdateAreas() {
return this.onSubmitUpdateAreas;
}
public static class AltRowStyle {
public String useWhen;
public String style;
public AltRowStyle(Element altRowStyleElement) {
this.useWhen = altRowStyleElement.getAttribute("use-when");
this.style = altRowStyleElement.getAttribute("style");
}
}
/**
* iterate through alt-row-styles list to see if should be used, then add style
* @return The style for item row
*/
public String getStyleAltRowStyle(Map<String, Object> context) {
String styles = "";
try {
// use the same Interpreter (ie with the same context setup) for all evals
GroovyShell shell = this.getGroovyShell(context);
for (AltRowStyle altRowStyle : this.altRowStyles) {
Object retVal = shell.evaluate(StringUtil.convertOperatorSubstitutions(altRowStyle.useWhen));
// retVal should be a Boolean, if not something weird is up...
if (retVal instanceof Boolean) {
Boolean boolVal = (Boolean) retVal;
if (boolVal.booleanValue()) {
styles += altRowStyle.style;
}
} else {
throw new IllegalArgumentException(
"Return value from style condition eval was not a Boolean: " + retVal.getClass().getName() + " [" + retVal + "] of form " + this.name);
}
}
} catch (CompilationFailedException e) {
String errmsg = "Error evaluating BeanShell style conditions on form " + this.name;
Debug.logError(e, errmsg, module);
throw new IllegalArgumentException(errmsg);
}
return styles;
}
public static class AltTarget {
public String useWhen;
public FlexibleStringExpander targetExdr;
public AltTarget(Element altTargetElement) {
this.useWhen = altTargetElement.getAttribute("use-when");
this.targetExdr = FlexibleStringExpander.getInstance(altTargetElement.getAttribute("target"));
}
@Override
public int hashCode() {
return useWhen.hashCode();
}
@Override
public boolean equals(Object obj) {
return obj instanceof AltTarget && obj.hashCode() == this.hashCode();
}
}
/** The UpdateArea class implements the <code>&lt;on-event-update-area&gt;</code>
* elements used in form widgets.
*/
public static class UpdateArea {
protected String eventType;
protected String areaId;
protected String areaTarget;
List<WidgetWorker.Parameter> parameterList =FastList.newInstance();
/** XML constructor.
* @param updateAreaElement The <code>&lt;on-xxx-update-area&gt;</code>
* XML element.
*/
public UpdateArea(Element updateAreaElement) {
this.eventType = updateAreaElement.getAttribute("event-type");
this.areaId = updateAreaElement.getAttribute("area-id");
this.areaTarget = updateAreaElement.getAttribute("area-target");
List<? extends Element> parameterElementList = UtilXml.childElementList(updateAreaElement, "parameter");
for (Element parameterElement: parameterElementList) {
this.parameterList.add(new WidgetWorker.Parameter(parameterElement));
}
}
/** String constructor.
* @param areaId The id of the widget element to be updated
* @param areaTarget The target URL called to update the area
*/
public UpdateArea(String eventType, String areaId, String areaTarget) {
this.eventType = eventType;
this.areaId = areaId;
this.areaTarget = areaTarget;
}
@Override
public int hashCode() {
return areaId.hashCode();
}
@Override
public boolean equals(Object obj) {
return obj instanceof UpdateArea && obj.hashCode() == this.hashCode();
}
public String getEventType() {
return eventType;
}
public String getAreaId() {
return areaId;
}
public String getAreaTarget(Map<String, ? extends Object> context) {
return FlexibleStringExpander.expandString(areaTarget, context);
}
public Map<String, String> getParameterMap(Map<String, Object> context) {
Map<String, String> fullParameterMap = FastMap.newInstance();
for (WidgetWorker.Parameter parameter: this.parameterList) {
fullParameterMap.put(parameter.getName(), parameter.getValue(context));
}
return fullParameterMap;
}
}
public static class AutoFieldsService {
public String serviceName;
public String mapName;
public String defaultFieldType;
public int defaultPosition;
public AutoFieldsService(Element element) {
this.serviceName = element.getAttribute("service-name");
this.mapName = element.getAttribute("map-name");
this.defaultFieldType = element.getAttribute("default-field-type");
String positionStr = element.getAttribute("default-position");
int position = 1;
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);
}
this.defaultPosition = position;
}
}
public static class AutoFieldsEntity {
public String entityName;
public String mapName;
public String defaultFieldType;
public int defaultPosition;
public AutoFieldsEntity(Element element) {
this.entityName = element.getAttribute("entity-name");
this.mapName = element.getAttribute("map-name");
this.defaultFieldType = element.getAttribute("default-field-type");
String positionStr = element.getAttribute("default-position");
int position = 1;
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);
}
this.defaultPosition = position;
}
}
public static class SortField {
protected String fieldName;
protected Integer position = null;
public SortField(String name, String position) {
this.fieldName = name;
if (UtilValidate.isNotEmpty(position)){
Integer posParam = null;
try {
posParam = Integer.valueOf(position);
}
catch(Exception e) {/* just ignore the exception*/}
this.position = posParam;
}
}
public SortField(String name) {
this(name, null);
}
public String getFieldName() {
return this.fieldName;
}
public Integer getPosition() {
return this.position;
}
}
public static interface FieldGroupBase {}
public static class FieldGroup implements FieldGroupBase {
public String id;
public String style;
public String title;
public boolean collapsible = false;
public boolean initiallyCollapsed = false;
protected ModelForm modelForm;
protected static int baseSeqNo = 0;
protected static String baseId = "_G";
public FieldGroup(Element sortOrderElement, ModelForm modelForm) {
this.modelForm = modelForm;
if (sortOrderElement != null) {
this.id = sortOrderElement.getAttribute("id");
if (UtilValidate.isEmpty(this.id)) {
String lastGroupId = baseId + baseSeqNo++ + "_";
this.setId(lastGroupId);
}
this.style = sortOrderElement.getAttribute("style");
this.title = sortOrderElement.getAttribute("title");
this.collapsible = "true".equals(sortOrderElement.getAttribute("collapsible"));
this.initiallyCollapsed = "true".equals(sortOrderElement.getAttribute("initially-collapsed"));
if (this.initiallyCollapsed) {
this.collapsible = true;
}
for (Element sortFieldElement: UtilXml.childElementList(sortOrderElement, "sort-field")) {
modelForm.sortOrderFields.add(new SortField(sortFieldElement.getAttribute("name"),sortFieldElement.getAttribute("position")));
modelForm.fieldGroupMap.put(sortFieldElement.getAttribute("name"), this);
}
} else {
String lastGroupId = baseId + baseSeqNo++ + "_";
this.setId(lastGroupId);
}
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public String getStyle() {
return this.style;
}
public String getTitle() {
return this.title;
}
public Boolean collapsible() {
return this.collapsible;
}
public Boolean initiallyCollapsed() {
return this.initiallyCollapsed;
}
public void renderStartString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer) throws IOException {
if (modelForm.fieldGroupList.size() > 0) {
formStringRenderer.renderFieldGroupOpen(writer, context, this);
}
formStringRenderer.renderFormatSingleWrapperOpen(writer, context, modelForm);
}
public void renderEndString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer) throws IOException {
formStringRenderer.renderFormatSingleWrapperClose(writer, context, modelForm);
if (modelForm.fieldGroupList.size() > 0) {
formStringRenderer.renderFieldGroupClose(writer, context, this);
}
}
}
public static class Banner implements FieldGroupBase {
protected ModelForm modelForm;
public FlexibleStringExpander style;
public FlexibleStringExpander text;
public FlexibleStringExpander textStyle;
public FlexibleStringExpander leftText;
public FlexibleStringExpander leftTextStyle;
public FlexibleStringExpander rightText;
public FlexibleStringExpander rightTextStyle;
public Banner(Element sortOrderElement, ModelForm modelForm) {
this.modelForm = modelForm;
this.style = FlexibleStringExpander.getInstance(sortOrderElement.getAttribute("style"));
this.text = FlexibleStringExpander.getInstance(sortOrderElement.getAttribute("text"));
this.textStyle = FlexibleStringExpander.getInstance(sortOrderElement.getAttribute("text-style"));
this.leftText = FlexibleStringExpander.getInstance(sortOrderElement.getAttribute("left-text"));
this.leftTextStyle = FlexibleStringExpander.getInstance(sortOrderElement.getAttribute("left-text-style"));
this.rightText = FlexibleStringExpander.getInstance(sortOrderElement.getAttribute("right-text"));
this.rightTextStyle = FlexibleStringExpander.getInstance(sortOrderElement.getAttribute("right-text-style"));
}
public String getStyle(Map<String, Object> context) { return this.style.expandString(context); }
public String getText(Map<String, Object> context) { return this.text.expandString(context); }
public String getTextStyle(Map<String, Object> context) { return this.textStyle.expandString(context); }
public String getLeftText(Map<String, Object> context) { return this.leftText.expandString(context); }
public String getLeftTextStyle(Map<String, Object> context) { return this.leftTextStyle.expandString(context); }
public String getRightText(Map<String, Object> context) { return this.rightText.expandString(context); }
public String getRightTextStyle(Map<String, Object> context) { return this.rightTextStyle.expandString(context); }
public void renderString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer) throws IOException {
formStringRenderer.renderBanner(writer, context, this);
}
}
public Set<String> getAllEntityNamesUsed() {
Set<String> allEntityNamesUsed = FastSet.newInstance();
for (AutoFieldsEntity autoFieldsEntity: this.autoFieldsEntities) {
allEntityNamesUsed.add(autoFieldsEntity.entityName);
}
if (this.actions != null) {
for (ModelFormAction modelFormAction: this.actions) {
if (modelFormAction instanceof ModelFormAction.EntityOne) {
allEntityNamesUsed.add(((ModelFormAction.EntityOne)modelFormAction).finder.getEntityName());
} else if (modelFormAction instanceof ModelFormAction.EntityAnd) {
allEntityNamesUsed.add(((ModelFormAction.EntityAnd)modelFormAction).finder.getEntityName());
} else if (modelFormAction instanceof ModelFormAction.EntityCondition) {
allEntityNamesUsed.add(((ModelFormAction.EntityCondition)modelFormAction).finder.getEntityName());
}
}
}
if (this.rowActions != null) {
for (ModelFormAction modelFormAction: this.rowActions) {
if (modelFormAction instanceof ModelFormAction.EntityOne) {
allEntityNamesUsed.add(((ModelFormAction.EntityOne)modelFormAction).finder.getEntityName());
} else if (modelFormAction instanceof ModelFormAction.EntityAnd) {
allEntityNamesUsed.add(((ModelFormAction.EntityAnd)modelFormAction).finder.getEntityName());
} else if (modelFormAction instanceof ModelFormAction.EntityCondition) {
allEntityNamesUsed.add(((ModelFormAction.EntityCondition)modelFormAction).finder.getEntityName());
}
}
}
for (ModelFormField modelFormField: this.fieldList) {
if (UtilValidate.isNotEmpty(modelFormField.getEntityName())) {
allEntityNamesUsed.add(modelFormField.getEntityName());
}
if (modelFormField.getFieldInfo() instanceof ModelFormField.DisplayEntityField) {
allEntityNamesUsed.add(((ModelFormField.DisplayEntityField)modelFormField.getFieldInfo()).entityName);
}
if (modelFormField.getFieldInfo() instanceof ModelFormField.FieldInfoWithOptions) {
for (ModelFormField.OptionSource optionSource: ((ModelFormField.FieldInfoWithOptions)modelFormField.getFieldInfo()).optionSources) {
if (optionSource instanceof ModelFormField.EntityOptions) {
allEntityNamesUsed.add(((ModelFormField.EntityOptions)optionSource).entityName);
}
}
}
}
return allEntityNamesUsed;
}
public Set<String> getAllServiceNamesUsed() {
Set<String> allServiceNamesUsed = FastSet.newInstance();
for (AutoFieldsService autoFieldsService: this.autoFieldsServices) {
allServiceNamesUsed.add(autoFieldsService.serviceName);
}
if (this.actions != null) {
for (ModelFormAction modelFormAction: this.actions) {
try {
ModelFormAction.Service service = (ModelFormAction.Service) modelFormAction;
if (!service.serviceNameExdr.isEmpty()) {
allServiceNamesUsed.add(service.serviceNameExdr.toString());
}
} catch (ClassCastException e) {}
}
}
if (this.rowActions != null) {
for (ModelFormAction modelFormAction: this.rowActions) {
try {
ModelFormAction.Service service = (ModelFormAction.Service) modelFormAction;
if (!service.serviceNameExdr.isEmpty()) {
allServiceNamesUsed.add(service.serviceNameExdr.toString());
}
} catch (ClassCastException e) {}
}
}
for (ModelFormField modelFormField: this.fieldList) {
if (UtilValidate.isNotEmpty(modelFormField.getServiceName())) {
allServiceNamesUsed.add(modelFormField.getServiceName());
}
}
return allServiceNamesUsed;
}
public Set<String> getLinkedRequestsLocationAndUri() throws GeneralException {
Set<String> allRequestsUsed = FastSet.newInstance();
if (this.fieldList != null) {
for (ModelFormField modelFormField: this.fieldList) {
if (modelFormField.getFieldInfo() instanceof ModelFormField.HyperlinkField) {
ModelFormField.HyperlinkField link = (ModelFormField.HyperlinkField) modelFormField.getFieldInfo();
String target = link.getTarget(null);
String urlMode = link.getTargetType();
// Debug.logInfo("In findRequestNamesLinkedtoInWidget found link [" + link.rawString() + "] with target [" + target + "]", module);
Set<String> controllerLocAndRequestSet = ConfigXMLReader.findControllerRequestUniqueForTargetType(target, urlMode);
if (controllerLocAndRequestSet != null) {
allRequestsUsed.addAll(controllerLocAndRequestSet);
}
} else if (modelFormField.getFieldInfo() instanceof ModelFormField.DisplayEntityField) {
ModelFormField.DisplayEntityField parentField = (ModelFormField.DisplayEntityField) modelFormField.getFieldInfo();
if (parentField.subHyperlink != null) {
Set<String> controllerLocAndRequestSet = ConfigXMLReader.findControllerRequestUniqueForTargetType(parentField.subHyperlink.getTarget(null), parentField.subHyperlink.getTargetType());
if (controllerLocAndRequestSet != null) {
allRequestsUsed.addAll(controllerLocAndRequestSet);
}
}
} else if (modelFormField.getFieldInfo() instanceof ModelFormField.TextField) {
ModelFormField.TextField parentField = (ModelFormField.TextField) modelFormField.getFieldInfo();
if (parentField.subHyperlink != null) {
Set<String> controllerLocAndRequestSet = ConfigXMLReader.findControllerRequestUniqueForTargetType(parentField.subHyperlink.getTarget(null), parentField.subHyperlink.getTargetType());
if (controllerLocAndRequestSet != null) {
allRequestsUsed.addAll(controllerLocAndRequestSet);
}
}
} else if (modelFormField.getFieldInfo() instanceof ModelFormField.DropDownField) {
ModelFormField.DropDownField parentField = (ModelFormField.DropDownField) modelFormField.getFieldInfo();
if (parentField.subHyperlink != null) {
Set<String> controllerLocAndRequestSet = ConfigXMLReader.findControllerRequestUniqueForTargetType(parentField.subHyperlink.getTarget(null), parentField.subHyperlink.getTargetType());
if (controllerLocAndRequestSet != null) {
allRequestsUsed.addAll(controllerLocAndRequestSet);
}
}
} else if (modelFormField.getFieldInfo() instanceof ModelFormField.ImageField) {
ModelFormField.ImageField parentField = (ModelFormField.ImageField) modelFormField.getFieldInfo();
if (parentField.subHyperlink != null) {
Set<String> controllerLocAndRequestSet = ConfigXMLReader.findControllerRequestUniqueForTargetType(parentField.subHyperlink.getTarget(null), parentField.subHyperlink.getTargetType());
if (controllerLocAndRequestSet != null) {
allRequestsUsed.addAll(controllerLocAndRequestSet);
}
}
}
}
}
return allRequestsUsed;
}
public Set<String> getTargetedRequestsLocationAndUri() throws GeneralException {
Set<String> allRequestsUsed = FastSet.newInstance();
if (this.altTargets != null) {
for (AltTarget altTarget: this.altTargets) {
String target = altTarget.targetExdr.getOriginal();
String urlMode = "intra-app";
Set<String> controllerLocAndRequestSet = ConfigXMLReader.findControllerRequestUniqueForTargetType(target, urlMode);
if (controllerLocAndRequestSet != null) {
allRequestsUsed.addAll(controllerLocAndRequestSet);
}
}
}
if (!this.target.isEmpty()) {
String target = this.target.getOriginal();
String urlMode = UtilValidate.isNotEmpty(this.targetType) ? this.targetType : "intra-app";
if (target.indexOf("${") < 0) {
Set<String> controllerLocAndRequestSet = ConfigXMLReader.findControllerRequestUniqueForTargetType(target, urlMode);
if (controllerLocAndRequestSet != null) {
allRequestsUsed.addAll(controllerLocAndRequestSet);
}
}
}
return allRequestsUsed;
}
}