/*******************************************************************************
 * 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;
    }
}
