svn commit: r1636437 [2/3] - in /ofbiz/trunk/framework/widget/src/org/ofbiz/widget: form/ html/ screen/

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r1636437 [2/3] - in /ofbiz/trunk/framework/widget/src/org/ofbiz/widget: form/ html/ screen/

adrianc
Modified: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/form/ModelForm.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/form/ModelForm.java?rev=1636437&r1=1636436&r2=1636437&view=diff
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/form/ModelForm.java (original)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/form/ModelForm.java Mon Nov  3 20:46:34 2014
@@ -20,7 +20,6 @@ package org.ofbiz.widget.form;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -29,29 +28,22 @@ import java.util.LinkedList;
 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 java.util.concurrent.atomic.AtomicInteger;
 
 import org.ofbiz.base.util.BshUtil;
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.base.util.StringUtil;
 import org.ofbiz.base.util.UtilGenerics;
-import org.ofbiz.base.util.UtilMisc;
 import org.ofbiz.base.util.UtilProperties;
 import org.ofbiz.base.util.UtilValidate;
 import org.ofbiz.base.util.UtilXml;
 import org.ofbiz.base.util.collections.FlexibleMapAccessor;
-import org.ofbiz.base.util.collections.MapStack;
 import org.ofbiz.base.util.string.FlexibleStringExpander;
-import org.ofbiz.entity.GenericEntity;
 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;
@@ -1028,11 +1020,6 @@ public class ModelForm extends ModelWidg
         return actions;
     }
 
-    public int getActualPageSize(Map<String, Object> context) {
-        Integer value = (Integer) context.get("actualPageSize");
-        return value != null ? value.intValue() : (getHighIndex(context) - getLowIndex(context));
-    }
-
     public List<AltRowStyle> getAltRowStyles() {
         return altRowStyles;
     }
@@ -1049,11 +1036,6 @@ public class ModelForm extends ModelWidg
         return autoFieldsServices;
     }
 
-    @Override
-    public String getBoundaryCommentName() {
-        return formLocation + "#" + getName();
-    }
-
     public Interpreter getBshInterpreter(Map<String, Object> context) throws EvalError {
         Interpreter bsh = (Interpreter) context.get("bshInterpreter");
         if (bsh == null) {
@@ -1063,6 +1045,11 @@ public class ModelForm extends ModelWidg
         return bsh;
     }
 
+    @Override
+    public String getBoundaryCommentName() {
+        return formLocation + "#" + getName();
+    }
+
     public boolean getClientAutocompleteFields() {
         return this.clientAutocompleteFields;
     }
@@ -1080,33 +1067,6 @@ public class ModelForm extends ModelWidg
         return this.containerStyle;
     }
 
-    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 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;
-        }
-    }
-
     public String getDefaultEntityName() {
         return this.defaultEntityName;
     }
@@ -1187,30 +1147,6 @@ public class ModelForm extends ModelWidg
         return fieldList;
     }
 
-    public List<ModelFormField> getFieldListByPosition(List<ModelFormField> modelFormFieldList, int position) {
-        List<ModelFormField> fieldListByPosition = new LinkedList<ModelFormField>();
-        for (ModelFormField modelFormField : modelFormFieldList) {
-            if (modelFormField.getPosition() == position) {
-                fieldListByPosition.add(modelFormField);
-            }
-        }
-        return fieldListByPosition;
-    }
-
-    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 = new LinkedList<ModelFormField>();
-                fieldsByPosition.put(position, fieldListByPosition);
-            }
-            fieldListByPosition.add(modelFormField);
-        }
-        return fieldsByPosition.values();
-    }
-
     public String getfocusFieldName() {
         return this.focusFieldName;
     }
@@ -1235,97 +1171,10 @@ public class ModelForm extends ModelWidg
         return this.headerRowStyle;
     }
 
-    public List<ModelFormField> getHiddenIgnoredFields(Map<String, Object> context, Set<String> alreadyRendered,
-            List<ModelFormField> fieldList, int position) {
-        List<ModelFormField> hiddenIgnoredFieldList = new LinkedList<ModelFormField>();
-        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 boolean getHideHeader() {
         return this.hideHeader;
     }
 
-    public int getHighIndex(Map<String, Object> context) {
-        Integer value = (Integer) context.get("highIndex");
-        return value != null ? value.intValue() : 0;
-    }
-
-    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 getItemIndexSeparator() {
         if (UtilValidate.isNotEmpty(this.itemIndexSeparator)) {
             return this.itemIndexSeparator;
@@ -1342,61 +1191,10 @@ public class ModelForm extends ModelWidg
         return this.listEntryName;
     }
 
-    public void getListLimits(Map<String, Object> context, Object entryList) {
-        int viewIndex = 0;
-        int viewSize = 0;
-        int lowIndex = 0;
-        int highIndex = 0;
-
-        int 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.getViewIndex(context);
-            viewSize = this.getViewSize(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 getListName() {
         return this.listName;
     }
 
-    public int getListSize(Map<String, Object> context) {
-        Integer value = (Integer) context.get("listSize");
-        return value != null ? value.intValue() : 0;
-    }
-
-    public int getLowIndex(Map<String, Object> context) {
-        Integer value = (Integer) context.get("lowIndex");
-        return value != null ? value.intValue() : 0;
-    }
-
     public String getMultiPaginateIndexField(Map<String, Object> context) {
         String field = this.paginateIndexField.expandString(context);
         if (UtilValidate.isEmpty(field)) {
@@ -1443,7 +1241,7 @@ public class ModelForm extends ModelWidg
         return overrideListSize.getOriginal();
     }
 
-    private int getOverrideListSize(Map<String, Object> context) {
+    public int getOverrideListSize(Map<String, Object> context) {
         int listSize = 0;
         if (!this.overrideListSize.isEmpty()) {
             String size = this.overrideListSize.expandString(context);
@@ -1798,1168 +1596,18 @@ public class ModelForm extends ModelWidg
     public Set<String> getUseWhenFields() {
         return useWhenFields;
     }
-
-    public int getViewIndex(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 int getViewSize(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 boolean getGroupColumns() {
         return groupColumns;
     }
 
-    private boolean isOverridenListSize() {
+    public boolean isOverridenListSize() {
         return !this.overrideListSize.isEmpty();
     }
 
-    public void preparePager(Map<String, Object> context) {
-
-        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);
-            }
-        }
-    }
-
-    /**
-     * 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 default view size
-        if (!getPaginate(context)) {
-            // FIXME: Don't modify model state
-            //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 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 = new LinkedList<ModelFormField>();
-        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 = new LinkedList<Map<String, List<ModelFormField>>>(); // 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 = new LinkedList<ModelFormField>();
-            List<ModelFormField> innerFormFields = new LinkedList<ModelFormField>();
-            List<ModelFormField> innerDisplayHyperlinkFieldsEnd = new LinkedList<ModelFormField>();
-
-            // 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;
-    }
-
-    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;
-            }
-        }
-    }
-
-    // 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 = new HashMap<String, Integer>();
-        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 void renderItemRows(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer,
-            boolean formPerItem, int numOfColumns) throws IOException {
-        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 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 = new HashMap<String, Object>();
-            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;
-                }
-
-                // reset/remove the BshInterpreter now as well as later because chances are there is an interpreter at this level of the stack too
-                this.resetBshInterpreter(context);
-
-                Map<String, Object> itemMap = UtilGenerics.checkMap(item);
-                MapStack<String> localContext = MapStack.create(context);
-                if (UtilValidate.isNotEmpty(this.getListEntryName())) {
-                    localContext.put(this.getListEntryName(), item);
-                } else {
-                    if (itemMap instanceof GenericEntity) {
-                        // Rendering code might try to modify the GenericEntity instance,
-                        // so we make a copy of it.
-                        Map<String, Object> genericEntityClone = UtilGenerics.cast(((GenericEntity) itemMap).clone());
-                        localContext.push(genericEntityClone);
-                    } 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.resetBshInterpreter(localContext);
-                localContext.push();
-                localContext.put("previousItem", previousItem);
-                previousItem = new HashMap<String, Object>();
-                previousItem.putAll(itemMap);
-
-                ModelWidgetAction.runSubActions(this.rowActions, localContext);
-
-                localContext.put("itemIndex", Integer.valueOf(itemIndex - lowIndex));
-                if (UtilValidate.isNotEmpty(context.get("renderFormSeqNumber"))) {
-                    localContext.put("formUniqueId", "_" + context.get("renderFormSeqNumber"));
-                }
-
-                this.resetBshInterpreter(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 = new LinkedList<ModelFormField>();
-                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
-
-                    List<ModelFormField> innerDisplayHyperlinkFieldsBegin = new LinkedList<ModelFormField>();
-                    List<ModelFormField> innerFormFields = new LinkedList<ModelFormField>();
-                    List<ModelFormField> innerDisplayHyperlinkFieldsEnd = new LinkedList<ModelFormField>();
-
-                    // 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);
-                }
-            }
-        }
-    }
-
-    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 void renderSingleFormString(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer,
-            int positions) throws IOException {
-        List<ModelFormField> tempFieldList = new LinkedList<ModelFormField>();
-        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)) {
-                if (UtilValidate.isNotEmpty(lastFormField)) {
-                    currentFormField = lastFormField;
-                }
-                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 resetBshInterpreter(Map<String, Object> context) {
-        context.remove("bshInterpreter");
-    }
-
     public void runFormActions(Map<String, Object> context) {
         ModelWidgetAction.runSubActions(this.actions, context);
     }
 
-    private <X> X safeNext(Iterator<X> iterator) {
-        try {
-            return iterator.next();
-        } catch (NoSuchElementException e) {
-            return null;
-        }
-    }
-
     public static class AltRowStyle {
         public final String useWhen;
         public final String style;

Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/form/Paginator.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/form/Paginator.java?rev=1636437&view=auto
==============================================================================
--- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/form/Paginator.java (added)
+++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/form/Paginator.java Mon Nov  3 20:46:34 2014
@@ -0,0 +1,236 @@
+/*******************************************************************************
+ * 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.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.UtilGenerics;
+import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.entity.GenericEntityException;
+import org.ofbiz.entity.util.EntityListIterator;
+import org.ofbiz.widget.WidgetWorker;
+
+/**
+ * Utility methods for handling list pagination.
+ *
+ */
+public final class Paginator {
+
+    public static final String module = Paginator.class.getName();
+
+    public static int getActualPageSize(Map<String, Object> context) {
+        Integer value = (Integer) context.get("actualPageSize");
+        return value != null ? value.intValue() : (getHighIndex(context) - getLowIndex(context));
+    }
+
+    public static int getHighIndex(Map<String, Object> context) {
+        Integer value = (Integer) context.get("highIndex");
+        return value != null ? value.intValue() : 0;
+    }
+
+    public static void getListLimits(ModelForm modelForm, Map<String, Object> context, Object entryList) {
+        int viewIndex = 0;
+        int viewSize = 0;
+        int lowIndex = 0;
+        int highIndex = 0;
+        int listSize = modelForm.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 (modelForm.getPaginate(context)) {
+            viewIndex = getViewIndex(modelForm, context);
+            viewSize = getViewSize(modelForm, context);
+            lowIndex = viewIndex * viewSize;
+            highIndex = (viewIndex + 1) * viewSize;
+        } else {
+            viewIndex = 0;
+            viewSize = ModelForm.MAX_PAGE_SIZE;
+            lowIndex = 0;
+            highIndex = ModelForm.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 static int getListSize(Map<String, Object> context) {
+        Integer value = (Integer) context.get("listSize");
+        return value != null ? value.intValue() : 0;
+    }
+
+    public static int getLowIndex(Map<String, Object> context) {
+        Integer value = (Integer) context.get("lowIndex");
+        return value != null ? value.intValue() : 0;
+    }
+
+    public static int getViewIndex(ModelForm modelForm, Map<String, Object> context) {
+        String field = modelForm.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 = modelForm.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 static int getViewSize(ModelForm modelForm, Map<String, Object> context) {
+        String field = modelForm.getMultiPaginateSizeField(context);
+        int viewSize = modelForm.getDefaultViewSize();
+        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 = modelForm.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 static void preparePager(ModelForm modelForm, Map<String, Object> context) {
+
+        String lookupName = modelForm.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(modelForm, 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 (modelForm.isOverridenListSize()) {
+            lowIndex = 0;
+            highIndex = ((Integer) context.get("viewSize")).intValue();
+        }
+
+        if (iter == null)
+            return;
+
+        // count item rows
+        int itemIndex = -1;
+        Object item = safeNext(iter);
+        while (item != null && itemIndex < highIndex) {
+            itemIndex++;
+            item = 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(modelForm.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);
+            }
+        }
+    }
+
+    private static <X> X safeNext(Iterator<X> iterator) {
+        try {
+            return iterator.next();
+        } catch (NoSuchElementException e) {
+            return null;
+        }
+    }
+}